feat(接口定义): 合并master 最新代码
This commit is contained in:
parent
22108b3048
commit
73204d7793
|
@ -7,7 +7,6 @@ import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter;
|
||||||
import io.metersphere.api.service.APITestService;
|
import io.metersphere.api.service.APITestService;
|
||||||
import io.metersphere.base.domain.ApiTest;
|
import io.metersphere.base.domain.ApiTest;
|
||||||
import io.metersphere.base.domain.Schedule;
|
import io.metersphere.base.domain.Schedule;
|
||||||
import io.metersphere.commons.constants.ApiRunMode;
|
|
||||||
import io.metersphere.commons.constants.RoleConstants;
|
import io.metersphere.commons.constants.RoleConstants;
|
||||||
import io.metersphere.commons.utils.PageUtils;
|
import io.metersphere.commons.utils.PageUtils;
|
||||||
import io.metersphere.commons.utils.Pager;
|
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.controller.request.QueryScheduleRequest;
|
||||||
import io.metersphere.dto.ScheduleDao;
|
import io.metersphere.dto.ScheduleDao;
|
||||||
import io.metersphere.service.CheckOwnerService;
|
import io.metersphere.service.CheckOwnerService;
|
||||||
|
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -75,19 +76,18 @@ public class APITestController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/create", consumes = {"multipart/form-data"})
|
@PostMapping(value = "/create", consumes = {"multipart/form-data"})
|
||||||
public void create(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
public void create(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||||
apiTestService.create(request, bodyFiles);
|
apiTestService.create(request, file, bodyFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/create/merge", consumes = {"multipart/form-data"})
|
@PostMapping(value = "/create/merge", consumes = {"multipart/form-data"})
|
||||||
public void mergeCreate(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "selectIds") List<String> selectIds) {
|
public void mergeCreate(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "selectIds") List<String> selectIds) {
|
||||||
apiTestService.mergeCreate(request, selectIds);
|
apiTestService.mergeCreate(request, file, selectIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/update", consumes = {"multipart/form-data"})
|
@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());
|
checkownerService.checkApiTestOwner(request.getId());
|
||||||
apiTestService.update(request, bodyFiles);
|
apiTestService.update(request, file, bodyFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/copy")
|
@PostMapping(value = "/copy")
|
||||||
|
@ -101,25 +101,21 @@ public class APITestController {
|
||||||
return apiTestService.get(testId);
|
return apiTestService.get(testId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/delete")
|
@PostMapping("/delete")
|
||||||
public void delete(@RequestBody DeleteAPITestRequest request) {
|
public void delete(@RequestBody DeleteAPITestRequest request) {
|
||||||
checkownerService.checkApiTestOwner(request.getId());
|
checkownerService.checkApiTestOwner(request.getId());
|
||||||
apiTestService.delete(request);
|
apiTestService.delete(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/jmx")
|
|
||||||
public String getJMX(@RequestBody SaveAPITestRequest request) {
|
|
||||||
return apiTestService.getJMX(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping(value = "/run")
|
@PostMapping(value = "/run")
|
||||||
public String run(@RequestBody SaveAPITestRequest request) {
|
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"})
|
@PostMapping(value = "/run/debug", consumes = {"multipart/form-data"})
|
||||||
public String runDebug(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
public String runDebug(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||||
return apiTestService.runDebug(request, bodyFiles, ApiRunMode.DEBUG.name());
|
return apiTestService.runDebug(request, file, bodyFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/checkName")
|
@PostMapping(value = "/checkName")
|
||||||
|
@ -140,7 +136,7 @@ public class APITestController {
|
||||||
|
|
||||||
@PostMapping("/list/schedule/{goPage}/{pageSize}")
|
@PostMapping("/list/schedule/{goPage}/{pageSize}")
|
||||||
public List<ScheduleDao> listSchedule(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryScheduleRequest request) {
|
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);
|
return apiTestService.listSchedule(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,13 +47,15 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
private final List<SampleResult> queue = new ArrayList<>();
|
private final List<SampleResult> queue = new ArrayList<>();
|
||||||
|
|
||||||
private APITestService apiTestService;
|
private APITestService apiTestService;
|
||||||
|
|
||||||
private APIReportService apiReportService;
|
private APIReportService apiReportService;
|
||||||
|
|
||||||
private TestPlanTestCaseService testPlanTestCaseService;
|
private TestPlanTestCaseService testPlanTestCaseService;
|
||||||
|
|
||||||
private NoticeService noticeService;
|
private NoticeService noticeService;
|
||||||
|
|
||||||
private MailService mailService;
|
private MailService mailService;
|
||||||
private DingTaskService dingTaskService;
|
|
||||||
private WxChatTaskService wxChatTaskService;
|
|
||||||
private SystemParameterService systemParameterService;
|
|
||||||
private ApiDefinitionService apiDefinitionService;
|
private ApiDefinitionService apiDefinitionService;
|
||||||
private ApiDefinitionExecResultService apiDefinitionExecResultService;
|
private ApiDefinitionExecResultService apiDefinitionExecResultService;
|
||||||
|
|
||||||
|
@ -64,6 +66,19 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
|
|
||||||
private String debugReportId;
|
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
|
@Override
|
||||||
public void setupTest(BackendListenerContext context) throws Exception {
|
public void setupTest(BackendListenerContext context) throws Exception {
|
||||||
setConsole();
|
setConsole();
|
||||||
|
@ -89,18 +104,6 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
if (mailService == null) {
|
if (mailService == null) {
|
||||||
LogUtil.error("mailService is required");
|
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);
|
apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
|
||||||
if (apiDefinitionService == null) {
|
if (apiDefinitionService == null) {
|
||||||
LogUtil.error("apiDefinitionService is required");
|
LogUtil.error("apiDefinitionService is required");
|
||||||
|
@ -109,22 +112,9 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
if (apiDefinitionExecResultService == null) {
|
if (apiDefinitionExecResultService == null) {
|
||||||
LogUtil.error("apiDefinitionExecResultService is required");
|
LogUtil.error("apiDefinitionExecResultService is required");
|
||||||
}
|
}
|
||||||
|
|
||||||
super.setupTest(context);
|
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
|
@Override
|
||||||
public void handleSampleResults(List<SampleResult> sampleResults, BackendListenerContext context) {
|
public void handleSampleResults(List<SampleResult> sampleResults, BackendListenerContext context) {
|
||||||
|
@ -136,9 +126,10 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
TestResult testResult = new TestResult();
|
TestResult testResult = new TestResult();
|
||||||
testResult.setTestId(testId);
|
testResult.setTestId(testId);
|
||||||
testResult.setTotal(queue.size());
|
testResult.setTotal(queue.size());
|
||||||
// 一个脚本里可能包含多个场景(MsThreadGroup),所以要区分开,key: 场景Id
|
|
||||||
|
// 一个脚本里可能包含多个场景(ThreadGroup),所以要区分开,key: 场景Id
|
||||||
final Map<String, ScenarioResult> scenarios = new LinkedHashMap<>();
|
final Map<String, ScenarioResult> scenarios = new LinkedHashMap<>();
|
||||||
queue.forEach(result -> {
|
queue.forEach(result -> {
|
||||||
// 线程名称: <场景名> <场景Index>-<请求Index>, 例如:Scenario 2-1
|
// 线程名称: <场景名> <场景Index>-<请求Index>, 例如:Scenario 2-1
|
||||||
String scenarioName = StringUtils.substringBeforeLast(result.getThreadName(), THREAD_SPLIT);
|
String scenarioName = StringUtils.substringBeforeLast(result.getThreadName(), THREAD_SPLIT);
|
||||||
String index = StringUtils.substringAfterLast(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.addPassAssertions(requestResult.getPassAssertions());
|
||||||
scenarioResult.addTotalAssertions(requestResult.getTotalAssertions());
|
scenarioResult.addTotalAssertions(requestResult.getTotalAssertions());
|
||||||
});
|
});
|
||||||
|
|
||||||
testResult.getScenarios().addAll(scenarios.values());
|
testResult.getScenarios().addAll(scenarios.values());
|
||||||
testResult.getScenarios().sort(Comparator.comparing(ScenarioResult::getId));
|
testResult.getScenarios().sort(Comparator.comparing(ScenarioResult::getId));
|
||||||
ApiTestReport report;
|
ApiTestReport report = null;
|
||||||
if (StringUtils.equals(this.runMode, ApiRunMode.DEBUG.name())) {
|
if (StringUtils.equals(this.runMode, ApiRunMode.DEBUG.name())) {
|
||||||
report = apiReportService.get(debugReportId);
|
report = apiReportService.get(debugReportId);
|
||||||
|
apiReportService.complete(testResult, report);
|
||||||
} else if (StringUtils.equals(this.runMode, ApiRunMode.DELIMIT.name())) {
|
} else if (StringUtils.equals(this.runMode, ApiRunMode.DELIMIT.name())) {
|
||||||
// 调试操作,不需要存储结果
|
// 调试操作,不需要存储结果
|
||||||
if (StringUtils.isBlank(debugReportId)) {
|
if (StringUtils.isBlank(debugReportId)) {
|
||||||
|
@ -190,15 +181,15 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
apiDefinitionService.addResult(testResult);
|
apiDefinitionService.addResult(testResult);
|
||||||
apiDefinitionExecResultService.saveApiResult(testResult);
|
apiDefinitionExecResultService.saveApiResult(testResult);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
apiTestService.changeStatus(testId, APITestStatus.Completed);
|
apiTestService.changeStatus(testId, APITestStatus.Completed);
|
||||||
report = apiReportService.getRunningReport(testResult.getTestId());
|
report = apiReportService.getRunningReport(testResult.getTestId());
|
||||||
|
apiReportService.complete(testResult, report);
|
||||||
}
|
}
|
||||||
apiReportService.complete(testResult, report);
|
|
||||||
queue.clear();
|
queue.clear();
|
||||||
super.teardownTest(context);
|
super.teardownTest(context);
|
||||||
|
|
||||||
|
TestPlanTestCaseService testPlanTestCaseService = CommonBeanFactory.getBean(TestPlanTestCaseService.class);
|
||||||
List<String> ids = testPlanTestCaseService.getTestPlanTestCaseIds(testResult.getTestId());
|
List<String> ids = testPlanTestCaseService.getTestPlanTestCaseIds(testResult.getTestId());
|
||||||
if (ids.size() > 0) {
|
if (ids.size() > 0) {
|
||||||
try {
|
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())) {
|
if (StringUtils.equals(NoticeConstants.API, report.getTriggerMode()) || StringUtils.equals(NoticeConstants.SCHEDULE, report.getTriggerMode())) {
|
||||||
List<String> userIds = new ArrayList<>();
|
List<String> userIds = new ArrayList<>();
|
||||||
List<MessageDetail> taskList = new ArrayList<>();
|
List<MessageDetail> taskList = new ArrayList<>();
|
||||||
|
@ -288,6 +284,10 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
HTTPSampleResult res = (HTTPSampleResult) result;
|
HTTPSampleResult res = (HTTPSampleResult) result;
|
||||||
requestResult.setCookies(res.getCookies());
|
requestResult.setCookies(res.getCookies());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (SampleResult subResult : result.getSubResults()) {
|
||||||
|
requestResult.getSubRequestResults().add(getRequestResult(subResult));
|
||||||
|
}
|
||||||
for (SampleResult subResult : result.getSubResults()) {
|
for (SampleResult subResult : result.getSubResults()) {
|
||||||
requestResult.getSubRequestResults().add(getRequestResult(subResult));
|
requestResult.getSubRequestResults().add(getRequestResult(subResult));
|
||||||
}
|
}
|
||||||
|
@ -300,7 +300,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
responseResult.setResponseSize(result.getResponseData().length);
|
responseResult.setResponseSize(result.getResponseData().length);
|
||||||
responseResult.setResponseTime(result.getTime());
|
responseResult.setResponseTime(result.getTime());
|
||||||
responseResult.setResponseMessage(result.getResponseMessage());
|
responseResult.setResponseMessage(result.getResponseMessage());
|
||||||
responseResult.setConsole(getConsole());
|
|
||||||
if (JMeterVars.get(result.hashCode()) != null) {
|
if (JMeterVars.get(result.hashCode()) != null) {
|
||||||
List<String> vars = new LinkedList<>();
|
List<String> vars = new LinkedList<>();
|
||||||
JMeterVars.get(result.hashCode()).entrySet().parallelStream().reduce(vars, (first, second) -> {
|
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.getAssertions().add(responseAssertionResult);
|
||||||
}
|
}
|
||||||
|
responseResult.setConsole(getConsole());
|
||||||
|
|
||||||
return requestResult;
|
return requestResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package io.metersphere.api.jmeter;
|
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.exception.MSException;
|
||||||
import io.metersphere.commons.utils.LogUtil;
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
import io.metersphere.config.JmeterProperties;
|
import io.metersphere.config.JmeterProperties;
|
||||||
|
@ -14,40 +14,30 @@ import org.apache.jorphan.collections.HashTree;
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class JMeterService {
|
public class JMeterService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private JmeterProperties jmeterProperties;
|
private JmeterProperties jmeterProperties;
|
||||||
@Resource
|
|
||||||
private JMXGenerator jmxGenerator;
|
|
||||||
|
|
||||||
@PostConstruct
|
public void run(String testId, String debugReportId, InputStream is) {
|
||||||
public void init() {
|
|
||||||
String JMETER_HOME = getJmeterHome();
|
String JMETER_HOME = getJmeterHome();
|
||||||
|
|
||||||
String JMETER_PROPERTIES = JMETER_HOME + "/bin/jmeter.properties";
|
String JMETER_PROPERTIES = JMETER_HOME + "/bin/jmeter.properties";
|
||||||
JMeterUtils.loadJMeterProperties(JMETER_PROPERTIES);
|
JMeterUtils.loadJMeterProperties(JMETER_PROPERTIES);
|
||||||
JMeterUtils.setJMeterHome(JMETER_HOME);
|
JMeterUtils.setJMeterHome(JMETER_HOME);
|
||||||
JMeterUtils.setLocale(LocaleContextHolder.getLocale());
|
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 {
|
try {
|
||||||
init();
|
Object scriptWrapper = SaveService.loadElement(is);
|
||||||
HashTree testPlan = getHashTree(testId, testName, scenarios);
|
HashTree testPlan = getHashTree(scriptWrapper);
|
||||||
JMeterVars.addJSR223PostProcessor(testPlan);
|
JMeterVars.addJSR223PostProcessor(testPlan);
|
||||||
addBackendListener(testId, debugReportId, runMode, testPlan);
|
addBackendListener(testId, debugReportId, ApiRunMode.DEBUG.name(), testPlan);
|
||||||
LocalRunner runner = new LocalRunner(testPlan);
|
LocalRunner runner = new LocalRunner(testPlan);
|
||||||
runner.run();
|
runner.run();
|
||||||
} catch (Exception e) {
|
} 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() {
|
public String getJmeterHome() {
|
||||||
String home = getClass().getResource("/").getPath() + "jmeter";
|
String home = getClass().getResource("/").getPath() + "jmeter";
|
||||||
try {
|
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 backendListener = new BackendListener();
|
||||||
backendListener.setName(testId);
|
backendListener.setName(testId);
|
||||||
Arguments arguments = new Arguments();
|
Arguments arguments = new Arguments();
|
||||||
arguments.addArgument(APIBackendListenerClient.TEST_ID, testId);
|
arguments.addArgument(APIBackendListenerClient.TEST_ID, testId);
|
||||||
if (StringUtils.isNotBlank(runMode)) {
|
if (StringUtils.isNotBlank(runMode)) {
|
||||||
arguments.addArgument("runMode", runMode);
|
arguments.addArgument("runMode",runMode); }
|
||||||
}
|
|
||||||
if (StringUtils.isNotBlank(debugReportId)) {
|
if (StringUtils.isNotBlank(debugReportId)) {
|
||||||
arguments.addArgument("debugReportId", debugReportId);
|
arguments.addArgument("debugReportId", debugReportId);
|
||||||
}
|
}
|
||||||
|
@ -109,5 +92,4 @@ public class JMeterService {
|
||||||
MSException.throwException(Translator.get("api_load_script_error"));
|
MSException.throwException(Translator.get("api_load_script_error"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package io.metersphere.job.sechedule;
|
||||||
|
|
||||||
import io.metersphere.api.dto.SaveAPITestRequest;
|
import io.metersphere.api.dto.SaveAPITestRequest;
|
||||||
import io.metersphere.api.service.APITestService;
|
import io.metersphere.api.service.APITestService;
|
||||||
import io.metersphere.commons.constants.ApiRunMode;
|
|
||||||
import io.metersphere.commons.constants.ReportTriggerMode;
|
import io.metersphere.commons.constants.ReportTriggerMode;
|
||||||
import io.metersphere.commons.constants.ScheduleGroup;
|
import io.metersphere.commons.constants.ScheduleGroup;
|
||||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
|
@ -14,7 +13,6 @@ import org.quartz.TriggerKey;
|
||||||
public class ApiTestJob extends MsScheduleJob {
|
public class ApiTestJob extends MsScheduleJob {
|
||||||
|
|
||||||
private APITestService apiTestService;
|
private APITestService apiTestService;
|
||||||
|
|
||||||
public ApiTestJob() {
|
public ApiTestJob() {
|
||||||
apiTestService = (APITestService) CommonBeanFactory.getBean(APITestService.class);
|
apiTestService = (APITestService) CommonBeanFactory.getBean(APITestService.class);
|
||||||
}
|
}
|
||||||
|
@ -25,7 +23,7 @@ public class ApiTestJob extends MsScheduleJob {
|
||||||
request.setId(resourceId);
|
request.setId(resourceId);
|
||||||
request.setUserId(userId);
|
request.setUserId(userId);
|
||||||
request.setTriggerMode(ReportTriggerMode.SCHEDULE.name());
|
request.setTriggerMode(ReportTriggerMode.SCHEDULE.name());
|
||||||
apiTestService.run(request, ApiRunMode.RUN.name());
|
apiTestService.run(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JobKey getJobKey(String testId) {
|
public static JobKey getJobKey(String testId) {
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
<!--返回结果-->
|
<!--返回结果-->
|
||||||
<!-- HTTP 请求返回数据 -->
|
<!-- HTTP 请求返回数据 -->
|
||||||
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
|
<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>
|
</el-card>
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,10 @@
|
||||||
{{ $t('load_test.save_and_run') }}
|
{{ $t('load_test.save_and_run') }}
|
||||||
</el-button>
|
</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 :disabled="isReadOnly" type="warning" plain @click="cancel">{{ $t('commons.cancel') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
|
@ -95,339 +99,331 @@ export default {
|
||||||
|
|
||||||
props: ["id"],
|
props: ["id"],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
reportVisible: false,
|
reportVisible: false,
|
||||||
create: false,
|
create: false,
|
||||||
result: {},
|
result: {},
|
||||||
projects: [],
|
projects: [],
|
||||||
change: false,
|
change: false,
|
||||||
test: new Test(),
|
test: new Test(),
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
debugReportId: ''
|
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;
|
|
||||||
}
|
}
|
||||||
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;
|
watch: {
|
||||||
// 更新引用场景
|
'$route': 'init',
|
||||||
this.result = this.$post("/api/list/ids", {ids: updateIds}, response => {
|
test: {
|
||||||
let scenarioMap = {};
|
handler: function () {
|
||||||
if (response.data) {
|
this.change = true;
|
||||||
response.data.forEach(test => {
|
},
|
||||||
JSON.parse(test.scenarioDefinition).forEach(options => {
|
deep: true
|
||||||
let referenceId = test.id + "#" + options.id;
|
}
|
||||||
scenarioMap[referenceId] = new Scenario(options);
|
},
|
||||||
scenarioMap[referenceId].id = referenceId;
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
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 => {
|
this.test.scenarioDefinition.forEach(scenario => {
|
||||||
if (scenario.isReference()) {
|
if (scenario.isReference()) {
|
||||||
if (scenarioMap[scenario.id]) scenarios.push(scenarioMap[scenario.id]);
|
updateIds.push(scenario.id.split("#")[0]);
|
||||||
} else {
|
|
||||||
scenarios.push(scenario);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
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({
|
if (updateIds.length === 0) return;
|
||||||
id: item.id,
|
// 更新引用场景
|
||||||
projectId: item.projectId,
|
this.result = this.$post("/api/list/ids", {ids: updateIds}, response => {
|
||||||
name: item.name,
|
let scenarioMap = {};
|
||||||
status: item.status,
|
if (response.data) {
|
||||||
scenarioDefinition: JSON.parse(item.scenarioDefinition),
|
response.data.forEach(test => {
|
||||||
schedule: item.schedule ? item.schedule : {},
|
JSON.parse(test.scenarioDefinition).forEach(options => {
|
||||||
});
|
let referenceId = test.id + "#" + options.id;
|
||||||
this.updateReference();
|
scenarioMap[referenceId] = new Scenario(options);
|
||||||
|
scenarioMap[referenceId].id = referenceId;
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
this.$refs.config.reset();
|
let scenarios = [];
|
||||||
}
|
this.test.scenarioDefinition.forEach(scenario => {
|
||||||
});
|
if (scenario.isReference()) {
|
||||||
},
|
if (scenarioMap[scenario.id]) scenarios.push(scenarioMap[scenario.id]);
|
||||||
save(callback) {
|
} else {
|
||||||
let validator = this.test.isValid();
|
scenarios.push(scenario);
|
||||||
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
|
|
||||||
})
|
})
|
||||||
}
|
this.test.scenarioDefinition = scenarios;
|
||||||
// 发送广播,刷新 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
|
|
||||||
})
|
})
|
||||||
});
|
},
|
||||||
},
|
getTest(id) {
|
||||||
saveRunTest() {
|
this.result = this.$get("/api/get/" + id, response => {
|
||||||
this.change = false;
|
if (response.data) {
|
||||||
if (!this.validateEnableTest()) {
|
let item = response.data;
|
||||||
this.$warning(this.$t('api_test.enable_validate_tip'));
|
|
||||||
return;
|
this.test = new Test({
|
||||||
}
|
id: item.id,
|
||||||
this.save(() => {
|
projectId: item.projectId,
|
||||||
this.$success(this.$t('commons.save_success'));
|
name: item.name,
|
||||||
this.runTest();
|
status: item.status,
|
||||||
// 发送广播,刷新 head 上的最新列表
|
scenarioDefinition: JSON.parse(item.scenarioDefinition),
|
||||||
ApiEvent.$emit(LIST_CHANGE);
|
schedule: item.schedule ? item.schedule : {},
|
||||||
})
|
|
||||||
},
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
this.updateReference();
|
||||||
|
|
||||||
|
this.$refs.config.reset();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
},
|
||||||
return bodyUploadFiles;
|
save(callback) {
|
||||||
},
|
let validator = this.test.isValid();
|
||||||
validateEnableTest() {
|
if (!validator.isValid) {
|
||||||
for (let scenario of this.test.scenarioDefinition) {
|
this.$warning(this.$t(validator.info));
|
||||||
if (scenario.enable) {
|
return;
|
||||||
for (let request of scenario.requests) {
|
}
|
||||||
if (request.enable) {
|
this.change = false;
|
||||||
return true;
|
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;
|
||||||
return false;
|
},
|
||||||
},
|
resetBodyFile() {
|
||||||
resetBodyFile() {
|
//下次保存不再上传已传文件
|
||||||
//下次保存不再上传已传文件
|
this.test.scenarioDefinition.forEach(scenario => {
|
||||||
this.test.scenarioDefinition.forEach(scenario => {
|
scenario.requests.forEach(request => {
|
||||||
scenario.requests.forEach(request => {
|
if (request.body) {
|
||||||
if (request.body) {
|
request.body.kvs.forEach(param => {
|
||||||
request.body.kvs.forEach(param => {
|
if (param.files) {
|
||||||
if (param.files) {
|
param.files.forEach(item => {
|
||||||
param.files.forEach(item => {
|
if (item.file) {
|
||||||
if (item.file) {
|
item.file = undefined;
|
||||||
item.file = undefined;
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
});
|
},
|
||||||
},
|
cancel() {
|
||||||
cancel() {
|
this.$router.push('/api/test/list/all');
|
||||||
this.$router.push('/api/test/list/all');
|
// console.log(this.test.toJMX().xml);
|
||||||
},
|
},
|
||||||
createPerformance() {
|
handleCommand(command) {
|
||||||
let validator = this.test.isValid();
|
switch (command) {
|
||||||
if (!validator.isValid) {
|
case "report":
|
||||||
this.$warning(this.$t(validator.info));
|
this.$refs.reportDialog.open();
|
||||||
return;
|
break;
|
||||||
}
|
case "performance":
|
||||||
this.result = this.$post("/api/jmx", this.test, response => {
|
this.$store.commit('setTest', {
|
||||||
let jmx = {
|
projectId: this.test.projectId,
|
||||||
name: this.test.name + '.jmx',
|
name: this.test.name,
|
||||||
xml: response.data
|
jmx: this.test.toJMX()
|
||||||
};
|
})
|
||||||
this.$store.commit('setTest', {
|
this.$router.push({
|
||||||
projectId: this.test.projectId,
|
path: "/performance/test/create"
|
||||||
name: this.test.name,
|
})
|
||||||
jmx: jmx
|
break;
|
||||||
})
|
case "export":
|
||||||
this.$router.push({
|
downloadFile(this.test.name + ".json", this.test.export());
|
||||||
path: "/performance/test/create"
|
break;
|
||||||
})
|
case "jar":
|
||||||
});
|
this.$refs.jarConfig.open();
|
||||||
},
|
break;
|
||||||
handleCommand(command) {
|
case "import":
|
||||||
switch (command) {
|
this.$refs.apiImport.open();
|
||||||
case "report":
|
break;
|
||||||
this.$refs.reportDialog.open();
|
}
|
||||||
break;
|
},
|
||||||
case "performance":
|
saveCronExpression(cronExpression) {
|
||||||
this.createPerformance();
|
this.test.schedule.enable = true;
|
||||||
break;
|
this.test.schedule.value = cronExpression;
|
||||||
case "export":
|
this.saveSchedule();
|
||||||
downloadFile(this.test.name + ".json", this.test.export());
|
},
|
||||||
break;
|
saveSchedule() {
|
||||||
case "jar":
|
this.checkScheduleEdit();
|
||||||
this.$refs.jarConfig.open();
|
let param = {};
|
||||||
break;
|
param = this.test.schedule;
|
||||||
case "import":
|
param.resourceId = this.test.id;
|
||||||
this.$refs.apiImport.open();
|
let url = '/api/schedule/create';
|
||||||
break;
|
if (param.id) {
|
||||||
}
|
url = '/api/schedule/update';
|
||||||
},
|
}
|
||||||
saveCronExpression(cronExpression) {
|
this.$post(url, param, () => {
|
||||||
this.test.schedule.enable = true;
|
this.$success(this.$t('commons.save_success'));
|
||||||
this.test.schedule.value = cronExpression;
|
this.getTest(this.test.id);
|
||||||
this.saveSchedule();
|
});
|
||||||
},
|
},
|
||||||
saveSchedule() {
|
checkScheduleEdit() {
|
||||||
this.checkScheduleEdit();
|
if (this.create) {
|
||||||
let param = {};
|
this.$message(this.$t('api_test.environment.please_save_test'));
|
||||||
param = this.test.schedule;
|
return false;
|
||||||
param.resourceId = this.test.id;
|
}
|
||||||
let url = '/api/schedule/create';
|
return true;
|
||||||
if (param.id) {
|
},
|
||||||
url = '/api/schedule/update';
|
runDebug(scenario) {
|
||||||
}
|
if (this.create) {
|
||||||
this.$post(url, param, () => {
|
this.$warning(this.$t('api_test.environment.please_save_test'));
|
||||||
this.$success(this.$t('commons.save_success'));
|
return;
|
||||||
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 url = "/api/run/debug";
|
||||||
let runningTest = new Test();
|
let runningTest = new Test();
|
||||||
Object.assign(runningTest, this.test);
|
Object.assign(runningTest, this.test);
|
||||||
let bodyFiles = this.getBodyUploadFiles();
|
let bodyFiles = this.getBodyUploadFiles();
|
||||||
runningTest.scenarioDefinition = [];
|
runningTest.scenarioDefinition = [];
|
||||||
runningTest.scenarioDefinition.push(scenario);
|
runningTest.scenarioDefinition.push(scenario);
|
||||||
let validator = runningTest.isValid();
|
let validator = runningTest.isValid();
|
||||||
if (!validator.isValid) {
|
if (!validator.isValid) {
|
||||||
this.$warning(this.$t(validator.info));
|
this.$warning(this.$t(validator.info));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$fileUpload(url, null, bodyFiles, this.test, response => {
|
let jmx = runningTest.toJMX();
|
||||||
this.debugReportId = response.data;
|
let blob = new Blob([jmx.xml], {type: "application/octet-stream"});
|
||||||
this.resetBodyFile();
|
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() {
|
created() {
|
||||||
this.init();
|
this.init();
|
||||||
//
|
//
|
||||||
document.addEventListener('keydown', this.handleEvent)
|
document.addEventListener('keydown', this.handleEvent)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
document.removeEventListener('keydown', this.handleEvent);
|
document.removeEventListener('keydown', this.handleEvent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.test-container {
|
.test-container {
|
||||||
height: calc(100vh - 155px);
|
height: calc(100vh - 155px);
|
||||||
min-height: 600px;
|
min-height: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.test-name {
|
.test-name {
|
||||||
width: 600px;
|
width: 600px;
|
||||||
margin-left: -20px;
|
margin-left: -20px;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.test-project {
|
.test-project {
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.test-container .more {
|
.test-container .more {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
import MsApiScenarioConfig from "./components/ApiScenarioConfig";
|
import MsApiScenarioConfig from "./components/ApiScenarioConfig";
|
||||||
import MsApiReportStatus from "../report/ApiReportStatus";
|
import MsApiReportStatus from "../report/ApiReportStatus";
|
||||||
import MsApiReportDialog from "./ApiReportDialog";
|
import MsApiReportDialog from "./ApiReportDialog";
|
||||||
|
import {getUUID} from "@/common/js/utils";
|
||||||
import {parseEnvironment} from "./model/EnvironmentModel";
|
import {parseEnvironment} from "./model/EnvironmentModel";
|
||||||
|
|
||||||
|
|
||||||
|
@ -180,6 +181,9 @@
|
||||||
type: "application/json"
|
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 {
|
return {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: url,
|
url: url,
|
||||||
|
|
|
@ -1218,13 +1218,13 @@ class JMXGenerator {
|
||||||
}
|
}
|
||||||
envArray.forEach(item => {
|
envArray.forEach(item => {
|
||||||
let targetItem = targetMap.get(item.name);
|
let targetItem = targetMap.get(item.name);
|
||||||
let hasItem;
|
let hasItem = undefined;
|
||||||
if (targetItem) {
|
if (targetItem) {
|
||||||
hasItem = (targetItem.enable !== false);
|
hasItem = (targetItem.enable === false ? false : true);
|
||||||
} else {
|
} else {
|
||||||
hasItem = false;
|
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}));
|
target.push(new KeyValue({name: item.name, value: item.value}));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1412,7 +1412,7 @@ class JMXGenerator {
|
||||||
let hasContentType = false;
|
let hasContentType = false;
|
||||||
for (let index in request.headers) {
|
for (let index in request.headers) {
|
||||||
if (request.headers.hasOwnProperty(index)) {
|
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;
|
hasContentType = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1426,7 +1426,7 @@ class JMXGenerator {
|
||||||
removeContentType(request) {
|
removeContentType(request) {
|
||||||
for (let index in request.headers) {
|
for (let index in request.headers) {
|
||||||
if (request.headers.hasOwnProperty(index)) {
|
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);
|
request.headers.splice(index, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1524,7 +1524,7 @@ class JMXGenerator {
|
||||||
|
|
||||||
getResponseAssertion(regex) {
|
getResponseAssertion(regex) {
|
||||||
let name = regex.description;
|
let name = regex.description;
|
||||||
let type = JMX_ASSERTION_CONDITION.CONTAINS;
|
let type = JMX_ASSERTION_CONDITION.CONTAINS; // 固定用Match,自己写正则
|
||||||
let value = regex.expression;
|
let value = regex.expression;
|
||||||
let assumeSuccess = regex.assumeSuccess;
|
let assumeSuccess = regex.assumeSuccess;
|
||||||
switch (regex.subject) {
|
switch (regex.subject) {
|
||||||
|
|
Loading…
Reference in New Issue