feat: 用例脑图支持添加模块

This commit is contained in:
chenjianxing 2021-11-09 19:16:05 +08:00 committed by jianxing
parent 99d6e8d171
commit a1e41339ec
12 changed files with 298 additions and 170 deletions

View File

@ -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());

View File

@ -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) {

View File

@ -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);
}
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}
}
}

View File

@ -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) {

View File

@ -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);

View File

@ -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",

View File

@ -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: []

View File

@ -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;

View File

@ -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);
}
}
}