Merge branch 'master' of https://github.com/metersphere/metersphere
Conflicts: frontend/src/business/components/api/automation/scenario/EditApiScenario.vue
This commit is contained in:
commit
8c2a2621e8
|
@ -268,7 +268,7 @@ public class APITestController {
|
||||||
if(allCount!=0){
|
if(allCount!=0){
|
||||||
float coverageRageNumber =(float)apiCountResult.getExecutionPassCount()*100/allCount;
|
float coverageRageNumber =(float)apiCountResult.getExecutionPassCount()*100/allCount;
|
||||||
DecimalFormat df = new DecimalFormat("0.0");
|
DecimalFormat df = new DecimalFormat("0.0");
|
||||||
apiCountResult.setCoverageRage(df.format(coverageRageNumber)+"%");
|
apiCountResult.setPassRage(df.format(coverageRageNumber)+"%");
|
||||||
}
|
}
|
||||||
|
|
||||||
return apiCountResult;
|
return apiCountResult;
|
||||||
|
@ -302,7 +302,7 @@ public class APITestController {
|
||||||
if(allCount!=0){
|
if(allCount!=0){
|
||||||
float coverageRageNumber =(float)apiCountResult.getSuccessCount()*100/allCount;
|
float coverageRageNumber =(float)apiCountResult.getSuccessCount()*100/allCount;
|
||||||
DecimalFormat df = new DecimalFormat("0.0");
|
DecimalFormat df = new DecimalFormat("0.0");
|
||||||
apiCountResult.setCoverageRage(df.format(coverageRageNumber)+"%");
|
apiCountResult.setSuccessRage(df.format(coverageRageNumber)+"%");
|
||||||
}
|
}
|
||||||
|
|
||||||
return apiCountResult;
|
return apiCountResult;
|
||||||
|
@ -354,6 +354,6 @@ public class APITestController {
|
||||||
public void updateScheduleEnableByPrimyKey(@RequestBody ScheduleInfoRequest request) {
|
public void updateScheduleEnableByPrimyKey(@RequestBody ScheduleInfoRequest request) {
|
||||||
Schedule schedule = scheduleService.getSchedule(request.getTaskID());
|
Schedule schedule = scheduleService.getSchedule(request.getTaskID());
|
||||||
schedule.setEnable(request.isEnable());
|
schedule.setEnable(request.isEnable());
|
||||||
apiTestService.updateSchedule(schedule);
|
apiAutomationService.updateSchedule(schedule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,21 +44,20 @@ public class ApiDefinitionController {
|
||||||
@PostMapping(value = "/create", consumes = {"multipart/form-data"})
|
@PostMapping(value = "/create", consumes = {"multipart/form-data"})
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR)
|
||||||
public void create(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
public void create(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||||
checkPermissionService.checkReadOnlyUser();
|
checkPermissionService.checkProjectOwner(request.getProjectId());
|
||||||
apiDefinitionService.create(request, bodyFiles);
|
apiDefinitionService.create(request, bodyFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/update", consumes = {"multipart/form-data"})
|
@PostMapping(value = "/update", consumes = {"multipart/form-data"})
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR)
|
||||||
public void update(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
public void update(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||||
checkPermissionService.checkReadOnlyUser();
|
checkPermissionService.checkProjectOwner(request.getProjectId());
|
||||||
apiDefinitionService.update(request, bodyFiles);
|
apiDefinitionService.update(request, bodyFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/delete/{id}")
|
@GetMapping("/delete/{id}")
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR)
|
||||||
public void delete(@PathVariable String id) {
|
public void delete(@PathVariable String id) {
|
||||||
checkPermissionService.checkReadOnlyUser();
|
|
||||||
apiDefinitionService.delete(id);
|
apiDefinitionService.delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(value = "/api/testcase")
|
@RequestMapping(value = "/api/testcase")
|
||||||
|
@ -43,6 +44,12 @@ public class ApiTestCaseController {
|
||||||
return PageUtils.setPageInfo(page, apiTestCaseService.listSimple(request));
|
return PageUtils.setPageInfo(page, apiTestCaseService.listSimple(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/get/request")
|
||||||
|
public Map<String, String> listSimple(@RequestBody ApiTestCaseRequest request) {
|
||||||
|
request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
|
||||||
|
return apiTestCaseService.getRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/create", consumes = {"multipart/form-data"})
|
@PostMapping(value = "/create", consumes = {"multipart/form-data"})
|
||||||
public void create(@RequestPart("request") SaveApiTestCaseRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
public void create(@RequestPart("request") SaveApiTestCaseRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||||
apiTestCaseService.create(request, bodyFiles);
|
apiTestCaseService.create(request, bodyFiles);
|
||||||
|
|
|
@ -206,35 +206,17 @@ public class MsHTTPSamplerProxy extends MsTestElement {
|
||||||
this.getRest().stream().filter(KeyValue::isEnable).filter(KeyValue::isValid).forEach(keyValue ->
|
this.getRest().stream().filter(KeyValue::isEnable).filter(KeyValue::isValid).forEach(keyValue ->
|
||||||
keyValueMap.put(keyValue.getName(), keyValue.getValue())
|
keyValueMap.put(keyValue.getName(), keyValue.getValue())
|
||||||
);
|
);
|
||||||
// 这块是否使用jmeter自身机制?
|
try {
|
||||||
Map<String, String> pubKeyValueMap = new HashMap<>();
|
|
||||||
if (config != null && config.getVariables() != null) {
|
|
||||||
config.getVariables().stream().forEach(keyValue -> {
|
|
||||||
pubKeyValueMap.put(keyValue.getName(), keyValue.getValue());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
for (String key : keyValueMap.keySet()) {
|
|
||||||
if (keyValueMap.get(key) != null && keyValueMap.get(key).startsWith("$")) {
|
|
||||||
String pubKey = keyValueMap.get(key).substring(2, keyValueMap.get(key).length() - 1);
|
|
||||||
keyValueMap.put(key, pubKeyValueMap.get(pubKey));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Pattern p = Pattern.compile("(\\{)([\\w]+)(\\})");
|
Pattern p = Pattern.compile("(\\{)([\\w]+)(\\})");
|
||||||
Matcher m = p.matcher(path);
|
Matcher m = p.matcher(path);
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
try {
|
|
||||||
while (m.find()) {
|
while (m.find()) {
|
||||||
String group = m.group(2);
|
String group = m.group(2);
|
||||||
//替换并且把替换好的值放到sb中
|
path = path.replace("{" + group + "}", keyValueMap.get(group));
|
||||||
m.appendReplacement(sb, keyValueMap.get(group));
|
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
//把符合的数据追加到sb尾
|
return path;
|
||||||
m.appendTail(sb);
|
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPostQueryParameters(String path) {
|
private String getPostQueryParameters(String path) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.api.jmeter;
|
package io.metersphere.api.jmeter;
|
||||||
|
|
||||||
import io.metersphere.api.service.*;
|
import io.metersphere.api.service.*;
|
||||||
|
import io.metersphere.base.domain.ApiScenarioReport;
|
||||||
import io.metersphere.base.domain.ApiTestReport;
|
import io.metersphere.base.domain.ApiTestReport;
|
||||||
import io.metersphere.commons.constants.APITestStatus;
|
import io.metersphere.commons.constants.APITestStatus;
|
||||||
import io.metersphere.commons.constants.ApiRunMode;
|
import io.metersphere.commons.constants.ApiRunMode;
|
||||||
|
@ -20,6 +21,7 @@ import org.apache.jmeter.protocol.http.sampler.HTTPSampleResult;
|
||||||
import org.apache.jmeter.samplers.SampleResult;
|
import org.apache.jmeter.samplers.SampleResult;
|
||||||
import org.apache.jmeter.visualizers.backend.AbstractBackendListenerClient;
|
import org.apache.jmeter.visualizers.backend.AbstractBackendListenerClient;
|
||||||
import org.apache.jmeter.visualizers.backend.BackendListenerContext;
|
import org.apache.jmeter.visualizers.backend.BackendListenerContext;
|
||||||
|
import org.python.antlr.ast.Str;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
@ -50,6 +52,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
|
|
||||||
private ApiScenarioReportService apiScenarioReportService;
|
private ApiScenarioReportService apiScenarioReportService;
|
||||||
|
|
||||||
|
|
||||||
public String runMode = ApiRunMode.RUN.name();
|
public String runMode = ApiRunMode.RUN.name();
|
||||||
|
|
||||||
// 测试ID
|
// 测试ID
|
||||||
|
@ -155,6 +158,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
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 = null;
|
ApiTestReport report = null;
|
||||||
|
String reportUrl = null;
|
||||||
// 这部分后续优化只留 DELIMIT 和 SCENARIO 两部分
|
// 这部分后续优化只留 DELIMIT 和 SCENARIO 两部分
|
||||||
if (StringUtils.equals(this.runMode, ApiRunMode.DEBUG.name())) {
|
if (StringUtils.equals(this.runMode, ApiRunMode.DEBUG.name())) {
|
||||||
report = apiReportService.get(debugReportId);
|
report = apiReportService.get(debugReportId);
|
||||||
|
@ -173,7 +177,31 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
} else if (StringUtils.equalsAny(this.runMode, ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name())) {
|
} else if (StringUtils.equalsAny(this.runMode, ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name())) {
|
||||||
// 执行报告不需要存储,由用户确认后在存储
|
// 执行报告不需要存储,由用户确认后在存储
|
||||||
testResult.setTestId(testId);
|
testResult.setTestId(testId);
|
||||||
apiScenarioReportService.complete(testResult, this.runMode);
|
ApiScenarioReport scenarioReport = apiScenarioReportService.complete(testResult, this.runMode);
|
||||||
|
|
||||||
|
|
||||||
|
report = new ApiTestReport();
|
||||||
|
report.setStatus(scenarioReport.getStatus());
|
||||||
|
report.setId(scenarioReport.getId());
|
||||||
|
report.setTriggerMode(scenarioReport.getTriggerMode());
|
||||||
|
report.setName(scenarioReport.getName());
|
||||||
|
|
||||||
|
|
||||||
|
SystemParameterService systemParameterService = CommonBeanFactory.getBean(SystemParameterService.class);
|
||||||
|
assert systemParameterService != null;
|
||||||
|
BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo();
|
||||||
|
reportUrl = baseSystemConfigDTO.getUrl() + "/#/api/automation/report";
|
||||||
|
|
||||||
|
|
||||||
|
String scenaName = scenarioReport.getName();
|
||||||
|
if(scenaName==null){
|
||||||
|
scenaName = "";
|
||||||
|
}else {
|
||||||
|
scenaName = scenaName.split("-")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
String scenarioID = apiScenarioReportService.getApiScenarioId(scenaName,scenarioReport.getProjectId());
|
||||||
|
testResult.setTestId(scenarioID);
|
||||||
} else {
|
} else {
|
||||||
apiTestService.changeStatus(testId, APITestStatus.Completed);
|
apiTestService.changeStatus(testId, APITestStatus.Completed);
|
||||||
report = apiReportService.getRunningReport(testResult.getTestId());
|
report = apiReportService.getRunningReport(testResult.getTestId());
|
||||||
|
@ -196,22 +224,24 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
sendTask(report, testResult);
|
sendTask(report,reportUrl, testResult);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtil.error(e.getMessage(), e);
|
LogUtil.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void sendTask(ApiTestReport report, TestResult testResult) {
|
private static void sendTask(ApiTestReport report,String reportUrl, TestResult testResult) {
|
||||||
SystemParameterService systemParameterService = CommonBeanFactory.getBean(SystemParameterService.class);
|
SystemParameterService systemParameterService = CommonBeanFactory.getBean(SystemParameterService.class);
|
||||||
NoticeSendService noticeSendService = CommonBeanFactory.getBean(NoticeSendService.class);
|
NoticeSendService noticeSendService = CommonBeanFactory.getBean(NoticeSendService.class);
|
||||||
assert systemParameterService != null;
|
assert systemParameterService != null;
|
||||||
assert noticeSendService != null;
|
assert noticeSendService != null;
|
||||||
|
|
||||||
BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo();
|
BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo();
|
||||||
String url = baseSystemConfigDTO.getUrl() + "/#/api/report/view/" + report.getId();
|
String url = reportUrl;
|
||||||
|
if(StringUtils.isEmpty(url)){
|
||||||
|
url = baseSystemConfigDTO.getUrl() + "/#/api/report/view/" + report.getId();
|
||||||
|
}
|
||||||
String successContext = "";
|
String successContext = "";
|
||||||
String failedContext = "";
|
String failedContext = "";
|
||||||
String subject = "";
|
String subject = "";
|
||||||
|
|
|
@ -30,9 +30,6 @@ import io.metersphere.service.ScheduleService;
|
||||||
import io.metersphere.track.dto.TestPlanDTO;
|
import io.metersphere.track.dto.TestPlanDTO;
|
||||||
import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest;
|
import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest;
|
||||||
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
|
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
|
||||||
import io.metersphere.track.request.testcase.TestPlanApiCaseBatchRequest;
|
|
||||||
import io.metersphere.track.service.TestPlanApiCaseService;
|
|
||||||
import io.metersphere.track.service.TestPlanScenarioCaseService;
|
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.ibatis.session.ExecutorType;
|
import org.apache.ibatis.session.ExecutorType;
|
||||||
|
@ -40,14 +37,13 @@ import org.apache.ibatis.session.SqlSession;
|
||||||
import org.apache.ibatis.session.SqlSessionFactory;
|
import org.apache.ibatis.session.SqlSessionFactory;
|
||||||
import org.apache.jorphan.collections.HashTree;
|
import org.apache.jorphan.collections.HashTree;
|
||||||
import org.apache.jorphan.collections.ListedHashTree;
|
import org.apache.jorphan.collections.ListedHashTree;
|
||||||
|
import org.python.antlr.ast.Str;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
@ -180,6 +176,7 @@ public class ApiAutomationService {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void preDelete(List<String> scenarioIDList) {
|
public void preDelete(List<String> scenarioIDList) {
|
||||||
List<String> testPlanApiScenarioIdList = new ArrayList<>();
|
List<String> testPlanApiScenarioIdList = new ArrayList<>();
|
||||||
List<String> scheduleIdList = new ArrayList<>();
|
List<String> scheduleIdList = new ArrayList<>();
|
||||||
|
@ -202,9 +199,11 @@ public class ApiAutomationService {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteBatch(List<String> ids) {
|
public void deleteBatch(List<String> ids) {
|
||||||
//及连删除外键表
|
//及连删除外键表
|
||||||
preDelete(ids);;
|
preDelete(ids);
|
||||||
|
;
|
||||||
ApiScenarioExample example = new ApiScenarioExample();
|
ApiScenarioExample example = new ApiScenarioExample();
|
||||||
example.createCriteria().andIdIn(ids);
|
example.createCriteria().andIdIn(ids);
|
||||||
apiScenarioMapper.deleteByExample(example);
|
apiScenarioMapper.deleteByExample(example);
|
||||||
|
@ -339,7 +338,6 @@ public class ApiAutomationService {
|
||||||
ParameterConfig config = new ParameterConfig();
|
ParameterConfig config = new ParameterConfig();
|
||||||
config.setConfig(envConfig);
|
config.setConfig(envConfig);
|
||||||
HashTree hashTree = request.getTestElement().generateHashTree(config);
|
HashTree hashTree = request.getTestElement().generateHashTree(config);
|
||||||
request.getTestElement().getJmx(hashTree);
|
|
||||||
// 调用执行方法
|
// 调用执行方法
|
||||||
jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), ApiRunMode.SCENARIO.name());
|
jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), ApiRunMode.SCENARIO.name());
|
||||||
createAPIScenarioReportResult(request.getId(), ReportTriggerMode.MANUAL.name(), request.getExecuteType(), request.getProjectId(),
|
createAPIScenarioReportResult(request.getId(), ReportTriggerMode.MANUAL.name(), request.getExecuteType(), request.getProjectId(),
|
||||||
|
|
|
@ -50,7 +50,18 @@ public class ApiScenarioReportService {
|
||||||
@Resource
|
@Resource
|
||||||
private TestPlanApiScenarioMapper testPlanApiScenarioMapper;
|
private TestPlanApiScenarioMapper testPlanApiScenarioMapper;
|
||||||
|
|
||||||
public void complete(TestResult result, String runMode) {
|
public String getApiScenarioId(String name, String projectID) {
|
||||||
|
ApiScenarioExample example = new ApiScenarioExample();
|
||||||
|
example.createCriteria().andNameEqualTo(name).andProjectIdEqualTo(projectID).andStatusNotEqualTo("Trash");
|
||||||
|
List<ApiScenario> list = apiScenarioMapper.selectByExample(example);
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return list.get(0).getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApiScenarioReport complete(TestResult result, String runMode) {
|
||||||
Object obj = cache.get(result.getTestId());
|
Object obj = cache.get(result.getTestId());
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
MSException.throwException(Translator.get("api_report_is_null"));
|
MSException.throwException(Translator.get("api_report_is_null"));
|
||||||
|
@ -83,6 +94,7 @@ public class ApiScenarioReportService {
|
||||||
if (!report.getTriggerMode().equals(ReportTriggerMode.SCHEDULE.name())) {
|
if (!report.getTriggerMode().equals(ReportTriggerMode.SCHEDULE.name())) {
|
||||||
cache.put(report.getId(), report);
|
cache.put(report.getId(), report);
|
||||||
}
|
}
|
||||||
|
return report;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -332,4 +332,9 @@ public class ApiTestCaseService {
|
||||||
example.createCriteria().andIdIn(caseIds);
|
example.createCriteria().andIdIn(caseIds);
|
||||||
return apiTestCaseMapper.selectByExample(example);
|
return apiTestCaseMapper.selectByExample(example);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getRequest(ApiTestCaseRequest request) {
|
||||||
|
List<ApiTestCaseWithBLOBs> list = extApiTestCaseMapper.getRequest(request);
|
||||||
|
return list.stream().collect(Collectors.toMap(ApiTestCaseWithBLOBs::getId, ApiTestCaseWithBLOBs::getRequest));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,12 +50,20 @@
|
||||||
) caseErrorCountData ON caseErrorCountData.testCaseID =testCase.testCaseID
|
) caseErrorCountData ON caseErrorCountData.testCaseID =testCase.testCaseID
|
||||||
WHERE caseErrorCountData.executeTime >= #{startTimestamp}
|
WHERE caseErrorCountData.executeTime >= #{startTimestamp}
|
||||||
UNION
|
UNION
|
||||||
SELECT scene.`name` AS caseName,testPlan.`name` AS testPlan,count(report.id) AS failureTimes,'scenario' AS caseType
|
SELECT scene.`name` AS caseName,apiScene.testPlanName AS testPlan,count(report.id) AS failureTimes,'scenario' AS caseType
|
||||||
FROM api_scenario_report report
|
FROM api_scenario_report report
|
||||||
INNER JOIN api_scenario_report_detail reportDetail ON report.id = reportDetail.report_id
|
INNER JOIN api_scenario_report_detail reportDetail ON report.id = reportDetail.report_id
|
||||||
INNER JOIN api_scenario scene ON reportDetail.content like concat('%"', scene.`name`,'"%')
|
INNER JOIN api_scenario scene ON reportDetail.content like concat('%"', scene.`name`,'"%')
|
||||||
LEFT JOIN test_plan_api_scenario apiScene ON apiScene.api_scenario_id = scene.id
|
LEFT JOIN
|
||||||
LEFT JOIN test_plan testPlan ON testPlan.id = apiScene.test_plan_id
|
(
|
||||||
|
SELECT
|
||||||
|
apiScene.api_scenario_id,
|
||||||
|
group_concat(testPlan.`name`) AS testPlanName
|
||||||
|
FROM
|
||||||
|
test_plan_api_scenario apiScene
|
||||||
|
INNER JOIN test_plan testPlan ON testPlan.id = apiScene.test_plan_id
|
||||||
|
GROUP BY apiScene.api_scenario_id
|
||||||
|
)apiScene ON apiScene.api_scenario_id = scene.id
|
||||||
WHERE report.project_id = #{projectId}
|
WHERE report.project_id = #{projectId}
|
||||||
AND report.status = 'Error' AND report.create_time >= #{startTimestamp}
|
AND report.status = 'Error' AND report.create_time >= #{startTimestamp}
|
||||||
GROUP BY scene.id
|
GROUP BY scene.id
|
||||||
|
|
|
@ -179,8 +179,8 @@
|
||||||
SELECT count(acr.report_id) AS countNumber FROM api_scenario_report_detail acr
|
SELECT count(acr.report_id) AS countNumber FROM api_scenario_report_detail acr
|
||||||
INNER JOIN api_scenario_report ar ON ar.id = acr.report_id
|
INNER JOIN api_scenario_report ar ON ar.id = acr.report_id
|
||||||
INNER JOIN (
|
INNER JOIN (
|
||||||
SELECT acitem.id FROM api_scenario acitem INNER JOIN `schedule` sc ON acitem.id = sc.resource_id
|
SELECT acitem.`name` FROM api_scenario acitem INNER JOIN `schedule` sc ON acitem.id = sc.resource_id
|
||||||
) ac on acr.content like CONCAT('%', ac.id,'%')
|
) ac on acr.content like CONCAT('%"', ac.`name`,'"%')
|
||||||
WHERE acr.project_id = #{projectId} AND ar.create_time BETWEEN #{firstDayTimestamp} AND #{lastDayTimestamp}
|
WHERE acr.project_id = #{projectId} AND ar.create_time BETWEEN #{firstDayTimestamp} AND #{lastDayTimestamp}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
@ -189,8 +189,8 @@
|
||||||
FROM api_scenario_report_detail acr
|
FROM api_scenario_report_detail acr
|
||||||
INNER JOIN api_scenario_report ar ON ar.id = acr.report_id
|
INNER JOIN api_scenario_report ar ON ar.id = acr.report_id
|
||||||
INNER JOIN (
|
INNER JOIN (
|
||||||
SELECT acitem.id FROM api_scenario acitem INNER JOIN `schedule` sc ON acitem.id = sc.resource_id
|
SELECT acitem.`name` FROM api_scenario acitem INNER JOIN `schedule` sc ON acitem.id = sc.resource_id
|
||||||
) ac on acr.content like CONCAT('%', ac.id,'%')
|
) ac on acr.content like CONCAT('%"', ac.`name`,'"%')
|
||||||
WHERE acr.project_id = #{projectId}
|
WHERE acr.project_id = #{projectId}
|
||||||
</select>
|
</select>
|
||||||
</mapper>
|
</mapper>
|
|
@ -4,10 +4,13 @@ import io.metersphere.api.dto.datacount.ApiDataCountResult;
|
||||||
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
||||||
import io.metersphere.api.dto.definition.ApiTestCaseRequest;
|
import io.metersphere.api.dto.definition.ApiTestCaseRequest;
|
||||||
import io.metersphere.api.dto.definition.ApiTestCaseResult;
|
import io.metersphere.api.dto.definition.ApiTestCaseResult;
|
||||||
|
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
|
||||||
|
import org.apache.ibatis.annotations.MapKey;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.apache.ibatis.annotations.Select;
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public interface ExtApiTestCaseMapper {
|
public interface ExtApiTestCaseMapper {
|
||||||
|
|
||||||
|
@ -20,4 +23,6 @@ public interface ExtApiTestCaseMapper {
|
||||||
List<ApiDataCountResult> countProtocolByProjectID(String projectId);
|
List<ApiDataCountResult> countProtocolByProjectID(String projectId);
|
||||||
|
|
||||||
long countByProjectIDAndCreateInThisWeek(@Param("projectId") String projectId, @Param("firstDayTimestamp") long firstDayTimestamp, @Param("lastDayTimestamp") long lastDayTimestamp);
|
long countByProjectIDAndCreateInThisWeek(@Param("projectId") String projectId, @Param("firstDayTimestamp") long firstDayTimestamp, @Param("lastDayTimestamp") long lastDayTimestamp);
|
||||||
|
|
||||||
|
List<ApiTestCaseWithBLOBs> getRequest(@Param("request") ApiTestCaseRequest request);
|
||||||
}
|
}
|
|
@ -290,5 +290,20 @@
|
||||||
AND testCase.create_time BETWEEN #{firstDayTimestamp} AND #{lastDayTimestamp}
|
AND testCase.create_time BETWEEN #{firstDayTimestamp} AND #{lastDayTimestamp}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="getRequest" resultType="io.metersphere.base.domain.ApiTestCaseWithBLOBs">
|
||||||
|
select id, request
|
||||||
|
from api_test_case
|
||||||
|
where 1
|
||||||
|
<if test="request.id != null and request.id!=''">
|
||||||
|
and id = #{request.id}
|
||||||
|
</if>
|
||||||
|
<if test="request.ids != null and request.ids.size() > 0">
|
||||||
|
and id in
|
||||||
|
<foreach collection="request.ids" item="caseId" separator="," open="(" close=")">
|
||||||
|
#{caseId}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
|
@ -160,7 +160,6 @@
|
||||||
WHERE sch.resource_id IN (
|
WHERE sch.resource_id IN (
|
||||||
SELECT id FROM api_test WHERE project_id = #{projectId,jdbcType=VARCHAR}
|
SELECT id FROM api_test WHERE project_id = #{projectId,jdbcType=VARCHAR}
|
||||||
)
|
)
|
||||||
AND `group` = #{group}
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="countByProjectIDAndCreateInThisWeek" resultType="java.lang.Long">
|
<select id="countByProjectIDAndCreateInThisWeek" resultType="java.lang.Long">
|
||||||
|
|
|
@ -231,6 +231,7 @@
|
||||||
<select id="selectTestPlanByRelevancy" resultMap="BaseResultMap" parameterType="io.metersphere.track.request.testcase.QueryTestPlanRequest">
|
<select id="selectTestPlanByRelevancy" resultMap="BaseResultMap" parameterType="io.metersphere.track.request.testcase.QueryTestPlanRequest">
|
||||||
SELECT * FROM TEST_PLAN p LEFT JOIN test_plan_project t ON t.test_plan_id=p.id
|
SELECT * FROM TEST_PLAN p LEFT JOIN test_plan_project t ON t.test_plan_id=p.id
|
||||||
<where>
|
<where>
|
||||||
|
AND t.project_id = #{request.projectId}
|
||||||
<if test="request.scenarioId != null">
|
<if test="request.scenarioId != null">
|
||||||
AND p.id IN (SELECT test_plan_id FROM test_plan_api_scenario WHERE api_scenario_id = #{request.scenarioId} )
|
AND p.id IN (SELECT test_plan_id FROM test_plan_api_scenario WHERE api_scenario_id = #{request.scenarioId} )
|
||||||
</if>
|
</if>
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class PerformanceTestController {
|
||||||
@RequestPart("request") SaveTestPlanRequest request,
|
@RequestPart("request") SaveTestPlanRequest request,
|
||||||
@RequestPart(value = "file") List<MultipartFile> files
|
@RequestPart(value = "file") List<MultipartFile> files
|
||||||
) {
|
) {
|
||||||
checkPermissionService.checkReadOnlyUser();
|
checkPermissionService.checkProjectOwner(request.getProjectId());
|
||||||
return performanceTestService.save(request, files);
|
return performanceTestService.save(request, files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,6 @@ public class PerformanceTestController {
|
||||||
@RequestPart("request") EditTestPlanRequest request,
|
@RequestPart("request") EditTestPlanRequest request,
|
||||||
@RequestPart(value = "file", required = false) List<MultipartFile> files
|
@RequestPart(value = "file", required = false) List<MultipartFile> files
|
||||||
) {
|
) {
|
||||||
checkPermissionService.checkReadOnlyUser();
|
|
||||||
checkPermissionService.checkPerformanceTestOwner(request.getId());
|
checkPermissionService.checkPerformanceTestOwner(request.getId());
|
||||||
return performanceTestService.edit(request, files);
|
return performanceTestService.edit(request, files);
|
||||||
}
|
}
|
||||||
|
@ -115,7 +114,6 @@ public class PerformanceTestController {
|
||||||
|
|
||||||
@PostMapping("/delete")
|
@PostMapping("/delete")
|
||||||
public void delete(@RequestBody DeleteTestPlanRequest request) {
|
public void delete(@RequestBody DeleteTestPlanRequest request) {
|
||||||
checkPermissionService.checkReadOnlyUser();
|
|
||||||
checkPermissionService.checkPerformanceTestOwner(request.getId());
|
checkPermissionService.checkPerformanceTestOwner(request.getId());
|
||||||
performanceTestService.delete(request);
|
performanceTestService.delete(request);
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,6 +212,8 @@ public class SystemParameterService {
|
||||||
public void saveBaseInfo(List<SystemParameter> parameters) {
|
public void saveBaseInfo(List<SystemParameter> parameters) {
|
||||||
SystemParameterExample example = new SystemParameterExample();
|
SystemParameterExample example = new SystemParameterExample();
|
||||||
parameters.forEach(param -> {
|
parameters.forEach(param -> {
|
||||||
|
// 去掉路径最后的 /
|
||||||
|
param.setParamValue(StringUtils.removeEnd(param.getParamValue(), "/"));
|
||||||
example.createCriteria().andParamKeyEqualTo(param.getParamKey());
|
example.createCriteria().andParamKeyEqualTo(param.getParamKey());
|
||||||
if (systemParameterMapper.countByExample(example) > 0) {
|
if (systemParameterMapper.countByExample(example) > 0) {
|
||||||
systemParameterMapper.updateByPrimaryKey(param);
|
systemParameterMapper.updateByPrimaryKey(param);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 79343a2763b014355f91fc21b2356a95ae437973
|
Subproject commit 9f4a9bbf46fc1333dbcccea21f83e27e3ec10b1f
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<el-card>
|
<el-card class="card-content">
|
||||||
<div class="card-content">
|
<div>
|
||||||
<div class="ms-main-div" @click="showAll">
|
<div class="ms-main-div" @click="showAll">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col>
|
<el-col>
|
||||||
|
@ -11,32 +11,31 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<div class="tip">{{$t('test_track.plan_view.base_info')}}</div>
|
<div class="tip">{{$t('test_track.plan_view.base_info')}}</div>
|
||||||
<el-form :model="currentScenario" label-position="right" label-width="80px" size="small" :rules="rules"
|
<el-form :model="currentScenario" label-position="right" label-width="80px" size="small" :rules="rules" ref="currentScenario" style="margin-right: 20px">
|
||||||
ref="currentScenario" style="margin-right: 20px">
|
|
||||||
<!-- 基础信息 -->
|
<!-- 基础信息 -->
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="7">
|
<el-col :span="12">
|
||||||
<el-form-item :label="$t('commons.name')" prop="name">
|
<el-form-item :label="$t('commons.name')" prop="name">
|
||||||
<el-input class="ms-scenario-input" size="small" v-model="currentScenario.name"/>
|
<el-input class="ms-scenario-input" size="small" v-model="currentScenario.name"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="7">
|
<el-col :span="12">
|
||||||
<el-form-item :label="$t('test_track.module.module')" prop="apiScenarioModuleId">
|
<el-form-item :label="$t('test_track.module.module')" prop="apiScenarioModuleId">
|
||||||
<el-select class="ms-scenario-input" size="small" v-model="currentScenario.apiScenarioModuleId">
|
<el-select class="ms-scenario-input" size="small" v-model="currentScenario.apiScenarioModuleId">
|
||||||
<el-option v-for="item in moduleOptions" :key="item.id" :label="item.path" :value="item.id"/>
|
<el-option v-for="item in moduleOptions" :key="item.id" :label="item.path" :value="item.id"/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="7">
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
<el-form-item :label="$t('commons.status')" prop="status">
|
<el-form-item :label="$t('commons.status')" prop="status">
|
||||||
<el-select class="ms-scenario-input" size="small" v-model="currentScenario.status">
|
<el-select class="ms-scenario-input" size="small" v-model="currentScenario.status">
|
||||||
<el-option v-for="item in options" :key="item.id" :label="item.label" :value="item.id"/>
|
<el-option v-for="item in options" :key="item.id" :label="item.label" :value="item.id"/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
<el-col :span="12">
|
||||||
<el-row>
|
|
||||||
<el-col :span="7">
|
|
||||||
<el-form-item :label="$t('api_test.definition.request.responsible')" prop="principal">
|
<el-form-item :label="$t('api_test.definition.request.responsible')" prop="principal">
|
||||||
<el-select v-model="currentScenario.principal"
|
<el-select v-model="currentScenario.principal"
|
||||||
:placeholder="$t('api_test.definition.request.responsible')" filterable size="small"
|
:placeholder="$t('api_test.definition.request.responsible')" filterable size="small"
|
||||||
|
@ -48,16 +47,20 @@
|
||||||
:value="item.id">
|
:value="item.id">
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="7">
|
</el-row>
|
||||||
|
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
<el-form-item :label="$t('test_track.case.priority')" prop="level">
|
<el-form-item :label="$t('test_track.case.priority')" prop="level">
|
||||||
<el-select class="ms-scenario-input" size="small" v-model="currentScenario.level">
|
<el-select class="ms-scenario-input" size="small" v-model="currentScenario.level">
|
||||||
<el-option v-for="item in levels" :key="item.id" :label="item.label" :value="item.id"/>
|
<el-option v-for="item in levels" :key="item.id" :label="item.label" :value="item.id"/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="7">
|
<el-col :span="12">
|
||||||
<el-form-item :label="$t('api_test.automation.follow_people')" prop="followPeople">
|
<el-form-item :label="$t('api_test.automation.follow_people')" prop="followPeople">
|
||||||
<el-select v-model="currentScenario.followPeople"
|
<el-select v-model="currentScenario.followPeople"
|
||||||
:placeholder="$t('api_test.automation.follow_people')" filterable size="small"
|
:placeholder="$t('api_test.automation.follow_people')" filterable size="small"
|
||||||
|
@ -73,13 +76,14 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="7">
|
<el-col :span="12">
|
||||||
<el-form-item label="Tag" prop="tags">
|
<el-form-item label="Tag" prop="tags">
|
||||||
<ms-input-tag :currentScenario="currentScenario" ref="tag"/>
|
<ms-input-tag :currentScenario="currentScenario" ref="tag"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="7">
|
<el-col :span="12">
|
||||||
<el-form-item :label="$t('commons.description')" prop="description">
|
<el-form-item :label="$t('commons.description')" prop="description">
|
||||||
<el-input class="ms-http-textarea"
|
<el-input class="ms-http-textarea"
|
||||||
v-model="currentScenario.description"
|
v-model="currentScenario.description"
|
||||||
|
@ -109,8 +113,7 @@
|
||||||
{{$t('api_test.automation.step_total')}}:{{scenarioDefinition.length}}
|
{{$t('api_test.automation.step_total')}}:{{scenarioDefinition.length}}
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="3" class="ms-col-one ms-font">
|
<el-col :span="3" class="ms-col-one ms-font">
|
||||||
<el-link class="head" @click="showScenarioParameters">{{ $t('api_test.automation.scenario_total') }}
|
<el-link class="head" @click="showScenarioParameters">{{$t('api_test.automation.scenario_total')}}</el-link>
|
||||||
</el-link>
|
|
||||||
:{{this.currentScenario.variables!=undefined?this.currentScenario.variables.length-1: 0}}
|
:{{this.currentScenario.variables!=undefined?this.currentScenario.variables.length-1: 0}}
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="3" class="ms-col-one ms-font">
|
<el-col :span="3" class="ms-col-one ms-font">
|
||||||
|
@ -137,8 +140,7 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="2">
|
<el-col :span="2">
|
||||||
<el-button size="small" type="primary" @click="runDebug">{{ $t('api_test.request.debug') }}
|
<el-button size="small" type="primary" @click="runDebug">{{$t('api_test.request.debug')}}</el-button>
|
||||||
</el-button>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
|
@ -149,54 +151,39 @@
|
||||||
:expand-on-click-node="false"
|
:expand-on-click-node="false"
|
||||||
@node-expand="nodeExpand"
|
@node-expand="nodeExpand"
|
||||||
@node-collapse="nodeCollapse"
|
@node-collapse="nodeCollapse"
|
||||||
:allow-drop="allowDrop" @node-drag-end="allowDrag" @node-click="nodeClick" v-if="!loading"
|
:allow-drop="allowDrop" @node-drag-end="allowDrag" @node-click="nodeClick" v-if="!loading" draggable>
|
||||||
draggable>
|
|
||||||
<span class="custom-tree-node father" slot-scope="{ node, data}" style="width: 96%">
|
<span class="custom-tree-node father" slot-scope="{ node, data}" style="width: 96%">
|
||||||
<template>
|
<template>
|
||||||
<!-- 场景 -->
|
<!-- 场景 -->
|
||||||
<ms-api-scenario-component v-if="data.type==='scenario'" :scenario="data" :node="node"
|
<ms-api-scenario-component v-if="data.type==='scenario'" :scenario="data" :node="node" @remove="remove" @copyRow="copyRow"/>
|
||||||
@remove="remove" @copyRow="copyRow"/>
|
|
||||||
<!--条件控制器-->
|
<!--条件控制器-->
|
||||||
<ms-if-controller :controller="data" :node="node" v-if="data.type==='IfController'"
|
<ms-if-controller :controller="data" :node="node" v-if="data.type==='IfController'" @remove="remove" @copyRow="copyRow"/>
|
||||||
@remove="remove" @copyRow="copyRow"/>
|
|
||||||
<!--等待控制器-->
|
<!--等待控制器-->
|
||||||
<ms-constant-timer :timer="data" :node="node" v-if="data.type==='ConstantTimer'" @remove="remove"
|
<ms-constant-timer :timer="data" :node="node" v-if="data.type==='ConstantTimer'" @remove="remove" @copyRow="copyRow"/>
|
||||||
@copyRow="copyRow"/>
|
|
||||||
<!--自定义脚本-->
|
<!--自定义脚本-->
|
||||||
<ms-jsr233-processor v-if="data.type==='JSR223Processor'" @remove="remove" @copyRow="copyRow"
|
<ms-jsr233-processor v-if="data.type==='JSR223Processor'" @remove="remove" @copyRow="copyRow" :title="$t('api_test.automation.customize_script')"
|
||||||
:title="$t('api_test.automation.customize_script')"
|
style-type="color: #7B4D12;background-color: #F1EEE9" :jsr223-processor="data" :node="node"/>
|
||||||
style-type="color: #7B4D12;background-color: #F1EEE9"
|
|
||||||
:jsr223-processor="data" :node="node"/>
|
|
||||||
<!--前置脚本-->
|
<!--前置脚本-->
|
||||||
<ms-jsr233-processor v-if="data.type==='JSR223PreProcessor'" @remove="remove" @copyRow="copyRow"
|
<ms-jsr233-processor v-if="data.type==='JSR223PreProcessor'" @remove="remove" @copyRow="copyRow" :title="$t('api_test.definition.request.pre_script')"
|
||||||
:title="$t('api_test.definition.request.pre_script')"
|
style-type="color: #B8741A;background-color: #F9F1EA" :jsr223-processor="data" :node="node"/>
|
||||||
style-type="color: #B8741A;background-color: #F9F1EA"
|
|
||||||
:jsr223-processor="data" :node="node"/>
|
|
||||||
<!--后置脚本-->
|
<!--后置脚本-->
|
||||||
<ms-jsr233-processor v-if="data.type==='JSR223PostProcessor'" @remove="remove" @copyRow="copyRow"
|
<ms-jsr233-processor v-if="data.type==='JSR223PostProcessor'" @remove="remove" @copyRow="copyRow" :title="$t('api_test.definition.request.post_script')"
|
||||||
:title="$t('api_test.definition.request.post_script')"
|
style-type="color: #783887;background-color: #F2ECF3" :jsr223-processor="data" :node="node"/>
|
||||||
style-type="color: #783887;background-color: #F2ECF3"
|
|
||||||
:jsr223-processor="data" :node="node"/>
|
|
||||||
<!--断言规则-->
|
<!--断言规则-->
|
||||||
<ms-api-assertions v-if="data.type==='Assertions'" @remove="remove" @copyRow="copyRow"
|
<ms-api-assertions v-if="data.type==='Assertions'" @remove="remove" @copyRow="copyRow" customizeStyle="margin-top: 0px" :assertions="data" :node="node"/>
|
||||||
customizeStyle="margin-top: 0px" :assertions="data" :node="node"/>
|
|
||||||
<!--提取规则-->
|
<!--提取规则-->
|
||||||
<ms-api-extract @remove="remove" @copyRow="copyRow" v-if="data.type==='Extract'"
|
<ms-api-extract @remove="remove" @copyRow="copyRow" v-if="data.type==='Extract'" customizeStyle="margin-top: 0px" :extract="data" :node="node"/>
|
||||||
customizeStyle="margin-top: 0px" :extract="data" :node="node"/>
|
|
||||||
<!--API 导入 -->
|
<!--API 导入 -->
|
||||||
<ms-api-component :request="data" :currentEnvironmentId="currentEnvironmentId" @remove="remove"
|
<ms-api-component :request="data" :currentEnvironmentId="currentEnvironmentId" @remove="remove" @copyRow="copyRow" v-if="data.type==='HTTPSamplerProxy'||data.type==='DubboSampler'||data.type==='JDBCSampler'||data.type==='TCPSampler'" :node="node"/>
|
||||||
@copyRow="copyRow"
|
|
||||||
v-if="data.type==='HTTPSamplerProxy'||data.type==='DubboSampler'||data.type==='JDBCSampler'||data.type==='TCPSampler'"
|
|
||||||
:node="node"/>
|
|
||||||
</template>
|
</template>
|
||||||
</span>
|
</span>
|
||||||
</el-tree>
|
</el-tree>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<!-- 按钮列表 -->
|
<!-- 按钮列表 -->
|
||||||
|
<div>
|
||||||
<el-col :span="3">
|
<el-col :span="3">
|
||||||
<vue-fab id="fab" mainBtnColor="#783887" size="small" :global-options="globalOptions"
|
<vue-fab id="fab" mainBtnColor="#783887" :click-auto-close="false">
|
||||||
:click-auto-close="false" v-outside-click="outsideClick">
|
|
||||||
<fab-item
|
<fab-item
|
||||||
v-for="(item, index) in buttons"
|
v-for="(item, index) in buttons"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
@ -209,30 +196,19 @@
|
||||||
@clickItem="item.click"/>
|
@clickItem="item.click"/>
|
||||||
</vue-fab>
|
</vue-fab>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
</div>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--接口列表-->
|
<!--接口列表-->
|
||||||
<el-drawer :visible.sync="apiListVisible" :destroy-on-close="true" direction="ltr" :withHeader="false"
|
<scenario-api-relevance @save="pushApiOrCase" ref="scenarioApiRelevance"/>
|
||||||
:modal="false" size="90%">
|
|
||||||
<ms-api-definition :visible="visibleRef" :currentRow="currentRow"/>
|
|
||||||
<el-button style="float: right;margin: 0px 20px 0px" type="primary" @click="pushApiOrCase('REF')">
|
|
||||||
{{ $t('api_test.scenario.reference') }}
|
|
||||||
</el-button>
|
|
||||||
<el-button style="float: right;" type="primary" @click="pushApiOrCase('Copy')">{{
|
|
||||||
$t('commons.copy')
|
|
||||||
}}
|
|
||||||
</el-button>
|
|
||||||
</el-drawer>
|
|
||||||
|
|
||||||
<!--自定义接口-->
|
<!--自定义接口-->
|
||||||
<el-drawer :visible.sync="customizeVisible" :destroy-on-close="true" direction="ltr" :withHeader="false"
|
<el-drawer :visible.sync="customizeVisible" :destroy-on-close="true" direction="ltr" :withHeader="false" :title="$t('api_test.automation.customize_req')" style="overflow: auto" :modal="false" size="90%">
|
||||||
:title="$t('api_test.automation.customize_req')" style="overflow: auto" :modal="false" size="90%">
|
|
||||||
<ms-api-customize :request="customizeRequest" @addCustomizeApi="addCustomizeApi"/>
|
<ms-api-customize :request="customizeRequest" @addCustomizeApi="addCustomizeApi"/>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
<!--场景导入 -->
|
<!--场景导入 -->
|
||||||
<el-drawer :visible.sync="scenarioVisible" :destroy-on-close="true" direction="ltr" :withHeader="false"
|
<el-drawer :visible.sync="scenarioVisible" :destroy-on-close="true" direction="ltr" :withHeader="false" :title="$t('api_test.automation.scenario_import')" style="overflow: auto" :modal="false" size="90%">
|
||||||
:title="$t('api_test.automation.scenario_import')" style="overflow: auto" :modal="false" size="90%">
|
|
||||||
<ms-import-api-scenario @addScenario="addScenario"/>
|
<ms-import-api-scenario @addScenario="addScenario"/>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
|
|
||||||
|
@ -243,14 +219,12 @@
|
||||||
<ms-run :debug="true" :environment="currentEnvironmentId" :reportId="reportId" :run-data="debugData"
|
<ms-run :debug="true" :environment="currentEnvironmentId" :reportId="reportId" :run-data="debugData"
|
||||||
@runRefresh="runRefresh" ref="runTest"/>
|
@runRefresh="runRefresh" ref="runTest"/>
|
||||||
<!-- 调试结果 -->
|
<!-- 调试结果 -->
|
||||||
<el-drawer :visible.sync="debugVisible" :destroy-on-close="true" direction="ltr" :withHeader="true" :modal="false"
|
<el-drawer :visible.sync="debugVisible" :destroy-on-close="true" direction="ltr" :withHeader="true" :modal="false" size="90%">
|
||||||
size="90%">
|
|
||||||
<ms-api-report-detail :report-id="reportId" :debug="true" :currentProjectId="projectId"/>
|
<ms-api-report-detail :report-id="reportId" :debug="true" :currentProjectId="projectId"/>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
|
|
||||||
<!--场景公共参数-->
|
<!--场景公共参数-->
|
||||||
<ms-scenario-parameters :currentScenario="currentScenario" @addParameters="addParameters"
|
<ms-scenario-parameters :currentScenario="currentScenario" @addParameters="addParameters" ref="scenarioParameters"/>
|
||||||
ref="scenarioParameters"/>
|
|
||||||
<!--外部导入-->
|
<!--外部导入-->
|
||||||
<api-import ref="apiImport" :saved="false" @refresh="apiImport"/>
|
<api-import ref="apiImport" :saved="false" @refresh="apiImport"/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -282,7 +256,7 @@ import MsScenarioParameters from "./ScenarioParameters";
|
||||||
import ApiImport from "../../definition/components/import/ApiImport";
|
import ApiImport from "../../definition/components/import/ApiImport";
|
||||||
import InputTag from 'vue-input-tag'
|
import InputTag from 'vue-input-tag'
|
||||||
import "@/common/css/material-icons.css"
|
import "@/common/css/material-icons.css"
|
||||||
import OutsideClick from "@/common/js/outside-click";
|
import ScenarioApiRelevance from "./api/ScenarioApiRelevance";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "EditApiScenario",
|
name: "EditApiScenario",
|
||||||
|
@ -291,6 +265,7 @@ export default {
|
||||||
currentScenario: {},
|
currentScenario: {},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
ScenarioApiRelevance,
|
||||||
ApiEnvironmentConfig,
|
ApiEnvironmentConfig,
|
||||||
MsScenarioParameters,
|
MsScenarioParameters,
|
||||||
MsApiReportDetail,
|
MsApiReportDetail,
|
||||||
|
@ -302,7 +277,6 @@ export default {
|
||||||
MsIfController,
|
MsIfController,
|
||||||
MsApiAssertions,
|
MsApiAssertions,
|
||||||
MsApiExtract,
|
MsApiExtract,
|
||||||
MsApiDefinition,
|
|
||||||
MsApiComponent,
|
MsApiComponent,
|
||||||
MsApiCustomize,
|
MsApiCustomize,
|
||||||
ApiImport,
|
ApiImport,
|
||||||
|
@ -346,11 +320,7 @@ export default {
|
||||||
debugData: {},
|
debugData: {},
|
||||||
reportId: "",
|
reportId: "",
|
||||||
projectId: "",
|
projectId: "",
|
||||||
visibleRef: "",
|
|
||||||
enableCookieShare: false,
|
enableCookieShare: false,
|
||||||
globalOptions: {
|
|
||||||
spacing: 30
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
@ -366,7 +336,6 @@ export default {
|
||||||
,
|
,
|
||||||
watch: {}
|
watch: {}
|
||||||
,
|
,
|
||||||
directives: {OutsideClick},
|
|
||||||
computed: {
|
computed: {
|
||||||
buttons() {
|
buttons() {
|
||||||
let buttons = [
|
let buttons = [
|
||||||
|
@ -474,7 +443,7 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getIdx(index) {
|
getIdx(index) {
|
||||||
return index - 0.33
|
return -1 * index - 2.25; // 为了向下展示菜单
|
||||||
},
|
},
|
||||||
showButton(...names) {
|
showButton(...names) {
|
||||||
for (const name of names) {
|
for (const name of names) {
|
||||||
|
@ -484,9 +453,6 @@ export default {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
outsideClick() {
|
|
||||||
this.operatingElements = ELEMENTS.get("ALL");
|
|
||||||
},
|
|
||||||
addComponent(type) {
|
addComponent(type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ELEMENT_TYPE.IfController:
|
case ELEMENT_TYPE.IfController:
|
||||||
|
@ -548,8 +514,7 @@ export default {
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
apiListImport() {
|
apiListImport() {
|
||||||
this.visibleRef = getUUID();
|
this.$refs.scenarioApiRelevance.open();
|
||||||
this.apiListVisible = true;
|
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
recursiveSorting(arr) {
|
recursiveSorting(arr) {
|
||||||
|
@ -629,20 +594,10 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
pushApiOrCase(referenced) {
|
pushApiOrCase(data, refType, referenced) {
|
||||||
if (this.currentRow.cases.length === 0 && this.currentRow.apis.length === 0) {
|
data.forEach(item => {
|
||||||
this.$warning(this.$t('api_test.automation.reference_info'));
|
this.setApiParameter(item, refType, referenced);
|
||||||
return;
|
});
|
||||||
}
|
|
||||||
this.currentRow.cases.forEach(item => {
|
|
||||||
this.setApiParameter(item, "CASE", referenced);
|
|
||||||
})
|
|
||||||
this.currentRow.apis.forEach(item => {
|
|
||||||
this.setApiParameter(item, "API", referenced);
|
|
||||||
})
|
|
||||||
this.apiListVisible = false;
|
|
||||||
this.currentRow.cases = [];
|
|
||||||
this.currentRow.apis = [];
|
|
||||||
this.sort();
|
this.sort();
|
||||||
this.reload();
|
this.reload();
|
||||||
}
|
}
|
||||||
|
@ -738,7 +693,8 @@ export default {
|
||||||
allowDrop(draggingNode, dropNode, dropType) {
|
allowDrop(draggingNode, dropNode, dropType) {
|
||||||
if (dropType != "inner") {
|
if (dropType != "inner") {
|
||||||
return true;
|
return true;
|
||||||
} else if (dropType === "inner" && dropNode.data.referenced != 'REF' && dropNode.data.referenced != 'Deleted'
|
}
|
||||||
|
else if (dropType === "inner" && dropNode.data.referenced != 'REF' && dropNode.data.referenced != 'Deleted'
|
||||||
&& ELEMENTS.get(dropNode.data.type).indexOf(draggingNode.data.type) != -1) {
|
&& ELEMENTS.get(dropNode.data.type).indexOf(draggingNode.data.type) != -1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -883,14 +839,8 @@ export default {
|
||||||
this.currentScenario.modulePath = this.getPath(this.currentScenario.apiScenarioModuleId);
|
this.currentScenario.modulePath = this.getPath(this.currentScenario.apiScenarioModuleId);
|
||||||
// 构建一个场景对象 方便引用处理
|
// 构建一个场景对象 方便引用处理
|
||||||
let scenario = {
|
let scenario = {
|
||||||
id: this.currentScenario.id,
|
id: this.currentScenario.id, enableCookieShare: this.enableCookieShare, name: this.currentScenario.name, variables: this.currentScenario.variables,
|
||||||
enableCookieShare: this.enableCookieShare,
|
type: "scenario", referenced: 'Created', environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition
|
||||||
name: this.currentScenario.name,
|
|
||||||
variables: this.currentScenario.variables,
|
|
||||||
type: "scenario",
|
|
||||||
referenced: 'Created',
|
|
||||||
environmentId: this.currentEnvironmentId,
|
|
||||||
hashTree: this.scenarioDefinition
|
|
||||||
};
|
};
|
||||||
this.currentScenario.scenarioDefinition = scenario;
|
this.currentScenario.scenarioDefinition = scenario;
|
||||||
if (this.currentScenario.tags instanceof Array) {
|
if (this.currentScenario.tags instanceof Array) {
|
||||||
|
@ -931,11 +881,6 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.card-content {
|
|
||||||
height: calc(100vh - 196px);
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-scenario-input {
|
.ms-scenario-input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -950,9 +895,10 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.ms-debug-div {
|
.ms-debug-div {
|
||||||
|
margin-left: 20px;
|
||||||
border: 1px #DCDFE6 solid;
|
border: 1px #DCDFE6 solid;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
margin-right: 20px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ms-scenario-button {
|
.ms-scenario-button {
|
||||||
|
@ -985,6 +931,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
#fab {
|
#fab {
|
||||||
|
bottom: unset;
|
||||||
right: 90px;
|
right: 90px;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog class="api-relevance" :title="$t('test_track.plan_view.relevance_test_case')"
|
||||||
|
:visible.sync="dialogVisible"
|
||||||
|
width="60%"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
top="50px">
|
||||||
|
|
||||||
|
<ms-container>
|
||||||
|
<ms-aside-container :enable-aside-hidden="false">
|
||||||
|
<ms-api-module
|
||||||
|
@nodeSelectEvent="nodeChange"
|
||||||
|
@protocolChange="handleProtocolChange"
|
||||||
|
@refreshTable="refresh"
|
||||||
|
@setModuleOptions="setModuleOptions"
|
||||||
|
:is-read-only="true"
|
||||||
|
ref="nodeTree"/>
|
||||||
|
</ms-aside-container>
|
||||||
|
|
||||||
|
<ms-main-container>
|
||||||
|
<scenario-relevance-api-list
|
||||||
|
v-if="isApiListEnable"
|
||||||
|
:current-protocol="currentProtocol"
|
||||||
|
:select-node-ids="selectNodeIds"
|
||||||
|
:is-api-list-enable="isApiListEnable"
|
||||||
|
@isApiListEnableChange="isApiListEnableChange"
|
||||||
|
ref="apiList"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<scenario-relevance-case-list
|
||||||
|
v-if="!isApiListEnable"
|
||||||
|
:current-protocol="currentProtocol"
|
||||||
|
:select-node-ids="selectNodeIds"
|
||||||
|
:is-api-list-enable="isApiListEnable"
|
||||||
|
@isApiListEnableChange="isApiListEnableChange"
|
||||||
|
ref="apiCaseList"/>
|
||||||
|
</ms-main-container>
|
||||||
|
</ms-container>
|
||||||
|
|
||||||
|
<template v-slot:footer>
|
||||||
|
<el-button type="primary" @click="copy" @keydown.enter.native.prevent>复制</el-button>
|
||||||
|
<el-button v-if="!isApiListEnable" type="primary" @click="reference" @keydown.enter.native.prevent>引用</el-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ScenarioRelevanceCaseList from "./ScenarioRelevanceCaseList";
|
||||||
|
import MsApiModule from "../../../definition/components/module/ApiModule";
|
||||||
|
import MsContainer from "../../../../common/components/MsContainer";
|
||||||
|
import MsAsideContainer from "../../../../common/components/MsAsideContainer";
|
||||||
|
import MsMainContainer from "../../../../common/components/MsMainContainer";
|
||||||
|
import ScenarioRelevanceApiList from "./ScenarioRelevanceApiList";
|
||||||
|
export default {
|
||||||
|
name: "ScenarioApiRelevance",
|
||||||
|
components: {
|
||||||
|
ScenarioRelevanceApiList,
|
||||||
|
MsMainContainer, MsAsideContainer, MsContainer, MsApiModule, ScenarioRelevanceCaseList},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dialogVisible: false,
|
||||||
|
result: {},
|
||||||
|
currentProtocol: null,
|
||||||
|
selectNodeIds: [],
|
||||||
|
moduleOptions: {},
|
||||||
|
isApiListEnable: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
reference() {
|
||||||
|
this.save('REF');
|
||||||
|
},
|
||||||
|
copy() {
|
||||||
|
this.save('Copy');
|
||||||
|
},
|
||||||
|
save(reference) {
|
||||||
|
if (this.isApiListEnable) {
|
||||||
|
this.$emit('save', this.$refs.apiList.selectRows, 'API', reference);
|
||||||
|
this.close();
|
||||||
|
} else {
|
||||||
|
let apiCases = this.$refs.apiCaseList.selectRows;
|
||||||
|
let ids = Array.from(apiCases).map(row => row.id);
|
||||||
|
this.result = this.$post("/api/testcase/get/request", {ids: ids}, (response) => {
|
||||||
|
apiCases.forEach((item) => {
|
||||||
|
item.request = response.data[item.id];
|
||||||
|
});
|
||||||
|
this.$emit('save', apiCases, 'CASE', reference);
|
||||||
|
this.close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
this.refresh();
|
||||||
|
this.dialogVisible = false;
|
||||||
|
},
|
||||||
|
open() {
|
||||||
|
this.dialogVisible = true;
|
||||||
|
},
|
||||||
|
isApiListEnableChange(data) {
|
||||||
|
this.isApiListEnable = data;
|
||||||
|
},
|
||||||
|
nodeChange(node, nodeIds, pNodes) {
|
||||||
|
this.selectNodeIds = nodeIds;
|
||||||
|
},
|
||||||
|
handleProtocolChange(protocol) {
|
||||||
|
this.currentProtocol = protocol;
|
||||||
|
},
|
||||||
|
setModuleOptions(data) {
|
||||||
|
this.moduleOptions = data;
|
||||||
|
},
|
||||||
|
|
||||||
|
saveCaseRelevance() {
|
||||||
|
|
||||||
|
let param = {};
|
||||||
|
let url = '';
|
||||||
|
let environmentId = undefined;
|
||||||
|
let selectIds = [];
|
||||||
|
if (this.isApiListEnable) {
|
||||||
|
url = '/api/definition/relevance';
|
||||||
|
environmentId = this.$refs.apiList.environmentId;
|
||||||
|
selectIds = Array.from(this.$refs.apiList.selectRows).map(row => row.id);
|
||||||
|
} else {
|
||||||
|
url = '/api/testcase/relevance';
|
||||||
|
environmentId = this.$refs.apiCaseList.environmentId;
|
||||||
|
selectIds = Array.from(this.$refs.apiCaseList.selectRows).map(row => row.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!environmentId) {
|
||||||
|
this.$warning(this.$t('api_test.environment.select_environment'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
param.planId = this.planId;
|
||||||
|
param.selectIds = selectIds;
|
||||||
|
param.environmentId = environmentId;
|
||||||
|
this.result = this.$post(url, param, () => {
|
||||||
|
this.$success(this.$t('commons.save_success'));
|
||||||
|
this.$emit('refresh');
|
||||||
|
this.refresh();
|
||||||
|
this.$refs.baseRelevance.close();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
refresh() {
|
||||||
|
if (this.isApiListEnable) {
|
||||||
|
this.$refs.apiList.initTable();
|
||||||
|
} else {
|
||||||
|
this.$refs.apiCaseList.initTable();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.ms-aside-container {
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-relevance >>> .el-dialog__body {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,248 @@
|
||||||
|
<template>
|
||||||
|
<api-list-container
|
||||||
|
:is-api-list-enable="isApiListEnable"
|
||||||
|
@isApiListEnableChange="isApiListEnableChange">
|
||||||
|
|
||||||
|
<el-input placeholder="搜索" @blur="initTable" class="search-input" size="small" @keyup.enter.native="initTable" v-model="condition.name"/>
|
||||||
|
|
||||||
|
<el-table v-loading="result.loading"
|
||||||
|
border
|
||||||
|
:data="tableData" row-key="id" class="test-content adjust-table"
|
||||||
|
@select-all="handleSelectAll"
|
||||||
|
@select="handleSelect">
|
||||||
|
<el-table-column type="selection"/>
|
||||||
|
|
||||||
|
<el-table-column prop="name" :label="$t('api_test.definition.api_name')" show-overflow-tooltip/>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
prop="status"
|
||||||
|
column-key="api_status"
|
||||||
|
:label="$t('api_test.definition.api_status')"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<ms-tag v-if="scope.row.status == 'Prepare'" type="info" effect="plain" :content="$t('test_track.plan.plan_status_prepare')"/>
|
||||||
|
<ms-tag v-if="scope.row.status == 'Underway'" type="warning" effect="plain" :content="$t('test_track.plan.plan_status_running')"/>
|
||||||
|
<ms-tag v-if="scope.row.status == 'Completed'" type="success" effect="plain" :content="$t('test_track.plan.plan_status_completed')"/>
|
||||||
|
<ms-tag v-if="scope.row.status == 'Trash'" type="danger" effect="plain" content="废弃"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
prop="method"
|
||||||
|
:label="$t('api_test.definition.api_type')"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
<template v-slot:default="scope" class="request-method">
|
||||||
|
<el-tag size="mini" :style="{'background-color': getColor(scope.row.method), border: getColor(true, scope.row.method)}" class="api-el-tag">
|
||||||
|
{{ scope.row.method}}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
prop="path"
|
||||||
|
:label="$t('api_test.definition.api_path')"
|
||||||
|
show-overflow-tooltip/>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
prop="userName"
|
||||||
|
:label="$t('api_test.definition.api_principal')"
|
||||||
|
show-overflow-tooltip/>
|
||||||
|
|
||||||
|
<el-table-column width="160" :label="$t('api_test.definition.api_last_time')" prop="updateTime">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
prop="caseTotal"
|
||||||
|
:label="$t('api_test.definition.api_case_number')"
|
||||||
|
show-overflow-tooltip/>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
prop="caseStatus"
|
||||||
|
:label="$t('api_test.definition.api_case_status')"
|
||||||
|
show-overflow-tooltip/>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
prop="casePassingRate"
|
||||||
|
:label="$t('api_test.definition.api_case_passing_rate')"
|
||||||
|
show-overflow-tooltip/>
|
||||||
|
</el-table>
|
||||||
|
<ms-table-pagination :change="initTable" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||||
|
:total="total"/>
|
||||||
|
</api-list-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import MsTableOperator from "../../../../common/components/MsTableOperator";
|
||||||
|
import MsTableOperatorButton from "../../../../common/components/MsTableOperatorButton";
|
||||||
|
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
|
||||||
|
import MsTablePagination from "../../../../common/pagination/TablePagination";
|
||||||
|
import MsTag from "../../../../common/components/MsTag";
|
||||||
|
import MsBottomContainer from "../../../definition/components/BottomContainer";
|
||||||
|
import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn";
|
||||||
|
import MsBatchEdit from "../../../definition/components/basis/BatchEdit";
|
||||||
|
import {API_METHOD_COLOUR, CASE_PRIORITY} from "../../../definition/model/JsonData";
|
||||||
|
import {getCurrentProjectID} from "@/common/js/utils";
|
||||||
|
import ApiListContainer from "../../../definition/components/list/ApiListContainer";
|
||||||
|
import PriorityTableItem from "../../../../track/common/tableItems/planview/PriorityTableItem";
|
||||||
|
import {_filter, _sort} from "../../../../../../common/js/utils";
|
||||||
|
import {_handleSelect, _handleSelectAll} from "../../../../../../common/js/tableUtils";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "ScenarioRelevanceApiList",
|
||||||
|
components: {
|
||||||
|
PriorityTableItem,
|
||||||
|
ApiListContainer,
|
||||||
|
MsTableOperatorButton,
|
||||||
|
MsTableOperator,
|
||||||
|
MsTablePagination,
|
||||||
|
MsTag,
|
||||||
|
MsBottomContainer,
|
||||||
|
ShowMoreBtn,
|
||||||
|
MsBatchEdit
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
condition: {},
|
||||||
|
selectCase: {},
|
||||||
|
result: {},
|
||||||
|
moduleId: "",
|
||||||
|
deletePath: "/test/case/delete",
|
||||||
|
selectRows: new Set(),
|
||||||
|
typeArr: [
|
||||||
|
{id: 'priority', name: this.$t('test_track.case.priority')},
|
||||||
|
],
|
||||||
|
priorityFilters: [
|
||||||
|
{text: 'P0', value: 'P0'},
|
||||||
|
{text: 'P1', value: 'P1'},
|
||||||
|
{text: 'P2', value: 'P2'},
|
||||||
|
{text: 'P3', value: 'P3'}
|
||||||
|
],
|
||||||
|
valueArr: {
|
||||||
|
priority: CASE_PRIORITY,
|
||||||
|
},
|
||||||
|
methodColorMap: new Map(API_METHOD_COLOUR),
|
||||||
|
tableData: [],
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
currentProtocol: String,
|
||||||
|
selectNodeIds: Array,
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
isApiListEnable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
isCaseRelevance: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
relevanceProjectId: String,
|
||||||
|
planId: String
|
||||||
|
},
|
||||||
|
created: function () {
|
||||||
|
this.initTable();
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
selectNodeIds() {
|
||||||
|
this.initTable();
|
||||||
|
},
|
||||||
|
currentProtocol() {
|
||||||
|
this.initTable();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isApiListEnableChange(data) {
|
||||||
|
this.$emit('isApiListEnableChange', data);
|
||||||
|
},
|
||||||
|
initTable() {
|
||||||
|
this.selectRows = new Set();
|
||||||
|
this.condition.filters = ["Prepare", "Underway", "Completed"];
|
||||||
|
this.condition.moduleIds = this.selectNodeIds;
|
||||||
|
if (this.trashEnable) {
|
||||||
|
this.condition.filters = ["Trash"];
|
||||||
|
this.condition.moduleIds = [];
|
||||||
|
}
|
||||||
|
if (this.projectId != null) {
|
||||||
|
this.condition.projectId = this.projectId;
|
||||||
|
}
|
||||||
|
if (this.currentProtocol != null) {
|
||||||
|
this.condition.protocol = this.currentProtocol;
|
||||||
|
}
|
||||||
|
this.result = this.$post("/api/definition/list/" + this.currentPage + "/" + this.pageSize, this.condition, response => {
|
||||||
|
this.total = response.data.itemCount;
|
||||||
|
this.tableData = response.data.listObject;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSelect(selection, row) {
|
||||||
|
_handleSelect(this, selection, row, this.selectRows);
|
||||||
|
},
|
||||||
|
showExecResult(row) {
|
||||||
|
this.visible = false;
|
||||||
|
this.$emit('showExecResult', row);
|
||||||
|
},
|
||||||
|
filter(filters) {
|
||||||
|
_filter(filters, this.condition);
|
||||||
|
this.initTable();
|
||||||
|
},
|
||||||
|
sort(column) {
|
||||||
|
// 每次只对一个字段排序
|
||||||
|
if (this.condition.orders) {
|
||||||
|
this.condition.orders = [];
|
||||||
|
}
|
||||||
|
_sort(column, this.condition);
|
||||||
|
this.initTable();
|
||||||
|
},
|
||||||
|
handleSelectAll(selection) {
|
||||||
|
_handleSelectAll(this, selection, this.tableData, this.selectRows);
|
||||||
|
},
|
||||||
|
buildPagePath(path) {
|
||||||
|
return path + "/" + this.currentPage + "/" + this.pageSize;
|
||||||
|
},
|
||||||
|
getColor(method) {
|
||||||
|
return this.methodColorMap.get(method);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.operate-button > div {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request-method {
|
||||||
|
padding: 0 5px;
|
||||||
|
color: #1E90FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-el-tag {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
float: right;
|
||||||
|
width: 300px;
|
||||||
|
/*margin-bottom: 20px;*/
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,239 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<api-list-container
|
||||||
|
:is-api-list-enable="isApiListEnable"
|
||||||
|
@isApiListEnableChange="isApiListEnableChange">
|
||||||
|
|
||||||
|
<el-input placeholder="搜索" @blur="initTable" @keyup.enter.native="initTable" class="search-input" size="small" v-model="condition.name"/>
|
||||||
|
|
||||||
|
<el-table v-loading="result.loading"
|
||||||
|
border
|
||||||
|
:data="tableData" row-key="id" class="test-content adjust-table"
|
||||||
|
@select-all="handleSelectAll"
|
||||||
|
@filter-change="filter"
|
||||||
|
@sort-change="sort"
|
||||||
|
@select="handleSelect">
|
||||||
|
<el-table-column type="selection"/>
|
||||||
|
|
||||||
|
<el-table-column prop="name" :label="$t('api_test.definition.api_name')" show-overflow-tooltip/>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
prop="priority"
|
||||||
|
:filters="priorityFilters"
|
||||||
|
column-key="priority"
|
||||||
|
:label="$t('test_track.case.priority')"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<priority-table-item :value="scope.row.priority"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
prop="path"
|
||||||
|
:label="$t('api_test.definition.api_path')"
|
||||||
|
show-overflow-tooltip/>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
prop="createUser"
|
||||||
|
:label="'创建人'"
|
||||||
|
show-overflow-tooltip/>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
sortable="custom"
|
||||||
|
width="160"
|
||||||
|
:label="$t('api_test.definition.api_last_time')"
|
||||||
|
prop="updateTime">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
</el-table>
|
||||||
|
<ms-table-pagination :change="initTable" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||||
|
:total="total"/>
|
||||||
|
</api-list-container>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import MsTableOperator from "../../../../common/components/MsTableOperator";
|
||||||
|
import MsTableOperatorButton from "../../../../common/components/MsTableOperatorButton";
|
||||||
|
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
|
||||||
|
import MsTablePagination from "../../../../common/pagination/TablePagination";
|
||||||
|
import MsTag from "../../../../common/components/MsTag";
|
||||||
|
import MsBottomContainer from "../../../definition/components/BottomContainer";
|
||||||
|
import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn";
|
||||||
|
import MsBatchEdit from "../../../definition/components/basis/BatchEdit";
|
||||||
|
import {API_METHOD_COLOUR, CASE_PRIORITY} from "../../../definition/model/JsonData";
|
||||||
|
import {getCurrentProjectID} from "@/common/js/utils";
|
||||||
|
import ApiListContainer from "../../../definition/components/list/ApiListContainer";
|
||||||
|
import PriorityTableItem from "../../../../track/common/tableItems/planview/PriorityTableItem";
|
||||||
|
import {_filter, _sort} from "../../../../../../common/js/utils";
|
||||||
|
import {_handleSelect, _handleSelectAll} from "../../../../../../common/js/tableUtils";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "ScenarioRelevanceCaseList",
|
||||||
|
components: {
|
||||||
|
PriorityTableItem,
|
||||||
|
ApiListContainer,
|
||||||
|
MsTableOperatorButton,
|
||||||
|
MsTableOperator,
|
||||||
|
MsTablePagination,
|
||||||
|
MsTag,
|
||||||
|
MsBottomContainer,
|
||||||
|
ShowMoreBtn,
|
||||||
|
MsBatchEdit
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
condition: {},
|
||||||
|
selectCase: {},
|
||||||
|
result: {},
|
||||||
|
moduleId: "",
|
||||||
|
selectRows: new Set(),
|
||||||
|
typeArr: [
|
||||||
|
{id: 'priority', name: this.$t('test_track.case.priority')},
|
||||||
|
],
|
||||||
|
priorityFilters: [
|
||||||
|
{text: 'P0', value: 'P0'},
|
||||||
|
{text: 'P1', value: 'P1'},
|
||||||
|
{text: 'P2', value: 'P2'},
|
||||||
|
{text: 'P3', value: 'P3'}
|
||||||
|
],
|
||||||
|
valueArr: {
|
||||||
|
priority: CASE_PRIORITY,
|
||||||
|
},
|
||||||
|
methodColorMap: new Map(API_METHOD_COLOUR),
|
||||||
|
tableData: [],
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
currentProtocol: String,
|
||||||
|
selectNodeIds: Array,
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
isApiListEnable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
isCaseRelevance: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
relevanceProjectId: String,
|
||||||
|
planId: String
|
||||||
|
},
|
||||||
|
created: function () {
|
||||||
|
this.initTable();
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
selectNodeIds() {
|
||||||
|
this.initTable();
|
||||||
|
},
|
||||||
|
currentProtocol() {
|
||||||
|
this.initTable();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isApiListEnableChange(data) {
|
||||||
|
this.$emit('isApiListEnableChange', data);
|
||||||
|
},
|
||||||
|
initTable() {
|
||||||
|
this.selectRows = new Set();
|
||||||
|
this.condition.status = "";
|
||||||
|
this.condition.moduleIds = this.selectNodeIds;
|
||||||
|
if (this.currentProtocol != null) {
|
||||||
|
this.condition.protocol = this.currentProtocol;
|
||||||
|
}
|
||||||
|
this.condition.projectId = getCurrentProjectID();
|
||||||
|
|
||||||
|
this.result = this.$post("/api/testcase/list/" + this.currentPage + "/" + this.pageSize, this.condition, response => {
|
||||||
|
this.total = response.data.itemCount;
|
||||||
|
this.tableData = response.data.listObject;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSelect(selection, row) {
|
||||||
|
_handleSelect(this, selection, row, this.selectRows);
|
||||||
|
},
|
||||||
|
showExecResult(row) {
|
||||||
|
this.visible = false;
|
||||||
|
this.$emit('showExecResult', row);
|
||||||
|
},
|
||||||
|
filter(filters) {
|
||||||
|
_filter(filters, this.condition);
|
||||||
|
this.initTable();
|
||||||
|
},
|
||||||
|
sort(column) {
|
||||||
|
// 每次只对一个字段排序
|
||||||
|
if (this.condition.orders) {
|
||||||
|
this.condition.orders = [];
|
||||||
|
}
|
||||||
|
_sort(column, this.condition);
|
||||||
|
this.initTable();
|
||||||
|
},
|
||||||
|
handleSelectAll(selection) {
|
||||||
|
_handleSelectAll(this, selection, this.tableData, this.selectRows);
|
||||||
|
},
|
||||||
|
buildPagePath(path) {
|
||||||
|
return path + "/" + this.currentPage + "/" + this.pageSize;
|
||||||
|
},
|
||||||
|
handleTestCase(testCase) {
|
||||||
|
this.$get('/api/definition/get/' + testCase.apiDefinitionId, (response) => {
|
||||||
|
let api = response.data;
|
||||||
|
let selectApi = api;
|
||||||
|
let request = {};
|
||||||
|
if (Object.prototype.toString.call(api.request).match(/\[object (\w+)\]/)[1].toLowerCase() === 'object') {
|
||||||
|
request = api.request;
|
||||||
|
} else {
|
||||||
|
request = JSON.parse(api.request);
|
||||||
|
}
|
||||||
|
if (!request.hashTree) {
|
||||||
|
request.hashTree = [];
|
||||||
|
}
|
||||||
|
selectApi.url = request.path;
|
||||||
|
this.$refs.caseList.open(selectApi, testCase.id);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.operate-button > div {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request-method {
|
||||||
|
padding: 0 5px;
|
||||||
|
color: #1E90FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-el-tag {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
float: right;
|
||||||
|
width: 300px;
|
||||||
|
/*margin-bottom: 20px;*/
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -273,7 +273,7 @@
|
||||||
} else if (this.isRelevanceModel) {
|
} else if (this.isRelevanceModel) {
|
||||||
return '/api/testcase/delete/' + apiCase.id;
|
return '/api/testcase/delete/' + apiCase.id;
|
||||||
} else {
|
} else {
|
||||||
return '/api/testcase/delete/' + +apiCase.id;
|
return '/api/testcase/delete/' + apiCase.id;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// getMaintainerOptions() {
|
// getMaintainerOptions() {
|
||||||
|
|
Loading…
Reference in New Issue