From dd10ae60a6ce6eec696494824374e8ef9fb5f37c Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Mon, 27 Sep 2021 11:57:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96)=20=E5=9C=BA=E6=99=AF=E5=A2=9E=E5=8A=A0=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=90=AF?= =?UTF-8?q?=E7=94=A8=E5=9C=BA=E6=99=AF=E7=8E=AF=E5=A2=83=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ApiAutomationController.java | 6 ++ .../dto/definition/request/ElementUtil.java | 29 +++++++- .../dto/definition/request/MsScenario.java | 30 ++++++-- .../api/service/ApiAutomationService.java | 17 ++++- .../automation/scenario/EditApiScenario.vue | 47 ++++++++---- .../scenario/common/ApiBaseComponent.vue | 3 + .../component/ApiScenarioComponent.vue | 71 ++++++++++++++++++- .../scenario/component/ComponentConfig.vue | 8 ++- .../common/select-tree/SelectTree.vue | 2 +- 9 files changed, 189 insertions(+), 24 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java index 3a90c6976d..e1ad2d3100 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java @@ -353,5 +353,11 @@ public class ApiAutomationController { return apiAutomationService.exportJmx(request); } + @PostMapping(value = "/checkScenarioEnv") + public boolean checkScenarioEnv(@RequestBody ApiScenarioWithBLOBs request) { + return apiAutomationService.checkScenarioEnv(request); + } + + } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/ElementUtil.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/ElementUtil.java index 15bd6362e0..af2a0a5676 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/ElementUtil.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/ElementUtil.java @@ -304,7 +304,28 @@ public class ElementUtil { try { for (int i = 0; i < hashTree.size(); i++) { JSONObject element = hashTree.getJSONObject(i); - if (element != null && element.get("type").toString().equals("HTTPSamplerProxy")) { + boolean isScenarioEnv = false; + ParameterConfig config = new ParameterConfig(); + if (element != null && element.get("type").toString().equals("scenario")) { + MsScenario scenario = JSONObject.toJavaObject(element, MsScenario.class); + if (scenario.isEnvironmentEnable()) { + isScenarioEnv = true; + Map envConfig = new HashMap<>(16); + Map environmentMap = (Map) element.get("environmentMap"); + 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); + env.setApiEnvironmentid(environment.getId()); + envConfig.put(projectId, env); + } + }); + config.setConfig(envConfig); + } + } + } else if (element != null && element.get("type").toString().equals("HTTPSamplerProxy")) { MsHTTPSamplerProxy httpSamplerProxy = JSON.toJavaObject(element, MsHTTPSamplerProxy.class); if (httpSamplerProxy != null && (!httpSamplerProxy.isCustomizeReq() || (httpSamplerProxy.isCustomizeReq() && httpSamplerProxy.getIsRefEnvironment()))) { @@ -320,7 +341,11 @@ public class ElementUtil { } if (element.containsKey("hashTree")) { JSONArray elementJSONArray = element.getJSONArray("hashTree"); - dataSetDomain(elementJSONArray, msParameter); + if (isScenarioEnv) { + dataSetDomain(elementJSONArray, config); + } else { + dataSetDomain(elementJSONArray, msParameter); + } } } } catch (Exception e) { 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 dad8a24edd..48fae7b315 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 @@ -64,9 +64,12 @@ public class MsScenario extends MsTestElement { @JSONField(ordinal = 27) private Map environmentMap; - @JSONField(ordinal = 24) + @JSONField(ordinal = 28) private Boolean onSampleError; + @JSONField(ordinal = 29) + private boolean environmentEnable; + private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR; public MsScenario() { @@ -152,8 +155,7 @@ public class MsScenario extends MsTestElement { } } else { Map map = config.getConfig(); - for (EnvironmentConfig evnConfig : - map.values()) { + for (EnvironmentConfig evnConfig : map.values()) { if (evnConfig.getHttpConfig() != null) { this.setMockEnvironment(evnConfig.getHttpConfig().isMock()); } @@ -174,12 +176,32 @@ public class MsScenario extends MsTestElement { //setHeader(tree, this.headers); config.setHeaders(this.headers); } + ParameterConfig newConfig = new ParameterConfig(); + if (this.isEnvironmentEnable() && this.environmentMap != null && !this.environmentMap.isEmpty()) { + 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); + env.setApiEnvironmentid(environment.getId()); + envConfig.put(projectId, env); + if (StringUtils.equals(environment.getName(), MockConfigStaticData.MOCK_EVN_NAME)) { + this.setMockEnvironment(true); + } + } + }); + newConfig.setConfig(envConfig); + } if (CollectionUtils.isNotEmpty(hashTree)) { for (MsTestElement el : hashTree) { // 给所有孩子加一个父亲标志 el.setParent(this); el.setMockEnvironment(this.isMockEnvironment()); - el.toHashTree(tree, el.getHashTree(), config); + if (this.isEnvironmentEnable()) { + el.toHashTree(tree, el.getHashTree(), newConfig); + } else { + el.toHashTree(tree, el.getHashTree(), 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 e393c69eb1..c239140e80 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -714,6 +714,10 @@ public class ApiAutomationService { } if (StringUtils.equals(tr.getType(), "scenario")) { + MsScenario scenario = (MsScenario) tr; + if (scenario.isEnvironmentEnable()) { + continue; + } env.getProjectIds().add(tr.getProjectId()); } if (CollectionUtils.isNotEmpty(tr.getHashTree())) { @@ -786,6 +790,10 @@ public class ApiAutomationService { } } if (StringUtils.equals(tr.getType(), "scenario")) { + MsScenario scenario = (MsScenario) tr; + if (scenario.isEnvironmentEnable()) { + continue; + } env.getProjectIds().add(tr.getProjectId()); } if (CollectionUtils.isNotEmpty(tr.getHashTree())) { @@ -1952,14 +1960,14 @@ public class ApiAutomationService { hashTree.set(i, object); } } else { - ApiScenarioWithBLOBs bloBs = this.getDto(object.getString("id")); + ApiScenarioWithBLOBs bloBs = apiScenarioMapper.selectByPrimaryKey(object.getString("id")); if (bloBs != null) { object = JSON.parseObject(bloBs.getScenarioDefinition()); hashTree.set(i, object); } } } else if ("scenario".equals(object.getString("type"))) { - ApiScenarioWithBLOBs bloBs = this.getDto(object.getString("id")); + ApiScenarioWithBLOBs bloBs = apiScenarioMapper.selectByPrimaryKey(object.getString("id")); if (bloBs != null) { object = JSON.parseObject(bloBs.getScenarioDefinition()); hashTree.set(i, object); @@ -2610,4 +2618,9 @@ public class ApiAutomationService { extApiScenarioMapper::getLastOrder, apiScenarioMapper::updateByPrimaryKeySelective); } + + public boolean checkScenarioEnv(ApiScenarioWithBLOBs request) { + return this.checkScenarioEnv(request, null); + } + } diff --git a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue index fe145701d0..54967468f7 100644 --- a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue +++ b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue @@ -214,6 +214,8 @@ @copyRow="copyRow" @suggestClick="suggestClick" @refReload="refReload" + @runScenario="runDebug" + @stopScenario="stop" @openScenario="openScenario"/> @@ -454,6 +456,7 @@ export default { stepFilter: new STEP, plugins: [], clearMessage: "", + runScenario: undefined, } }, created() { @@ -571,6 +574,7 @@ export default { this.debugLoading = false; } }); + this.runScenario = undefined; }, clearDebug() { this.reqError = 0; @@ -655,7 +659,9 @@ export default { this.message = getUUID(); if (data.end) { this.removeReport(); + this.runScenario = undefined; this.debugLoading = false; + this.message = "stop"; this.stopDebug = "stop"; } } @@ -775,7 +781,11 @@ export default { this.reqTotalTime = endTime - startTime + 100; } this.debugResult = resMap; - this.sort(); + if (this.runScenario && this.runScenario.hashTree) { + this.sort(this.runScenario.hashTree); + } else { + this.sort(); + } this.reloadDebug = getUUID(); }, removeReport() { @@ -1127,7 +1137,7 @@ export default { this.showHideTree = true }); }, - runDebug() { + runDebug(runScenario) { if (this.scenarioDefinition.length < 1) { return; } @@ -1149,22 +1159,32 @@ export default { this.clearMessage = getUUID().substring(0, 8); return; } + let scenario = undefined; + if (runScenario && runScenario.type === 'scenario') { + scenario = runScenario; + this.runScenario = runScenario; + } //调试时不再保存 this.debugData = { - id: this.currentScenario.id, - name: this.currentScenario.name, + id: scenario ? scenario.id : this.currentScenario.id, + name: scenario ? scenario.name : this.currentScenario.name, type: "scenario", - variables: this.currentScenario.variables, + variables: scenario ? scenario.variables : this.currentScenario.variables, referenced: 'Created', - enableCookieShare: this.enableCookieShare, - headers: this.currentScenario.headers, - environmentMap: this.projectEnvMap, - hashTree: this.scenarioDefinition, - onSampleError: this.onSampleError, + enableCookieShare: scenario ? scenario.enableCookieShare : this.enableCookieShare, + headers: scenario ? scenario.headers : this.currentScenario.headers, + environmentMap: scenario && scenario.environmentEnable ? scenario.environmentMap : this.projectEnvMap, + hashTree: scenario ? scenario.hashTree : this.scenarioDefinition, + onSampleError: scenario ? scenario.onSampleError : this.onSampleError, }; + if (scenario && scenario.environmentEnable) { + this.debugData.environmentEnable = scenario.environmentEnable; + this.debugLoading = false; + }else{ + this.debugLoading = true; + } this.reportId = getUUID().substring(0, 8); this.debug = true; - this.debugLoading = true; }) }) } else { @@ -1219,8 +1239,7 @@ export default { } return true; } else if (dropType === "inner" && dropNode.data.referenced !== 'REF' && dropNode.data.referenced !== 'Deleted' - && (this.stepFilter.get(dropNode.data.type) && this.stepFilter.get(dropNode.data.type).indexOf(draggingNode.data.type) != -1) - && !draggingNode.data.disabled) { + && (this.stepFilter.get(dropNode.data.type) && this.stepFilter.get(dropNode.data.type).indexOf(draggingNode.data.type) != -1)) { return true; } return false; @@ -1412,6 +1431,8 @@ export default { this.debugLoading = false; this.debugVisible = false; this.loading = false; + this.runScenario = undefined; + this.message = "stop"; this.clearMessage = getUUID().substring(0, 8); }, showScenarioParameters() { diff --git a/frontend/src/business/components/api/automation/scenario/common/ApiBaseComponent.vue b/frontend/src/business/components/api/automation/scenario/common/ApiBaseComponent.vue index b1cebd82ff..cc7f6f1384 100644 --- a/frontend/src/business/components/api/automation/scenario/common/ApiBaseComponent.vue +++ b/frontend/src/business/components/api/automation/scenario/common/ApiBaseComponent.vue @@ -26,6 +26,9 @@ + + +
diff --git a/frontend/src/business/components/api/automation/scenario/component/ApiScenarioComponent.vue b/frontend/src/business/components/api/automation/scenario/component/ApiScenarioComponent.vue index 831c4448a9..f00496b2c9 100644 --- a/frontend/src/business/components/api/automation/scenario/component/ApiScenarioComponent.vue +++ b/frontend/src/business/components/api/automation/scenario/component/ApiScenarioComponent.vue @@ -19,7 +19,6 @@ {{ $t('api_test.automation.reference_deleted') }} {{ $t('commons.copy') }} {{ $t('api_test.scenario.reference') }} - {{ getProjectName(scenario.projectId) }} + + @@ -66,6 +82,9 @@ export default { }, watch: { message() { + if (this.message === "stop") { + this.scenario.run = false; + } this.reload(); }, }, @@ -121,6 +140,35 @@ export default { }, }, methods: { + run() { + this.scenario.run = true; + this.$emit('runScenario', this.scenario); + }, + stop() { + this.scenario.run = false; + this.$emit('stopScenario'); + this.reload(); + }, + checkEnv() { + this.$post("/api/automation/checkScenarioEnv", {scenarioDefinition: JSON.stringify(this.scenario), projectId: this.projectId}, res => { + if (this.scenario.environmentEnable && !res.data) { + this.scenario.environmentEnable = false; + this.$warning("当前场景没有环境,需要先设置自身环境"); + return; + } + this.setDomain(); + }); + }, + setDomain() { + if (this.scenario.environmentEnable) { + this.$post("/api/automation/setDomain", {definition: JSON.stringify(this.scenario)}, res => { + if (res.data) { + let data = JSON.parse(res.data); + this.scenario.hashTree = data.hashTree; + } + }) + } + }, getCode() { if (this.node && this.node.data.code && this.node.data.debug) { if (this.node.data.code && this.node.data.code === 'error') { @@ -210,10 +258,30 @@ export default { color: #F56C6C; } +.ms-test-running { + color: #6D317C; +} + .ms-req-success { color: #67C23A; } +.ms-btn { + background-color: #409EFF; + color: white; +} + +.ms-btn-flot { + margin: 20px; + float: right; +} + +.stop-btn { + background-color: #E62424; + border-color: #EE6161; + color: white; +} + .ms-step-debug-code { display: inline-block; margin: 0 5px; @@ -224,6 +292,7 @@ export default { white-space: nowrap; width: 60px; } + .ms-test-running { color: #6D317C; } diff --git a/frontend/src/business/components/api/automation/scenario/component/ComponentConfig.vue b/frontend/src/business/components/api/automation/scenario/component/ComponentConfig.vue index 3f13b85e96..45f4c0de9a 100644 --- a/frontend/src/business/components/api/automation/scenario/component/ComponentConfig.vue +++ b/frontend/src/business/components/api/automation/scenario/component/ComponentConfig.vue @@ -4,7 +4,7 @@ + @remove="remove" @runScenario="runScenario" @stopScenario="stopScenario" @copyRow="copyRow" @refReload="refReload" @openScenario="openScenario" :project-list="projectList" :env-map="envMap" :message="message"/>
@@ -184,6 +184,12 @@ export default { }, refReload(data, node) { this.$emit('refReload', data, node); + }, + runScenario(scenario) { + this.$emit('runScenario', scenario); + }, + stopScenario(){ + this.$emit('stopScenario'); } } } diff --git a/frontend/src/business/components/common/select-tree/SelectTree.vue b/frontend/src/business/components/common/select-tree/SelectTree.vue index 5d61c9a383..87fcaddea6 100644 --- a/frontend/src/business/components/common/select-tree/SelectTree.vue +++ b/frontend/src/business/components/common/select-tree/SelectTree.vue @@ -412,7 +412,7 @@ export default { }, data:{ handler:function(){ - if(this.defaultKey && this.defaultKey.length > 0){ + if(this.defaultKey && this.defaultKey.length > 0 && this.defaultKey instanceof Array){ this.$refs.tree.setCheckedKeys(this.defaultKey); } },