From 492dbb42bd3e454d5888893cec2327eb71631926 Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Wed, 17 Mar 2021 11:45:49 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=E6=B5=8B=E8=AF=95=E8=AE=A1?= =?UTF-8?q?=E5=88=92=E8=84=91=E5=9B=BE=E7=BC=96=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TestPlanTestCaseController.java | 6 ++ .../service/TestPlanTestCaseService.java | 7 ++ .../service/TestReviewTestCaseService.java | 2 + .../track/common/minder/TestPlanMinder.vue | 94 ++++++++----------- .../track/common/minder/TestReviewMinder.vue | 7 +- 5 files changed, 55 insertions(+), 61 deletions(-) diff --git a/backend/src/main/java/io/metersphere/track/controller/TestPlanTestCaseController.java b/backend/src/main/java/io/metersphere/track/controller/TestPlanTestCaseController.java index f3362abbd0..0082a69169 100644 --- a/backend/src/main/java/io/metersphere/track/controller/TestPlanTestCaseController.java +++ b/backend/src/main/java/io/metersphere/track/controller/TestPlanTestCaseController.java @@ -101,6 +101,12 @@ public class TestPlanTestCaseController { testPlanTestCaseService.editTestCase(testPlanTestCase); } + @PostMapping("/minder/edit") + @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) + public void editTestCaseForMinder(@RequestBody List testPlanTestCases) { + testPlanTestCaseService.editTestCaseForMinder(testPlanTestCases); + } + @PostMapping("/batch/edit") @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) public void editTestCaseBath(@RequestBody TestPlanCaseBatchRequest request) { diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanTestCaseService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanTestCaseService.java index 7617f37d07..3b103d1aaf 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanTestCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanTestCaseService.java @@ -154,4 +154,11 @@ public class TestPlanTestCaseService { public List listForMinder(String planId) { return extTestPlanTestCaseMapper.listForMinder(planId); } + + public void editTestCaseForMinder(List testPlanTestCases) { + testPlanTestCases.forEach(item -> { + item.setUpdateTime(System.currentTimeMillis()); + testPlanTestCaseMapper.updateByPrimaryKeySelective(item); + }); + } } diff --git a/backend/src/main/java/io/metersphere/track/service/TestReviewTestCaseService.java b/backend/src/main/java/io/metersphere/track/service/TestReviewTestCaseService.java index d2576841f5..e77d06373d 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestReviewTestCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestReviewTestCaseService.java @@ -172,6 +172,8 @@ public class TestReviewTestCaseService { testCase.setId(item.getCaseId()); testCase.setReviewStatus(item.getStatus()); testCaseList.add(testCase); + testCase.setUpdateTime(System.currentTimeMillis()); + item.setUpdateTime(System.currentTimeMillis()); testCaseReviewTestCaseMapper.updateByPrimaryKeySelective(item); }); testCaseList.forEach(testCaseMapper::updateByPrimaryKeySelective); diff --git a/frontend/src/business/components/track/common/minder/TestPlanMinder.vue b/frontend/src/business/components/track/common/minder/TestPlanMinder.vue index f15a0c0ecd..012b08ece6 100644 --- a/frontend/src/business/components/track/common/minder/TestPlanMinder.vue +++ b/frontend/src/business/components/track/common/minder/TestPlanMinder.vue @@ -3,6 +3,7 @@ v-loading="result.loading" :tree-nodes="treeNodes" :data-map="dataMap" + :tags="tags" @save="save" /> @@ -15,9 +16,9 @@ name: "TestPlanMinder", components: {MsModuleMinder}, data() { return{ - testCase: [], dataMap: new Map(), - result: {} + result: {}, + tags: ['通过', '失败', '阻塞', '跳过'], } }, props: { @@ -44,24 +45,30 @@ name: "TestPlanMinder", getTestCases() { if (this.projectId) { this.result = this.$get('/test/plan/case/list/minder/' + this.planId, response => { - this.testCase = response.data; - this.dataMap = getTestCaseDataMap(this.testCase); + this.dataMap = getTestCaseDataMap(response.data, true, (data, item) => { + if (item.stats === 'Pass') { + data.resource.push("通过"); + } else if (item.reviewStatus === 'Failure') { + data.resource.push("失败"); + } else if (item.reviewStatus === 'Blocking') { + data.resource.push("阻塞"); + } else if (item.reviewStatus === 'Skip') { + data.resource.push("跳过"); + } else { + data.resource.push("未开始"); + } + }); }); } }, save(data) { - // let saveCases = []; - // this.buildSaveCase(data.root, saveCases, undefined); - // console.log(saveCases); - // let param = { - // projectId: this.projectId, - // data: saveCases - // } - // this.result = this.$post('/test/case/minder/edit', param, () => { - // this.$success(this.$t('commons.save_success')); - // }); + let saveCases = []; + this.buildSaveCase(data.root, saveCases); + this.result = this.$post('/test/plan/case/minder/edit', saveCases, () => { + this.$success(this.$t('commons.save_success')); + }); }, - buildSaveCase(root, saveCases, parent) { + buildSaveCase(root, saveCases) { let data = root.data; if (data.resource && data.resource.indexOf("用例") > -1) { this._buildSaveCase(root, saveCases, parent); @@ -73,52 +80,27 @@ name: "TestPlanMinder", } } }, - _buildSaveCase(node, saveCases, parent) { + _buildSaveCase(node, saveCases) { let data = node.data; - let isChange = false; + if (!data.changed) { + return; + } let testCase = { id: data.id, - name: data.text, - nodeId: parent ? parent.id : "", - nodePath: parent ? parent.path : "", - type: data.type ? data.type : 'functional', - method: data.method ? data.method : 'manual', - maintainer: data.maintainer, - priority: 'P' + data.priority, }; - if (data.changed) isChange = true; - let steps = []; - let stepNum = 1; - if (node.children) { - node.children.forEach((childNode) => { - let childData = childNode.data; - if (childData.resource && childData.resource.indexOf('前置条件') > -1) { - testCase.prerequisite = childData.text; - } else if (childData.resource && childData.resource.indexOf('备注') > -1) { - testCase.remark = childData.text; - } else { - // 测试步骤 - let step = {}; - step.num = stepNum++; - step.desc = childData.text; - if (childNode.children) { - let result = ""; - childNode.children.forEach((child) => { - result += child.data.text; - if (child.data.changed) isChange = true; - }) - step.result = result; - } - steps.push(step); - } - if (childData.changed) isChange = true; - }) + if (data.resource.length > 1) { + if (data.resource.indexOf('失败') > -1) { + testCase.status = 'Failure'; + } else if (data.resource.indexOf('通过') > -1) { + testCase.status = 'Pass'; + } else if (data.resource.indexOf('阻塞') > -1) { + testCase.status = 'Blocking'; + } else if (data.resource.indexOf('跳过') > -1) { + testCase.status = 'Skip'; + } } - testCase.steps = JSON.stringify(steps); - if (isChange) { - saveCases.push(testCase); - } - }, + saveCases.push(testCase); + } } } diff --git a/frontend/src/business/components/track/common/minder/TestReviewMinder.vue b/frontend/src/business/components/track/common/minder/TestReviewMinder.vue index a6444f3ede..b42b16be99 100644 --- a/frontend/src/business/components/track/common/minder/TestReviewMinder.vue +++ b/frontend/src/business/components/track/common/minder/TestReviewMinder.vue @@ -16,7 +16,6 @@ name: "TestReviewMinder", components: {MsModuleMinder}, data() { return{ - testCase: [], dataMap: new Map(), tags: ['通过', '不通过'], result: {} @@ -60,10 +59,8 @@ name: "TestReviewMinder", } }, save(data) { - console.log(data); let saveCases = []; this.buildSaveCase(data.root, saveCases); - console.log(saveCases); this.result = this.$post('/test/review/case/minder/edit', saveCases, () => { this.$success(this.$t('commons.save_success')); }); @@ -91,9 +88,9 @@ name: "TestReviewMinder", // name: data.text, }; if (data.resource.length > 1) { - if (data.resource.indexOf('不通过')) { + if (data.resource.indexOf('不通过') > -1) { testCase.status = 'UnPass'; - } else if (data.resource.indexOf('通过')) { + } else if (data.resource.indexOf('通过') > -1) { testCase.status = 'Pass'; } } From e30209e990436d9d57ca834cafb2dda4ee5d3692 Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Wed, 17 Mar 2021 13:03:59 +0800 Subject: [PATCH 2/4] =?UTF-8?q?refactor:=20=E6=B5=8B=E8=AF=95=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E4=B8=8E=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92=E8=84=91?= =?UTF-8?q?=E5=9B=BE=E7=BC=96=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/package.json | 2 +- .../components/common/components/MsModuleMinder.vue | 7 +++++++ .../components/track/common/minder/TestCaseMinder.vue | 2 ++ .../components/track/common/minder/TestPlanMinder.vue | 1 + .../components/track/common/minder/TestReviewMinder.vue | 1 + 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index 95dc60202e..6dc8af31e0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -49,7 +49,7 @@ "xml-js": "^1.6.11", "yan-progress": "^1.0.3", "jsonpath": "^1.1.0", - "vue-minder-editor-plus": "^1.0.17", + "vue-minder-editor-plus": "^1.0.18", "jsencrypt": "^3.1.0" }, "devDependencies": { diff --git a/frontend/src/business/components/common/components/MsModuleMinder.vue b/frontend/src/business/components/common/components/MsModuleMinder.vue index b57b3fe069..f489472ba8 100644 --- a/frontend/src/business/components/common/components/MsModuleMinder.vue +++ b/frontend/src/business/components/common/components/MsModuleMinder.vue @@ -7,6 +7,7 @@ :height="700" :progress-enable="false" :tags="tags" + :distinct-tags="distinctTags" @save="save" /> @@ -36,6 +37,12 @@ export default { return [] } }, + distinctTags: { + type: Array, + default() { + return [] + } + } }, data() { return { diff --git a/frontend/src/business/components/track/common/minder/TestCaseMinder.vue b/frontend/src/business/components/track/common/minder/TestCaseMinder.vue index 85340c98f2..e5ddc1fbfe 100644 --- a/frontend/src/business/components/track/common/minder/TestCaseMinder.vue +++ b/frontend/src/business/components/track/common/minder/TestCaseMinder.vue @@ -3,6 +3,7 @@ v-loading="result.loading" :tree-nodes="treeNodes" :data-map="dataMap" + :tags="tags" @save="save" /> @@ -17,6 +18,7 @@ name: "TestCaseMinder", return{ testCase: [], dataMap: new Map(), + tags: ['用例', '测试步骤', '预期结果', '备注'], result: {} } }, diff --git a/frontend/src/business/components/track/common/minder/TestPlanMinder.vue b/frontend/src/business/components/track/common/minder/TestPlanMinder.vue index 012b08ece6..b9a163da1f 100644 --- a/frontend/src/business/components/track/common/minder/TestPlanMinder.vue +++ b/frontend/src/business/components/track/common/minder/TestPlanMinder.vue @@ -4,6 +4,7 @@ :tree-nodes="treeNodes" :data-map="dataMap" :tags="tags" + :distinct-tags="[...tags, '未开始']" @save="save" /> diff --git a/frontend/src/business/components/track/common/minder/TestReviewMinder.vue b/frontend/src/business/components/track/common/minder/TestReviewMinder.vue index b42b16be99..6295625b19 100644 --- a/frontend/src/business/components/track/common/minder/TestReviewMinder.vue +++ b/frontend/src/business/components/track/common/minder/TestReviewMinder.vue @@ -4,6 +4,7 @@ :tree-nodes="treeNodes" :data-map="dataMap" :tags="tags" + :distinct-tags="[...tags, '未开始']" @save="save" /> From 51e0461dc3754b470e16e3d94ca90b02dad87dd2 Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Wed, 17 Mar 2021 13:17:33 +0800 Subject: [PATCH 3/4] =?UTF-8?q?refactor:=20=E8=84=91=E5=9B=BE=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E6=AD=A5=E9=AA=A4=E5=92=8C=E9=A2=84=E6=9C=9F=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=E4=B8=8D=E5=8A=A0=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/business/components/common/head/HeaderCustom.vue | 1 - .../components/track/case/components/TestCaseEdit.vue | 2 -- .../components/track/common/minder/TestCaseMinder.vue | 2 +- .../business/components/track/common/minder/minderUtils.js | 6 +++--- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/frontend/src/business/components/common/head/HeaderCustom.vue b/frontend/src/business/components/common/head/HeaderCustom.vue index c50d5bb577..c99050641c 100644 --- a/frontend/src/business/components/common/head/HeaderCustom.vue +++ b/frontend/src/business/components/common/head/HeaderCustom.vue @@ -54,7 +54,6 @@ export default { /*this.optionalField = items*/ }, saveHeader() { - console.log(this.type) let param = { userId: getCurrentUser().id, type: this.type, diff --git a/frontend/src/business/components/track/case/components/TestCaseEdit.vue b/frontend/src/business/components/track/case/components/TestCaseEdit.vue index c1800b8268..4ddd1d4e2a 100644 --- a/frontend/src/business/components/track/case/components/TestCaseEdit.vue +++ b/frontend/src/business/components/track/case/components/TestCaseEdit.vue @@ -679,8 +679,6 @@ export default { return param; }, getOption(param) { - console.log(this.type) - console.log("3452") let formData = new FormData(); let type = this.type if (this.type === 'copy') { diff --git a/frontend/src/business/components/track/common/minder/TestCaseMinder.vue b/frontend/src/business/components/track/common/minder/TestCaseMinder.vue index e5ddc1fbfe..fd374674d8 100644 --- a/frontend/src/business/components/track/common/minder/TestCaseMinder.vue +++ b/frontend/src/business/components/track/common/minder/TestCaseMinder.vue @@ -18,7 +18,7 @@ name: "TestCaseMinder", return{ testCase: [], dataMap: new Map(), - tags: ['用例', '测试步骤', '预期结果', '备注'], + tags: ['用例', '前置条件', '备注'], result: {} } }, diff --git a/frontend/src/business/components/track/common/minder/minderUtils.js b/frontend/src/business/components/track/common/minder/minderUtils.js index bbe404d280..29c77aa44c 100644 --- a/frontend/src/business/components/track/common/minder/minderUtils.js +++ b/frontend/src/business/components/track/common/minder/minderUtils.js @@ -42,11 +42,11 @@ function parseChildren(nodeItem, item, isDisable) { let children = []; _parseChildren(children, item.prerequisite, "前置条件", isDisable); item.steps.forEach((step) => { - let descNode = _parseChildren(children, step.desc, "测试步骤", isDisable); + let descNode = _parseChildren(children, step.desc, undefined, isDisable); if (descNode) { descNode.data.num = step.num; descNode.children = []; - _parseChildren(descNode.children, step.result, "预期结果", isDisable); + _parseChildren(descNode.children, step.result, undefined, isDisable); } }); _parseChildren(children, item.remark, "备注", isDisable); @@ -58,7 +58,7 @@ function _parseChildren(children, k, v, isDisable) { let node = { data: { text: k, - resource: [v] + resource: v ? [v] : [] } } if (isDisable) { From e58dcf4d889c4f6a3c885a2da34b1a753fa9fc20 Mon Sep 17 00:00:00 2001 From: shiziyuan9527 Date: Wed, 17 Mar 2021 14:05:44 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20=E6=89=B9=E9=87=8F=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E7=8E=AF=E5=A2=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ApiAutomationController.java | 2 +- .../api/dto/automation/ApiScenarioDTO.java | 2 + .../api/service/ApiAutomationService.java | 50 +++++++++---------- .../base/mapper/ext/ExtApiScenarioMapper.xml | 2 - .../TestCaseReviewScenarioCaseService.java | 37 -------------- .../service/TestPlanScenarioCaseService.java | 31 ------------ .../automation/scenario/ApiScenarioList.vue | 14 ++---- .../scenario/testplan/TestPlanList.vue | 11 ++-- .../track/case/components/BatchEdit.vue | 25 +++++++--- .../comonents/api/RelevanceScenarioList.vue | 7 ++- .../api/TestCaseScenarioRelevance.vue | 6 +-- .../comonents/api/TestPlanApiScenarioList.vue | 8 +-- 12 files changed, 66 insertions(+), 129 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 fa4e5d86ef..bc38ce887f 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java @@ -86,7 +86,7 @@ public class ApiAutomationController { } @GetMapping("/getApiScenario/{id}") - public ApiScenario getScenarioDefinition(@PathVariable String id) { + public ApiScenarioDTO getScenarioDefinition(@PathVariable String id) { return apiAutomationService.getApiScenario(id); } diff --git a/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenarioDTO.java b/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenarioDTO.java index b1f9e6e044..540ee78564 100644 --- a/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenarioDTO.java +++ b/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenarioDTO.java @@ -18,4 +18,6 @@ public class ApiScenarioDTO extends ApiScenarioWithBLOBs { * 场景跨项目ID */ private List projectIds; + + private String caseId; } 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 ebc994c1c4..9da3974953 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -94,42 +94,38 @@ public class ApiAutomationService { public List list(ApiScenarioRequest request) { request = this.initRequest(request, true, true); List list = extApiScenarioMapper.list(request); - setApiScenarioProjectIds(list); return list; } public List listReview(ApiScenarioRequest request) { request = this.initRequest(request, true, true); List list = extApiScenarioMapper.listReview(request); - setApiScenarioProjectIds(list); return list; } - private void setApiScenarioProjectIds(List list) { + private void setApiScenarioProjectIds(ApiScenarioDTO data) { // 如果场景步骤涉及多项目,则把涉及到的项目ID保存在projectIds属性 - list.forEach(data -> { - List idList = new ArrayList<>(); - String definition = data.getScenarioDefinition(); - if (StringUtils.isNotBlank(definition)) { - RunDefinitionRequest d = JSON.parseObject(definition, RunDefinitionRequest.class); + List idList = new ArrayList<>(); + String definition = data.getScenarioDefinition(); + if (StringUtils.isNotBlank(definition)) { + RunDefinitionRequest d = JSON.parseObject(definition, RunDefinitionRequest.class); - if (d != null) { - Map map = d.getEnvironmentMap(); - if (map != null) { - if (map.isEmpty()) { - List ids = (List) JSONPath.read(definition, "$..projectId"); - idList.addAll(new HashSet<>(ids)); - } else { - Set set = d.getEnvironmentMap().keySet(); - idList = new ArrayList<>(set); - } + if (d != null) { + Map map = d.getEnvironmentMap(); + if (map != null) { + if (map.isEmpty()) { + List ids = (List) JSONPath.read(definition, "$..projectId"); + idList.addAll(new HashSet<>(ids)); } else { - // 兼容历史数据,无EnvironmentMap直接赋值场景所属项目 - idList.add(data.getProjectId()); + Set set = d.getEnvironmentMap().keySet(); + idList = new ArrayList<>(set); } + } else { + // 兼容历史数据,无EnvironmentMap直接赋值场景所属项目 + idList.add(data.getProjectId()); } - } - data.setProjectIds(idList); - }); + + } + data.setProjectIds(idList); } /** @@ -333,8 +329,12 @@ public class ApiAutomationService { } } - public ApiScenarioWithBLOBs getApiScenario(String id) { - return apiScenarioMapper.selectByPrimaryKey(id); + public ApiScenarioDTO getApiScenario(String id) { + ApiScenarioDTO apiScenarioDTO = new ApiScenarioDTO(); + ApiScenarioWithBLOBs scenarioWithBLOBs = apiScenarioMapper.selectByPrimaryKey(id); + BeanUtils.copyBean(apiScenarioDTO, scenarioWithBLOBs); + setApiScenarioProjectIds(apiScenarioDTO); + return apiScenarioDTO; } public List getApiScenarios(List ids) { diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml index 033111900a..c7db6225fe 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml @@ -134,7 +134,6 @@