diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java index 6ca67bba17..ce580ed8da 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java @@ -201,7 +201,7 @@ public abstract class MsTestElement { return null; } - protected void addCsvDataSet(HashTree tree, List variables,ParameterConfig config) { + protected void addCsvDataSet(HashTree tree, List variables, ParameterConfig config) { if (CollectionUtils.isNotEmpty(variables)) { List list = variables.stream().filter(ScenarioVariable::isCSVValid).collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(list)) { @@ -276,10 +276,7 @@ public abstract class MsTestElement { if (element.getParent() == null) { return; } - if (MsTestElementConstants.LoopController.name().equals(element.getType())) { - return; - } - path.append(element.getResourceId()).append("/"); + path.append(StringUtils.isEmpty(element.getName()) ? element.getType() : element.getName()).append("^@~@^"); getFullPath(element.getParent(), path); } @@ -300,7 +297,6 @@ public abstract class MsTestElement { // 获取全路径以备后面使用 StringBuilder fullPath = new StringBuilder(); getFullPath(parent, fullPath); - return fullPath + "<->" + parent.getName(); } return ""; diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/unknown/MsJmeterElement.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/unknown/MsJmeterElement.java index 060fbd3215..e5f2027080 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/unknown/MsJmeterElement.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/unknown/MsJmeterElement.java @@ -66,6 +66,8 @@ public class MsJmeterElement extends MsTestElement { } if (CollectionUtils.isNotEmpty(hashTree)) { for (MsTestElement el : hashTree) { + // 给所有孩子加一个父亲标志 + el.setParent(this); el.toHashTree(elementTree, el.getHashTree(), config); } } diff --git a/backend/src/main/java/io/metersphere/api/jmeter/TestResult.java b/backend/src/main/java/io/metersphere/api/jmeter/TestResult.java index e5d705b46e..94e9a9213d 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/TestResult.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/TestResult.java @@ -43,50 +43,16 @@ public class TestResult { private static final String SEPARATOR = "<->"; public void addScenario(ScenarioResult result) { - Map> requestResultMap = new LinkedHashMap<>(); if (result != null && CollectionUtils.isNotEmpty(result.getRequestResults())) { result.getRequestResults().forEach(item -> { if (StringUtils.isNotEmpty(item.getName()) && item.getName().indexOf(SEPARATOR) != -1) { String array[] = item.getName().split(SEPARATOR); - String scenarioName = item.getName().replace(array[0] + SEPARATOR, ""); - item.setName(array[0]); - if (requestResultMap.containsKey(scenarioName)) { - requestResultMap.get(scenarioName).add(item); - } else { - List requestResults = new LinkedList<>(); - requestResults.add(item); - requestResultMap.put(scenarioName, requestResults); - } + item.setName(array[1] + array[0]); item.getSubRequestResults().forEach(subItem -> { - subItem.setName(item.getName()); + subItem.setName(array[0]); }); - } else { - if (requestResultMap.containsKey(result.getName())) { - requestResultMap.get(result.getName()).add(item); - } else { - List requestResults = new LinkedList<>(); - requestResults.add(item); - requestResultMap.put(result.getName(), requestResults); - } - item.getSubRequestResults().forEach(subItem -> { - subItem.setName(item.getName()); - }); - } }); - } - if (!requestResultMap.isEmpty()) { - requestResultMap.forEach((k, v) -> { - ScenarioResult scenarioResult = new ScenarioResult(); - BeanUtils.copyBean(scenarioResult, result); - scenarioResult.setName(k); - if (k.indexOf(SEPARATOR) != -1) { - scenarioResult.setName(k.split(SEPARATOR)[1]); - } - scenarioResult.setRequestResults(v); - scenarios.add(scenarioResult); - }); - } else { scenarios.add(result); } } diff --git a/frontend/src/business/components/api/automation/report/ApiReportDetail.vue b/frontend/src/business/components/api/automation/report/ApiReportDetail.vue index 2fb0c281f8..46022d23bd 100644 --- a/frontend/src/business/components/api/automation/report/ApiReportDetail.vue +++ b/frontend/src/business/components/api/automation/report/ApiReportDetail.vue @@ -3,26 +3,21 @@
- - -
+
- - - + - + -
@@ -62,6 +57,7 @@ report: {}, loading: true, fails: [], + failsTreeNodes: [], totalTime: 0, isRequestResult: false, request: {}, @@ -69,6 +65,7 @@ scenarioName: null, reportExportVisible: false, requestType: undefined, + fullTreeNodes: [], } }, activated() { @@ -92,6 +89,8 @@ this.content = {}; this.fails = []; this.report = {}; + this.fullTreeNodes = []; + this.failsTreeNodes = []; this.isRequestResult = false; }, handleClick(tab, event) { @@ -102,17 +101,81 @@ }, formatResult(res) { let resMap = new Map; + let array = []; + let i = 0; if (res && res.scenarios) { res.scenarios.forEach(item => { if (item && item.requestResults) { item.requestResults.forEach(req => { resMap.set(req.id, req); + req.index = i; + i++; + array.push(req); }) } }) } + this.formatTree(array, this.fullTreeNodes); + this.sort(this.fullTreeNodes); this.$emit('refresh', resMap); }, + formatTree(array, tree) { + array.map((item) => { + let key = item.name; + let nodeArray = key.split('^@~@^'); + let children = tree; + // 循环构建子节点 + for (let i in nodeArray) { + let node = { + label: nodeArray[i], + value: item, + }; + if (i != nodeArray.length) { + node.children = []; + } + + if (children.length == 0) { + children.push(node); + } + + let isExist = false; + for (let j in children) { + if (children[j].label == node.label) { + if (i != nodeArray.length - 1 && !children[j].children) { + children[j].children = []; + } + children = (i == nodeArray.length - 1 ? children : children[j].children); + isExist = true; + break; + } + } + if (!isExist) { + children.push(node); + if (i != nodeArray.length - 1 && !children[children.length - 1].children) { + children[children.length - 1].children = []; + } + children = (i == nodeArray.length - 1 ? children : children[children.length - 1].children); + } + } + }) + }, + recursiveSorting(arr) { + for (let i in arr) { + arr[i].index = Number(i) + 1; + if (arr[i].children != undefined && arr[i].children.length > 0) { + this.recursiveSorting(arr[i].children); + } + } + }, + sort(scenarioDefinition) { + for (let i in scenarioDefinition) { + // 排序 + scenarioDefinition[i].index = Number(i) + 1; + if (scenarioDefinition[i].children != undefined && scenarioDefinition[i].children.length > 0) { + this.recursiveSorting(scenarioDefinition[i].children); + } + } + }, getReport() { this.init(); if (this.reportId) { @@ -146,6 +209,7 @@ getFails() { if (this.isNotRunning) { this.fails = []; + let array = []; this.totalTime = 0 if (this.content.scenarios) { this.content.scenarios.forEach((scenario) => { @@ -158,11 +222,14 @@ if (!request.success) { let failRequest = Object.assign({}, request); failScenario.requestResults.push(failRequest); + array.push(request) } }) } }) } + this.formatTree(array, this.failsTreeNodes); + this.sort(this.failsTreeNodes); } }, computeTotalTime() { diff --git a/frontend/src/business/components/api/automation/report/components/RequestResult.vue b/frontend/src/business/components/api/automation/report/components/RequestResult.vue index 3af4ceb7aa..ab0ba991a3 100644 --- a/frontend/src/business/components/api/automation/report/components/RequestResult.vue +++ b/frontend/src/business/components/api/automation/report/components/RequestResult.vue @@ -1,55 +1,58 @@ diff --git a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue index c294314450..24e5687ee8 100644 --- a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue +++ b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue @@ -1199,7 +1199,7 @@ /deep/ .el-tree-node__content { height: 100%; - margin-top: 8px; + margin-top: 3px; vertical-align: center; }