This commit is contained in:
chenjianxing 2020-04-21 16:26:59 +08:00
commit 68c7c8f92f
11 changed files with 237 additions and 188 deletions

View File

@ -3,23 +3,16 @@ package io.metersphere.report;
import com.opencsv.bean.CsvToBean;
import com.opencsv.bean.CsvToBeanBuilder;
import com.opencsv.bean.HeaderColumnNameMappingStrategy;
import io.metersphere.commons.utils.MsJMeterUtils;
import io.metersphere.report.base.*;
import io.metersphere.report.dto.ErrorsTop5DTO;
import io.metersphere.report.dto.RequestStatisticsDTO;
import io.metersphere.report.parse.ResultDataParse;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.report.core.Sample;
import org.apache.jmeter.report.core.SampleMetadata;
import org.apache.jmeter.report.dashboard.JsonizerVisitor;
import org.apache.jmeter.report.processor.*;
import org.apache.jmeter.report.processor.graph.AbstractOverTimeGraphConsumer;
import org.apache.jmeter.report.processor.graph.impl.ActiveThreadsGraphConsumer;
import org.apache.jmeter.report.processor.graph.impl.HitsPerSecondGraphConsumer;
import org.apache.jmeter.report.processor.graph.impl.ResponseTimeOverTimeGraphConsumer;
import java.io.Reader;
import java.io.StringReader;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@ -31,7 +24,7 @@ import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
public class JtlResolver {
public class GenerateReport {
private static final Integer ERRORS_TOP_SIZE = 5;
private static final String DATE_TIME_PATTERN = "yyyy/MM/dd HH:mm:ss";
@ -193,7 +186,7 @@ public class JtlResolver {
}
}
Map<String, List<Metric>> jtlMap = falseList.stream().collect(Collectors.groupingBy(JtlResolver::getResponseCodeAndFailureMessage));
Map<String, List<Metric>> jtlMap = falseList.stream().collect(Collectors.groupingBy(GenerateReport::getResponseCodeAndFailureMessage));
for (Map.Entry<String, List<Metric>> next : jtlMap.entrySet()) {
String key = next.getKey();
@ -226,7 +219,7 @@ public class JtlResolver {
.collect(Collectors.toList());
Map<String, List<Metric>> collect = falseList.stream()
.collect(Collectors.groupingBy(JtlResolver::getResponseCodeAndFailureMessage));
.collect(Collectors.groupingBy(GenerateReport::getResponseCodeAndFailureMessage));
for (Map.Entry<String, List<Metric>> next : collect.entrySet()) {
String key = next.getKey();
@ -277,9 +270,9 @@ public class JtlResolver {
TestOverview testOverview = new TestOverview();
DecimalFormat decimalFormat = new DecimalFormat("0.00");
List<Metric> totalLineList = JtlResolver.resolver(jtlString);
// todo
List<Metric> totalLineList2 = JtlResolver.resolver(jtlString);
List<Metric> totalLineList = GenerateReport.resolver(jtlString);
// todo 修改测试概览的数值
List<Metric> totalLineList2 = GenerateReport.resolver(jtlString);
// 时间戳转时间
for (Metric metric : totalLineList2) {
metric.setTimestamp(stampToDate(DATE_TIME_PATTERN, metric.getTimestamp()));
@ -343,120 +336,26 @@ public class JtlResolver {
}
public static List<ChartsData> getLoadChartData(String jtlString) {
Map<String, Object> activeThreadMap = getResultDataMap(jtlString, new ActiveThreadsGraphConsumer());
Map<String, Object> hitsMap = getResultDataMap(jtlString, new HitsPerSecondGraphConsumer());
List<ChartsData> activeThreadList = new ArrayList<>();
List<ChartsData> hitsList = new ArrayList<>();
mapResolver(activeThreadMap, activeThreadList, "users");
mapResolver(hitsMap, hitsList, "hits");
activeThreadList.addAll(hitsList);
return activeThreadList;
Map<String, Object> activeThreadMap = ResultDataParse.getGraphDataMap(jtlString, new ActiveThreadsGraphConsumer());
Map<String, Object> hitsMap = ResultDataParse.getGraphDataMap(jtlString, new HitsPerSecondGraphConsumer());
List<ChartsData> resultList = ResultDataParse.graphMapParsing(activeThreadMap, "users");
List<ChartsData> hitsList = ResultDataParse.graphMapParsing(hitsMap, "hits");
resultList.addAll(hitsList);
return resultList;
}
public static List<ChartsData> getResponseTimeChartData(String jtlString) {
Map<String, Object> activeThreadMap = getResultDataMap(jtlString, new ActiveThreadsGraphConsumer());
Map<String, Object> responseTimeMap = getResultDataMap(jtlString, new ResponseTimeOverTimeGraphConsumer());
List<ChartsData> activeThreadList = new ArrayList<>();
List<ChartsData> responseTimeList = new ArrayList<>();
mapResolver(activeThreadMap, activeThreadList, "users");
mapResolver(responseTimeMap, responseTimeList, "responseTime");
activeThreadList.addAll(responseTimeList);
return activeThreadList;
}
public static void mapResolver(Map<String, Object> map, List list, String seriesName) {
// ThreadGroup-1
for (String key : map.keySet()) {
MapResultData mapResultData = (MapResultData) map.get(key);
ResultData maxY = mapResultData.getResult("maxY");
ListResultData series = (ListResultData) mapResultData.getResult("series");
if (series.getSize() > 0) {
for (int j = 0; j < series.getSize(); j++) {
MapResultData resultData = (MapResultData) series.get(j);
// data, isOverall, label, isController
ListResultData data = (ListResultData) resultData.getResult("data");
ValueResultData label = (ValueResultData) resultData.getResult("label");
if (data.getSize() > 0) {
for (int i = 0; i < data.getSize(); i++) {
ListResultData listResultData = (ListResultData) data.get(i);
String result = listResultData.accept(new JsonizerVisitor());
result = result.substring(1, result.length() - 1);
String[] split = result.split(",");
ChartsData chartsData = new ChartsData();
BigDecimal bigDecimal = new BigDecimal(split[0]);
String timeStamp = bigDecimal.toPlainString();
String time = null;
try {
time = formatDate(stampToDate(DATE_TIME_PATTERN, timeStamp));
} catch (ParseException e) {
e.printStackTrace();
}
chartsData.setxAxis(time);
chartsData.setyAxis(new BigDecimal(split[1].trim()));
if (series.getSize() == 1) {
chartsData.setGroupName(seriesName);
} else {
chartsData.setGroupName((String) label.getValue());
}
list.add(chartsData);
}
}
}
}
}
}
public static Map<String, Object> getResultDataMap(String jtlString, AbstractOverTimeGraphConsumer timeGraphConsumer) {
int row = 0;
AbstractOverTimeGraphConsumer abstractOverTimeGraphConsumer = timeGraphConsumer;
abstractOverTimeGraphConsumer.setGranularity(60000);
// 使用反射获取properties
MsJMeterUtils.loadJMeterProperties("jmeter.properties"); // 这个路径不存在
SampleMetadata sampleMetaData = createTestMetaData();
SampleContext sampleContext = new SampleContext();
abstractOverTimeGraphConsumer.setSampleContext(sampleContext);
abstractOverTimeGraphConsumer.initialize();
abstractOverTimeGraphConsumer.startConsuming();
StringTokenizer tokenizer = new StringTokenizer(jtlString, "\n");
// 去掉第一行
tokenizer.nextToken();
while (tokenizer.hasMoreTokens()) {
String line = tokenizer.nextToken();
String[] data = line.split(",", -1);
Sample sample = new Sample(row++, sampleMetaData, data);
abstractOverTimeGraphConsumer.consume(sample, 0);
}
abstractOverTimeGraphConsumer.stopConsuming();
return sampleContext.getData();
}
// Create a static SampleMetadataObject
private static SampleMetadata createTestMetaData() {
String columnsString = "timeStamp,elapsed,label,responseCode,responseMessage,threadName,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect";
columnsString = "timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect";
String[] columns = new String[17];
int lastComa = 0;
int columnIndex = 0;
for (int i = 0; i < columnsString.length(); i++) {
if (columnsString.charAt(i) == ',') {
columns[columnIndex] = columnsString.substring(lastComa, i);
lastComa = i + 1;
columnIndex++;
} else if (i + 1 == columnsString.length()) {
columns[columnIndex] = columnsString.substring(lastComa, i + 1);
}
}
return new SampleMetadata(',', columns);
Map<String, Object> activeThreadMap = ResultDataParse.getGraphDataMap(jtlString, new ActiveThreadsGraphConsumer());
Map<String, Object> responseTimeMap = ResultDataParse.getGraphDataMap(jtlString, new ResponseTimeOverTimeGraphConsumer());
List<ChartsData> resultList = ResultDataParse.graphMapParsing(activeThreadMap, "users");
List<ChartsData> responseTimeList = ResultDataParse.graphMapParsing(responseTimeMap, "responseTime");
resultList.addAll(responseTimeList);
return resultList;
}
public static ReportTimeInfo getReportTimeInfo(String jtlString) {
ReportTimeInfo reportTimeInfo = new ReportTimeInfo();
List<Metric> totalLineList = JtlResolver.resolver(jtlString);
List<Metric> totalLineList = GenerateReport.resolver(jtlString);
totalLineList.sort(Comparator.comparing(t0 -> Long.valueOf(t0.getTimestamp())));

View File

@ -0,0 +1,139 @@
package io.metersphere.report.parse;
import io.metersphere.commons.utils.MsJMeterUtils;
import io.metersphere.report.base.ChartsData;
import org.apache.jmeter.report.core.Sample;
import org.apache.jmeter.report.core.SampleMetadata;
import org.apache.jmeter.report.dashboard.JsonizerVisitor;
import org.apache.jmeter.report.processor.*;
import org.apache.jmeter.report.processor.graph.AbstractOverTimeGraphConsumer;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
public class ResultDataParse {
private static final String DATE_TIME_PATTERN = "yyyy/MM/dd HH:mm:ss";
private static final String TIME_PATTERN = "HH:mm:ss";
public static List<ChartsData> graphMapParsing(Map<String, Object> map, String seriesName) {
List<ChartsData> list = new ArrayList<>();
// ThreadGroup
for (String key : map.keySet()) {
MapResultData mapResultData = (MapResultData) map.get(key);
ResultData maxY = mapResultData.getResult("maxY");
ListResultData series = (ListResultData) mapResultData.getResult("series");
if (series.getSize() > 0) {
for (int j = 0; j < series.getSize(); j++) {
MapResultData resultData = (MapResultData) series.get(j);
// data, isOverall, label, isController
ListResultData data = (ListResultData) resultData.getResult("data");
ValueResultData label = (ValueResultData) resultData.getResult("label");
if (data.getSize() > 0) {
for (int i = 0; i < data.getSize(); i++) {
ListResultData listResultData = (ListResultData) data.get(i);
String result = listResultData.accept(new JsonizerVisitor());
result = result.substring(1, result.length() - 1);
String[] split = result.split(",");
ChartsData chartsData = new ChartsData();
BigDecimal bigDecimal = new BigDecimal(split[0]);
String timeStamp = bigDecimal.toPlainString();
String time = null;
try {
time = formatDate(stampToDate(DATE_TIME_PATTERN, timeStamp));
} catch (ParseException e) {
e.printStackTrace();
}
chartsData.setxAxis(time);
chartsData.setyAxis(new BigDecimal(split[1].trim()));
if (series.getSize() == 1) {
chartsData.setGroupName(seriesName);
} else {
chartsData.setGroupName((String) label.getValue());
}
list.add(chartsData);
}
}
}
}
}
return list;
}
public static Map<String, Object> getGraphDataMap(String jtlString, AbstractOverTimeGraphConsumer timeGraphConsumer) {
AbstractOverTimeGraphConsumer abstractOverTimeGraphConsumer = timeGraphConsumer;
abstractOverTimeGraphConsumer.setGranularity(60000);
abstractOverTimeGraphConsumer.initialize();
SampleContext sampleContext = initJmeterConsumer(jtlString, abstractOverTimeGraphConsumer);
return sampleContext.getData();
}
public static Map<String, Object> getSummryDataMap(String jtlString, AbstractSummaryConsumer<?> summaryConsumer) {
AbstractSummaryConsumer<?> abstractSummaryConsumer = summaryConsumer;
SampleContext sampleContext = initJmeterConsumer(jtlString, summaryConsumer);
return sampleContext.getData();
}
private static SampleContext initJmeterConsumer(String jtlString, AbstractSampleConsumer abstractSampleConsumer) {
int row = 0;
// 使用反射获取properties
MsJMeterUtils.loadJMeterProperties("jmeter.properties");
SampleMetadata sampleMetaData = createTestMetaData();
SampleContext sampleContext = new SampleContext();
abstractSampleConsumer.setSampleContext(sampleContext);
abstractSampleConsumer.startConsuming();
StringTokenizer tokenizer = new StringTokenizer(jtlString, "\n");
// 去掉第一行
tokenizer.nextToken();
while (tokenizer.hasMoreTokens()) {
String line = tokenizer.nextToken();
String[] data = line.split(",", -1);
Sample sample = new Sample(row++, sampleMetaData, data);
abstractSampleConsumer.consume(sample, 0);
}
abstractSampleConsumer.stopConsuming();
return sampleContext;
}
// Create a static SampleMetadataObject
private static SampleMetadata createTestMetaData() {
String columnsString = "timeStamp,elapsed,label,responseCode,responseMessage,threadName,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect";
columnsString = "timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect";
String[] columns = new String[17];
int lastComa = 0;
int columnIndex = 0;
for (int i = 0; i < columnsString.length(); i++) {
if (columnsString.charAt(i) == ',') {
columns[columnIndex] = columnsString.substring(lastComa, i);
lastComa = i + 1;
columnIndex++;
} else if (i + 1 == columnsString.length()) {
columns[columnIndex] = columnsString.substring(lastComa, i + 1);
}
}
return new SampleMetadata(',', columns);
}
private static String stampToDate(String pattern, String timeStamp) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(Long.parseLong(timeStamp)), ZoneId.systemDefault());
return localDateTime.format(dateTimeFormatter);
}
private static String formatDate(String dateString) throws ParseException {
SimpleDateFormat before = new SimpleDateFormat(DATE_TIME_PATTERN);
SimpleDateFormat after = new SimpleDateFormat(TIME_PATTERN);
return after.format(before.parse(dateString));
}
}

View File

@ -11,7 +11,7 @@ import io.metersphere.controller.request.ReportRequest;
import io.metersphere.dto.ReportDTO;
import io.metersphere.engine.Engine;
import io.metersphere.engine.EngineFactory;
import io.metersphere.report.JtlResolver;
import io.metersphere.report.GenerateReport;
import io.metersphere.report.base.ChartsData;
import io.metersphere.report.base.Errors;
import io.metersphere.report.base.ReportTimeInfo;
@ -90,7 +90,7 @@ public class ReportService {
checkReportStatus(id);
LoadTestReportWithBLOBs loadTestReport = loadTestReportMapper.selectByPrimaryKey(id);
String content = loadTestReport.getContent();
RequestStatisticsDTO requestStatistics = JtlResolver.getRequestStatistics(content);
RequestStatisticsDTO requestStatistics = GenerateReport.getRequestStatistics(content);
return requestStatistics;
}
@ -98,7 +98,7 @@ public class ReportService {
checkReportStatus(id);
LoadTestReportWithBLOBs loadTestReport = loadTestReportMapper.selectByPrimaryKey(id);
String content = loadTestReport.getContent();
List<Errors> errors = JtlResolver.getErrorsList(content);
List<Errors> errors = GenerateReport.getErrorsList(content);
return errors;
}
@ -106,7 +106,7 @@ public class ReportService {
checkReportStatus(id);
LoadTestReportWithBLOBs loadTestReport = loadTestReportMapper.selectByPrimaryKey(id);
String content = loadTestReport.getContent();
ErrorsTop5DTO errors = JtlResolver.getErrorsTop5DTO(content);
ErrorsTop5DTO errors = GenerateReport.getErrorsTop5DTO(content);
return errors;
}
@ -114,7 +114,7 @@ public class ReportService {
checkReportStatus(id);
LoadTestReportWithBLOBs loadTestReport = loadTestReportMapper.selectByPrimaryKey(id);
String content = loadTestReport.getContent();
TestOverview testOverview = JtlResolver.getTestOverview(content);
TestOverview testOverview = GenerateReport.getTestOverview(content);
return testOverview;
}
@ -122,7 +122,7 @@ public class ReportService {
checkReportStatus(id);
LoadTestReportWithBLOBs loadTestReport = loadTestReportMapper.selectByPrimaryKey(id);
String content = loadTestReport.getContent();
ReportTimeInfo reportTimeInfo = JtlResolver.getReportTimeInfo(content);
ReportTimeInfo reportTimeInfo = GenerateReport.getReportTimeInfo(content);
return reportTimeInfo;
}
@ -130,7 +130,7 @@ public class ReportService {
checkReportStatus(id);
LoadTestReportWithBLOBs loadTestReport = loadTestReportMapper.selectByPrimaryKey(id);
String content = loadTestReport.getContent();
List<ChartsData> chartsDataList = JtlResolver.getLoadChartData(content);
List<ChartsData> chartsDataList = GenerateReport.getLoadChartData(content);
return chartsDataList;
}
@ -138,7 +138,7 @@ public class ReportService {
checkReportStatus(id);
LoadTestReportWithBLOBs loadTestReport = loadTestReportMapper.selectByPrimaryKey(id);
String content = loadTestReport.getContent();
List<ChartsData> chartsDataList = JtlResolver.getResponseTimeChartData(content);
List<ChartsData> chartsDataList = GenerateReport.getResponseTimeChartData(content);
return chartsDataList;
}

View File

@ -8,13 +8,13 @@
<el-input class="test-name" v-model="test.name" maxlength="64" :placeholder="$t('api_test.input_name')">
<el-select class="test-project" v-model="test.projectId" slot="prepend"
:placeholder="$t('api_test.select_project')">
<el-option v-for="item in projects" :key="item.id" :label="item.name" :value="item.id"/>
<el-option v-for="project in projects" :key="project.id" :label="project.name" :value="project.id"/>
</el-select>
</el-input>
<el-button type="primary" plain :disabled="isDisabled" @click="saveTest">保存</el-button>
</el-row>
</el-header>
<ms-api-scenario-config :scenarios="test.scenario_definition"/>
<ms-api-scenario-config :scenarios="test.scenarioDefinition"/>
</el-container>
</el-card>
</div>
@ -35,9 +35,10 @@
projects: [],
change: false,
test: {
id: null,
projectId: null,
name: null,
scenario_definition: []
scenarioDefinition: []
}
}
},
@ -53,11 +54,21 @@
methods: {
saveTest: function () {
this.change = false;
this.$message({
message: this.$t('commons.save_success'),
type: 'success'
let param = {
id: this.test.id,
projectId: this.test.projectId,
name: this.test.name,
scenarioDefinition: JSON.stringify(this.test.scenarioDefinition)
}
this.result = this.$post("/api/save", param, response => {
this.test.id = response.data;
this.$message({
message: this.$t('commons.save_success'),
type: 'success'
});
});
}
},

View File

@ -4,9 +4,9 @@
<el-col class="assertion-select">
<el-select class="assertion-item" v-model="regex.subject" size="small"
:placeholder="$t('api_test.request.assertions.select_subject')">
<el-option label="Http-Code" value="HTTP-CODE"></el-option>
<el-option label="Header" value="HEADER"></el-option>
<el-option label="Body" value="BODY"></el-option>
<el-option label="HttpCode" value="HTTP_CODE"/>
<el-option label="Header" value="HEADER"/>
<el-option label="Body" value="BODY"/>
</el-select>
</el-col>
<el-col>

View File

@ -4,19 +4,19 @@
<el-col class="assertion-select">
<el-select class="assertion-item" v-model="subject" size="small"
:placeholder="$t('api_test.request.assertions.select_subject')">
<el-option label="Http-Code" value="HTTP-CODE"></el-option>
<el-option label="Header" value="HEADER"></el-option>
<el-option label="Body" value="BODY"></el-option>
<el-option label="HttpCode" value="HTTP_CODE"/>
<el-option label="Header" value="HEADER"/>
<el-option label="Body" value="BODY"/>
</el-select>
</el-col>
<el-col class="assertion-select">
<el-select class="assertion-item" v-model="condition" size="small"
:placeholder="$t('api_test.request.assertions.select_contains')">
<el-option :label="$t('api_test.request.assertions.contains')" value="CONTAINS"></el-option>
<el-option :label="$t('api_test.request.assertions.not_contains')" value="NOT_CONTAINS"></el-option>
<el-option :label="$t('api_test.request.assertions.equals')" value="EQUALS"></el-option>
<el-option :label="$t('api_test.request.assertions.start_with')" value="START_WITH"></el-option>
<el-option :label="$t('api_test.request.assertions.end_with')" value="END_WITH"></el-option>
<el-option :label="$t('api_test.request.assertions.contains')" value="CONTAINS"/>
<el-option :label="$t('api_test.request.assertions.not_contains')" value="NOT_CONTAINS"/>
<el-option :label="$t('api_test.request.assertions.equals')" value="EQUALS"/>
<el-option :label="$t('api_test.request.assertions.start_with')" value="START_WITH"/>
<el-option :label="$t('api_test.request.assertions.end_with')" value="END_WITH"/>
</el-select>
</el-col>
<el-col>

View File

@ -12,8 +12,21 @@
<el-input v-model="item.value" placeholder="Value" size="small" maxlength="100" @change="check"/>
</el-col>
<el-col class="kv-delete">
<el-button size="mini" class="el-icon-delete-solid" circle @click="remove(index)"
:disabled="isDisable(index)"/>
<el-button size="mini" class="el-icon-delete-solid" circle @click="remove(index)"/>
</el-col>
</el-row>
</div>
<div class="kv-row">
<el-row type="flex" :gutter="20" justify="space-between" align="middle">
<el-col>
<el-input v-model="kv.key" placeholder="Key" size="small" maxlength="100" @change="add"/>
</el-col>
<el-col>
<el-input v-model="kv.value" placeholder="Value" size="small" maxlength="100" @change="add"/>
</el-col>
<el-col class="kv-delete">
<el-button size="mini" class="el-icon-delete-solid" circle :disabled="true"/>
</el-col>
</el-row>
</div>
@ -31,45 +44,33 @@
items: Array
},
data() {
return {
kv: new KeyValue()
}
},
methods: {
add: function () {
this.items.push(new KeyValue());
if (this.kv.key || this.kv.value) {
this.items.push(this.kv);
this.kv = new KeyValue();
}
},
remove: function (index) {
this.items.splice(index, 1);
if (this.items.length === 0) {
this.add();
}
},
check: function () {
let isNeedCreate = true;
let removeIndex = -1;
this.items.forEach((item, index) => {
if (!item.key && !item.value) {
//
if (index !== this.items.length - 1) {
removeIndex = index;
}
//
isNeedCreate = false;
removeIndex = index;
}
});
if (isNeedCreate) {
this.add();
}
if (removeIndex !== -1) {
this.remove(removeIndex);
}
// TODO key
},
isDisable: function (index) {
return this.items.length - 1 === index;
}
},
created() {
if (this.items.length === 0) {
this.add();
}
}
}

View File

@ -11,7 +11,7 @@
</div>
<div class="request-btn">
<el-dropdown trigger="click" @command="handleCommand">
<span class="el-dropdown-link el-icon-more"></span>
<span class="el-dropdown-link el-icon-more"/>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type: 'copy', index: index}">复制请求</el-dropdown-item>
<el-dropdown-item :command="{type: 'delete', index: index}">删除请求</el-dropdown-item>

View File

@ -1,20 +1,20 @@
<template>
<el-form :model="request" :rules="rules" ref="request" label-width="100px">
<el-form-item :label="$t('api_test.request.name')" prop="name">
<el-input v-model="request.name" maxlength="100"></el-input>
<el-input v-model="request.name" maxlength="100"/>
</el-form-item>
<el-form-item :label="$t('api_test.request.url')" prop="url">
<el-input v-model="request.url" maxlength="100" :placeholder="$t('api_test.request.url_description')">
<el-select v-model="request.method" slot="prepend" class="request-method-select">
<el-option label="GET" value="GET"></el-option>
<el-option label="POST" value="POST"></el-option>
<el-option label="PUT" value="PUT"></el-option>
<el-option label="PATCH" value="PATCH"></el-option>
<el-option label="DELETE" value="DELETE"></el-option>
<el-option label="OPTIONS" value="OPTIONS"></el-option>
<el-option label="HEAD" value="HEAD"></el-option>
<el-option label="CONNECT" value="CONNECT"></el-option>
<el-option label="GET" value="GET"/>
<el-option label="POST" value="POST"/>
<el-option label="PUT" value="PUT"/>
<el-option label="PATCH" value="PATCH"/>
<el-option label="DELETE" value="DELETE"/>
<el-option label="OPTIONS" value="OPTIONS"/>
<el-option label="HEAD" value="HEAD"/>
<el-option label="CONNECT" value="CONNECT"/>
</el-select>
</el-input>
</el-form-item>
@ -30,7 +30,7 @@
<ms-api-body :body="request.body"/>
</el-tab-pane>
<el-tab-pane :label="$t('api_test.request.assertions.label')" name="assertions">
<ms-api-assertions :assertions="request.assertions"></ms-api-assertions>
<ms-api-assertions :assertions="request.assertions"/>
</el-tab-pane>
<el-tab-pane :label="$t('api_test.request.extract')" name="extract" v-if="false">
TODO

View File

@ -18,14 +18,13 @@
</ms-api-collapse-item>
</ms-api-collapse>
</div>
<el-button class="scenario-create" type="primary" size="mini" icon="el-icon-plus" plain
@click="createScenario"/>
<el-button class="scenario-create" type="primary" size="mini" icon="el-icon-plus" plain @click="createScenario"/>
</el-aside>
<el-main class="scenario-main">
<div class="scenario-form">
<ms-api-scenario-form :scenario="selected" v-if="isScenario"></ms-api-scenario-form>
<ms-api-request-form :request="selected" v-if="isRequest"></ms-api-request-form>
<ms-api-scenario-form :scenario="selected" v-if="isScenario"/>
<ms-api-request-form :request="selected" v-if="isRequest"/>
</div>
</el-main>
</el-container>

View File

@ -1,7 +1,7 @@
<template>
<el-form :model="scenario" :rules="rules" ref="scenario" label-width="100px">
<el-form-item :label="$t('api_test.scenario.name')" prop="name">
<el-input v-model="scenario.name" maxlength="100"></el-input>
<el-input v-model="scenario.name" maxlength="100"/>
</el-form-item>
<el-form-item :label="$t('api_test.scenario.base_url')" prop="url">