From 933b508da0416c7aace974900aa194e05fb2fd7b Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Mon, 29 Mar 2021 16:23:04 +0800 Subject: [PATCH 01/18] =?UTF-8?q?fix(=E5=9C=BA=E6=99=AF=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E4=BF=AE=E5=A4=8D=E5=8D=87=E7=BA=A7=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/HistoricalDataUpgradeService.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java b/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java index a9e25176e5..ea15c56062 100644 --- a/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java +++ b/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java @@ -76,12 +76,17 @@ public class HistoricalDataUpgradeService { return scenario; } - private MsScenario createScenario(Scenario oldScenario) { + private MsScenario createScenario(Scenario oldScenario, String projectId) { MsScenario scenario = new MsScenario(); scenario.setOldVariables(oldScenario.getVariables()); scenario.setName(oldScenario.getName()); scenario.setEnableCookieShare(oldScenario.isEnableCookieShare()); scenario.setEnvironmentId(oldScenario.getEnvironmentId()); + if (StringUtils.isNotEmpty(oldScenario.getEnvironmentId())) { + HashMap envMap = new HashMap<>(); + envMap.put(projectId, oldScenario.getEnvironmentId()); + scenario.setEnvironmentMap(envMap); + } scenario.setReferenced("Upgrade"); scenario.setId(oldScenario.getId()); scenario.setResourceId(UUID.randomUUID().toString()); @@ -397,6 +402,7 @@ public class HistoricalDataUpgradeService { MsScenario scenarioTest = createScenarioByTest(test); LinkedList listSteps = new LinkedList<>(); List scenarios = JSON.parseArray(test.getScenarioDefinition(), Scenario.class); + String envId = null; if (CollectionUtils.isNotEmpty(scenarios)) { // 批量处理 for (Scenario scenario : scenarios) { @@ -405,7 +411,7 @@ public class HistoricalDataUpgradeService { } scenario.setId(test.getId() + "=" + scenario.getId()); scenario.setName(test.getName() + "_" + scenario.getName()); - MsScenario scenario1 = createScenario(scenario); + MsScenario scenario1 = createScenario(scenario, saveHistoricalDataUpgrade.getProjectId()); String scenarioDefinition = JSON.toJSONString(scenario1); num++; createApiScenarioWithBLOBs(saveHistoricalDataUpgrade, scenario.getId(), scenario.getName(), scenario.getRequests().size(), scenarioDefinition, mapper, num); @@ -417,10 +423,20 @@ public class HistoricalDataUpgradeService { step.setResourceId(UUID.randomUUID().toString()); step.setReferenced("REF"); listSteps.add(step); + if (StringUtils.isNotEmpty(scenario.getEnvironmentId())) { + envId = scenario.getEnvironmentId(); + } } } num++; scenarioTest.setHashTree(listSteps); + if (StringUtils.isNotEmpty(envId)) { + HashMap envMap = new HashMap<>(); + envMap.put(saveHistoricalDataUpgrade.getProjectId(), envId); + scenarioTest.setEnvironmentMap(envMap); + scenarioTest.setEnvironmentId(envId); + } + String scenarioDefinition = JSON.toJSONString(scenarioTest); createApiScenarioWithBLOBs(saveHistoricalDataUpgrade, scenarioTest.getId(), scenarioTest.getName(), listSteps.size(), scenarioDefinition, mapper, num); } From 52b07097534491ac283a39279e405d0a67f29130 Mon Sep 17 00:00:00 2001 From: wenyann <64353056+wenyann@users.noreply.github.com> Date: Mon, 29 Mar 2021 16:43:52 +0800 Subject: [PATCH 02/18] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E8=A1=A8=E5=A4=B4?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/business/components/common/head/HeaderCustom.vue | 4 ++++ frontend/src/business/components/common/model/JsonData.js | 7 +++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/frontend/src/business/components/common/head/HeaderCustom.vue b/frontend/src/business/components/common/head/HeaderCustom.vue index 99bb68f0ae..bd8f9ad28a 100644 --- a/frontend/src/business/components/common/head/HeaderCustom.vue +++ b/frontend/src/business/components/common/head/HeaderCustom.vue @@ -52,6 +52,10 @@ export default { this.defaultCheckedKeys.push(i.id) } ) + if(this.type==='api_list'||this.type==='api_case_list'||this.type==='api_scenario_list'||this.type==='test_plan_function_test_case' + ||this.type==='test_plan_api_case'||this.type==='test_plan_load_case'||this.type==='test_plan_scenario_case'){ + this.fieldSelected=items + } }, saveHeader() { let param = { diff --git a/frontend/src/business/components/common/model/JsonData.js b/frontend/src/business/components/common/model/JsonData.js index 57c5bc5b9a..f064c52d91 100644 --- a/frontend/src/business/components/common/model/JsonData.js +++ b/frontend/src/business/components/common/model/JsonData.js @@ -81,7 +81,6 @@ export const Test_Case_Review_Case_List = [ {id: 'name', label: i18n.t('commons.name')}, {id: 'priority', label: i18n.t('test_track.case.priority')}, {id: 'type', label: i18n.t('test_track.case.type')}, - {id: 'method', label: i18n.t('test_track.case.method')}, {id: 'nodePath', label: i18n.t('test_track.case.module')}, {id: 'projectName', label: i18n.t('test_track.review.review_project')}, {id: 'reviewerName', label: i18n.t('test_track.review.reviewer')}, @@ -107,7 +106,7 @@ export const Test_Plan_Function_Test_Case = [ //测试计划-api用例 export const Test_Plan_Api_Case = [ {id: 'num', label: i18n.t('commons.id')}, - {id: 'name', label: i18n.t('commons.name')}, + {id: 'name', label: i18n.t('api_test.definition.api_name')}, {id: 'priority', label: i18n.t('test_track.case.priority')}, {id: 'path', label: i18n.t('api_test.definition.api_path')}, {id: 'createUser', label: '创建人'}, @@ -124,12 +123,12 @@ export const Test_Plan_Load_Case = [ {id: 'createTime', label: i18n.t('commons.create_time')}, {id: 'status', label: i18n.t('commons.status')}, {id: 'caseStatus', label: i18n.t('test_track.plan.load_case.execution_status')}, - {id: 'loadReportId', label: i18n.t('test_track.plan.load_case.view_report')}, + {id: 'loadReportId', label: i18n.t('test_track.plan.load_case.report')}, ] //测试计划-场景用例 export const Test_Plan_Scenario_Case = [ {id: 'num', label: i18n.t('commons.id')}, - {id: 'name', label: i18n.t('commons.name')}, + {id: 'name', label: i18n.t('api_test.automation.scenario_name')}, {id: 'level', label: i18n.t('api_test.automation.case_level')}, {id: 'tagNames', label: i18n.t('api_test.automation.tag')}, {id: 'userId', label: i18n.t('api_test.automation.creator')}, From 809142af53fc6d07de5d88c953755fb51978c1fa Mon Sep 17 00:00:00 2001 From: "song.tianyang" Date: Mon, 29 Mar 2021 16:50:33 +0800 Subject: [PATCH 03/18] =?UTF-8?q?fix:=20=E5=9C=BA=E6=99=AF=E5=85=B3?= =?UTF-8?q?=E8=81=94ESB=E6=8E=A5=E5=8F=A3=E6=97=B6=E5=A4=8D=E5=88=B6?= =?UTF-8?q?=E7=9A=84ESB=E6=A1=88=E4=BE=8B=E6=97=A0=E6=B3=95=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E6=A0=91=E7=BB=93=E6=9E=84=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复场景关联ESB接口时复制的ESB案例无法构建树结构数据 --- .../api/dto/automation/EsbDataStruct.java | 4 ++ .../request/sampler/MsTCPSampler.java | 7 +++ .../api/service/ApiAutomationService.java | 8 +++ .../api/service/EsbApiParamService.java | 53 +++++++++++++++++++ .../automation/scenario/api/ApiRelevance.vue | 36 ++++++------- 5 files changed, 90 insertions(+), 18 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/dto/automation/EsbDataStruct.java b/backend/src/main/java/io/metersphere/api/dto/automation/EsbDataStruct.java index 49f30fdfcd..c15ddce336 100644 --- a/backend/src/main/java/io/metersphere/api/dto/automation/EsbDataStruct.java +++ b/backend/src/main/java/io/metersphere/api/dto/automation/EsbDataStruct.java @@ -29,6 +29,7 @@ public class EsbDataStruct { private boolean required; private String description; private List children; + private String status = ""; public void init(){ this.uuid = UUID.randomUUID().toString(); @@ -127,6 +128,9 @@ public class EsbDataStruct { if (element != null) { if (this.children == null || this.children.isEmpty()) { + if(this.value == null ){ + this.value = ""; + } element.addText(this.value); } else { for (EsbDataStruct child : children) { diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsTCPSampler.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsTCPSampler.java index d1b8fe7b55..4ae022bfec 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsTCPSampler.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsTCPSampler.java @@ -2,6 +2,7 @@ package io.metersphere.api.dto.definition.request.sampler; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; +import io.metersphere.api.dto.automation.EsbDataStruct; import io.metersphere.api.dto.definition.request.MsTestElement; import io.metersphere.api.dto.definition.request.ParameterConfig; import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor; @@ -70,6 +71,12 @@ public class MsTCPSampler extends MsTestElement { @JSONField(ordinal = 39) private String projectId; + /** + * 新加两个参数,场景保存/修改时需要的参数。不会传递JMeter,只是用于最后的保留。 + */ + private List esbDataStruct; + private List backEsbDataStruct; + @Override public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { // 非导出操作,且不是启用状态则跳过执行 diff --git a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java index 3fdb6bd2a2..36e51b9489 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -90,6 +90,8 @@ public class ApiAutomationService { @Resource @Lazy private TestPlanScenarioCaseService testPlanScenarioCaseService; + @Resource + private EsbApiParamService esbApiParamService; public List list(ApiScenarioRequest request) { request = this.initRequest(request, true, true); @@ -184,6 +186,9 @@ public class ApiAutomationService { scenario.setCreateTime(System.currentTimeMillis()); scenario.setNum(getNextNum(request.getProjectId())); + //检查场景的请求步骤。如果含有ESB请求步骤的话,要做参数计算处理。 + esbApiParamService.checkScenarioRequests(request); + apiScenarioMapper.insert(scenario); List bodyUploadIds = request.getBodyUploadIds(); @@ -205,6 +210,9 @@ public class ApiAutomationService { List bodyUploadIds = request.getBodyUploadIds(); FileUtils.createBodyFiles(bodyUploadIds, bodyFiles); + //检查场景的请求步骤。如果含有ESB请求步骤的话,要做参数计算处理。 + esbApiParamService.checkScenarioRequests(request); + final ApiScenarioWithBLOBs scenario = buildSaveScenario(request); apiScenarioMapper.updateByPrimaryKeySelective(scenario); extScheduleMapper.updateNameByResourceID(request.getId(), request.getName());// 修改场景name,同步到修改首页定时任务 diff --git a/backend/src/main/java/io/metersphere/api/service/EsbApiParamService.java b/backend/src/main/java/io/metersphere/api/service/EsbApiParamService.java index 06ae6dd45f..60e557d4bb 100644 --- a/backend/src/main/java/io/metersphere/api/service/EsbApiParamService.java +++ b/backend/src/main/java/io/metersphere/api/service/EsbApiParamService.java @@ -3,11 +3,13 @@ package io.metersphere.api.service; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import io.metersphere.api.dto.automation.EsbDataStruct; +import io.metersphere.api.dto.automation.SaveApiScenarioRequest; import io.metersphere.api.dto.automation.parse.EsbDataParser; import io.metersphere.api.dto.definition.ApiDefinitionResult; import io.metersphere.api.dto.definition.ApiTestCaseResult; import io.metersphere.api.dto.definition.SaveApiDefinitionRequest; import io.metersphere.api.dto.definition.SaveApiTestCaseRequest; +import io.metersphere.api.dto.definition.request.MsTestElement; import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler; import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.base.domain.ApiTestCaseWithBLOBs; @@ -313,6 +315,35 @@ public class EsbApiParamService { return keyValueList; } + private List genKeyValueListByDataStruct(MsTCPSampler tcpSampler, List dataStructRequestList) { + List keyValueList = new ArrayList<>(); + String sendRequest = tcpSampler.getRequest(); + String paramRegexStr = "\\$\\{([^}]*)\\}"; + try { + if (StringUtils.isNotEmpty(sendRequest)) { + List paramList = new ArrayList<>(); + Pattern regex = Pattern.compile(paramRegexStr); + Matcher matcher = regex.matcher(sendRequest); + while (matcher.find()) { + paramList.add(matcher.group(1)); + } + for (String param : paramList) { + String value = this.genValueFromEsbDataStructByParam(dataStructRequestList, param); + if (StringUtils.isNotEmpty(value)) { + KeyValue kv = new KeyValue(); + kv.setName(param); + kv.setValue(value); + kv.setRequired(true); + keyValueList.add(kv); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return keyValueList; + } + //通过报文模版中的变量参数,解析报文数据结构,生成对应的xml数据 private String genValueFromEsbDataStructByParam(List dataStructRequestList, String param) { String returnValue = ""; @@ -341,10 +372,32 @@ public class EsbApiParamService { return request; } + public void handleEsbRequest(MsTCPSampler tcpSampler) { + try { + //修改reqeust.parameters, 将树结构类型数据转化为表格类型数据,供执行时参数的提取 + if (tcpSampler.getEsbDataStruct() != null ) { + List keyValueList = this.genKeyValueListByDataStruct(tcpSampler, tcpSampler.getEsbDataStruct()); + tcpSampler.setParameters(keyValueList); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + public void deleteByResourceIdIn(List apiIds) { EsbApiParamsExample example = new EsbApiParamsExample(); example.createCriteria().andResourceIdIn(apiIds); esbApiParamsMapper.deleteByExample(example); } + public void checkScenarioRequests(SaveApiScenarioRequest request) { + if(request.getScenarioDefinition() != null ){ + List hashTreeList = request.getScenarioDefinition().getHashTree(); + for (MsTestElement testElement :hashTreeList) { + if(testElement instanceof MsTCPSampler){ + this.handleEsbRequest((MsTCPSampler)testElement); + } + } + } + } } diff --git a/frontend/src/business/components/api/automation/scenario/api/ApiRelevance.vue b/frontend/src/business/components/api/automation/scenario/api/ApiRelevance.vue index 1a453d7153..62e1356f3b 100644 --- a/frontend/src/business/components/api/automation/scenario/api/ApiRelevance.vue +++ b/frontend/src/business/components/api/automation/scenario/api/ApiRelevance.vue @@ -101,25 +101,25 @@ export default { let requestObj = JSON.parse(item.request); if(requestObj.esbDataStruct != null ){ - //ESB接口 - let param = {}; - param.request = requestObj; - param.method = "ESB"; - param.esbDataStruct = JSON.stringify(requestObj.esbDataStruct); - if(requestObj.backEsbDataStruct != null){ - param.backEsbDataStruct = JSON.stringify(requestObj.backEsbDataStruct); - }else{ - param.backEsbDataStruct = ""; - } + // //ESB接口 + // let param = {}; + // param.request = requestObj; + // param.method = "ESB"; + // param.esbDataStruct = JSON.stringify(requestObj.esbDataStruct); + // if(requestObj.backEsbDataStruct != null){ + // param.backEsbDataStruct = JSON.stringify(requestObj.backEsbDataStruct); + // }else{ + // param.backEsbDataStruct = ""; + // } - this.$post("/api/definition/updateEsbRequest", param, response => { - if(response.data!=null){ - if(response.data.request!=null){ - item.request = JSON.stringify(response.data.request); - param.method = "TCP"; - } - } - }) + // this.$post("/api/definition/updateEsbRequest", param, response => { + // if(response.data!=null){ + // if(response.data.request!=null){ + // item.request = JSON.stringify(response.data.request); + // param.method = "TCP"; + // } + // } + // }) } }); this.$emit('save', apiCases, 'CASE', reference); From 7a9079a4790a4435eb47551d611c95c2dc2da68b Mon Sep 17 00:00:00 2001 From: shiziyuan9527 Date: Mon, 29 Mar 2021 17:02:34 +0800 Subject: [PATCH 04/18] =?UTF-8?q?fix(=E5=9C=BA=E6=99=AF=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E5=9C=BA=E6=99=AF=E4=B8=8B=E6=AD=A5=E9=AA=A4?= =?UTF-8?q?=E6=9C=AA=E5=90=AF=E7=94=A8=E5=BD=93=E5=89=8D=E5=9C=BA=E6=99=AF?= =?UTF-8?q?=E7=9A=84=E7=8E=AF=E5=A2=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/definition/request/MsScenario.java | 35 ++++++++++--------- .../request/sampler/MsHTTPSamplerProxy.java | 5 +++ .../api/definition/components/Run.vue | 4 +-- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java index 7a3ec79943..aa9e8d7a9f 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java @@ -114,23 +114,26 @@ public class MsScenario extends MsTestElement { // 设置共享cookie config.setEnableCookieShare(enableCookieShare); Map envConfig = new HashMap<>(16); - // 兼容历史数据 - if (environmentMap == null || environmentMap.isEmpty()) { - environmentMap = new HashMap<>(16); - if (StringUtils.isNotBlank(environmentId)) { - environmentMap.put(SessionUtils.getCurrentProjectId(), environmentId); - } - } - if (environmentMap != null && !environmentMap.isEmpty()) { - environmentMap.keySet().forEach(projectId -> { - ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class); - ApiTestEnvironmentWithBLOBs environment = environmentService.get(environmentMap.get(projectId)); - if (environment != null && environment.getConfig() != null) { - EnvironmentConfig env = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class); - envConfig.put(projectId, env); + if (config.getConfig() == null) { + // 兼容历史数据 + if (this.environmentMap == null || this.environmentMap.isEmpty()) { + this.environmentMap = new HashMap<>(16); + if (StringUtils.isNotBlank(environmentId)) { + // 兼容1.8之前 没有environmentMap但有environmentId的数据 + this.environmentMap.put("historyProjectID", environmentId); } - }); - config.setConfig(envConfig); + } + if (this.environmentMap != null && !this.environmentMap.isEmpty()) { + this.environmentMap.keySet().forEach(projectId -> { + ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class); + ApiTestEnvironmentWithBLOBs environment = environmentService.get(this.environmentMap.get(projectId)); + if (environment != null && environment.getConfig() != null) { + EnvironmentConfig env = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class); + envConfig.put(projectId, env); + } + }); + config.setConfig(envConfig); + } } if (CollectionUtils.isNotEmpty(this.getVariables())) { config.setVariables(this.variables); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java index b5c2c8f85e..2d88dde7f5 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java @@ -129,6 +129,11 @@ public class MsHTTPSamplerProxy extends MsTestElement { config.setConfig(getEnvironmentConfig(useEnvironment)); } + // 1.8 之前历史数据 + if(StringUtils.isEmpty(this.getProjectId()) && config.getConfig()!= null && !config.getConfig().isEmpty()){ + this.setProjectId("historyProjectID"); + } + // 添加环境中的公共变量 Arguments arguments = this.addArguments(config); if (arguments != null) { diff --git a/frontend/src/business/components/api/definition/components/Run.vue b/frontend/src/business/components/api/definition/components/Run.vue index 4245075e55..734419b84f 100644 --- a/frontend/src/business/components/api/definition/components/Run.vue +++ b/frontend/src/business/components/api/definition/components/Run.vue @@ -68,8 +68,8 @@ let projectId = ""; // 如果envMap不存在,是单接口调用 - if (!this.envMap) { - projectId = getCurrentProjectID(); + if (!this.envMap || this.envMap.size === 0) { + projectId = this.$store.state.projectId; } else { // 场景步骤下接口调用 projectId = this.runData.projectId; From 2fac88cca8efd8a9943f2c81a6651e55ada0be4a Mon Sep 17 00:00:00 2001 From: "song.tianyang" Date: Mon, 29 Mar 2021 17:28:56 +0800 Subject: [PATCH 05/18] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E5=B1=95=E7=8E=B0XML=E6=A0=BC=E5=BC=8F=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=97=B6=E4=BC=9A=E8=87=AA=E5=8A=A8=E8=BD=AC=E5=8C=96?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复页面展现XML格式数据时会自动转化标签的问题 --- .../components/document/ApiDocumentAnchor.vue | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/frontend/src/business/components/api/definition/components/document/ApiDocumentAnchor.vue b/frontend/src/business/components/api/definition/components/document/ApiDocumentAnchor.vue index 5b28afe295..194a337c8a 100644 --- a/frontend/src/business/components/api/definition/components/document/ApiDocumentAnchor.vue +++ b/frontend/src/business/components/api/definition/components/document/ApiDocumentAnchor.vue @@ -178,6 +178,10 @@
+ + + +

'); + + if(dataType === 'XML'){ + returnData = "

"+returnData+""; + }else{ + returnData = data.replace(/\n/g, '
'); + } } return returnData; }, From c1d7f5df42170a4f9f5d6bcd3f42d01ad70d1c4f Mon Sep 17 00:00:00 2001 From: Ambitiousliga <73278880+Ambitiousliga@users.noreply.github.com> Date: Mon, 29 Mar 2021 09:35:12 +0800 Subject: [PATCH 06/18] =?UTF-8?q?feat(=E6=B5=8B=E8=AF=95=E8=B7=9F=E8=B8=AA?= =?UTF-8?q?):=E9=80=9A=E8=BF=87Excel=E5=AF=BC=E5=85=A5=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E6=97=B6=E6=9C=89ID=E5=AD=97=E6=AE=B5=EF=BC=8C=E5=8F=AF?= =?UTF-8?q?=E9=80=9A=E8=BF=87Excel=E5=AF=BC=E5=85=A5=E6=9D=A5=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E7=94=A8=E4=BE=8B=E3=80=82=20(#1727)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 黎龙鑫 --- .../base/domain/TestCaseWithBLOBs.java | 5 +- .../excel/domain/ExcelResponse.java | 2 + .../excel/domain/TestCaseExcelData.java | 2 + .../excel/domain/TestCaseExcelDataCn.java | 4 + .../excel/domain/TestCaseExcelDataTw.java | 4 + .../excel/domain/TestCaseExcelDataUs.java | 4 + .../excel/listener/TestCaseDataListener.java | 129 ++++++++++++++++-- .../track/service/TestCaseService.java | 87 +++++++++++- .../track/case/components/TestCaseImport.vue | 10 +- 9 files changed, 232 insertions(+), 15 deletions(-) diff --git a/backend/src/main/java/io/metersphere/base/domain/TestCaseWithBLOBs.java b/backend/src/main/java/io/metersphere/base/domain/TestCaseWithBLOBs.java index 8c58c01094..49fe510c41 100644 --- a/backend/src/main/java/io/metersphere/base/domain/TestCaseWithBLOBs.java +++ b/backend/src/main/java/io/metersphere/base/domain/TestCaseWithBLOBs.java @@ -1,17 +1,18 @@ package io.metersphere.base.domain; -import java.io.Serializable; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; +import java.io.Serializable; + @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class TestCaseWithBLOBs extends TestCase implements Serializable { private String remark; - private String steps; + private String steps; //与TestCaseExcelData里的属性名不一致,BeanUtils.copyBean()复制不了值,需要手动赋值 private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/excel/domain/ExcelResponse.java b/backend/src/main/java/io/metersphere/excel/domain/ExcelResponse.java index d4cb6ce786..b47c168904 100644 --- a/backend/src/main/java/io/metersphere/excel/domain/ExcelResponse.java +++ b/backend/src/main/java/io/metersphere/excel/domain/ExcelResponse.java @@ -9,5 +9,7 @@ public class ExcelResponse { private Boolean success; private List> errList; + private Boolean isUpdated; //是否有更新过用例 + } diff --git a/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelData.java b/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelData.java index 161486e0fc..099c9b462f 100644 --- a/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelData.java +++ b/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelData.java @@ -8,6 +8,8 @@ import lombok.Setter; @Setter public class TestCaseExcelData { + @ExcelIgnore + private Integer num; @ExcelIgnore private String name; @ExcelIgnore diff --git a/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataCn.java b/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataCn.java index 218a59e01e..6cc4b5fca4 100644 --- a/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataCn.java +++ b/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataCn.java @@ -13,6 +13,10 @@ import javax.validation.constraints.Pattern; @ColumnWidth(15) public class TestCaseExcelDataCn extends TestCaseExcelData { + @ExcelProperty("ID") + @NotRequired + private Integer num; + @NotBlank(message = "{cannot_be_null}") @Length(max = 255) @ExcelProperty("用例名称") diff --git a/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataTw.java b/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataTw.java index d60c24fa2a..aeea86ca0f 100644 --- a/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataTw.java +++ b/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataTw.java @@ -13,6 +13,10 @@ import javax.validation.constraints.Pattern; @ColumnWidth(15) public class TestCaseExcelDataTw extends TestCaseExcelData { + @ExcelProperty("ID") + @NotRequired + private Integer num; + @NotBlank(message = "{cannot_be_null}") @Length(max = 255) @ExcelProperty("用例名稱") diff --git a/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataUs.java b/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataUs.java index 6916c3a5ec..c56260b523 100644 --- a/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataUs.java +++ b/backend/src/main/java/io/metersphere/excel/domain/TestCaseExcelDataUs.java @@ -14,6 +14,10 @@ import javax.validation.constraints.Pattern; @ColumnWidth(15) public class TestCaseExcelDataUs extends TestCaseExcelData { + @ExcelProperty("ID") + @NotRequired + private Integer num; + @NotBlank(message = "{cannot_be_null}") @Length(max = 255) @ExcelProperty("Name") diff --git a/backend/src/main/java/io/metersphere/excel/listener/TestCaseDataListener.java b/backend/src/main/java/io/metersphere/excel/listener/TestCaseDataListener.java index 9397a20ef9..ad588dc8cd 100644 --- a/backend/src/main/java/io/metersphere/excel/listener/TestCaseDataListener.java +++ b/backend/src/main/java/io/metersphere/excel/listener/TestCaseDataListener.java @@ -1,12 +1,16 @@ package io.metersphere.excel.listener; +import com.alibaba.excel.context.AnalysisContext; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import io.metersphere.base.domain.TestCaseWithBLOBs; import io.metersphere.commons.constants.TestCaseConstants; import io.metersphere.commons.utils.BeanUtils; import io.metersphere.commons.utils.CommonBeanFactory; +import io.metersphere.commons.utils.LogUtil; +import io.metersphere.excel.domain.ExcelErrData; import io.metersphere.excel.domain.TestCaseExcelData; +import io.metersphere.excel.utils.ExcelValidateHelper; import io.metersphere.i18n.Translator; import io.metersphere.track.service.TestCaseService; import org.apache.commons.lang3.StringUtils; @@ -22,10 +26,18 @@ public class TestCaseDataListener extends EasyExcelListener { private String projectId; + protected List updateList = new ArrayList<>(); //存储待更新用例的集合 + + protected boolean isUpdated = false; //判断是否更新过用例,将会传给前端 + Set testCaseNames; Set userIds; + public boolean isUpdated() { + return isUpdated; + } + public TestCaseDataListener(Class clazz, String projectId, Set testCaseNames, Set userIds) { this.clazz = clazz; this.testCaseService = (TestCaseService) CommonBeanFactory.getBean("testCaseService"); @@ -39,12 +51,15 @@ public class TestCaseDataListener extends EasyExcelListener { String nodePath = data.getNodePath(); StringBuilder stringBuilder = new StringBuilder(errMsg); + //校验”所属模块" if (nodePath != null) { String[] nodes = nodePath.split("/"); + //校验模块深度 if (nodes.length > TestCaseConstants.MAX_NODE_DEPTH + 1) { stringBuilder.append(Translator.get("test_case_node_level_tip") + TestCaseConstants.MAX_NODE_DEPTH + Translator.get("test_case_node_level") + "; "); } + //模块名不能为空 for (int i = 0; i < nodes.length; i++) { if (i != 0 && StringUtils.equals(nodes[i].trim(), "")) { stringBuilder.append(Translator.get("module_not_null") + "; "); @@ -57,10 +72,39 @@ public class TestCaseDataListener extends EasyExcelListener { // stringBuilder.append(Translator.get("functional_method_tip") + "; "); // } + + //校验维护人 if (!userIds.contains(data.getMaintainer())) { stringBuilder.append(Translator.get("user_not_exists") + ":" + data.getMaintainer() + "; "); } + /* + 校验Excel中是否有ID + 有的话校验ID是否已在当前项目中存在,存在则更新用例, + 不存在则继续校验看是否重复,不重复则新建用例。 + */ + if (null != data.getNum()) { //当前读取的数据有ID + + if (null != testCaseService.checkIdExist(data.getNum(), projectId)) { //该ID在当前项目中存在 + //如果前面所经过的校验都没报错 + if (StringUtils.isEmpty(stringBuilder)) { + updateList.add(data); //将当前数据存入更新列表 + stringBuilder.append("update_testcase"); //该信息用于在invoke方法中判断是否该更新用例 + } + return stringBuilder.toString(); + } else { + /* + 该ID在当前数据库中不存在,应当继续校验用例是否重复, + 在下面的校验过程中,num的值会被用于判断是否重复,所以应当先设置为null + */ + data.setNum(null); + } + } + + + /* + 校验用例 + */ if (testCaseNames.contains(data.getName())) { TestCaseWithBLOBs testCase = new TestCaseWithBLOBs(); BeanUtils.copyBean(testCase, data); @@ -96,18 +140,27 @@ public class TestCaseDataListener extends EasyExcelListener { @Override public void saveData() { - //无错误数据才插入数据 - if (!errList.isEmpty()) { + //excel中用例都有错误时就返回,只要有用例可用于更新或者插入就不返回 + if (!errList.isEmpty() && list.size() == 0 && updateList.size() == 0) { return; } - Collections.reverse(list); + if (!(list.size() == 0)){ + Collections.reverse(list); //因为saveImportData里面是先分配最大的ID,这个ID应该先发给list中最后的数据,所以要reverse + List result = list.stream() + .map(item -> this.convert2TestCase(item)) + .collect(Collectors.toList()); + testCaseService.saveImportData(result, projectId); + } - List result = list.stream() - .map(item -> this.convert2TestCase(item)) - .collect(Collectors.toList()); - - testCaseService.saveImportData(result, projectId); + if (!(updateList.size() == 0)) { + List result2 = updateList.stream() + .map(item -> this.convert2TestCaseForUpdate(item)) + .collect(Collectors.toList()); + testCaseService.updateImportDataCarryId(result2, projectId); + this.isUpdated = true; + updateList.clear(); + } } @@ -131,6 +184,32 @@ public class TestCaseDataListener extends EasyExcelListener { testCase.setNodePath(nodePath); + String steps = getSteps(data); + testCase.setSteps(steps); + + return testCase; +} + + /** + * 将Excel中的数据对象转换为用于更新操作的用例数据对象, + * @param data + * @return + */ + private TestCaseWithBLOBs convert2TestCaseForUpdate(TestCaseExcelData data) { + TestCaseWithBLOBs testCase = new TestCaseWithBLOBs(); + BeanUtils.copyBean(testCase, data); + testCase.setProjectId(this.projectId); + testCase.setUpdateTime(System.currentTimeMillis()); + + String nodePath = data.getNodePath(); + if (!nodePath.startsWith("/")) { + nodePath = "/" + nodePath; + } + if (nodePath.endsWith("/")) { + nodePath = nodePath.substring(0, nodePath.length() - 1); + } + testCase.setNodePath(nodePath); + String steps = getSteps(data); testCase.setSteps(steps); @@ -189,4 +268,38 @@ public class TestCaseDataListener extends EasyExcelListener { return jsonArray.toJSONString(); } + @Override + public void invoke(TestCaseExcelData testCaseExcelData, AnalysisContext analysisContext) { + String errMsg; + Integer rowIndex = analysisContext.readRowHolder().getRowIndex(); + String updateMsg = "update_testcase"; + try { + //根据excel数据实体中的javax.validation + 正则表达式来校验excel数据 + errMsg = ExcelValidateHelper.validateEntity(testCaseExcelData); + //自定义校验规则 + errMsg = validate(testCaseExcelData, errMsg); + } catch (NoSuchFieldException e) { + errMsg = Translator.get("parse_data_error"); + LogUtil.error(e.getMessage(), e); + } + + if (!StringUtils.isEmpty(errMsg)) { + + //如果errMsg只有"update testcase",说明用例待更新 + if (!errMsg.equals(updateMsg)){ + ExcelErrData excelErrData = new ExcelErrData(testCaseExcelData, rowIndex, + Translator.get("number") + " " + rowIndex + " " + Translator.get("row") + Translator.get("error") + + ":" + errMsg); + + errList.add(excelErrData); + } + } else { + list.add(testCaseExcelData); + } + + if (list.size() > BATCH_COUNT) { + saveData(); + list.clear(); + } + } } diff --git a/backend/src/main/java/io/metersphere/track/service/TestCaseService.java b/backend/src/main/java/io/metersphere/track/service/TestCaseService.java index 313901669b..1ed153236f 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestCaseService.java @@ -19,7 +19,6 @@ import io.metersphere.excel.domain.ExcelErrData; import io.metersphere.excel.domain.ExcelResponse; import io.metersphere.excel.domain.TestCaseExcelData; import io.metersphere.excel.domain.TestCaseExcelDataFactory; -import io.metersphere.excel.listener.EasyExcelListener; import io.metersphere.excel.listener.TestCaseDataListener; import io.metersphere.excel.utils.EasyExcelExporter; import io.metersphere.i18n.Translator; @@ -126,11 +125,26 @@ public class TestCaseService { // 全部字段值相同才判断为用例存在 if (testCase != null) { + + /* + 例如对于“/模块5”,用户的输入可能为“模块5”或者“/模块5/”或者“模块5/”。 + 不这样处理的话,下面进行判断时就会用用户输入的错误格式进行判断,而模块名为“/模块5”、 + “模块5”、“/模块5/”、“模块5/”时,它们应该被认为是同一个模块。 + 数据库存储的node_path都是“/模块5”这种格式的 + */ + String nodePath = testCase.getNodePath(); + if (!nodePath.startsWith("/")) { + nodePath = "/" + nodePath; + } + if (nodePath.endsWith("/")) { + nodePath = nodePath.substring(0, nodePath.length() - 1); + } + TestCaseExample example = new TestCaseExample(); TestCaseExample.Criteria criteria = example.createCriteria(); criteria.andNameEqualTo(testCase.getName()) .andProjectIdEqualTo(testCase.getProjectId()) - .andNodePathEqualTo(testCase.getNodePath()) + .andNodePathEqualTo(nodePath) .andTypeEqualTo(testCase.getType()) .andMaintainerEqualTo(testCase.getMaintainer()) .andPriorityEqualTo(testCase.getPriority()); @@ -177,6 +191,26 @@ public class TestCaseService { return null; } + /** + * 根据id和pojectId查询id是否在数据库中存在。 + * 在数据库中单id的话是可重复的,id与projectId的组合是唯一的 + */ + public Integer checkIdExist(Integer id, String projectId){ + TestCaseExample example = new TestCaseExample(); + TestCaseExample.Criteria criteria = example.createCriteria(); + if (null != id) { + criteria.andNumEqualTo(id); + criteria.andProjectIdEqualTo(projectId); + long count = testCaseMapper.countByExample(example); //查询是否有包含此ID的数据 + if(count == 0){ //如果ID不存在 + return null; + }else { //有对应ID的数据 + return id; + } + } + return null; + } + public int deleteTestCase(String testCaseId) { TestPlanTestCaseExample example = new TestPlanTestCaseExample(); example.createCriteria().andCaseIdEqualTo(testCaseId); @@ -286,6 +320,7 @@ public class TestCaseService { public ExcelResponse testCaseImport(MultipartFile multipartFile, String projectId, String userId) { ExcelResponse excelResponse = new ExcelResponse(); + boolean isUpdated = false; //判断是否更新了用例 String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId(); QueryTestCaseRequest queryTestCaseRequest = new QueryTestCaseRequest(); queryTestCaseRequest.setProjectId(projectId); @@ -338,10 +373,15 @@ public class TestCaseService { Set userIds = userRoleMapper.selectByExample(userRoleExample).stream().map(UserRole::getUserId).collect(Collectors.toSet()); try { + //根据本地语言环境选择用哪种数据对象进行存放读取的数据 Class clazz = new TestCaseExcelDataFactory().getExcelDataByLocal(); - EasyExcelListener easyExcelListener = new TestCaseDataListener(clazz, projectId, testCaseNames, userIds); + + TestCaseDataListener easyExcelListener = new TestCaseDataListener(clazz, projectId, testCaseNames, userIds); + //读取excel数据 EasyExcelFactory.read(multipartFile.getInputStream(), clazz, easyExcelListener).sheet().doRead(); + errList = easyExcelListener.getErrList(); + isUpdated = easyExcelListener.isUpdated(); } catch (Exception e) { LogUtil.error(e.getMessage(), e); MSException.throwException(e.getMessage()); @@ -352,6 +392,7 @@ public class TestCaseService { if (!errList.isEmpty()) { excelResponse.setSuccess(false); excelResponse.setErrList(errList); + excelResponse.setIsUpdated(isUpdated); } else { excelResponse.setSuccess(true); } @@ -374,7 +415,7 @@ public class TestCaseService { testcase.setSort(sort.getAndIncrement()); testcase.setNum(num.decrementAndGet()); testcase.setReviewStatus(TestCaseReviewStatus.Prepare.name()); - mapper.insert(testcase); + mapper.insert(testcase); }); } sqlSession.flushStatements(); @@ -400,6 +441,43 @@ public class TestCaseService { sqlSession.flushStatements(); } + /** + * 把Excel中带ID的数据更新到数据库 + * @param testCases + * @param projectId + */ + public void updateImportDataCarryId(List testCases, String projectId) { + Map nodePathMap = testCaseNodeService.createNodeByTestCases(testCases, projectId); + SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); + TestCaseMapper mapper = sqlSession.getMapper(TestCaseMapper.class); + + /* + 获取用例的“网页上所显示id”与“数据库ID”映射。 + */ + List nums = testCases.stream() + .map(TestCase::getNum) + .collect(Collectors.toList()); + TestCaseExample example = new TestCaseExample(); + example.createCriteria().andNumIn(nums) + .andProjectIdEqualTo(projectId); + List testCasesList = testCaseMapper.selectByExample(example); + Map numIdMap = testCasesList.stream() + .collect(Collectors.toMap(TestCase::getNum, TestCase::getId)); + + + if (!testCases.isEmpty()) { + AtomicInteger sort = new AtomicInteger(); + testCases.forEach(testcase -> { + testcase.setUpdateTime(System.currentTimeMillis()); + testcase.setNodeId(nodePathMap.get(testcase.getNodePath())); + testcase.setSort(sort.getAndIncrement()); + testcase.setId(numIdMap.get(testcase.getNum())); + mapper.updateByPrimaryKeySelective(testcase); + }); + } + sqlSession.flushStatements(); + } + public void testCaseTemplateExport(HttpServletResponse response) { try { @@ -510,6 +588,7 @@ public class TestCaseService { StringBuilder result = new StringBuilder(""); TestCaseList.forEach(t -> { TestCaseExcelData data = new TestCaseExcelData(); + data.setNum(t.getNum()); data.setName(t.getName()); data.setNodePath(t.getNodePath()); data.setPriority(t.getPriority()); diff --git a/frontend/src/business/components/track/case/components/TestCaseImport.vue b/frontend/src/business/components/track/case/components/TestCaseImport.vue index a82195348f..1410afc46f 100644 --- a/frontend/src/business/components/track/case/components/TestCaseImport.vue +++ b/frontend/src/business/components/track/case/components/TestCaseImport.vue @@ -126,7 +126,8 @@ fileList: [], errList: [], xmindErrList: [], - isLoading: false + isLoading: false, + isUpdated: false } }, methods: { @@ -180,6 +181,12 @@ this.fileList = []; this.errList = []; this.xmindErrList = []; + + //通过excel导入更新过数据的话就刷新页面 + if (this.isUpdated === true){ + this.$emit("refreshAll"); + this.isUpdated = false; + } }, downloadTemplate() { this.$fileDownload('/test/case/export/template'); @@ -207,6 +214,7 @@ this.$emit("refreshAll"); } else { this.errList = res.errList; + this.isUpdated = res.isUpdated; } this.fileList = []; }, erro => { From 1d9059de346268569a9f24c2957e9b15fb7abdcc Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Mon, 29 Mar 2021 18:23:10 +0800 Subject: [PATCH 07/18] =?UTF-8?q?refactor(=E6=8E=A5=E5=8F=A3=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=8C=96=EF=BC=8C=E6=8E=A5=E5=8F=A3=E5=AE=9A=E4=B9=89?= =?UTF-8?q?):=20=E5=88=A0=E9=99=A4=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96=E5=9C=BA=E6=99=AF=E8=B0=83=E8=AF=95=E4=BA=A7=E7=94=9F?= =?UTF-8?q?=E7=9A=84=E8=AE=B0=E5=BD=95=E8=AF=A6=E6=83=85=EF=BC=8C=E4=BF=9D?= =?UTF-8?q?=E7=95=99=E6=9C=80=E5=90=8E=E4=B8=80=E6=9D=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ApiDefinitionExecResultService.java | 22 ++++++++++++++----- .../api/service/ApiScenarioReportService.java | 7 ++++++ .../ext/ExtApiScenarioReportMapper.java | 4 ++++ .../mapper/ext/ExtApiScenarioReportMapper.xml | 5 +++++ frontend/src/business/components/xpack | 2 +- 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java index 9be4f831ac..e2631f175c 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java @@ -3,10 +3,7 @@ package io.metersphere.api.service; import com.alibaba.fastjson.JSON; import io.metersphere.api.dto.datacount.ExecutedCaseInfoResult; import io.metersphere.api.jmeter.TestResult; -import io.metersphere.base.domain.ApiDefinitionExecResult; -import io.metersphere.base.domain.ApiDefinitionExecResultExample; -import io.metersphere.base.domain.ApiTestCaseWithBLOBs; -import io.metersphere.base.domain.TestPlanApiCase; +import io.metersphere.base.domain.*; import io.metersphere.base.mapper.ApiDefinitionExecResultMapper; import io.metersphere.base.mapper.ApiTestCaseMapper; import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper; @@ -43,7 +40,7 @@ public class ApiDefinitionExecResultService { @Resource private ApiTestCaseMapper apiTestCaseMapper; @Resource - private TestCaseReviewApiCaseService testCaseReviewApiCaseService; + private TestCaseReviewApiCaseService testCaseReviewApiCaseService; @Resource SqlSessionFactory sqlSessionFactory; @@ -73,6 +70,13 @@ public class ApiDefinitionExecResultService { testCaseReviewApiCaseService.setExecResult(item.getName(), status); } + + // 清空上次执行结果的内容,只保留当前最新一条内容 + ApiDefinitionExecResult prevResult = extApiDefinitionExecResultMapper.selectMaxResultByResourceIdAndType(item.getName(), type); + if (prevResult != null) { + prevResult.setContent(null); + definitionExecResultMapper.updateByPrimaryKeyWithBLOBs(prevResult); + } // 更新用例最后执行结果 ApiTestCaseWithBLOBs apiTestCaseWithBLOBs = new ApiTestCaseWithBLOBs(); apiTestCaseWithBLOBs.setId(saveResult.getResourceId()); @@ -94,7 +98,7 @@ public class ApiDefinitionExecResultService { */ public void saveApiResultByScheduleTask(TestResult result, String type) { String saveResultType = type; - if(StringUtils.equalsAny(ApiRunMode.SCHEDULE_API_PLAN.name(),saveResultType)){ + if (StringUtils.equalsAny(ApiRunMode.SCHEDULE_API_PLAN.name(), saveResultType)) { saveResultType = ApiRunMode.API_PLAN.name(); } @@ -127,6 +131,12 @@ public class ApiDefinitionExecResultService { } saveResult.setUserId(userID); + // 前一条数据内容清空 + ApiDefinitionExecResult prevResult = extApiDefinitionExecResultMapper.selectMaxResultByResourceIdAndType(item.getName(), finalSaveResultType); + if (prevResult != null) { + prevResult.setContent(null); + apiDefinitionExecResultMapper.updateByPrimaryKeyWithBLOBs(prevResult); + } apiDefinitionExecResultMapper.insert(saveResult); }); } diff --git a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java index adb9a5f556..43064ccb39 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java @@ -253,6 +253,13 @@ public class ApiScenarioReportService { String status = "Success"; report.setStatus(status); scenarioReportMapper.updateByPrimaryKeySelective(report); + // 把上一条调试的数据内容清空 + ApiScenarioReport prevResult = extApiScenarioReportMapper.selectPreviousReportByScenarioId(report.getScenarioId(), reportId); + if (prevResult != null) { + ApiScenarioReportDetailExample example = new ApiScenarioReportDetailExample(); + example.createCriteria().andReportIdEqualTo(prevResult.getId()); + apiScenarioReportDetailMapper.deleteByExample(example); + } }); sqlSession.flushStatements(); } diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioReportMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioReportMapper.java index 8fd7e161be..d38d6be6ab 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioReportMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioReportMapper.java @@ -3,6 +3,7 @@ package io.metersphere.base.mapper.ext; import io.metersphere.api.dto.QueryAPIReportRequest; import io.metersphere.api.dto.automation.APIScenarioReportResult; import io.metersphere.api.dto.datacount.ApiDataCountResult; +import io.metersphere.base.domain.ApiDefinitionExecResult; import io.metersphere.base.domain.ApiScenarioReport; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; @@ -23,4 +24,7 @@ public interface ExtApiScenarioReportMapper { List countByProjectIdGroupByExecuteResult(String projectId); List selectLastReportByIds(@Param("scenarioIdList") List ids); + + ApiScenarioReport selectPreviousReportByScenarioId(@Param("scenarioId") String scenarioId, @Param("nowId") String nowId); + } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioReportMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioReportMapper.xml index 5a552d03e3..93463a6929 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioReportMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioReportMapper.xml @@ -216,4 +216,9 @@ ) orderData ON orderData.id = report.id; + + \ No newline at end of file diff --git a/frontend/src/business/components/xpack b/frontend/src/business/components/xpack index 2115bd28a9..07951ba17a 160000 --- a/frontend/src/business/components/xpack +++ b/frontend/src/business/components/xpack @@ -1 +1 @@ -Subproject commit 2115bd28a90854d2b6276a90878934715498c584 +Subproject commit 07951ba17aef6f29e50cfd68e40de3266f9a60cd From 7332bd41ecface53aa32afeab9bb06a6f10f5d30 Mon Sep 17 00:00:00 2001 From: wenyann <64353056+wenyann@users.noreply.github.com> Date: Mon, 29 Mar 2021 18:27:46 +0800 Subject: [PATCH 08/18] =?UTF-8?q?fix:=E7=94=A8=E4=BE=8B=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=BA=86=E8=AF=84=E8=AE=BA=EF=BC=8C=E4=BD=86=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E7=9A=84=E6=97=B6=E5=80=99=E7=9C=8B=E4=B8=8D=E5=88=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/track/case/components/TestCaseEdit.vue | 4 +++- .../track/plan/view/comonents/api/TestPlanApiCaseList.vue | 2 +- .../track/plan/view/comonents/load/TestPlanLoadCaseList.vue | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/src/business/components/track/case/components/TestCaseEdit.vue b/frontend/src/business/components/track/case/components/TestCaseEdit.vue index 1c3b739cf9..78f0deb323 100644 --- a/frontend/src/business/components/track/case/components/TestCaseEdit.vue +++ b/frontend/src/business/components/track/case/components/TestCaseEdit.vue @@ -309,7 +309,7 @@ export default { sysList: [],//一级选择框的数据 options: REVIEW_STATUS, statuOptions: API_STATUS, - comments: [], + comments: [], result: {}, dialogFormVisible: false, form: { @@ -406,6 +406,7 @@ export default { this.getSelectOptions(); if (this.type === 'edit' || this.type === 'copy') { this.open(this.currentTestCaseInfo) + this.getComments(this.currentTestCaseInfo) } // Cascader 级联选择器: 点击文本就让它自动点击前面的input就可以触发选择。 setInterval(function () { @@ -431,6 +432,7 @@ export default { created() { this.loadOptions(); this.addListener(); // 添加 ctrl s 监听 + }, methods: { setModule(id,data) { diff --git a/frontend/src/business/components/track/plan/view/comonents/api/TestPlanApiCaseList.vue b/frontend/src/business/components/track/plan/view/comonents/api/TestPlanApiCaseList.vue index 7bdc9737b3..3ad46ae991 100644 --- a/frontend/src/business/components/track/plan/view/comonents/api/TestPlanApiCaseList.vue +++ b/frontend/src/business/components/track/plan/view/comonents/api/TestPlanApiCaseList.vue @@ -104,7 +104,7 @@ - + diff --git a/frontend/src/business/components/track/plan/view/comonents/load/TestPlanLoadCaseList.vue b/frontend/src/business/components/track/plan/view/comonents/load/TestPlanLoadCaseList.vue index caec94d7a2..d292a02dd6 100644 --- a/frontend/src/business/components/track/plan/view/comonents/load/TestPlanLoadCaseList.vue +++ b/frontend/src/business/components/track/plan/view/comonents/load/TestPlanLoadCaseList.vue @@ -100,7 +100,7 @@ - + From 09c027a79ca39de7c7960f89fa4218bdff3763a4 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Mon, 29 Mar 2021 18:38:06 +0800 Subject: [PATCH 09/18] =?UTF-8?q?fix(=E5=9C=BA=E6=99=AF=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E4=BF=AE=E5=A4=8D=E6=9C=80=E5=A4=A7=E5=8C=96?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E6=95=B0=E6=8D=AE=E5=B1=95=E7=A4=BA=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scenario/maximize/MaximizeScenario.vue | 69 ++++++++++--------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/frontend/src/business/components/api/automation/scenario/maximize/MaximizeScenario.vue b/frontend/src/business/components/api/automation/scenario/maximize/MaximizeScenario.vue index 77a8070542..f6d519954c 100644 --- a/frontend/src/business/components/api/automation/scenario/maximize/MaximizeScenario.vue +++ b/frontend/src/business/components/api/automation/scenario/maximize/MaximizeScenario.vue @@ -50,39 +50,41 @@
- - - - -
-
- + +
+ + + +
+
+ +
@@ -477,6 +479,7 @@ } this.selectedTreeNode = data; this.selectedNode = node; + this.reload(); }, suggestClick(node) { this.response = {}; From b6faf61f73fe40424bc2cb9fcb077a02ba04b9e6 Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Mon, 29 Mar 2021 18:50:59 +0800 Subject: [PATCH 10/18] =?UTF-8?q?fix:=20=E6=97=A7=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E6=96=87=E4=BB=B6=E6=8E=A5=E5=8F=A3=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E5=AF=BC=E5=85=A5=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../definition/parse/MsDefinitionParser.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/MsDefinitionParser.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/MsDefinitionParser.java index db0a5bf459..ce76eddb03 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/parse/MsDefinitionParser.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/MsDefinitionParser.java @@ -58,14 +58,16 @@ public class MsDefinitionParser extends MsAbstractParser { private ApiDefinitionImport parseMsFormat(String testStr, ApiTestImportRequest importRequest) { ApiDefinitionImport apiDefinitionImport = JSON.parseObject(testStr, ApiDefinitionImport.class); Map> caseMap = new HashMap<>(); - apiDefinitionImport.getCases().forEach(item -> { - List caseList = caseMap.get(item.getApiDefinitionId()); - if (caseList == null) { - caseList = new ArrayList<>(); - caseMap.put(item.getApiDefinitionId(), caseList); - } - caseList.add(item); - }); + if (apiDefinitionImport.getCases() != null) { + apiDefinitionImport.getCases().forEach(item -> { + List caseList = caseMap.get(item.getApiDefinitionId()); + if (caseList == null) { + caseList = new ArrayList<>(); + caseMap.put(item.getApiDefinitionId(), caseList); + } + caseList.add(item); + }); + } apiDefinitionImport.getData().forEach(apiDefinition -> { parseApiDefinition(apiDefinition, importRequest, caseMap); }); From 2ba7cd8b1a938fde59098704cded301f2085d716 Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Mon, 29 Mar 2021 19:03:17 +0800 Subject: [PATCH 11/18] =?UTF-8?q?fix:=20swgger=20base-url=20=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E5=90=8E=E8=B7=AF=E5=BE=84=E5=A4=9A=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E4=B8=AA'/'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../metersphere/api/dto/definition/parse/Swagger2Parser.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger2Parser.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger2Parser.java index c51b92ac47..a830b1d656 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger2Parser.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger2Parser.java @@ -70,8 +70,9 @@ public class Swagger2Parser extends SwaggerAbstractParser { parseParameters(operation, request); addBodyHeader(request); if (StringUtils.isNotBlank(basePath)) { - apiDefinition.setPath(basePath + apiDefinition.getPath()); - request.setPath(basePath + request.getPath()); + String pathStr = basePath + apiDefinition.getPath().replaceAll("//","/"); + apiDefinition.setPath(pathStr); + request.setPath(pathStr); } apiDefinition.setRequest(JSON.toJSONString(request)); apiDefinition.setResponse(JSON.toJSONString(parseResponse(operation, operation.getResponses()))); From 53212d75e8cc96d4a07d547401faf2213a7cc97c Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Mon, 29 Mar 2021 19:34:15 +0800 Subject: [PATCH 12/18] =?UTF-8?q?fix(=E5=9C=BA=E6=99=AF=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E6=89=A7=E8=A1=8C=E6=97=A5=E5=BF=97=E6=8A=A5?= =?UTF-8?q?=E9=94=99=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/metersphere/api/service/ApiDefinitionService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java index c1a488f9cc..c9d1c62f6f 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -517,7 +517,7 @@ public class ApiDefinitionService { } public void addResult(TestResult res) { - if (!res.getScenarios().isEmpty() && !res.getScenarios().get(0).getRequestResults().isEmpty()) { + if (res != null && CollectionUtils.isNotEmpty(res.getScenarios()) && res.getScenarios().get(0) != null && CollectionUtils.isNotEmpty(res.getScenarios().get(0).getRequestResults())) { RequestResult result = res.getScenarios().get(0).getRequestResults().get(0); if (result.getName().indexOf("<->") != -1) { result.setName(result.getName().substring(0, result.getName().indexOf("<->"))); From ca3b951e2d29485769c1637655c9cb86c0be525e Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Mon, 29 Mar 2021 20:00:51 +0800 Subject: [PATCH 13/18] =?UTF-8?q?fix:=20=E6=B5=8B=E8=AF=95=E8=AE=A1?= =?UTF-8?q?=E5=88=92=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/metersphere/track/service/TestPlanService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanService.java index b746b225bd..7d9c4047ac 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanService.java @@ -409,7 +409,7 @@ public class TestPlanService { || StringUtils.equals(res, "success") || StringUtils.equals(res, ScenarioStatus.Success.name())) { passNum++; - } else if (res == null) { + } else if (res == null || StringUtils.equals(TestPlanStatus.Prepare.name(), res)) { prepareNum++; } else { failNum++; From 47120c97cbd7d0e5f36f986e763c7f9c37272a6a Mon Sep 17 00:00:00 2001 From: shiziyuan9527 Date: Mon, 29 Mar 2021 22:41:29 +0800 Subject: [PATCH 14/18] =?UTF-8?q?refactor(=E5=9C=BA=E6=99=AF=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=8C=96):=20=E5=9B=9E=E9=80=80=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E7=8E=AF=E5=A2=83=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../automation/scenario/EditApiScenario.vue | 94 +++++-------------- .../scenario/maximize/MaximizeScenario.vue | 82 ++++------------ .../scenario/maximize/ScenarioHeader.vue | 2 - 3 files changed, 41 insertions(+), 137 deletions(-) diff --git a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue index 67f1a0fc01..8978fd056a 100644 --- a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue +++ b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue @@ -114,9 +114,7 @@ + :project-list="projectList" ref="envPopover"/> {{$t('api_test.request.debug')}} @@ -202,10 +200,7 @@ + :currentScenario="currentScenario" :type="type" ref="maximizeScenario" @openScenario="openScenario"/>
@@ -320,8 +315,6 @@ projectList: [], debugResult: new Map, drawer: false, - isHaveExec: false, - isExecWithOutEnv: true } }, created() { @@ -596,25 +589,9 @@ if (arr[i].type === ELEMENT_TYPE.LoopController && arr[i].loopType === "LOOP_COUNT" && arr[i].hashTree && arr[i].hashTree.length > 1) { arr[i].countController.proceed = true; } - - let type = arr[i].type; - const canExec = this.checkCanExec(type); - if (!this.isHaveExec) { - // 判断此步骤是否可执行 - this.isHaveExec = canExec; - } - if (canExec) { - const execWithOutEnv = this.canExecWithOutEnv(type, arr[i].url); - if (!execWithOutEnv) { - if (!arr[i].projectId) { - // 如果自身没有ID并且场景有ID则赋值场景ID,否则赋值当前项目ID - arr[i].projectId = scenarioProjectId ? scenarioProjectId : this.projectId; - } - this.projectIds.add(arr[i].projectId); - } - } - if (this.isExecWithOutEnv) { - this.isExecWithOutEnv = this.canExecWithOutEnv(type, arr[i].url) + if (!arr[i].projectId) { + // 如果自身没有ID并且场景有ID则赋值场景ID,否则赋值当前项目ID + arr[i].projectId = scenarioProjectId ? scenarioProjectId : this.projectId; } if (arr[i].hashTree != undefined && arr[i].hashTree.length > 0) { @@ -626,24 +603,7 @@ } } }, - canExecWithOutEnv(type, path) { - if (type === ELEMENT_TYPE.HTTPSamplerProxy) { - return this.isHTTPFullPath(path); - } - return type === ELEMENT_TYPE.JSR223Processor ? true : !this.checkCanExec(type); - }, - isHTTPFullPath(path) { - return path ? path.startsWith("http://") || path.startsWith("https://") : false; - }, - checkCanExec(type) { - const allCanExecType = ELEMENTS.get("AllCanExecType"); - const index = allCanExecType.indexOf(type); - return index !== -1; - }, sort() { - this.projectIds.clear(); - this.isHaveExec = false; - this.isExecWithOutEnv = true; for (let i in this.scenarioDefinition) { // 排序 this.scenarioDefinition[i].index = Number(i) + 1; @@ -657,22 +617,6 @@ this.scenarioDefinition[i].projectId = this.projectId; } - let type = this.scenarioDefinition[i].type; - const canExec = this.checkCanExec(type); - if (!this.isHaveExec) { - // 判断此步骤是否可执行 - this.isHaveExec = canExec; - } - if (canExec) { - const execWithOutEnv = this.canExecWithOutEnv(type, this.scenarioDefinition[i].url); - if (!execWithOutEnv) { - this.projectIds.add(this.scenarioDefinition[i].projectId); - } - } - if (this.isExecWithOutEnv) { - this.isExecWithOutEnv = this.canExecWithOutEnv(type, this.scenarioDefinition[i].url) - } - if (this.scenarioDefinition[i].hashTree != undefined && this.scenarioDefinition[i].hashTree.length > 0) { this.recursiveSorting(this.scenarioDefinition[i].hashTree, this.scenarioDefinition[i].projectId); } @@ -693,6 +637,7 @@ this.customizeRequest = {}; this.sort(); this.reload(); + this.initProjectIds(); }, addScenario(arr) { if (arr && arr.length > 0) { @@ -715,6 +660,7 @@ this.isBtnHide = false; this.sort(); this.reload(); + this.initProjectIds(); }, setApiParameter(item, refType, referenced) { let request = {}; @@ -756,6 +702,7 @@ this.isBtnHide = false; this.sort(); this.reload(); + this.initProjectIds(); }, getMaintainerOptions() { let workspaceId = localStorage.getItem(WORKSPACE_ID); @@ -782,6 +729,7 @@ hashTree.splice(index, 1); this.sort(); this.reload(); + this.initProjectIds(); } } }); @@ -812,19 +760,11 @@ }, runDebug() { /*触发执行操作*/ - if (!this.isHaveExec) { - this.$warning("无可执行步骤!"); + let sign = this.$refs.envPopover.checkEnv(); + if (!sign) { return; } - // 运行时是否需要检查环境 - if (!this.isExecWithOutEnv) { - let sign = this.$refs.envPopover.checkEnv(); - if (!sign) { - return; - } - } - this.$refs['currentScenario'].validate((valid) => { if (valid) { Promise.all([ @@ -1063,6 +1003,7 @@ } } this.sort(); + this.initProjectIds(); // this.getEnvironments(); }) } @@ -1132,8 +1073,19 @@ }) }, refReload() { + this.initProjectIds(); this.reload(); }, + initProjectIds() { + // 加载环境配置 + this.$nextTick(() => { + this.projectIds.clear(); + this.scenarioDefinition.forEach(data => { + let arr = jsonPath.query(data, "$..projectId"); + arr.forEach(a => this.projectIds.add(a)); + }) + }) + }, detailRefresh(result) { // 把执行结果分发给各个请求 this.debugResult = result; diff --git a/frontend/src/business/components/api/automation/scenario/maximize/MaximizeScenario.vue b/frontend/src/business/components/api/automation/scenario/maximize/MaximizeScenario.vue index f6d519954c..bd670d739f 100644 --- a/frontend/src/business/components/api/automation/scenario/maximize/MaximizeScenario.vue +++ b/frontend/src/business/components/api/automation/scenario/maximize/MaximizeScenario.vue @@ -164,7 +164,6 @@ type: String, scenarioDefinition: Array, envMap: Map, - projectList: Array }, components: { MsVariableList, @@ -225,10 +224,8 @@ response: {}, projectIds: new Set, projectEnvMap: new Map, - // projectList: [], + projectList: [], debugResult: new Map, - isHaveExec: false, - isExecWithOutEnv: true } }, created() { @@ -502,27 +499,8 @@ if (arr[i].type === ELEMENT_TYPE.LoopController && arr[i].loopType === "LOOP_COUNT" && arr[i].hashTree && arr[i].hashTree.length > 1) { arr[i].countController.proceed = true; } - let type = arr[i].type; - const canExec = this.checkCanExec(type); - if (!this.isHaveExec) { - // 判断此步骤是否可执行 - this.isHaveExec = canExec; - this.$emit("update:isHaveExec", canExec); - } - if (canExec) { - const execWithOutEnv = this.canExecWithOutEnv(type, arr[i].url); - if (!execWithOutEnv) { - if (!arr[i].projectId) { - // 如果自身没有ID并且场景有ID则赋值场景ID,否则赋值当前项目ID - arr[i].projectId = scenarioProjectId ? scenarioProjectId : this.projectId; - } - this.projectIds.add(arr[i].projectId); - this.$emit('update:projectIds', this.projectIds); - } - } - if (this.isExecWithOutEnv) { - this.isExecWithOutEnv = this.canExecWithOutEnv(type, arr[i].url); - this.$emit('update:isExecWithOutEnv', this.canExecWithOutEnv(type, arr[i].url)) + if (!arr[i].projectId) { + arr[i].projectId = scenarioProjectId ? scenarioProjectId : this.projectId; } if (arr[i].hashTree != undefined && arr[i].hashTree.length > 0) { this.recursiveSorting(arr[i].hashTree, arr[i].projectId); @@ -533,27 +511,7 @@ } } }, - canExecWithOutEnv(type, path) { - if (type === ELEMENT_TYPE.HTTPSamplerProxy) { - return this.isHTTPFullPath(path); - } - return type === ELEMENT_TYPE.JSR223Processor ? true : !this.checkCanExec(type); - }, - isHTTPFullPath(path) { - return path ? path.startsWith("http://") || path.startsWith("https://") : false; - }, - checkCanExec(type) { - const allCanExecType = ELEMENTS.get("AllCanExecType"); - const index = allCanExecType.indexOf(type); - return index !== -1; - }, sort() { - this.projectIds.clear(); - this.$emit('update:projectIds', this.projectIds); - this.isHaveExec = false; - this.isExecWithOutEnv = true; - this.$emit('update:isHaveExec', false); - this.$emit('update:isExecWithOutEnv', true); for (let i in this.scenarioDefinition) { // 排序 this.scenarioDefinition[i].index = Number(i) + 1; @@ -567,25 +525,6 @@ this.scenarioDefinition[i].projectId = this.projectId; } - let type = this.scenarioDefinition[i].type; - const canExec = this.checkCanExec(type); - if (!this.isHaveExec) { - // 判断此步骤是否可执行 - this.isHaveExec = canExec; - this.$emit('update:isHaveExec', canExec); - } - if (canExec) { - const execWithOutEnv = this.canExecWithOutEnv(type, this.scenarioDefinition[i].url); - if (!execWithOutEnv) { - this.projectIds.add(this.scenarioDefinition[i].projectId); - this.$emit('update:projectIds', this.projectIds); - } - } - if (this.isExecWithOutEnv) { - this.isExecWithOutEnv = this.canExecWithOutEnv(type, this.scenarioDefinition[i].url); - this.$emit('update:isExecWithOutEnv', this.canExecWithOutEnv(type, this.scenarioDefinition[i].url)); - } - if (this.scenarioDefinition[i].hashTree != undefined && this.scenarioDefinition[i].hashTree.length > 0) { this.recursiveSorting(this.scenarioDefinition[i].hashTree, this.scenarioDefinition[i].projectId); } @@ -606,6 +545,7 @@ this.customizeRequest = {}; this.sort(); this.reload(); + this.initProjectIds(); }, addScenario(arr) { if (arr && arr.length > 0) { @@ -623,6 +563,7 @@ } this.sort(); this.reload(); + this.initProjectIds(); this.scenarioVisible = false; }, setApiParameter(item, refType, referenced) { @@ -664,6 +605,7 @@ }); this.sort(); this.reload(); + this.initProjectIds(); }, openTagConfig() { if (!this.projectId) { @@ -684,6 +626,7 @@ hashTree.splice(index, 1); this.sort(); this.reload(); + this.initProjectIds(); } } }); @@ -980,8 +923,19 @@ refReload(data, node) { this.selectedTreeNode = data; this.selectedNode = node; + this.initProjectIds(); this.reload(); }, + initProjectIds() { + // 加载环境配置 + this.$nextTick(() => { + this.projectIds.clear(); + this.scenarioDefinition.forEach(data => { + let arr = jsonPath.query(data, "$..projectId"); + arr.forEach(a => this.projectIds.add(a)); + }) + }) + }, detailRefresh(result) { // 把执行结果分发给各个请求 this.debugResult = result; diff --git a/frontend/src/business/components/api/automation/scenario/maximize/ScenarioHeader.vue b/frontend/src/business/components/api/automation/scenario/maximize/ScenarioHeader.vue index e6382b985c..2588a23bb2 100644 --- a/frontend/src/business/components/api/automation/scenario/maximize/ScenarioHeader.vue +++ b/frontend/src/business/components/api/automation/scenario/maximize/ScenarioHeader.vue @@ -19,8 +19,6 @@ 共享cookie {{$t('api_test.request.debug')}} From 0cfd281d072a5cc6768c97bca90b6221f6707658 Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Tue, 30 Mar 2021 10:04:20 +0800 Subject: [PATCH 15/18] =?UTF-8?q?feat(=E6=80=A7=E8=83=BD=E6=B5=8B=E8=AF=95?= =?UTF-8?q?):=20=E9=99=90=E5=88=B6=E6=99=AE=E9=80=9A=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E7=BB=84=E7=9A=84=E9=A2=84=E7=83=AD=E6=97=B6=E9=97=B4=E6=9C=80?= =?UTF-8?q?=E5=A4=A7=E5=80=BC=E4=B8=8D=E8=83=BD=E8=B6=85=E5=A4=9A=E5=8E=8B?= =?UTF-8?q?=E6=B5=8B=E6=97=B6=E9=95=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../performance/test/components/PerformancePressureConfig.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/business/components/performance/test/components/PerformancePressureConfig.vue b/frontend/src/business/components/performance/test/components/PerformancePressureConfig.vue index 33efdc24c6..07617d348e 100644 --- a/frontend/src/business/components/performance/test/components/PerformancePressureConfig.vue +++ b/frontend/src/business/components/performance/test/components/PerformancePressureConfig.vue @@ -118,6 +118,7 @@ From 391a2924c83dff0a1fc646c14413a6d9aca3bd58 Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Tue, 30 Mar 2021 10:04:58 +0800 Subject: [PATCH 16/18] chore: sync --- frontend/src/business/components/xpack | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/business/components/xpack b/frontend/src/business/components/xpack index 07951ba17a..2115bd28a9 160000 --- a/frontend/src/business/components/xpack +++ b/frontend/src/business/components/xpack @@ -1 +1 @@ -Subproject commit 07951ba17aef6f29e50cfd68e40de3266f9a60cd +Subproject commit 2115bd28a90854d2b6276a90878934715498c584 From e451a47f5565243884533a5aebf912aed763d706 Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Tue, 30 Mar 2021 10:10:17 +0800 Subject: [PATCH 17/18] =?UTF-8?q?refactor:=20=E4=BF=AE=E6=94=B9swagger-par?= =?UTF-8?q?se=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/pom.xml | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/backend/pom.xml b/backend/pom.xml index 3af82d43e6..be89a74d2e 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -276,18 +276,11 @@ spring-boot-starter-data-ldap - - - io.swagger - swagger-parser - 1.0.51 - - - + io.swagger.parser.v3 swagger-parser - 2.0.18 + 2.0.22 @@ -674,4 +667,4 @@ - \ No newline at end of file + From f2a6341b4cd2f6e444af3bf0513b1865de0f58f5 Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Tue, 30 Mar 2021 10:27:04 +0800 Subject: [PATCH 18/18] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=8A=A0=E8=BD=BD=E6=97=B6=E6=96=87=E4=BB=B6=E5=90=8D?= =?UTF-8?q?=E9=87=8D=E5=A4=8D=E6=B2=A1=E6=9C=89=E6=98=BE=E7=A4=BA=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=90=8D=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/performance/test/components/ExistFiles.vue | 4 ++-- .../components/performance/test/components/ExistScenarios.vue | 2 +- .../components/track/case/components/TestCaseEdit.vue | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/business/components/performance/test/components/ExistFiles.vue b/frontend/src/business/components/performance/test/components/ExistFiles.vue index fc75b9f832..bcecb0713c 100644 --- a/frontend/src/business/components/performance/test/components/ExistFiles.vue +++ b/frontend/src/business/components/performance/test/components/ExistFiles.vue @@ -157,7 +157,7 @@ export default { for (let i = 0; i < rows.length; i++) { let row = rows[i]; if (this.tableData.filter(f => f.name === row.name).length > 0) { - this.$error(this.$t('load_test.delete_file')); + this.$error(this.$t('load_test.delete_file') + ', name: ' + row.name); this.selectIds.clear(); return; } @@ -216,7 +216,7 @@ export default { } if (this.tableData.filter(f => f.name === file.name).length > 0) { - this.$error(this.$t('load_test.delete_file')); + this.$error(this.$t('load_test.delete_file') + ', name: ' + file.name); return false; } }, diff --git a/frontend/src/business/components/performance/test/components/ExistScenarios.vue b/frontend/src/business/components/performance/test/components/ExistScenarios.vue index e159ef00f0..72926742e6 100644 --- a/frontend/src/business/components/performance/test/components/ExistScenarios.vue +++ b/frontend/src/business/components/performance/test/components/ExistScenarios.vue @@ -121,7 +121,7 @@ export default { for (let i = 0; i < rows.length; i++) { let row = rows[i]; if (this.tableData.filter(f => f.name === row.name + ".jmx").length > 0) { - this.$error(this.$t('load_test.delete_file')); + this.$error(this.$t('load_test.delete_file') + ', name: ' + row.name); return; } } diff --git a/frontend/src/business/components/track/case/components/TestCaseEdit.vue b/frontend/src/business/components/track/case/components/TestCaseEdit.vue index 78f0deb323..5ed25a3951 100644 --- a/frontend/src/business/components/track/case/components/TestCaseEdit.vue +++ b/frontend/src/business/components/track/case/components/TestCaseEdit.vue @@ -923,7 +923,7 @@ export default { } if (this.tableData.filter(f => f.name === file.name).length > 0) { - this.$error(this.$t('load_test.delete_file')); + this.$error(this.$t('load_test.delete_file') + ', name: ' + file.name); return false; }