feat(接口定义): 合并master 最新代码

This commit is contained in:
fit2-zhao 2020-11-27 13:59:18 +08:00
parent 22108b3048
commit 73204d7793
8 changed files with 379 additions and 401 deletions

View File

@ -7,7 +7,6 @@ import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter;
import io.metersphere.api.service.APITestService;
import io.metersphere.base.domain.ApiTest;
import io.metersphere.base.domain.Schedule;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.RoleConstants;
import io.metersphere.commons.utils.PageUtils;
import io.metersphere.commons.utils.Pager;
@ -15,12 +14,14 @@ import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.controller.request.QueryScheduleRequest;
import io.metersphere.dto.ScheduleDao;
import io.metersphere.service.CheckOwnerService;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
@ -75,19 +76,18 @@ public class APITestController {
}
@PostMapping(value = "/create", consumes = {"multipart/form-data"})
public void create(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
apiTestService.create(request, bodyFiles);
public void create(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
apiTestService.create(request, file, bodyFiles);
}
@PostMapping(value = "/create/merge", consumes = {"multipart/form-data"})
public void mergeCreate(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "selectIds") List<String> selectIds) {
apiTestService.mergeCreate(request, selectIds);
public void mergeCreate(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "selectIds") List<String> selectIds) {
apiTestService.mergeCreate(request, file, selectIds);
}
@PostMapping(value = "/update", consumes = {"multipart/form-data"})
public void update(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
public void update(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
checkownerService.checkApiTestOwner(request.getId());
apiTestService.update(request, bodyFiles);
apiTestService.update(request, file, bodyFiles);
}
@PostMapping(value = "/copy")
@ -101,25 +101,21 @@ public class APITestController {
return apiTestService.get(testId);
}
@PostMapping("/delete")
public void delete(@RequestBody DeleteAPITestRequest request) {
checkownerService.checkApiTestOwner(request.getId());
apiTestService.delete(request);
}
@PostMapping(value = "/jmx")
public String getJMX(@RequestBody SaveAPITestRequest request) {
return apiTestService.getJMX(request);
}
@PostMapping(value = "/run")
public String run(@RequestBody SaveAPITestRequest request) {
return apiTestService.run(request, ApiRunMode.RUN.name());
return apiTestService.run(request);
}
@PostMapping(value = "/run/debug", consumes = {"multipart/form-data"})
public String runDebug(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
return apiTestService.runDebug(request, bodyFiles, ApiRunMode.DEBUG.name());
public String runDebug(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
return apiTestService.runDebug(request, file, bodyFiles);
}
@PostMapping(value = "/checkName")
@ -140,7 +136,7 @@ public class APITestController {
@PostMapping("/list/schedule/{goPage}/{pageSize}")
public List<ScheduleDao> listSchedule(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryScheduleRequest request) {
PageHelper.startPage(goPage, pageSize, true);
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return apiTestService.listSchedule(request);
}

View File

@ -47,13 +47,15 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
private final List<SampleResult> queue = new ArrayList<>();
private APITestService apiTestService;
private APIReportService apiReportService;
private TestPlanTestCaseService testPlanTestCaseService;
private NoticeService noticeService;
private MailService mailService;
private DingTaskService dingTaskService;
private WxChatTaskService wxChatTaskService;
private SystemParameterService systemParameterService;
private ApiDefinitionService apiDefinitionService;
private ApiDefinitionExecResultService apiDefinitionExecResultService;
@ -64,6 +66,19 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
private String debugReportId;
//获得控制台内容
private PrintStream oldPrintStream = System.out;
private ByteArrayOutputStream bos = new ByteArrayOutputStream();
private void setConsole() {
System.setOut(new PrintStream(bos)); //设置新的out
}
private String getConsole() {
System.setOut(oldPrintStream);
return bos.toString();
}
@Override
public void setupTest(BackendListenerContext context) throws Exception {
setConsole();
@ -89,18 +104,6 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
if (mailService == null) {
LogUtil.error("mailService is required");
}
dingTaskService = CommonBeanFactory.getBean(DingTaskService.class);
if (dingTaskService == null) {
LogUtil.error("dingTaskService is required");
}
wxChatTaskService = CommonBeanFactory.getBean(WxChatTaskService.class);
if (wxChatTaskService == null) {
LogUtil.error("wxChatTaskService is required");
}
systemParameterService = CommonBeanFactory.getBean(SystemParameterService.class);
if (systemParameterService == null) {
LogUtil.error("systemParameterService is required");
}
apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
if (apiDefinitionService == null) {
LogUtil.error("apiDefinitionService is required");
@ -109,22 +112,9 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
if (apiDefinitionExecResultService == null) {
LogUtil.error("apiDefinitionExecResultService is required");
}
super.setupTest(context);
}
//获得控制台内容
private PrintStream oldPrintStream = System.out;
private ByteArrayOutputStream bos = new ByteArrayOutputStream();
private void setConsole() {
System.setOut(new PrintStream(bos)); //设置新的out
}
private String getConsole() {
System.setOut(oldPrintStream);
return bos.toString();
}
@Override
public void handleSampleResults(List<SampleResult> sampleResults, BackendListenerContext context) {
@ -136,9 +126,10 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
TestResult testResult = new TestResult();
testResult.setTestId(testId);
testResult.setTotal(queue.size());
// 一个脚本里可能包含多个场景(MsThreadGroup)所以要区分开key: 场景Id
// 一个脚本里可能包含多个场景(ThreadGroup)所以要区分开key: 场景Id
final Map<String, ScenarioResult> scenarios = new LinkedHashMap<>();
queue.forEach(result -> {
queue.forEach(result -> {
// 线程名称: <场景名> <场景Index>-<请求Index>, 例如Scenario 2-1
String scenarioName = StringUtils.substringBeforeLast(result.getThreadName(), THREAD_SPLIT);
String index = StringUtils.substringAfterLast(result.getThreadName(), THREAD_SPLIT);
@ -176,12 +167,12 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
scenarioResult.addPassAssertions(requestResult.getPassAssertions());
scenarioResult.addTotalAssertions(requestResult.getTotalAssertions());
});
testResult.getScenarios().addAll(scenarios.values());
testResult.getScenarios().sort(Comparator.comparing(ScenarioResult::getId));
ApiTestReport report;
ApiTestReport report = null;
if (StringUtils.equals(this.runMode, ApiRunMode.DEBUG.name())) {
report = apiReportService.get(debugReportId);
apiReportService.complete(testResult, report);
} else if (StringUtils.equals(this.runMode, ApiRunMode.DELIMIT.name())) {
// 调试操作不需要存储结果
if (StringUtils.isBlank(debugReportId)) {
@ -190,15 +181,15 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
apiDefinitionService.addResult(testResult);
apiDefinitionExecResultService.saveApiResult(testResult);
}
return;
} else {
apiTestService.changeStatus(testId, APITestStatus.Completed);
report = apiReportService.getRunningReport(testResult.getTestId());
apiReportService.complete(testResult, report);
}
apiReportService.complete(testResult, report);
queue.clear();
super.teardownTest(context);
TestPlanTestCaseService testPlanTestCaseService = CommonBeanFactory.getBean(TestPlanTestCaseService.class);
List<String> ids = testPlanTestCaseService.getTestPlanTestCaseIds(testResult.getTestId());
if (ids.size() > 0) {
try {
@ -219,7 +210,12 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
}
private void sendTask(ApiTestReport report, TestResult testResult) {
private static void sendTask(ApiTestReport report, TestResult testResult) {
NoticeService noticeService = CommonBeanFactory.getBean(NoticeService.class);
MailService mailService = CommonBeanFactory.getBean(MailService.class);
DingTaskService dingTaskService = CommonBeanFactory.getBean(DingTaskService.class);
WxChatTaskService wxChatTaskService = CommonBeanFactory.getBean(WxChatTaskService.class);
SystemParameterService systemParameterService = CommonBeanFactory.getBean(SystemParameterService.class);
if (StringUtils.equals(NoticeConstants.API, report.getTriggerMode()) || StringUtils.equals(NoticeConstants.SCHEDULE, report.getTriggerMode())) {
List<String> userIds = new ArrayList<>();
List<MessageDetail> taskList = new ArrayList<>();
@ -288,6 +284,10 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
HTTPSampleResult res = (HTTPSampleResult) result;
requestResult.setCookies(res.getCookies());
}
for (SampleResult subResult : result.getSubResults()) {
requestResult.getSubRequestResults().add(getRequestResult(subResult));
}
for (SampleResult subResult : result.getSubResults()) {
requestResult.getSubRequestResults().add(getRequestResult(subResult));
}
@ -300,7 +300,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
responseResult.setResponseSize(result.getResponseData().length);
responseResult.setResponseTime(result.getTime());
responseResult.setResponseMessage(result.getResponseMessage());
responseResult.setConsole(getConsole());
if (JMeterVars.get(result.hashCode()) != null) {
List<String> vars = new LinkedList<>();
JMeterVars.get(result.hashCode()).entrySet().parallelStream().reduce(vars, (first, second) -> {
@ -323,6 +323,8 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
}
responseResult.getAssertions().add(responseAssertionResult);
}
responseResult.setConsole(getConsole());
return requestResult;
}

View File

@ -1,6 +1,6 @@
package io.metersphere.api.jmeter;
import io.metersphere.api.dto.scenario.Scenario;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.config.JmeterProperties;
@ -14,40 +14,30 @@ import org.apache.jorphan.collections.HashTree;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.List;
import java.io.InputStream;
import java.lang.reflect.Field;
@Service
public class JMeterService {
@Resource
private JmeterProperties jmeterProperties;
@Resource
private JMXGenerator jmxGenerator;
@PostConstruct
public void init() {
public void run(String testId, String debugReportId, InputStream is) {
String JMETER_HOME = getJmeterHome();
String JMETER_PROPERTIES = JMETER_HOME + "/bin/jmeter.properties";
JMeterUtils.loadJMeterProperties(JMETER_PROPERTIES);
JMeterUtils.setJMeterHome(JMETER_HOME);
JMeterUtils.setLocale(LocaleContextHolder.getLocale());
}
public HashTree getHashTree(String testId, String testName, List<Scenario> scenarios) {
return jmxGenerator.parse(testId, testName, scenarios);
}
public void run(String testId, String testName, List<Scenario> scenarios, String debugReportId, String runMode) {
try {
init();
HashTree testPlan = getHashTree(testId, testName, scenarios);
Object scriptWrapper = SaveService.loadElement(is);
HashTree testPlan = getHashTree(scriptWrapper);
JMeterVars.addJSR223PostProcessor(testPlan);
addBackendListener(testId, debugReportId, runMode, testPlan);
addBackendListener(testId, debugReportId, ApiRunMode.DEBUG.name(), testPlan);
LocalRunner runner = new LocalRunner(testPlan);
runner.run();
} catch (Exception e) {
@ -56,18 +46,6 @@ public class JMeterService {
}
}
public String getJMX(HashTree hashTree) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
SaveService.saveTree(hashTree, baos);
LogUtil.debug(baos.toString());
return baos.toString();
} catch (Exception e) {
e.printStackTrace();
LogUtil.warn("HashTree error, can't log jmx content");
}
return null;
}
public String getJmeterHome() {
String home = getClass().getResource("/").getPath() + "jmeter";
try {
@ -82,14 +60,19 @@ public class JMeterService {
}
}
private void addBackendListener(String testId, String debugReportId, String runMode, HashTree testPlan) {
private HashTree getHashTree(Object scriptWrapper) throws Exception {
Field field = scriptWrapper.getClass().getDeclaredField("testPlan");
field.setAccessible(true);
return (HashTree) field.get(scriptWrapper);
}
private void addBackendListener(String testId, String debugReportId,String runMode, HashTree testPlan) {
BackendListener backendListener = new BackendListener();
backendListener.setName(testId);
Arguments arguments = new Arguments();
arguments.addArgument(APIBackendListenerClient.TEST_ID, testId);
if (StringUtils.isNotBlank(runMode)) {
arguments.addArgument("runMode", runMode);
}
arguments.addArgument("runMode",runMode); }
if (StringUtils.isNotBlank(debugReportId)) {
arguments.addArgument("debugReportId", debugReportId);
}
@ -109,5 +92,4 @@ public class JMeterService {
MSException.throwException(Translator.get("api_load_script_error"));
}
}
}

View File

@ -2,7 +2,6 @@ package io.metersphere.job.sechedule;
import io.metersphere.api.dto.SaveAPITestRequest;
import io.metersphere.api.service.APITestService;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.constants.ScheduleGroup;
import io.metersphere.commons.utils.CommonBeanFactory;
@ -14,7 +13,6 @@ import org.quartz.TriggerKey;
public class ApiTestJob extends MsScheduleJob {
private APITestService apiTestService;
public ApiTestJob() {
apiTestService = (APITestService) CommonBeanFactory.getBean(APITestService.class);
}
@ -25,7 +23,7 @@ public class ApiTestJob extends MsScheduleJob {
request.setId(resourceId);
request.setUserId(userId);
request.setTriggerMode(ReportTriggerMode.SCHEDULE.name());
apiTestService.run(request, ApiRunMode.RUN.name());
apiTestService.run(request);
}
public static JobKey getJobKey(String testId) {

View File

@ -24,7 +24,7 @@
<!--返回结果-->
<!-- HTTP 请求返回数据 -->
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
<ms-request-result-tail :response="responseData" ref="runResult"/>
<ms-request-result-tail :response="responseData" :currentProtocol="currentProtocol" ref="runResult"/>
</el-card>

View File

@ -27,6 +27,10 @@
{{ $t('load_test.save_and_run') }}
</el-button>
<!-- <el-button :disabled="isReadOnly" type="primary" plain v-if="isShowRun" @click="runTest">-->
<!-- {{$t('api_test.run')}}-->
<!-- </el-button>-->
<el-button :disabled="isReadOnly" type="warning" plain @click="cancel">{{ $t('commons.cancel') }}
</el-button>
@ -95,339 +99,331 @@ export default {
props: ["id"],
data() {
return {
reportVisible: false,
create: false,
result: {},
projects: [],
change: false,
test: new Test(),
isReadOnly: false,
debugReportId: ''
}
},
watch: {
'$route': 'init',
test: {
handler: function () {
this.change = true;
},
deep: true
}
},
methods: {
init() {
let projectId;
this.isReadOnly = !checkoutTestManagerOrTestUser();
if (this.id) {
this.create = false;
this.getTest(this.id);
} else {
this.create = true;
this.test = new Test();
if (this.$refs.config) {
this.$refs.config.reset();
}
//
projectId = this.$store.state.common.projectId;
data() {
return {
reportVisible: false,
create: false,
result: {},
projects: [],
change: false,
test: new Test(),
isReadOnly: false,
debugReportId: ''
}
this.result = this.$get("/project/listAll", response => {
this.projects = response.data;
//
if (projectId) this.test.projectId = projectId;
})
},
updateReference() {
let updateIds = [];
this.test.scenarioDefinition.forEach(scenario => {
if (scenario.isReference()) {
updateIds.push(scenario.id.split("#")[0]);
}
})
if (updateIds.length === 0) return;
//
this.result = this.$post("/api/list/ids", {ids: updateIds}, response => {
let scenarioMap = {};
if (response.data) {
response.data.forEach(test => {
JSON.parse(test.scenarioDefinition).forEach(options => {
let referenceId = test.id + "#" + options.id;
scenarioMap[referenceId] = new Scenario(options);
scenarioMap[referenceId].id = referenceId;
})
})
}
watch: {
'$route': 'init',
test: {
handler: function () {
this.change = true;
},
deep: true
}
},
let scenarios = [];
methods: {
init() {
let projectId;
this.isReadOnly = !checkoutTestManagerOrTestUser();
if (this.id) {
this.create = false;
this.getTest(this.id);
} else {
this.create = true;
this.test = new Test();
if (this.$refs.config) {
this.$refs.config.reset();
}
//
projectId = this.$store.state.common.projectId;
}
this.result = this.$get("/project/listAll", response => {
this.projects = response.data;
//
if (projectId) this.test.projectId = projectId;
})
},
updateReference() {
let updateIds = [];
this.test.scenarioDefinition.forEach(scenario => {
if (scenario.isReference()) {
if (scenarioMap[scenario.id]) scenarios.push(scenarioMap[scenario.id]);
} else {
scenarios.push(scenario);
updateIds.push(scenario.id.split("#")[0]);
}
})
this.test.scenarioDefinition = scenarios;
})
},
getTest(id) {
this.result = this.$get("/api/get/" + id, response => {
if (response.data) {
let item = response.data;
this.test = new Test({
id: item.id,
projectId: item.projectId,
name: item.name,
status: item.status,
scenarioDefinition: JSON.parse(item.scenarioDefinition),
schedule: item.schedule ? item.schedule : {},
});
this.updateReference();
if (updateIds.length === 0) return;
//
this.result = this.$post("/api/list/ids", {ids: updateIds}, response => {
let scenarioMap = {};
if (response.data) {
response.data.forEach(test => {
JSON.parse(test.scenarioDefinition).forEach(options => {
let referenceId = test.id + "#" + options.id;
scenarioMap[referenceId] = new Scenario(options);
scenarioMap[referenceId].id = referenceId;
})
})
}
this.$refs.config.reset();
}
});
},
save(callback) {
let validator = this.test.isValid();
if (!validator.isValid) {
this.$warning(this.$t(validator.info));
return;
}
this.change = false;
let bodyFiles = this.getBodyUploadFiles();
let url = this.create ? "/api/create" : "/api/update";
this.result = this.$fileUpload(url, null, bodyFiles, this.test, () => {
if (callback) callback();
this.create = false;
this.resetBodyFile();
});
},
saveTest() {
this.save(() => {
this.$success(this.$t('commons.save_success'));
if (this.create) {
this.$router.push({
path: '/api/test/edit?id=' + this.test.id
let scenarios = [];
this.test.scenarioDefinition.forEach(scenario => {
if (scenario.isReference()) {
if (scenarioMap[scenario.id]) scenarios.push(scenarioMap[scenario.id]);
} else {
scenarios.push(scenario);
}
})
}
// 广 head
ApiEvent.$emit(LIST_CHANGE);
})
},
runTest() {
this.test.triggerMode = 'MANUAL';
this.result = this.$post("/api/run", this.test, (response) => {
this.$success(this.$t('api_test.running'));
this.$router.push({
path: '/api/report/view/' + response.data
this.test.scenarioDefinition = scenarios;
})
});
},
saveRunTest() {
this.change = false;
if (!this.validateEnableTest()) {
this.$warning(this.$t('api_test.enable_validate_tip'));
return;
}
this.save(() => {
this.$success(this.$t('commons.save_success'));
this.runTest();
// 广 head
ApiEvent.$emit(LIST_CHANGE);
})
},
getBodyUploadFiles() {
let bodyUploadFiles = [];
this.test.bodyUploadIds = [];
this.test.scenarioDefinition.forEach(scenario => {
scenario.requests.forEach(request => {
if (request.body) {
request.body.kvs.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
this.test.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
},
getTest(id) {
this.result = this.$get("/api/get/" + id, response => {
if (response.data) {
let item = response.data;
this.test = new Test({
id: item.id,
projectId: item.projectId,
name: item.name,
status: item.status,
scenarioDefinition: JSON.parse(item.scenarioDefinition),
schedule: item.schedule ? item.schedule : {},
});
this.updateReference();
this.$refs.config.reset();
}
});
});
return bodyUploadFiles;
},
validateEnableTest() {
for (let scenario of this.test.scenarioDefinition) {
if (scenario.enable) {
for (let request of scenario.requests) {
if (request.enable) {
return true;
},
save(callback) {
let validator = this.test.isValid();
if (!validator.isValid) {
this.$warning(this.$t(validator.info));
return;
}
this.change = false;
let bodyFiles = this.getBodyUploadFiles();
let url = this.create ? "/api/create" : "/api/update";
let jmx = this.test.toJMX();
let blob = new Blob([jmx.xml], {type: "application/octet-stream"});
let file = new File([blob], jmx.name);
this.result = this.$fileUpload(url, file, bodyFiles, this.test, () => {
if (callback) callback();
this.create = false;
this.resetBodyFile();
});
},
saveTest() {
this.save(() => {
this.$success(this.$t('commons.save_success'));
if (this.create) {
this.$router.push({
path: '/api/test/edit?id=' + this.test.id
})
}
// 广 head
ApiEvent.$emit(LIST_CHANGE);
})
},
runTest() {
this.result = this.$post("/api/run", {id: this.test.id, triggerMode: 'MANUAL'}, (response) => {
this.$success(this.$t('api_test.running'));
this.$router.push({
path: '/api/report/view/' + response.data
})
});
},
saveRunTest() {
this.change = false;
if (!this.validateEnableTest()) {
this.$warning(this.$t('api_test.enable_validate_tip'));
return;
}
this.save(() => {
this.$success(this.$t('commons.save_success'));
this.runTest();
// 广 head
ApiEvent.$emit(LIST_CHANGE);
})
},
getBodyUploadFiles() {
let bodyUploadFiles = [];
this.test.bodyUploadIds = [];
this.test.scenarioDefinition.forEach(scenario => {
scenario.requests.forEach(request => {
if (request.body) {
request.body.kvs.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
this.test.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
}
});
});
return bodyUploadFiles;
},
validateEnableTest() {
for (let scenario of this.test.scenarioDefinition) {
if (scenario.enable) {
for (let request of scenario.requests) {
if (request.enable) {
return true;
}
}
}
}
}
return false;
},
resetBodyFile() {
//
this.test.scenarioDefinition.forEach(scenario => {
scenario.requests.forEach(request => {
if (request.body) {
request.body.kvs.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
item.file = undefined;
}
});
}
});
}
return false;
},
resetBodyFile() {
//
this.test.scenarioDefinition.forEach(scenario => {
scenario.requests.forEach(request => {
if (request.body) {
request.body.kvs.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
item.file = undefined;
}
});
}
});
}
});
});
});
},
cancel() {
this.$router.push('/api/test/list/all');
},
createPerformance() {
let validator = this.test.isValid();
if (!validator.isValid) {
this.$warning(this.$t(validator.info));
return;
}
this.result = this.$post("/api/jmx", this.test, response => {
let jmx = {
name: this.test.name + '.jmx',
xml: response.data
};
this.$store.commit('setTest', {
projectId: this.test.projectId,
name: this.test.name,
jmx: jmx
})
this.$router.push({
path: "/performance/test/create"
})
});
},
handleCommand(command) {
switch (command) {
case "report":
this.$refs.reportDialog.open();
break;
case "performance":
this.createPerformance();
break;
case "export":
downloadFile(this.test.name + ".json", this.test.export());
break;
case "jar":
this.$refs.jarConfig.open();
break;
case "import":
this.$refs.apiImport.open();
break;
}
},
saveCronExpression(cronExpression) {
this.test.schedule.enable = true;
this.test.schedule.value = cronExpression;
this.saveSchedule();
},
saveSchedule() {
this.checkScheduleEdit();
let param = {};
param = this.test.schedule;
param.resourceId = this.test.id;
let url = '/api/schedule/create';
if (param.id) {
url = '/api/schedule/update';
}
this.$post(url, param, () => {
this.$success(this.$t('commons.save_success'));
this.getTest(this.test.id);
});
},
checkScheduleEdit() {
if (this.create) {
this.$message(this.$t('api_test.environment.please_save_test'));
return false;
}
return true;
},
runDebug(scenario) {
if (this.create) {
this.$warning(this.$t('api_test.environment.please_save_test'));
return;
}
},
cancel() {
this.$router.push('/api/test/list/all');
// console.log(this.test.toJMX().xml);
},
handleCommand(command) {
switch (command) {
case "report":
this.$refs.reportDialog.open();
break;
case "performance":
this.$store.commit('setTest', {
projectId: this.test.projectId,
name: this.test.name,
jmx: this.test.toJMX()
})
this.$router.push({
path: "/performance/test/create"
})
break;
case "export":
downloadFile(this.test.name + ".json", this.test.export());
break;
case "jar":
this.$refs.jarConfig.open();
break;
case "import":
this.$refs.apiImport.open();
break;
}
},
saveCronExpression(cronExpression) {
this.test.schedule.enable = true;
this.test.schedule.value = cronExpression;
this.saveSchedule();
},
saveSchedule() {
this.checkScheduleEdit();
let param = {};
param = this.test.schedule;
param.resourceId = this.test.id;
let url = '/api/schedule/create';
if (param.id) {
url = '/api/schedule/update';
}
this.$post(url, param, () => {
this.$success(this.$t('commons.save_success'));
this.getTest(this.test.id);
});
},
checkScheduleEdit() {
if (this.create) {
this.$message(this.$t('api_test.environment.please_save_test'));
return false;
}
return true;
},
runDebug(scenario) {
if (this.create) {
this.$warning(this.$t('api_test.environment.please_save_test'));
return;
}
let url = "/api/run/debug";
let runningTest = new Test();
Object.assign(runningTest, this.test);
let bodyFiles = this.getBodyUploadFiles();
runningTest.scenarioDefinition = [];
runningTest.scenarioDefinition.push(scenario);
let validator = runningTest.isValid();
if (!validator.isValid) {
this.$warning(this.$t(validator.info));
return;
}
let url = "/api/run/debug";
let runningTest = new Test();
Object.assign(runningTest, this.test);
let bodyFiles = this.getBodyUploadFiles();
runningTest.scenarioDefinition = [];
runningTest.scenarioDefinition.push(scenario);
let validator = runningTest.isValid();
if (!validator.isValid) {
this.$warning(this.$t(validator.info));
return;
}
this.$fileUpload(url, null, bodyFiles, this.test, response => {
this.debugReportId = response.data;
this.resetBodyFile();
});
let jmx = runningTest.toJMX();
let blob = new Blob([jmx.xml], {type: "application/octet-stream"});
let file = new File([blob], jmx.name);
this.$fileUpload(url, file, bodyFiles, this.test, response => {
this.debugReportId = response.data;
this.resetBodyFile();
});
},
handleEvent(event) {
if (event.keyCode === 83 && event.ctrlKey) {
// console.log(' ctrl + s');//ctrl+s
this.saveTest();
event.preventDefault();
event.returnValue = false;
return false;
}
},
},
handleEvent(event) {
if (event.keyCode === 83 && event.ctrlKey) {
console.log('拦截到 ctrl + s');//ctrl+s
this.saveTest();
event.preventDefault();
event.returnValue = false;
return false;
}
},
},
created() {
this.init();
//
document.addEventListener('keydown', this.handleEvent)
},
beforeDestroy() {
document.removeEventListener('keydown', this.handleEvent);
created() {
this.init();
//
document.addEventListener('keydown', this.handleEvent)
},
beforeDestroy() {
document.removeEventListener('keydown', this.handleEvent);
}
}
}
</script>
<style scoped>
.test-container {
height: calc(100vh - 155px);
min-height: 600px;
}
.test-container {
height: calc(100vh - 155px);
min-height: 600px;
}
.test-name {
width: 600px;
margin-left: -20px;
margin-right: 20px;
}
.test-name {
width: 600px;
margin-left: -20px;
margin-right: 20px;
}
.test-project {
min-width: 150px;
}
.test-project {
min-width: 150px;
}
.test-container .more {
margin-left: 10px;
}
.test-container .more {
margin-left: 10px;
}
</style>

View File

@ -26,6 +26,7 @@
import MsApiScenarioConfig from "./components/ApiScenarioConfig";
import MsApiReportStatus from "../report/ApiReportStatus";
import MsApiReportDialog from "./ApiReportDialog";
import {getUUID} from "@/common/js/utils";
import {parseEnvironment} from "./model/EnvironmentModel";
@ -180,6 +181,9 @@
type: "application/json"
}));
let jmx = this.test.toJMX();
let blob = new Blob([jmx.xml], {type: "application/octet-stream"});
formData.append("file", new File([blob], jmx.name));
return {
method: 'POST',
url: url,

View File

@ -1218,13 +1218,13 @@ class JMXGenerator {
}
envArray.forEach(item => {
let targetItem = targetMap.get(item.name);
let hasItem;
let hasItem = undefined;
if (targetItem) {
hasItem = (targetItem.enable !== false);
hasItem = (targetItem.enable === false ? false : true);
} else {
hasItem = false;
}
if (item.enable !== false && item.name && !hasItem) {
if (item.enable != false && item.name && !hasItem) {
target.push(new KeyValue({name: item.name, value: item.value}));
}
})
@ -1412,7 +1412,7 @@ class JMXGenerator {
let hasContentType = false;
for (let index in request.headers) {
if (request.headers.hasOwnProperty(index)) {
if (request.headers[index].name === 'Content-Type' && request.headers[index].enable !== false) {
if (request.headers[index].name === 'Content-Type' && request.headers[index].enable != false) {
hasContentType = true;
break;
}
@ -1426,7 +1426,7 @@ class JMXGenerator {
removeContentType(request) {
for (let index in request.headers) {
if (request.headers.hasOwnProperty(index)) {
if (request.headers[index].name === 'Content-Type' && request.headers[index].enable !== false) {
if (request.headers[index].name === 'Content-Type' && request.headers[index].enable != false) {
request.headers.splice(index, 1);
break;
}
@ -1524,7 +1524,7 @@ class JMXGenerator {
getResponseAssertion(regex) {
let name = regex.description;
let type = JMX_ASSERTION_CONDITION.CONTAINS;
let type = JMX_ASSERTION_CONDITION.CONTAINS; // 固定用Match自己写正则
let value = regex.expression;
let assumeSuccess = regex.assumeSuccess;
switch (regex.subject) {