diff --git a/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java b/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java index b7886c9379..b8639fbd0e 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java @@ -198,11 +198,11 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl apiDefinitionService.addResult(testResult); //测试计划定时任务-接口执行逻辑的话,需要同步测试计划的报告数据 - if (StringUtils.equals(this.runMode, ApiRunMode.SCHEDULE_API_PLAN.name())) { + if (StringUtils.equalsAny(this.runMode, ApiRunMode.SCHEDULE_API_PLAN.name(), ApiRunMode.JENKINS_API_PLAN.name())) { apiDefinitionExecResultService.saveApiResultByScheduleTask(testResult, ApiRunMode.SCHEDULE_API_PLAN.name()); List testPlanReportIdList = new ArrayList<>(); testPlanReportIdList.add(debugReportId); - for(String testPlanReportId : testPlanReportIdList) { // 更新每个测试计划的状态 + for (String testPlanReportId : testPlanReportIdList) { // 更新每个测试计划的状态 testPlanReportService.checkTestPlanStatus(testPlanReportId); } testPlanReportService.updateReport(testPlanReportIdList, ApiRunMode.SCHEDULE_API_PLAN.name(), ReportTriggerMode.SCHEDULE.name()); diff --git a/backend/src/main/java/io/metersphere/track/service/TestCaseReviewService.java b/backend/src/main/java/io/metersphere/track/service/TestCaseReviewService.java index 3a6d74178e..3582052a02 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestCaseReviewService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestCaseReviewService.java @@ -331,20 +331,6 @@ public class TestCaseReviewService { } public void testReviewRelevance(ReviewRelevanceRequest request) { - String reviewId = request.getReviewId(); - List userIds = getTestCaseReviewerIds(reviewId); - - String creator = ""; - TestCaseReview review = testCaseReviewMapper.selectByPrimaryKey(reviewId); - if (review != null) { - creator = review.getCreator(); - } - - String currentId = SessionUtils.getUser().getId(); - if (!userIds.contains(currentId) && !StringUtils.equals(creator, currentId)) { - MSException.throwException("没有权限,不能关联用例!"); - } - List testCaseIds = request.getTestCaseIds(); if (testCaseIds.isEmpty()) { diff --git a/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue b/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue index 038a86345a..a3b7e1afe8 100644 --- a/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue +++ b/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue @@ -69,7 +69,8 @@ diff --git a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue index 4ebeeea4c4..78c24f661f 100644 --- a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue +++ b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue @@ -116,7 +116,9 @@ + :project-list="projectList" ref="envPopover" + :disabled="scenarioDefinition.length < 1" + :is-read-only="scenarioDefinition.length < 1"/> {{$t('api_test.request.debug')}} @@ -201,7 +203,11 @@ @closePage="close" @unFullScreen="unFullScreen" @showAllBtn="showAllBtn" @runDebug="runDebug" @setProjectEnvMap="setProjectEnvMap" @showScenarioParameters="showScenarioParameters" @setCookieShare="setCookieShare" ref="maximizeHeader"/> - + @@ -310,6 +316,8 @@ projectList: [], debugResult: new Map, drawer: false, + isHaveExec: false, + isExecWithOutEnv: true } }, created() { @@ -580,10 +588,27 @@ 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; } - if (!arr[i].projectId) { - // 如果自身没有ID并且场景有ID则赋值场景ID,否则赋值当前项目ID - arr[i].projectId = scenarioProjectId ? scenarioProjectId : this.projectId; + + 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].hashTree != undefined && arr[i].hashTree.length > 0) { this.recursiveSorting(arr[i].hashTree, arr[i].projectId); } @@ -593,7 +618,21 @@ } } }, + canExecWithOutEnv(type, path) { + return type !== ELEMENT_TYPE.HTTPSamplerProxy ? !this.checkCanExec(type) : this.isHTTPFullPath(path); + }, + 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; @@ -606,6 +645,23 @@ if (!this.scenarioDefinition[i].projectId) { 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); } @@ -626,7 +682,6 @@ this.customizeRequest = {}; this.sort(); this.reload(); - this.initProjectIds(); }, addScenario(arr) { if (arr && arr.length > 0) { @@ -649,7 +704,6 @@ this.isBtnHide = false; this.sort(); this.reload(); - this.initProjectIds(); }, setApiParameter(item, refType, referenced) { let request = {}; @@ -691,7 +745,6 @@ this.isBtnHide = false; this.sort(); this.reload(); - this.initProjectIds(); }, getMaintainerOptions() { let workspaceId = localStorage.getItem(WORKSPACE_ID); @@ -718,7 +771,6 @@ hashTree.splice(index, 1); this.sort(); this.reload(); - this.initProjectIds(); } } }); @@ -749,10 +801,19 @@ }, runDebug() { /*触发执行操作*/ - let sign = this.$refs.envPopover.checkEnv(); - if (!sign) { + if (!this.isHaveExec) { + this.$warning("无可执行步骤!"); return; } + + // 运行时是否需要检查环境 + if (!this.isExecWithOutEnv) { + let sign = this.$refs.envPopover.checkEnv(); + if (!sign) { + return; + } + } + this.$refs['currentScenario'].validate((valid) => { if (valid) { Promise.all([ @@ -1000,7 +1061,6 @@ } } this.sort(); - this.initProjectIds(); // this.getEnvironments(); }) } @@ -1071,19 +1131,8 @@ }) }, 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/EnvPopover.vue b/frontend/src/business/components/api/automation/scenario/EnvPopover.vue index f17b968995..bc7296c026 100644 --- a/frontend/src/business/components/api/automation/scenario/EnvPopover.vue +++ b/frontend/src/business/components/api/automation/scenario/EnvPopover.vue @@ -3,6 +3,7 @@ v-model="visible" placement="bottom" width="400" + :disabled="isReadOnly" @show="showPopover" trigger="click"> 1) { arr[i].countController.proceed = true; } - if (!arr[i].projectId) { - arr[i].projectId = scenarioProjectId ? scenarioProjectId : this.projectId; + 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].hashTree != undefined && arr[i].hashTree.length > 0) { this.recursiveSorting(arr[i].hashTree, arr[i].projectId); @@ -508,7 +530,24 @@ } } }, + canExecWithOutEnv(type, path) { + return type !== ELEMENT_TYPE.HTTPSamplerProxy ? !this.checkCanExec(type) : this.isHTTPFullPath(path); + }, + 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; @@ -521,6 +560,26 @@ if (!this.scenarioDefinition[i].projectId) { 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); } @@ -541,7 +600,6 @@ this.customizeRequest = {}; this.sort(); this.reload(); - this.initProjectIds(); }, addScenario(arr) { if (arr && arr.length > 0) { @@ -559,7 +617,6 @@ } this.sort(); this.reload(); - this.initProjectIds(); this.scenarioVisible = false; }, setApiParameter(item, refType, referenced) { @@ -601,7 +658,6 @@ }); this.sort(); this.reload(); - this.initProjectIds(); }, openTagConfig() { if (!this.projectId) { @@ -622,7 +678,6 @@ hashTree.splice(index, 1); this.sort(); this.reload(); - this.initProjectIds(); } } }); @@ -919,19 +974,8 @@ 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 2588a23bb2..e6382b985c 100644 --- a/frontend/src/business/components/api/automation/scenario/maximize/ScenarioHeader.vue +++ b/frontend/src/business/components/api/automation/scenario/maximize/ScenarioHeader.vue @@ -19,6 +19,8 @@ 共享cookie {{$t('api_test.request.debug')}} diff --git a/frontend/src/business/components/api/definition/components/list/ApiCaseSimpleList.vue b/frontend/src/business/components/api/definition/components/list/ApiCaseSimpleList.vue index 58c29b614b..6eba64260c 100644 --- a/frontend/src/business/components/api/definition/components/list/ApiCaseSimpleList.vue +++ b/frontend/src/business/components/api/definition/components/list/ApiCaseSimpleList.vue @@ -353,7 +353,10 @@ export default { } }) if (this.$refs.caseTable) { - setTimeout(this.$refs.caseTable.doLayout, 200) + setTimeout(() => { + this.$refs.caseTable.doLayout(); + this.result.loading = false; + }, 500) } this.$nextTick(function(){ this.checkTableRowIsSelect(); diff --git a/frontend/src/business/components/api/definition/components/list/ApiList.vue b/frontend/src/business/components/api/definition/components/list/ApiList.vue index 7a183da83b..7a3ba079aa 100644 --- a/frontend/src/business/components/api/definition/components/list/ApiList.vue +++ b/frontend/src/business/components/api/definition/components/list/ApiList.vue @@ -465,7 +465,10 @@ } }) if (this.$refs.apiDefinitionTable) { - setTimeout(this.$refs.apiDefinitionTable.doLayout, 200) + setTimeout(() => { + this.$refs.apiDefinitionTable.doLayout(); + this.result.loading = false; + }, 500) } // nexttick:表格加载完成之后触发。判断是否需要勾选行 this.$nextTick(function(){ diff --git a/frontend/src/business/components/track/case/components/TestCaseList.vue b/frontend/src/business/components/track/case/components/TestCaseList.vue index cf05354822..a1241f5dd7 100644 --- a/frontend/src/business/components/track/case/components/TestCaseList.vue +++ b/frontend/src/business/components/track/case/components/TestCaseList.vue @@ -393,7 +393,10 @@ export default { item.tags = JSON.parse(item.tags); }) if (this.$refs.table) { - setTimeout(this.$refs.table.doLayout, 200) + setTimeout(() => { + this.$refs.table.doLayout(); + this.result.loading = false; + }, 500) } this.$nextTick(function(){ diff --git a/frontend/src/business/components/track/plan/view/comonents/functional/FunctionalTestCaseList.vue b/frontend/src/business/components/track/plan/view/comonents/functional/FunctionalTestCaseList.vue index 7c21e48f3a..c23f1847a4 100644 --- a/frontend/src/business/components/track/plan/view/comonents/functional/FunctionalTestCaseList.vue +++ b/frontend/src/business/components/track/plan/view/comonents/functional/FunctionalTestCaseList.vue @@ -476,7 +476,10 @@ export default { } this.selectRows.clear(); if (this.$refs.table) { - setTimeout(this.$refs.table.doLayout, 200) + setTimeout(() => { + this.$refs.table.doLayout(); + this.result.loading = false; + }, 500) } }); }