feat: 用例脑图支持添加模块
This commit is contained in:
parent
99d6e8d171
commit
a1e41339ec
|
@ -295,6 +295,7 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
|||
}
|
||||
|
||||
private void parseKvBody(Schema schema, Body body, Object data, Map<String, Schema> infoMap) {
|
||||
if (data == null) return;
|
||||
if (data instanceof JSONObject) {
|
||||
((JSONObject) data).forEach((k, v) -> {
|
||||
Schema dataSchema = (Schema) v;
|
||||
|
@ -311,6 +312,9 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
|||
body.getKvs().add(kv);
|
||||
});
|
||||
} else {
|
||||
if (data instanceof String && StringUtils.isBlank((String) data)) {
|
||||
return;
|
||||
}
|
||||
Schema dataSchema = (Schema) data;
|
||||
KeyValue kv = new KeyValue(schema.getName(), String.valueOf(dataSchema.getExample()), schema.getDescription());
|
||||
Schema schemaInfo = infoMap.get(schema.getName());
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package io.metersphere.controller;
|
||||
|
||||
import io.metersphere.base.domain.MinderExtraNode;
|
||||
import io.metersphere.commons.constants.PermissionConstants;
|
||||
import io.metersphere.service.MinderExtraNodeService;
|
||||
import io.metersphere.track.request.MinderExtraNodeEditRequest;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
@ -17,11 +17,11 @@ public class MinderExtraNodeController {
|
|||
@Resource
|
||||
MinderExtraNodeService minderExtraNodeService;
|
||||
|
||||
@PostMapping("/batch/edit")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_CASE_READ_EDIT)
|
||||
public void minderEdit(@RequestBody MinderExtraNodeEditRequest request) {
|
||||
minderExtraNodeService.batchEdit(request);
|
||||
}
|
||||
// @PostMapping("/batch/edit")
|
||||
// @RequiresPermissions(PermissionConstants.PROJECT_TRACK_CASE_READ_EDIT)
|
||||
// public void minderEdit(@RequestBody TestCaseMinderEditRequest.MinderExtraNodeEditRequest request) {
|
||||
// minderExtraNodeService.batchEdit(request);
|
||||
// }
|
||||
|
||||
@GetMapping("/list/{groupId}/{parentId}")
|
||||
public List<MinderExtraNode> list(@PathVariable String groupId, @PathVariable String parentId) {
|
||||
|
|
|
@ -4,16 +4,14 @@ import com.alibaba.fastjson.JSONObject;
|
|||
import io.metersphere.base.domain.MinderExtraNode;
|
||||
import io.metersphere.base.domain.MinderExtraNodeExample;
|
||||
import io.metersphere.base.mapper.MinderExtraNodeMapper;
|
||||
import io.metersphere.track.request.MinderExtraNodeEditRequest;
|
||||
import io.metersphere.track.request.testcase.TestCaseMinderEditRequest;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
|
@ -22,8 +20,9 @@ public class MinderExtraNodeService {
|
|||
@Resource
|
||||
MinderExtraNodeMapper minderExtraNodeMapper;
|
||||
|
||||
public void batchEdit(MinderExtraNodeEditRequest request) {
|
||||
Map<String, List<String>> data = request.getData();
|
||||
public void batchEdit(TestCaseMinderEditRequest request) {
|
||||
TestCaseMinderEditRequest.MinderExtraNodeEditRequest extraNodeRequest = request.getExtraNodeRequest();
|
||||
Map<String, List<String>> data = extraNodeRequest.getData();
|
||||
if (data != null) {
|
||||
data.forEach((parentId, nodes) -> {
|
||||
nodes.forEach(node -> {
|
||||
|
@ -32,16 +31,14 @@ public class MinderExtraNodeService {
|
|||
minderExtraNode.setParentId(parentId);
|
||||
JSONObject nodeObj = JSONObject.parseObject(node);
|
||||
String id = nodeObj.getString("id");
|
||||
if (StringUtils.isBlank(id) || id.length() < 20) {
|
||||
minderExtraNode.setId(UUID.randomUUID().toString());
|
||||
minderExtraNode.setGroupId(request.getGroupId());
|
||||
minderExtraNode.setType(request.getType());
|
||||
nodeObj.put("id", minderExtraNode.getId());
|
||||
minderExtraNode.setId(id);
|
||||
if (nodeObj.getBoolean("isEdit")) {
|
||||
minderExtraNodeMapper.updateByPrimaryKeySelective(minderExtraNode);
|
||||
} else {
|
||||
minderExtraNode.setGroupId(extraNodeRequest.getGroupId());
|
||||
minderExtraNode.setType(extraNodeRequest.getType());
|
||||
minderExtraNode.setNodeData(nodeObj.toJSONString());
|
||||
minderExtraNodeMapper.insert(minderExtraNode);
|
||||
} else {
|
||||
minderExtraNode.setId(id);
|
||||
minderExtraNodeMapper.updateByPrimaryKeySelective(minderExtraNode);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -59,4 +56,4 @@ public class MinderExtraNodeService {
|
|||
example.createCriteria().andParentIdEqualTo(parentId).andGroupIdEqualTo(groupId);
|
||||
return minderExtraNodeMapper.selectByExampleWithBLOBs(example);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
package io.metersphere.track.request;
|
||||
|
||||
import io.metersphere.base.domain.MinderExtraNode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class MinderExtraNodeEditRequest extends MinderExtraNode {
|
||||
private String projectId;
|
||||
// 删除的id
|
||||
private List<String> ids;
|
||||
// key 为父节点id
|
||||
private Map<String, List<String>> data;
|
||||
}
|
|
@ -1,22 +1,42 @@
|
|||
package io.metersphere.track.request.testcase;
|
||||
|
||||
import io.metersphere.base.domain.MinderExtraNode;
|
||||
import io.metersphere.base.domain.TestCaseNode;
|
||||
import io.metersphere.base.domain.TestCaseWithBLOBs;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class TestCaseMinderEditRequest {
|
||||
private String projectId;
|
||||
private List<String> ids;
|
||||
List<TestCaseMinderEditItem> data;
|
||||
private List<TestCaseMinderEditItem> data;
|
||||
private List<TestCaseNodeMinderEditItem> testCaseNodes;
|
||||
|
||||
private MinderExtraNodeEditRequest extraNodeRequest;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class MinderExtraNodeEditRequest extends MinderExtraNode {
|
||||
private Map<String, List<String>> data;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class TestCaseMinderEditItem extends TestCaseWithBLOBs {
|
||||
private Boolean isEdit;
|
||||
private String targetId;
|
||||
private String moveMode;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class TestCaseNodeMinderEditItem extends TestCaseNode {
|
||||
private Boolean isEdit;
|
||||
private List<String> nodeIds;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import io.metersphere.base.mapper.ext.ExtTestCaseNodeMapper;
|
|||
import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
|
||||
import io.metersphere.commons.constants.TestCaseConstants;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.BeanUtils;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.dto.NodeNumDTO;
|
||||
|
@ -23,10 +24,7 @@ import io.metersphere.service.NodeTreeService;
|
|||
import io.metersphere.track.dto.TestCaseDTO;
|
||||
import io.metersphere.track.dto.TestCaseNodeDTO;
|
||||
import io.metersphere.track.dto.TestPlanCaseDTO;
|
||||
import io.metersphere.track.request.testcase.DragNodeRequest;
|
||||
import io.metersphere.track.request.testcase.QueryNodeRequest;
|
||||
import io.metersphere.track.request.testcase.QueryTestCaseRequest;
|
||||
import io.metersphere.track.request.testcase.TestCaseBatchRequest;
|
||||
import io.metersphere.track.request.testcase.*;
|
||||
import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.session.ExecutorType;
|
||||
|
@ -65,8 +63,6 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
|
|||
@Resource
|
||||
ProjectMapper projectMapper;
|
||||
@Resource
|
||||
TestCaseReviewService testCaseReviewService;
|
||||
@Resource
|
||||
TestCaseReviewTestCaseMapper testCaseReviewTestCaseMapper;
|
||||
@Resource
|
||||
TestCaseReviewMapper testCaseReviewMapper;
|
||||
|
@ -79,7 +75,9 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
|
|||
validateNode(node);
|
||||
node.setCreateTime(System.currentTimeMillis());
|
||||
node.setUpdateTime(System.currentTimeMillis());
|
||||
node.setId(UUID.randomUUID().toString());
|
||||
if (StringUtils.isBlank(node.getId())) {
|
||||
node.setId(UUID.randomUUID().toString());
|
||||
}
|
||||
node.setCreateUser(SessionUtils.getUserId());
|
||||
double pos = getNextLevelPos(node.getProjectId(), node.getLevel(), node.getParentId());
|
||||
node.setPos(pos);
|
||||
|
@ -91,8 +89,6 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
|
|||
return extTestCaseNodeMapper.getNodes(nodeId);
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private void validateNode(TestCaseNode node) {
|
||||
if (node.getLevel() > TestCaseConstants.MAX_NODE_DEPTH) {
|
||||
throw new RuntimeException(Translator.get("test_case_node_level_tip")
|
||||
|
@ -236,25 +232,27 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
|
|||
public int editNode(DragNodeRequest request) {
|
||||
request.setUpdateTime(System.currentTimeMillis());
|
||||
checkTestCaseNodeExist(request);
|
||||
List<TestCaseDTO> testCases = QueryTestCaseByNodeIds(request.getNodeIds());
|
||||
|
||||
testCases.forEach(testCase -> {
|
||||
StringBuilder path = new StringBuilder(testCase.getNodePath());
|
||||
List<String> pathLists = Arrays.asList(path.toString().split("/"));
|
||||
pathLists.set(request.getLevel(), request.getName());
|
||||
path.delete(0, path.length());
|
||||
for (int i = 1; i < pathLists.size(); i++) {
|
||||
path = path.append("/").append(pathLists.get(i));
|
||||
}
|
||||
testCase.setNodePath(path.toString());
|
||||
});
|
||||
|
||||
batchUpdateTestCase(testCases);
|
||||
|
||||
if (!CollectionUtils.isEmpty(request.getNodeIds())) {
|
||||
List<TestCaseDTO> testCases = QueryTestCaseByNodeIds(request.getNodeIds());
|
||||
testCases.forEach(testCase -> {
|
||||
StringBuilder path = new StringBuilder(testCase.getNodePath());
|
||||
List<String> pathLists = Arrays.asList(path.toString().split("/"));
|
||||
pathLists.set(request.getLevel(), request.getName());
|
||||
path.delete(0, path.length());
|
||||
for (int i = 1; i < pathLists.size(); i++) {
|
||||
path = path.append("/").append(pathLists.get(i));
|
||||
}
|
||||
testCase.setNodePath(path.toString());
|
||||
});
|
||||
batchUpdateTestCase(testCases);
|
||||
}
|
||||
return testCaseNodeMapper.updateByPrimaryKeySelective(request);
|
||||
}
|
||||
|
||||
public int deleteNode(List<String> nodeIds) {
|
||||
if (CollectionUtils.isEmpty(nodeIds)) {
|
||||
return 1;
|
||||
}
|
||||
TestCaseService testCaseService = CommonBeanFactory.getBean(TestCaseService.class);
|
||||
List<String> testCaseIdList = this.selectCaseIdByNodeIds(nodeIds);
|
||||
TestCaseBatchRequest request = new TestCaseBatchRequest();
|
||||
|
@ -770,4 +768,29 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
|
|||
testCaseExample.createCriteria().andProjectIdEqualTo(projectId).andStatusEqualTo("Trash");
|
||||
return testCaseMapper.countByExample(testCaseExample);
|
||||
}
|
||||
|
||||
public void minderEdit(TestCaseMinderEditRequest request) {
|
||||
deleteNode(request.getIds());
|
||||
|
||||
List<TestCaseMinderEditRequest.TestCaseNodeMinderEditItem> testCaseNodes = request.getTestCaseNodes();
|
||||
if (org.apache.commons.collections.CollectionUtils.isNotEmpty(testCaseNodes)) {
|
||||
|
||||
for (TestCaseMinderEditRequest.TestCaseNodeMinderEditItem item: testCaseNodes) {
|
||||
if (StringUtils.isBlank(item.getParentId()) || item.getParentId().equals("root")) {
|
||||
item.setParentId("");
|
||||
}
|
||||
item.setProjectId(request.getProjectId());
|
||||
if (item.getIsEdit()) {
|
||||
DragNodeRequest editNode = new DragNodeRequest();
|
||||
BeanUtils.copyBean(editNode, item);
|
||||
editNode(editNode);
|
||||
} else {
|
||||
TestCaseNode testCaseNode = new TestCaseNode();
|
||||
BeanUtils.copyBean(testCaseNode, item);
|
||||
testCaseNode.setProjectId(request.getProjectId());
|
||||
addNode(testCaseNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,6 +145,8 @@ public class TestCaseService {
|
|||
@Resource
|
||||
@Lazy
|
||||
private TestPlanService testPlanService;
|
||||
@Resource
|
||||
private MinderExtraNodeService minderExtraNodeService;
|
||||
|
||||
private void setNode(TestCaseWithBLOBs testCase) {
|
||||
if (StringUtils.isEmpty(testCase.getNodeId()) || "default-module".equals(testCase.getNodeId())) {
|
||||
|
@ -1480,10 +1482,15 @@ public class TestCaseService {
|
|||
}
|
||||
|
||||
public void minderEdit(TestCaseMinderEditRequest request) {
|
||||
|
||||
deleteToGcBatch(request.getIds());
|
||||
|
||||
testCaseNodeService.minderEdit(request);
|
||||
|
||||
List<TestCaseMinderEditRequest.TestCaseMinderEditItem> data = request.getData();
|
||||
if (CollectionUtils.isNotEmpty(data)) {
|
||||
List<String> editIds = data.stream()
|
||||
.filter(t -> StringUtils.isNotBlank(t.getId()) && t.getId().length() > 20)
|
||||
.filter(TestCaseMinderEditRequest.TestCaseMinderEditItem::getIsEdit)
|
||||
.map(TestCaseWithBLOBs::getId).collect(Collectors.toList());
|
||||
|
||||
Map<String, TestCaseWithBLOBs> testCaseMap = new HashMap<>();
|
||||
|
@ -1494,31 +1501,29 @@ public class TestCaseService {
|
|||
testCaseMap = testCaseWithBLOBs.stream().collect(Collectors.toMap(TestCaseWithBLOBs::getId, t -> t));
|
||||
}
|
||||
|
||||
Map<String, TestCaseWithBLOBs> finalTestCaseMap = testCaseMap;
|
||||
data.forEach(item -> {
|
||||
for (TestCaseMinderEditRequest.TestCaseMinderEditItem item: data) {
|
||||
if (StringUtils.isBlank(item.getNodeId()) || item.getNodeId().equals("root")) {
|
||||
item.setNodeId("");
|
||||
}
|
||||
item.setProjectId(request.getProjectId());
|
||||
if (StringUtils.isBlank(item.getId()) || item.getId().length() < 20) {
|
||||
item.setId(UUID.randomUUID().toString());
|
||||
item.setMaintainer(SessionUtils.getUserId());
|
||||
EditTestCaseRequest editTestCaseRequest = new EditTestCaseRequest();
|
||||
BeanUtils.copyBean(editTestCaseRequest, item);
|
||||
addTestCase(editTestCaseRequest);
|
||||
changeOrder(item, request.getProjectId());
|
||||
} else {
|
||||
TestCaseWithBLOBs dbCase = finalTestCaseMap.get(item.getId());
|
||||
if (item.getIsEdit()) {
|
||||
TestCaseWithBLOBs dbCase = testCaseMap.get(item.getId());
|
||||
if (editCustomFieldsPriority(dbCase, item.getPriority())) {
|
||||
item.setCustomFields(dbCase.getCustomFields());
|
||||
}
|
||||
editTestCase(item);
|
||||
changeOrder(item, request.getProjectId());
|
||||
} else {
|
||||
item.setMaintainer(SessionUtils.getUserId());
|
||||
EditTestCaseRequest editTestCaseRequest = new EditTestCaseRequest();
|
||||
BeanUtils.copyBean(editTestCaseRequest, item);
|
||||
addTestCase(editTestCaseRequest);
|
||||
changeOrder(item, request.getProjectId());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
List<String> ids = request.getIds();
|
||||
deleteToGcBatch(ids);
|
||||
|
||||
minderExtraNodeService.batchEdit(request);
|
||||
}
|
||||
|
||||
private void changeOrder(TestCaseMinderEditRequest.TestCaseMinderEditItem item, String projectId) {
|
||||
|
|
|
@ -268,9 +268,9 @@ public class TestPlanReportService {
|
|||
|
||||
// testPlanReport.setPrincipal(testPlan.getPrincipal());
|
||||
if (testPlanReport.getIsScenarioExecuting() || testPlanReport.getIsApiCaseExecuting() || testPlanReport.getIsPerformanceExecuting()) {
|
||||
testPlanReport.setStatus(APITestStatus.Running.name());
|
||||
testPlanReport.setStatus(TestPlanReportStatus.RUNNING.name());
|
||||
} else {
|
||||
testPlanReport.setStatus(APITestStatus.Completed.name());
|
||||
testPlanReport.setStatus(TestPlanReportStatus.COMPLETED.name());
|
||||
}
|
||||
|
||||
testPlanReportMapper.insert(testPlanReport);
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
"vue-float-action-button": "^0.6.6",
|
||||
"vue-i18n": "^8.15.3",
|
||||
"vue-jsonpath-picker": "^1.1.5",
|
||||
"vue-minder-editor-plus": "1.0.30",
|
||||
"vue-minder-editor-plus": "1.0.33",
|
||||
"vue-papa-parse": "^2.0.0",
|
||||
"vue-pdf": "^4.2.0",
|
||||
"vue-router": "^3.1.3",
|
||||
|
|
|
@ -69,7 +69,13 @@ export default {
|
|||
priorityDisableCheck: Function,
|
||||
disabled: Boolean,
|
||||
ignoreNum: Boolean,
|
||||
showModuleTag: Boolean
|
||||
showModuleTag: Boolean,
|
||||
moduleDisable: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -80,6 +86,7 @@ export default {
|
|||
disable: true,
|
||||
id: "root",
|
||||
type: 'node',
|
||||
level: 0,
|
||||
resource: this.showModuleTag ? ['模块'] : [],
|
||||
path: "",
|
||||
tagEnable: this.tagEnable
|
||||
|
@ -150,8 +157,9 @@ export default {
|
|||
data: {
|
||||
text: item.name,
|
||||
id: item.id,
|
||||
disable: true,
|
||||
disable: this.moduleDisable,
|
||||
type: 'node',
|
||||
level: item.level,
|
||||
resource: this.showModuleTag ? ['模块'] : [],
|
||||
caseNum: item.caseNum,
|
||||
path: root.data.path + "/" + item.name,
|
||||
|
@ -206,9 +214,10 @@ export default {
|
|||
data: {
|
||||
text: nodeData.name,
|
||||
id: nodeData.id,
|
||||
disable: true,
|
||||
disable: this.moduleDisable,
|
||||
tagEnable: this.tagEnable,
|
||||
type: 'node',
|
||||
level: nodeData.level,
|
||||
resource: this.showModuleTag ? ['模块'] : [],
|
||||
},
|
||||
children: []
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
minder-key="testCase"
|
||||
:select-node="selectNode"
|
||||
:distinct-tags="tags"
|
||||
:module-disable="false"
|
||||
:show-module-tag="true"
|
||||
:tag-edit-check="tagEditCheck()"
|
||||
@afterMount="handleAfterMount"
|
||||
|
@ -19,6 +20,7 @@
|
|||
<script>
|
||||
import MsModuleMinder from "@/business/components/common/components/MsModuleMinder";
|
||||
import {
|
||||
getChildNodeId,
|
||||
handleAfterSave,
|
||||
handleExpandToLevel, handleTestCaseAdd, handTestCaeEdit,
|
||||
listenBeforeExecCommand, listenDblclick,
|
||||
|
@ -27,7 +29,7 @@ import {
|
|||
priorityDisableCheck,
|
||||
tagEditCheck,
|
||||
} from "@/business/components/track/common/minder/minderUtils";
|
||||
import {getNodePath, hasPermission} from "@/common/js/utils";
|
||||
import {getNodePath, getUUID, hasPermission} from "@/common/js/utils";
|
||||
import {getTestCasesForMinder, getMinderExtraNode} from "@/network/testCase";
|
||||
export default {
|
||||
name: "TestCaseMinder",
|
||||
|
@ -36,9 +38,14 @@ name: "TestCaseMinder",
|
|||
return{
|
||||
testCase: [],
|
||||
dataMap: new Map(),
|
||||
tags: [this.$t('api_test.definition.request.case'), this.$t('test_track.case.prerequisite'), this.$t('commons.remark'), '模块'],
|
||||
tags: [this.$t('api_test.definition.request.case'), this.$t('test_track.case.prerequisite'), this.$t('commons.remark'), this.$t('test_track.module.module')],
|
||||
result: {loading: false},
|
||||
needRefresh: false,
|
||||
saveCases: [],
|
||||
saveModules: [],
|
||||
saveModuleNodeMap: new Map(),
|
||||
deleteNodes: [], // 包含测试模块、用例和临时节点
|
||||
saveExtraNode: {}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
|
@ -127,72 +134,59 @@ name: "TestCaseMinder",
|
|||
setIsChange(isChanged) {
|
||||
this.$store.commit('setIsTestCaseMinderChanged', isChanged);
|
||||
},
|
||||
save(data) {
|
||||
let saveCases = [];
|
||||
let deleteCases = []; // 包含测试用例和临时节点
|
||||
let saveExtraNode = {};
|
||||
this.buildSaveCase(data.root, saveCases, deleteCases, saveExtraNode);
|
||||
save() {
|
||||
this.saveCases = [];
|
||||
this.saveModules = [];
|
||||
this.deleteNodes = []; // 包含测试模块、用例和临时节点
|
||||
this.saveExtraNode = {};
|
||||
this.saveModuleNodeMap = new Map();
|
||||
this.buildSaveParam(window.minder.getRoot());
|
||||
|
||||
this.saveModules.forEach(module => {
|
||||
let nodeIds = [];
|
||||
getChildNodeId(this.saveModuleNodeMap.get(module.id), nodeIds);
|
||||
module.nodeIds = nodeIds;
|
||||
});
|
||||
|
||||
let param = {
|
||||
projectId: this.projectId,
|
||||
data: saveCases,
|
||||
ids: deleteCases.map(item => item.id)
|
||||
data: this.saveCases,
|
||||
ids: this.deleteNodes.map(item => item.id),
|
||||
testCaseNodes: this.saveModules,
|
||||
extraNodeRequest: {
|
||||
groupId: this.projectId,
|
||||
type: "TEST_CASE",
|
||||
data: this.saveExtraNode,
|
||||
}
|
||||
}
|
||||
|
||||
let saveCase = new Promise((resolve) => {
|
||||
this.result = this.$post('/test/case/minder/edit', param, () => {
|
||||
resolve();
|
||||
});
|
||||
this.result = this.$post('/test/case/minder/edit', param, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
handleAfterSave(window.minder.getRoot());
|
||||
this.$emit('refresh');
|
||||
this.setIsChange(false);
|
||||
});
|
||||
|
||||
|
||||
let extraNodeParam = {
|
||||
groupId: this.projectId,
|
||||
type: "TEST_CASE",
|
||||
data: saveExtraNode,
|
||||
ids: deleteCases.map(item => item.id)
|
||||
}
|
||||
|
||||
let saveExtraNodePromise = new Promise((resolve) => {
|
||||
this.result = this.$post('/minder/extra/node/batch/edit', extraNodeParam, () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
Promise.all([saveCase, saveExtraNodePromise])
|
||||
.then(() => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
handleAfterSave(window.minder.getRoot(), this.getParam());
|
||||
this.$emit('refresh');
|
||||
this.setIsChange(false);
|
||||
});
|
||||
},
|
||||
buildSaveCase(root, saveCases, deleteCases, saveExtraNode, parent, preNode, nextNode) {
|
||||
buildSaveParam(root, parent, preNode, nextNode) {
|
||||
let data = root.data;
|
||||
if (data.resource && data.resource.indexOf(this.$t('api_test.definition.request.case')) > -1) {
|
||||
this._buildSaveCase(root, saveCases, deleteCases, parent, preNode, nextNode);
|
||||
this.buildSaveCase(root, parent, preNode, nextNode);
|
||||
} else {
|
||||
let deleteChild = data.deleteChild;
|
||||
if (deleteChild && deleteChild.length > 0 && data.type === 'node') {
|
||||
deleteCases.push(...deleteChild);
|
||||
this.deleteNodes.push(...deleteChild);
|
||||
}
|
||||
|
||||
if (data.type !== 'node' && data.type !== 'tmp'
|
||||
&& parent && parent.type === 'node' && data.changed === true) {
|
||||
// 保存额外信息,只保存模块下的一级子节点
|
||||
let nodes = saveExtraNode[parent.id];
|
||||
if (!nodes) {
|
||||
nodes = [];
|
||||
if (data.type !== 'tmp' && data.changed) {
|
||||
if (data.contextChanged && data.resource && data.resource.indexOf(this.$t('test_track.module.module')) > -1) {
|
||||
this.buildSaveModules(root, data, parent);
|
||||
} else {
|
||||
// 保存临时节点
|
||||
this.buildExtraNode(data, parent, root);
|
||||
}
|
||||
nodes.push(JSON.stringify(this.buildExtraNode(root)));
|
||||
saveExtraNode[parent.id] = nodes;
|
||||
}
|
||||
|
||||
if (data.id === null) {
|
||||
let tip = '脑图编辑无法创建模块:' + data.text + '';
|
||||
this.$error(tip)
|
||||
throw new Error(tip);
|
||||
}
|
||||
if (root.children) {
|
||||
for (let i = 0; i < root.children.length; i++) {
|
||||
let childNode = root.children[i];
|
||||
|
@ -204,12 +198,60 @@ name: "TestCaseMinder",
|
|||
if (i + 1 < root.children.length) {
|
||||
nextNode = root.children[i + 1];
|
||||
}
|
||||
this.buildSaveCase(childNode, saveCases, deleteCases, saveExtraNode, root.data, preNode, nextNode);
|
||||
this.buildSaveParam(childNode, root.data, preNode, nextNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_buildSaveCase(node, saveCases, deleteCases, parent, preNode, nextNode) {
|
||||
buildSaveModules(node, data, parent) {
|
||||
if (!data.text) {
|
||||
return;
|
||||
}
|
||||
let pId = parent ? (parent.newId ? parent.newId : parent.id) : null;
|
||||
|
||||
let module = {
|
||||
id: data.id,
|
||||
name: data.text,
|
||||
level: data.level ? data.level : (parent.level + 1),
|
||||
parentId: pId
|
||||
};
|
||||
data.level = module.level;
|
||||
|
||||
if (data.isExtraNode) {
|
||||
// 如果是临时节点,打上了模块标签,则删除临时节点并新建模块
|
||||
this.pushDeleteNode(data);
|
||||
}
|
||||
|
||||
if (data.type === 'case') {
|
||||
// 如果是用例节点,打上了模块标签,则用例节点并新建模块
|
||||
this.pushDeleteNode(data);
|
||||
}
|
||||
|
||||
if (module.id && module.id.length > 20) {
|
||||
module.isEdit = true; // 编辑
|
||||
} else {
|
||||
module.isEdit = false; // 新增
|
||||
module.id = getUUID();
|
||||
data.newId = module.id;
|
||||
this.moduleOptions.push({id: data.newId, path: getNodePath(pId, this.moduleOptions) + '/' + module.name});
|
||||
}
|
||||
|
||||
this.saveModuleNodeMap.set(module.id, node);
|
||||
this.saveModules.push(module);
|
||||
},
|
||||
buildExtraNode(data, parent, root) {
|
||||
if (data.type !== 'node' && data.type !== 'tmp'
|
||||
&& parent && parent.type === 'node' && data.changed === true) {
|
||||
// 保存额外信息,只保存模块下的一级子节点
|
||||
let nodes = this.saveExtraNode[parent.id];
|
||||
if (!nodes) {
|
||||
nodes = [];
|
||||
}
|
||||
nodes.push(JSON.stringify(this._buildExtraNode(root)));
|
||||
this.saveExtraNode[parent.id] = nodes;
|
||||
}
|
||||
},
|
||||
buildSaveCase(node, parent, preNode, nextNode) {
|
||||
let data = node.data;
|
||||
if (!data.text) {
|
||||
return;
|
||||
|
@ -221,20 +263,25 @@ name: "TestCaseMinder",
|
|||
throw new Error(tip);
|
||||
}
|
||||
|
||||
if (data.type === 'node') {
|
||||
let tip = data.text + '是模块,不能修改为用例';
|
||||
this.$error(tip)
|
||||
throw new Error(tip);
|
||||
}
|
||||
|
||||
if (data.isExtraNode) {
|
||||
// 如果是临时节点,打上了用例标签,则删除临时节点并新建用例节点
|
||||
let deleteData = {};
|
||||
Object.assign(deleteData, data);
|
||||
deleteCases.push(deleteData);
|
||||
data.id = "";
|
||||
this.pushDeleteNode(data);
|
||||
}
|
||||
|
||||
let isChange = false;
|
||||
|
||||
let nodeId = parent ? (parent.newId ? parent.newId : parent.id) : "";
|
||||
let testCase = {
|
||||
id: data.id,
|
||||
name: data.text,
|
||||
nodeId: parent ? parent.id : "",
|
||||
nodePath: getNodePath(parent ? parent.id : '', this.moduleOptions),
|
||||
nodeId: nodeId,
|
||||
nodePath: getNodePath(nodeId, this.moduleOptions),
|
||||
type: data.type ? data.type : 'functional',
|
||||
method: data.method ? data.method: 'manual',
|
||||
maintainer: data.maintainer,
|
||||
|
@ -297,7 +344,14 @@ name: "TestCaseMinder",
|
|||
}
|
||||
}
|
||||
|
||||
saveCases.push(testCase);
|
||||
if (testCase.id && testCase.id.length > 20) {
|
||||
testCase.isEdit = true; // 编辑
|
||||
} else {
|
||||
testCase.isEdit = false; // 新增
|
||||
testCase.id = getUUID();
|
||||
data.newId = testCase.id;
|
||||
}
|
||||
this.saveCases.push(testCase);
|
||||
}
|
||||
if (testCase.nodeId !== 'root' && testCase.nodeId.length < 15) {
|
||||
let tip = this.$t('test_track.case.create_case') + "'" + testCase.name + "'" + this.$t('test_track.case.minder_create_tip');
|
||||
|
@ -305,23 +359,37 @@ name: "TestCaseMinder",
|
|||
throw new Error(tip);
|
||||
}
|
||||
},
|
||||
pushDeleteNode(data) {
|
||||
// 如果是临时节点,打上了用例标签,则删除临时节点并新建用例节点
|
||||
let deleteData = {};
|
||||
Object.assign(deleteData, data);
|
||||
this.deleteNodes.push(deleteData);
|
||||
data.id = "";
|
||||
},
|
||||
isCaseNode(node) {
|
||||
if (node && node.resource && node.resource.indexOf(this.$t('api_test.definition.request.case')) > -1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
buildExtraNode(node) {
|
||||
_buildExtraNode(node) {
|
||||
let data = node.data;
|
||||
let nodeData = {
|
||||
text: data.text,
|
||||
id: data.id,
|
||||
resource: data.resource,
|
||||
};
|
||||
if (nodeData.id && nodeData.id.length > 20) {
|
||||
nodeData.isEdit = true; // 编辑
|
||||
} else {
|
||||
nodeData.isEdit = false; // 新增
|
||||
nodeData.id = getUUID();
|
||||
data.newId = nodeData.id;
|
||||
}
|
||||
if (node.children) {
|
||||
nodeData.children = [];
|
||||
node.children.forEach(item => {
|
||||
nodeData.children.push(this.buildExtraNode(item));
|
||||
nodeData.children.push(this._buildExtraNode(item));
|
||||
});
|
||||
}
|
||||
return nodeData;
|
||||
|
|
|
@ -180,7 +180,7 @@ export function appendCase(parent, item, isDisable, setParamCallback) {
|
|||
text: item.name,
|
||||
priority: Number.parseInt(item.priority.substring(item.priority.length - 1 )) + 1,
|
||||
resource: [i18n.t('api_test.definition.request.case')],
|
||||
type: item.type,
|
||||
type: 'case',
|
||||
method: item.method,
|
||||
maintainer: item.maintainer,
|
||||
stepModel: item.stepModel
|
||||
|
@ -356,16 +356,25 @@ export function tagBatch(distinctTags) {
|
|||
});
|
||||
}
|
||||
|
||||
function parentIsModule(parentNode) {
|
||||
let lastNodeResource = parentNode ? parentNode.data.resource : null;
|
||||
return parentNode.data.type === 'node' || (lastNodeResource && lastNodeResource.indexOf('模块') > -1);
|
||||
}
|
||||
|
||||
export function tagEditCheck(resourceName) {
|
||||
let minder = window.minder;
|
||||
let selectNodes = minder.getSelectedNodes();
|
||||
if (selectNodes && selectNodes.length > 0) {
|
||||
let lastNodeResource = selectNodes[0].getParent().data.resource;
|
||||
if ( resourceName === '模块') {
|
||||
// 模块不能编辑
|
||||
let type = selectNodes[0].data.type;
|
||||
if (type === 'case' || type === 'node') {// 已存在的模块和用例不能修改标签
|
||||
return false;
|
||||
}
|
||||
if (lastNodeResource && lastNodeResource.indexOf('用例') > -1 && resourceName === '用例') {
|
||||
let parentIsModuleNode = parentIsModule(selectNodes[0].getParent());
|
||||
if (resourceName === '用例' && !parentIsModuleNode) {
|
||||
return false;
|
||||
}
|
||||
// 父节点必须是模块
|
||||
if (resourceName === '模块' && !parentIsModuleNode) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -377,7 +386,8 @@ export function priorityDisableCheck() {
|
|||
let minder = window.minder;
|
||||
let selectNodes = minder.getSelectedNodes();
|
||||
if (selectNodes && selectNodes.length > 0) {
|
||||
let resource = selectNodes[0].getParent().data.resource;
|
||||
let parentNode = selectNodes[0].getParent();
|
||||
let resource = parentNode ? parentNode.data.resource : null;
|
||||
if (resource && resource.indexOf('用例') > -1) {
|
||||
return true;
|
||||
}
|
||||
|
@ -385,22 +395,32 @@ export function priorityDisableCheck() {
|
|||
return false;
|
||||
}
|
||||
|
||||
export function handleAfterSave(pNode, param) {
|
||||
let children = pNode.children;
|
||||
if (children) {
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let item = children[i];
|
||||
if (item.data.id === null || (item.data.id && item.data.id.length < 20)) {
|
||||
pNode.data.loaded = false;
|
||||
loadNode(pNode, param, getTestCasesForMinder, null, getMinderExtraNode);
|
||||
return;
|
||||
}
|
||||
if (item.data.changed) {
|
||||
item.data.changed = false;
|
||||
}
|
||||
if (item.data.type === 'node') {
|
||||
handleAfterSave(item, param);
|
||||
}
|
||||
export function handleAfterSave(rootNode) {
|
||||
if (rootNode.data.newId) {
|
||||
rootNode.data.id = rootNode.data.newId;
|
||||
rootNode.data.newId = null;
|
||||
}
|
||||
rootNode.data.deleteChild = null;
|
||||
rootNode.data.changed = false;
|
||||
if (rootNode.children) {
|
||||
for (let i = 0; i < rootNode.children.length; i++) {
|
||||
handleAfterSave(rootNode.children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getChildNodeId(rootNode, nodeIds) {
|
||||
//递归获取所有子节点ID
|
||||
if (rootNode.data.id) {
|
||||
if (rootNode.data.newId) {
|
||||
nodeIds.push(rootNode.data.newId);
|
||||
} else {
|
||||
nodeIds.push(rootNode.data.id);
|
||||
}
|
||||
}
|
||||
if (rootNode.children) {
|
||||
for (let i = 0; i < rootNode.children.length; i++) {
|
||||
getChildNodeId(rootNode.children[i], nodeIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue