提交 8539b5d0 编写于 作者: F fit2-zhao

Merge branch 'v1.8' into pr@master@fix_合并1.8

# Conflicts:
#	frontend/src/business/components/api/automation/report/ApiReportDetail.vue
#	frontend/src/business/components/api/automation/report/components/RequestResult.vue
#	frontend/src/business/components/api/definition/components/case/ApiCaseList.vue
#	frontend/src/business/components/api/definition/components/list/ApiCaseSimpleList.vue
#	frontend/src/business/components/common/components/MsModuleMinder.vue
#	frontend/src/business/components/track/review/view/components/TestReviewTestCaseList.vue
......@@ -13,10 +13,10 @@ import java.util.List;
public class ApiScenarioImportUtil {
public static ApiScenarioModule getSelectModule(String moduleId) {
ApiScenarioModuleService apiModuleService = CommonBeanFactory.getBean(ApiScenarioModuleService.class);
ApiScenarioModuleService apiScenarioModuleService = CommonBeanFactory.getBean(ApiScenarioModuleService.class);
if (StringUtils.isNotBlank(moduleId) && !StringUtils.equals("root", moduleId)) {
ApiScenarioModule module = new ApiScenarioModule();
ApiScenarioModuleDTO moduleDTO = apiModuleService.getNode(moduleId);
ApiScenarioModuleDTO moduleDTO = apiScenarioModuleService.getNode(moduleId);
if (moduleDTO != null) {
BeanUtils.copyBean(module, moduleDTO);
}
......@@ -25,6 +25,17 @@ public class ApiScenarioImportUtil {
return null;
}
public static String getSelectModulePath(String path, String pid) {
ApiScenarioModuleService apiScenarioModuleService = CommonBeanFactory.getBean(ApiScenarioModuleService.class);
if (StringUtils.isNotBlank(pid)) {
ApiScenarioModuleDTO moduleDTO = apiScenarioModuleService.getNode(pid);
if (moduleDTO != null) {
return getSelectModulePath(moduleDTO.getName() + "/" + path, moduleDTO.getParentId());
}
}
return "/" + path;
}
public static ApiScenarioModule buildModule(ApiScenarioModule parentModule, String name, String projectId) {
ApiScenarioModuleService apiModuleService = CommonBeanFactory.getBean(ApiScenarioModuleService.class);
ApiScenarioModule module;
......
......@@ -18,6 +18,7 @@ import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.InputStream;
import java.util.ArrayList;
......@@ -62,16 +63,20 @@ public class HarScenarioParser extends HarScenarioAbstractParser<ScenarioImport>
}
private void parseScenarioWithBLOBs(List<ApiScenarioWithBLOBs> scenarioWithBLOBsList, MsScenario msScenario, ApiTestImportRequest request) {
ApiScenarioModule module = ApiScenarioImportUtil.getSelectModule(request.getModuleId());
if (module == null) {
ApiScenarioModuleService apiModuleService = CommonBeanFactory.getBean(ApiScenarioModuleService.class);
module = apiModuleService.getNewModule(msScenario.getName(), projectId, 1);
ApiScenarioModule selectModule = null;
if (StringUtils.isNotBlank(request.getModuleId())) {
selectModule = ApiScenarioImportUtil.getSelectModule(request.getModuleId());
}
ApiScenarioModule module = ApiScenarioImportUtil.buildModule(selectModule, msScenario.getName(), this.projectId);
ApiScenarioWithBLOBs scenarioWithBLOBs = parseScenario(msScenario);
if (module != null) {
scenarioWithBLOBs.setApiScenarioModuleId(module.getId());
scenarioWithBLOBs.setModulePath("/" + module.getName());
if (selectModule != null) {
String selectModulePath = ApiScenarioImportUtil.getSelectModulePath(selectModule.getName(), selectModule.getParentId());
scenarioWithBLOBs.setModulePath(selectModulePath + "/" + module.getName());
} else {
scenarioWithBLOBs.setModulePath("/" + module.getName());
}
}
scenarioWithBLOBsList.add(scenarioWithBLOBs);
}
......
......@@ -112,7 +112,15 @@ public class MsJmeterParser extends ApiImportAbstractParser<ScenarioImport> {
private List<ApiScenarioWithBLOBs> paseObj(MsScenario msScenario, ApiTestImportRequest request) {
List<ApiScenarioWithBLOBs> scenarioWithBLOBsList = new ArrayList<>();
ApiScenarioWithBLOBs scenarioWithBLOBs = new ApiScenarioWithBLOBs();
ApiScenarioModule module = ApiScenarioImportUtil.buildModule(ApiScenarioImportUtil.getSelectModule(request.getModuleId()), msScenario.getName(), this.projectId);
ApiScenarioModule selectModule = null;
String selectModulePath = null;
if (StringUtils.isNotBlank(request.getModuleId())) {
selectModule = ApiScenarioImportUtil.getSelectModule(request.getModuleId());
if (selectModule != null) {
selectModulePath = ApiScenarioImportUtil.getSelectModulePath(selectModule.getName(), selectModule.getParentId());
}
}
ApiScenarioModule module = ApiScenarioImportUtil.buildModule(selectModule, msScenario.getName(), this.projectId);
scenarioWithBLOBs.setName(msScenario.getName());
scenarioWithBLOBs.setProjectId(request.getProjectId());
if (msScenario != null && CollectionUtils.isNotEmpty(msScenario.getHashTree())) {
......@@ -120,7 +128,11 @@ public class MsJmeterParser extends ApiImportAbstractParser<ScenarioImport> {
}
if (module != null) {
scenarioWithBLOBs.setApiScenarioModuleId(module.getId());
scenarioWithBLOBs.setModulePath("/" + module.getName());
if (StringUtils.isNotBlank(selectModulePath)) {
scenarioWithBLOBs.setModulePath(selectModulePath + "/" + module.getName());
} else {
scenarioWithBLOBs.setModulePath("/" + module.getName());
}
}
scenarioWithBLOBs.setId(UUID.randomUUID().toString());
scenarioWithBLOBs.setScenarioDefinition(JSON.toJSONString(msScenario));
......
......@@ -17,11 +17,23 @@ import java.util.*;
public class MsScenarioParser extends MsAbstractParser<ScenarioImport> {
private ApiScenarioModule selectModule;
private String selectModulePath;
@Override
public ScenarioImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
this.projectId = request.getProjectId();
JSONObject testObject = JSONObject.parseObject(testStr, Feature.OrderedField);
if (StringUtils.isNotBlank(request.getModuleId())) {
this.selectModule = ApiScenarioImportUtil.getSelectModule(request.getModuleId());
if (this.selectModule != null) {
this.selectModulePath = ApiScenarioImportUtil.getSelectModulePath(this.selectModule.getName(), this.selectModule.getParentId());
}
}
if (testObject.get("projectName") != null || testObject.get("projectId") != null ) {
return parseMsFormat(testStr, request);
} else {
......@@ -73,13 +85,19 @@ public class MsScenarioParser extends MsAbstractParser<ScenarioImport> {
modulePath = modulePath.substring(0, modulePath.length() - 1);
}
List<String> modules = Arrays.asList(modulePath.split("/"));
ApiScenarioModule parent = ApiScenarioImportUtil.getSelectModule(importRequest.getModuleId());
ApiScenarioModule parent = this.selectModule;
Iterator<String> iterator = modules.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
parent = ApiScenarioImportUtil.buildModule(parent, item, this.projectId);
if (!iterator.hasNext()) {
apiScenarioWithBLOBs.setApiScenarioModuleId(parent.getId());
String path = apiScenarioWithBLOBs.getModulePath() == null ? "" : apiScenarioWithBLOBs.getModulePath();
if (StringUtils.isNotBlank(this.selectModulePath)) {
apiScenarioWithBLOBs.setModulePath(this.selectModulePath + path);
} else if (StringUtils.isBlank(importRequest.getModuleId())) {
apiScenarioWithBLOBs.setModulePath("/默认模块" + path);
}
}
}
}
......
......@@ -46,11 +46,18 @@ public class PostmanScenarioParser extends PostmanAbstractParserParser<ScenarioI
}
private void parseScenarioWithBLOBs(List<ApiScenarioWithBLOBs> scenarioWithBLOBsList, MsScenario msScenario, ApiTestImportRequest request) {
ApiScenarioModule module = ApiScenarioImportUtil.buildModule(ApiScenarioImportUtil.getSelectModule(request.getModuleId()), msScenario.getName(), this.projectId);
ApiScenarioModule selectModule = ApiScenarioImportUtil.getSelectModule(request.getModuleId());
ApiScenarioModule module = ApiScenarioImportUtil.buildModule(selectModule, msScenario.getName(), this.projectId);
ApiScenarioWithBLOBs scenarioWithBLOBs = parseScenario(msScenario);
if (module != null) {
scenarioWithBLOBs.setApiScenarioModuleId(module.getId());
scenarioWithBLOBs.setModulePath("/" + module.getName());
if (selectModule != null) {
String selectModulePath = ApiScenarioImportUtil.getSelectModulePath(selectModule.getName(), selectModule.getParentId());
scenarioWithBLOBs.setModulePath(selectModulePath + "/" + module.getName());
} else {
scenarioWithBLOBs.setModulePath("/" + module.getName());
}
}
scenarioWithBLOBsList.add(scenarioWithBLOBs);
}
......
......@@ -26,6 +26,24 @@ public class ApiDefinitionImportUtil {
return null;
}
public static String getSelectModulePath(String path, String pid) {
ApiModuleService apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
if (StringUtils.isNotBlank(pid)) {
ApiModuleDTO moduleDTO = apiModuleService.getNode(pid);
if (moduleDTO != null) {
return getSelectModulePath(moduleDTO.getName() + "/" + path, moduleDTO.getParentId());
}
}
return "/" + path;
}
public static ApiModule getNodeTree(String projectId) {
ApiModuleService apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
List<ApiModuleDTO> nodeTrees = apiModuleService.getNodeTreeByProjectId(projectId, RequestType.HTTP);
return null;
}
public static ApiModule buildModule(ApiModule parentModule, String name, String projectId) {
ApiModuleService apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
ApiModule module;
......
package io.metersphere.api.dto.definition.parse;
import io.metersphere.api.parse.ApiImportAbstractParser;
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiModule;
import java.util.List;
/**
* @author song.tianyang
* @Date 2021/3/10 11:15 上午
* @Description
*/
public abstract class HarAbstractParser extends ApiImportAbstractParser<ApiDefinitionImport> {
protected void buildModule(ApiModule parentModule, ApiDefinitionWithBLOBs apiDefinition, List<String> tags) {
if (tags != null) {
tags.forEach(tag -> {
ApiModule module = ApiDefinitionImportUtil.buildModule(parentModule, tag, this.projectId);
apiDefinition.setModuleId(module.getId());
});
}else {
apiDefinition.setModuleId(parentModule.getId());
}
}
}
......@@ -61,7 +61,15 @@ public class HarParser extends HarAbstractParser {
private List<ApiDefinitionWithBLOBs> parseRequests(Har har, ApiTestImportRequest importRequest) {
List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
ApiModule parentNode = ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId());
ApiModule selectModule = null;
String selectModulePath = null;
if (StringUtils.isNotBlank(importRequest.getModuleId())) {
selectModule = ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId());
if (selectModule != null) {
selectModulePath = ApiDefinitionImportUtil.getSelectModulePath(selectModule.getName(), selectModule.getParentId());
}
}
List<HarEntry> harEntryList = new ArrayList<>();
if (har.log != null && har.log.entries != null) {
......@@ -103,7 +111,17 @@ public class HarParser extends HarAbstractParser {
addBodyHeader(request);
apiDefinition.setRequest(JSON.toJSONString(request));
apiDefinition.setResponse(JSON.toJSONString(parseResponse(entry.response)));
buildModule(parentNode, apiDefinition, null);
if (selectModule == null) {
apiDefinition.setModuleId("default-module");
} else {
apiDefinition.setModuleId(selectModule.getId());
}
if (StringUtils.isNotBlank(selectModulePath)) {
apiDefinition.setModulePath(selectModulePath);
} else {
apiDefinition.setModulePath("/默认模块");
}
results.add(apiDefinition);
}
}
......
......@@ -19,11 +19,22 @@ import java.util.*;
public class MsDefinitionParser extends MsAbstractParser<ApiDefinitionImport> {
private ApiModule selectModule;
private String selectModulePath;
@Override
public ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
JSONObject testObject = JSONObject.parseObject(testStr, Feature.OrderedField);
this.projectId = request.getProjectId();
if (StringUtils.isNotBlank(request.getModuleId())) {
this.selectModule = ApiDefinitionImportUtil.getSelectModule(request.getModuleId());
if (this.selectModule != null) {
this.selectModulePath = ApiDefinitionImportUtil.getSelectModulePath(this.selectModule.getName(), this.selectModule.getParentId());
}
}
if (testObject.get("projectName") != null || testObject.get("projectId") != null ) {// metersphere 格式导入
return parseMsFormat(testStr, request);
} else { // chrome 插件录制格式导入
......@@ -40,7 +51,7 @@ public class MsDefinitionParser extends MsAbstractParser<ApiDefinitionImport> {
testObject.keySet().forEach(tag -> {
String moduleId = null;
if (isCreateModule) {
moduleId = ApiDefinitionImportUtil.buildModule(ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId()), tag, this.projectId).getId();
moduleId = ApiDefinitionImportUtil.buildModule(this.selectModule, tag, this.projectId).getId();
}
List<MsHTTPSamplerProxy> msHTTPSamplerProxies = parseMsHTTPSamplerProxy(testObject, tag);
for (MsHTTPSamplerProxy msHTTPSamplerProxy : msHTTPSamplerProxies) {
......@@ -113,13 +124,19 @@ public class MsDefinitionParser extends MsAbstractParser<ApiDefinitionImport> {
modulePath = modulePath.substring(0, modulePath.length() - 1);
}
List<String> modules = Arrays.asList(modulePath.split("/"));
ApiModule parent = ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId());
ApiModule parent = this.selectModule;
Iterator<String> iterator = modules.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
parent = ApiDefinitionImportUtil.buildModule(parent, item, this.projectId);
if (!iterator.hasNext()) {
apiDefinition.setModuleId(parent.getId());
String path = apiDefinition.getModulePath() == null ? "" : apiDefinition.getModulePath();
if (StringUtils.isNotBlank(this.selectModulePath)) {
apiDefinition.setModulePath(this.selectModulePath + path);
} else if (StringUtils.isBlank(importRequest.getModuleId())){
apiDefinition.setModulePath("/默认模块" + path);
}
}
}
}
......
......@@ -9,13 +9,22 @@ import io.metersphere.api.dto.parse.postman.PostmanKeyValue;
import io.metersphere.api.parse.PostmanAbstractParserParser;
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiModule;
import org.apache.commons.lang3.StringUtils;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.base.domain.Project;
import io.metersphere.base.mapper.ProjectMapper;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
public class PostmanDefinitionParser extends PostmanAbstractParserParser<ApiDefinitionImport> {
private ApiModule selectModule;
private String selectModulePath;
@Override
public ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
......@@ -24,33 +33,57 @@ public class PostmanDefinitionParser extends PostmanAbstractParserParser<ApiDefi
List<PostmanKeyValue> variables = postmanCollection.getVariable();
ApiDefinitionImport apiImport = new ApiDefinitionImport();
List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
this.selectModule = ApiDefinitionImportUtil.getSelectModule(request.getModuleId());
if (this.selectModule != null) {
this.selectModulePath = ApiDefinitionImportUtil.getSelectModulePath(this.selectModule.getName(), this.selectModule.getParentId());
}
ApiModule apiModule = ApiDefinitionImportUtil.buildModule(this.selectModule, postmanCollection.getInfo().getName(), this.projectId);
List<ApiTestCaseWithBLOBs> cases = new ArrayList<>();
Map<String, String> repeatMap = new HashMap();
ProjectMapper projectMapper = CommonBeanFactory.getBean(ProjectMapper.class);
Project project = projectMapper.selectByPrimaryKey(request.getProjectId());
parseItem(postmanCollection.getItem(), variables, results,
ApiDefinitionImportUtil.buildModule(ApiDefinitionImportUtil.getSelectModule(request.getModuleId()), postmanCollection.getInfo().getName(), this.projectId), true);
apiModule, apiModule.getName(), cases, repeatMap, project.getRepeatable());
apiImport.setData(results);
apiImport.setCases(cases);
return apiImport;
}
protected void parseItem(List<PostmanItem> items, List<PostmanKeyValue> variables, List<ApiDefinitionWithBLOBs> results, ApiModule parentModule, Boolean isCreateModule) {
protected void parseItem(List<PostmanItem> items, List<PostmanKeyValue> variables, List<ApiDefinitionWithBLOBs> results,
ApiModule parentModule, String path, List<ApiTestCaseWithBLOBs> cases, Map<String, String> repeatMap, Boolean repeatable) {
for (PostmanItem item : items) {
List<PostmanItem> childItems = item.getItem();
if (childItems != null) {
ApiModule module = null;
if (isCreateModule) {
module = ApiDefinitionImportUtil.buildModule(parentModule, item.getName(), this.projectId);
}
parseItem(childItems, variables, results, module, isCreateModule);
module = ApiDefinitionImportUtil.buildModule(parentModule, item.getName(), this.projectId);
parseItem(childItems, variables, results, module, path + "/" + module.getName(), cases, repeatMap, repeatable);
} else {
MsHTTPSamplerProxy msHTTPSamplerProxy = parsePostman(item);
ApiDefinitionWithBLOBs request = buildApiDefinition(msHTTPSamplerProxy.getId(), msHTTPSamplerProxy.getName(),
msHTTPSamplerProxy.getPath(), msHTTPSamplerProxy.getMethod(), new ApiTestImportRequest());
request.setPath(msHTTPSamplerProxy.getPath());
request.setRequest(JSON.toJSONString(msHTTPSamplerProxy));
if (request != null) {
results.add(request);
}
if (parentModule != null) {
request.setModuleId(parentModule.getId());
if (StringUtils.isNotBlank(this.selectModulePath)) {
request.setModulePath(this.selectModulePath + "/" + path);
} else {
request.setModulePath("/" + path);
}
}
if (request != null) {
if (repeatMap.keySet().contains(request.getMethod() + request.getPath())
&& (repeatable == null || repeatable == false)) {
ApiTestCaseWithBLOBs apiTestCase = new ApiTestCaseWithBLOBs();
BeanUtils.copyBean(apiTestCase, request);
apiTestCase.setApiDefinitionId(repeatMap.get(request.getMethod() + request.getPath()));
apiTestCase.setPriority("P0");
cases.add(apiTestCase);
} else {
repeatMap.put(request.getMethod() + request.getPath(), request.getId());
results.add(request);
}
}
}
}
......
......@@ -56,7 +56,14 @@ public class Swagger2Parser extends SwaggerAbstractParser {
List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
ApiModule parentNode = ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId());
ApiModule selectModule = null;
String selectModulePath = null;
if (StringUtils.isNotBlank(importRequest.getModuleId())) {
selectModule = ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId());
if (selectModule != null) {
selectModulePath = ApiDefinitionImportUtil.getSelectModulePath(selectModule.getName(), selectModule.getParentId());
}
}
String basePath = swagger.getBasePath();
for (String pathName : pathNames) {
......@@ -76,7 +83,7 @@ public class Swagger2Parser extends SwaggerAbstractParser {
}
apiDefinition.setRequest(JSON.toJSONString(request));
apiDefinition.setResponse(JSON.toJSONString(parseResponse(operation, operation.getResponses())));
buildModule(parentNode, apiDefinition, operation.getTags());
buildModule(selectModule, apiDefinition, operation.getTags(), selectModulePath);
results.add(apiDefinition);
}
}
......
......@@ -26,15 +26,12 @@ import io.swagger.v3.oas.models.parameters.*;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
import io.swagger.v3.parser.core.models.SwaggerParseResult;
import net.sf.saxon.ma.json.XMLToJsonFn;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.fife.ui.rsyntaxtextarea.parser.XmlParser;
import org.springframework.http.HttpMethod;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
......@@ -84,7 +81,14 @@ public class Swagger3Parser extends SwaggerAbstractParser {
List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
ApiModule parentNode = ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId());
ApiModule selectModule = null;
String selectModulePath = null;
if (StringUtils.isNotBlank(importRequest.getModuleId())) {
selectModule = ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId());
if (selectModule != null) {
selectModulePath = ApiDefinitionImportUtil.getSelectModulePath(selectModule.getName(), selectModule.getParentId());
}
}
for (String pathName : pathNames) {
PathItem pathItem = paths.get(pathName);
......@@ -112,7 +116,7 @@ public class Swagger3Parser extends SwaggerAbstractParser {
} // 有数据的话,去掉 Kvs 里初始化的第一个全 null 的数据,否则有空行
apiDefinition.setRequest(JSON.toJSONString(request));
apiDefinition.setResponse(JSON.toJSONString(parseResponse(operation.getResponses())));
buildModule(parentNode, apiDefinition, operation.getTags());
buildModule(selectModule, apiDefinition, operation.getTags(), selectModulePath);
results.add(apiDefinition);
}
}
......
......@@ -3,16 +3,23 @@ package io.metersphere.api.dto.definition.parse;
import io.metersphere.api.parse.ApiImportAbstractParser;
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiModule;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
public abstract class SwaggerAbstractParser extends ApiImportAbstractParser<ApiDefinitionImport> {
protected void buildModule(ApiModule parentModule, ApiDefinitionWithBLOBs apiDefinition, List<String> tags) {
protected void buildModule(ApiModule parentModule, ApiDefinitionWithBLOBs apiDefinition,
List<String> tags, String selectModulePath) {
if (tags != null) {
tags.forEach(tag -> {
ApiModule module = ApiDefinitionImportUtil.buildModule(parentModule, tag, this.projectId);
apiDefinition.setModuleId(module.getId());
if (StringUtils.isNotBlank(selectModulePath)) {
apiDefinition.setModulePath(selectModulePath + "/" + tag);
} else {
apiDefinition.setModulePath("/" + tag);
}
});
}
}
......
......@@ -198,20 +198,14 @@ public abstract class ApiImportAbstractParser<T> implements ApiImportParser<T> {
}
protected ApiScenarioWithBLOBs parseScenario(MsScenario msScenario) {
// ApiScenarioModule module = ApiScenarioImportUtil.buildModule(ApiScenarioImportUtil.getSelectModule(request.getModuleId()), msScenario.getName(), this.projectId);
ApiScenarioWithBLOBs scenarioWithBLOBs = new ApiScenarioWithBLOBs();
scenarioWithBLOBs.setName(msScenario.getName());
scenarioWithBLOBs.setProjectId(this.projectId);
if (msScenario != null && CollectionUtils.isNotEmpty(msScenario.getHashTree())) {
scenarioWithBLOBs.setStepTotal(msScenario.getHashTree().size());
}
// if (module != null) {
// scenarioWithBLOBs.setApiScenarioModuleId(module.getId());
// scenarioWithBLOBs.setModulePath("/" + module.getName());
// }
scenarioWithBLOBs.setId(UUID.randomUUID().toString());
scenarioWithBLOBs.setScenarioDefinition(JSON.toJSONString(msScenario));
return scenarioWithBLOBs;
// scenarioWithBLOBsList.add(scenarioWithBLOBs);
}
}
......@@ -240,6 +240,19 @@ public class ApiDefinitionService {
}
}
private List<ApiDefinition> getSameRequestWithName(SaveApiDefinitionRequest request) {
ApiDefinitionExample example = new ApiDefinitionExample();
example.createCriteria()
.andMethodEqualTo(request.getMethod())
.andStatusNotEqualTo("Trash")
.andPathEqualTo(request.getPath())
.andNameEqualTo(request.getName())
.andProjectIdEqualTo(request.getProjectId())
.andIdNotEqualTo(request.getId());
return apiDefinitionMapper.selectByExample(example);
}
private ApiDefinition updateTest(SaveApiDefinitionRequest request) {
checkNameExist(request);
if (StringUtils.equals(request.getMethod(), "ESB")) {
......@@ -322,7 +335,8 @@ public class ApiDefinitionService {
}
private ApiDefinition importCreate(ApiDefinitionWithBLOBs apiDefinition, ApiDefinitionMapper batchMapper,
ApiTestCaseMapper apiTestCaseMapper, ApiTestImportRequest apiTestImportRequest, List<ApiTestCaseWithBLOBs> cases) {
ApiTestCaseMapper apiTestCaseMapper, ApiTestImportRequest apiTestImportRequest, List<ApiTestCaseWithBLOBs> cases,
Boolean repeatable) {
SaveApiDefinitionRequest saveReq = new SaveApiDefinitionRequest();
BeanUtils.copyBean(saveReq, apiDefinition);
apiDefinition.setCreateTime(System.currentTimeMillis());
......@@ -335,7 +349,13 @@ public class ApiDefinitionService {
}
apiDefinition.setDescription(apiDefinition.getDescription());
List<ApiDefinition> sameRequest = getSameRequest(saveReq);
List<ApiDefinition> sameRequest;
if (repeatable == null || repeatable == false) {
sameRequest = getSameRequest(saveReq);
} else {
// 如果勾选了允许重复,则判断更新要加上name字段
sameRequest = getSameRequestWithName(saveReq);
}
if (StringUtils.equals("fullCoverage", apiTestImportRequest.getModeId())) {
_importCreate(sameRequest, batchMapper, apiDefinition, apiTestCaseMapper, apiTestImportRequest, cases);
} else if (StringUtils.equals("incrementalMerge", apiTestImportRequest.getModeId())) {
......@@ -417,15 +437,13 @@ public class ApiDefinitionService {
private void importMsCase(ApiDefinitionImport apiImport, SqlSession sqlSession, ApiTestCaseMapper apiTestCaseMapper) {
List<ApiTestCaseWithBLOBs> cases = apiImport.getCases();
List<String> caseNames = apiTestCaseService.listPorjectAllCaseName(SessionUtils.getCurrentProjectId());
Set<String> existCaseName = new HashSet<>();
caseNames.forEach(item -> {
existCaseName.add(item);
});
SaveApiTestCaseRequest checkRequest = new SaveApiTestCaseRequest();
if (CollectionUtils.isNotEmpty(cases)) {
int batchCount = 0;
cases.forEach(item -> {
if (!existCaseName.contains(item.getName())) {
checkRequest.setName(item.getName());
checkRequest.setApiDefinitionId(item.getApiDefinitionId());
if (!apiTestCaseService.hasSameCase(checkRequest)) {
item.setId(UUID.randomUUID().toString());
item.setCreateTime(System.currentTimeMillis());
item.setUpdateTime(System.currentTimeMillis());
......@@ -615,6 +633,7 @@ public class ApiDefinitionService {
List<ApiDefinitionWithBLOBs> data = apiImport.getData();
ApiDefinitionMapper batchMapper = sqlSession.getMapper(ApiDefinitionMapper.class);
ApiTestCaseMapper apiTestCaseMapper = sqlSession.getMapper(ApiTestCaseMapper.class);
Project project = projectMapper.selectByPrimaryKey(request.getProjectId());
int num = 0;
if (!CollectionUtils.isEmpty(data) && data.get(0) != null && data.get(0).getProjectId() != null) {
num = getNextNum(data.get(0).getProjectId());
......@@ -630,14 +649,14 @@ public class ApiDefinitionService {
if (apiImport.getEsbApiParamsMap() != null) {
String apiId = item.getId();
EsbApiParamsWithBLOBs model = apiImport.getEsbApiParamsMap().get(apiId);
importCreate(item, batchMapper, apiTestCaseMapper, request, apiImport.getCases());
importCreate(item, batchMapper, apiTestCaseMapper, request, apiImport.getCases(), project.getRepeatable());
if (model != null) {
apiImport.getEsbApiParamsMap().remove(apiId);
model.setResourceId(item.getId());
apiImport.getEsbApiParamsMap().put(item.getId(), model);
}
} else {
importCreate(item, batchMapper, apiTestCaseMapper, request, apiImport.getCases());
importCreate(item, batchMapper, apiTestCaseMapper, request, apiImport.getCases(), project.getRepeatable());
}
if (i % 300 == 0) {
sqlSession.flushStatements();
......
......@@ -275,6 +275,9 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
@Override
public ApiModuleDTO getNode(String id) {
ApiModule module = apiModuleMapper.selectByPrimaryKey(id);
if (module == null) {
return null;
}
ApiModuleDTO dto = JSON.parseObject(JSON.toJSONString(module), ApiModuleDTO.class);
return dto;
}
......
......@@ -81,10 +81,6 @@ public class ApiTestCaseService {
private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR;
public List<String> listPorjectAllCaseName(String projectId) {
return extApiTestCaseMapper.listPorjectAllCaseName(projectId);
}
public List<ApiTestCaseResult> list(ApiTestCaseRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
List<ApiTestCaseResult> returnList = extApiTestCaseMapper.list(request);
......@@ -233,14 +229,24 @@ public class ApiTestCaseService {
}
}
private void checkNameExist(SaveApiTestCaseRequest request) {
ApiTestCaseExample example = new ApiTestCaseExample();
example.createCriteria().andNameEqualTo(request.getName()).andApiDefinitionIdEqualTo(request.getApiDefinitionId()).andIdNotEqualTo(request.getId());
if (apiTestCaseMapper.countByExample(example) > 0) {
public void checkNameExist(SaveApiTestCaseRequest request) {
if (hasSameCase(request)) {
MSException.throwException(Translator.get("load_test_already_exists"));
}
}
public Boolean hasSameCase(SaveApiTestCaseRequest request) {
ApiTestCaseExample example = new ApiTestCaseExample();
ApiTestCaseExample.Criteria criteria = example.createCriteria();
criteria.andNameEqualTo(request.getName()).andApiDefinitionIdEqualTo(request.getApiDefinitionId());
if (StringUtils.isNotBlank(request.getId())) {
criteria.andIdNotEqualTo(request.getId());
}
if (apiTestCaseMapper.countByExample(example) > 0) {
return true;
}
return false;
}
private ApiTestCase updateTest(SaveApiTestCaseRequest request) {
checkNameExist(request);
......
......@@ -12,8 +12,6 @@ import java.util.List;
public interface ExtApiTestCaseMapper {
List<String> listPorjectAllCaseName(@Param("projectId") String projectId);
List<ApiTestCaseResult> list(@Param("request") ApiTestCaseRequest request);
List<ApiTestCaseDTO> listSimple(@Param("request") ApiTestCaseRequest request);
......@@ -33,4 +31,4 @@ public interface ExtApiTestCaseMapper {
ApiTestCaseInfo selectApiCaseInfoByPrimaryKey(String id);
List<ApiTestCase> selectEffectiveTestCaseByProjectId(String projectId);
}
\ No newline at end of file
}
......@@ -391,11 +391,8 @@
<select id="getNextNum" resultType="io.metersphere.base.domain.ApiTestCase">
SELECT * FROM api_test_case WHERE api_test_case.api_definition_id = #{definitionId} ORDER BY num DESC LIMIT 1;
</select>
<select id="listPorjectAllCaseName" resultType="java.lang.String">
select name from api_test_case where project_id = #{projectId}
</select>
<select id="selectEffectiveTestCaseByProjectId" resultType="io.metersphere.base.domain.ApiTestCase">
select id,api_definition_id from api_test_case where project_id = #{projectId}
</select>
</mapper>
\ No newline at end of file
</mapper>
......@@ -50,7 +50,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.19",
"vue-minder-editor-plus": "^1.0.21",
"vue-papa-parse": "^2.0.0",
"vue-pdf": "^4.2.0",
"vue-router": "^3.1.3",
......
......@@ -19,6 +19,7 @@
<ms-table-header-select-popover v-show="total>0"
:page-size="pageSize>total?total:pageSize"
:total="total"
:select-data-counts="selectDataCounts"
@selectPageAll="isSelectDataAll(false)"
@selectAll="isSelectDataAll(true)"/>
......@@ -617,7 +618,7 @@ export default {
});
},
handleSelectAll(selection) {
_handleSelectAll(this, selection, this.tableData, this.selectRows);
_handleSelectAll(this, selection, this.tableData, this.selectRows, this.condition);
setUnSelectIds(this.tableData, this.condition, this.selectRows);
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
this.$emit('selection', selection);
......
......@@ -39,7 +39,7 @@
</el-select>
</el-col>
<el-col class="item" v-if="item.type !== 'file'">
<el-col class="item" v-if="isActive && item.type !== 'file'">
<el-autocomplete
:disabled="isReadOnly"
size="small"
......@@ -64,7 +64,7 @@
</el-col>
<el-col v-if="item.type === 'file'" class="item">
<el-col v-if="isActive && item.type === 'file'" class="item">
<ms-api-body-file-upload :parameter="item"/>
</el-col>
......@@ -126,6 +126,7 @@
currentItem: null,
requireds: REQUIRED,
isSelectAll: true,
isActive: true
}
},
watch: {
......@@ -231,6 +232,7 @@
} else {
item.contentType = 'text/plain';
}
this.reload();
},
selectAll() {
this.parameters.forEach(item => {
......@@ -242,6 +244,12 @@
item.enable = false;
});
},
reload() {
this.isActive = false;
this.$nextTick(() => {
this.isActive = true;
});
}
},
created() {
if (this.parameters.length === 0 || this.parameters[this.parameters.length - 1].name) {
......
......@@ -23,6 +23,7 @@
<ms-table-header-select-popover v-show="total>0"
:page-size="pageSize>total?total:pageSize"
:total="total"
:select-data-counts="selectDataCounts"
@selectPageAll="isSelectDataAll(false)"
@selectAll="isSelectDataAll(true)"/>
......@@ -415,6 +416,8 @@ export default {
this.initTable();
},
handleSelectAll(selection) {
_handleSelectAll(this, selection, this.tableData, this.selectRows, this.condition);
this.selectRowsCount(this.selectRows)
_handleSelectAll(this, selection, this.tableData, this.selectRows);
this.selectRowsCount(this.selectRows);
},
......
......@@ -22,6 +22,7 @@
<ms-table-header-select-popover v-show="total>0"
:page-size="pageSize>total?total:pageSize"
:total="total"
:select-data-counts="selectDataCounts"
@selectPageAll="isSelectDataAll(false)"
@selectAll="isSelectDataAll(true)"/>
......@@ -547,7 +548,7 @@ export default {
});
},
handleSelectAll(selection) {
_handleSelectAll(this, selection, this.tableData, this.selectRows);
_handleSelectAll(this, selection, this.tableData, this.selectRows, this.condition);
setUnSelectIds(this.tableData, this.condition, this.selectRows);
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
},
......
......@@ -9,6 +9,7 @@
:tags="tags"
:height="height"
:distinct-tags="distinctTags"
@afterMount="$emit('afterMount')"
@save="save"
/>
</div>
......@@ -17,6 +18,7 @@
<script>
import MsFullScreenButton from "@/business/components/common/components/MsFullScreenButton";
import {listenNodeSelected} from "@/business/components/track/common/minder/minderUtils";
export default {
name: "MsModuleMinder",
components: {MsFullScreenButton},
......@@ -39,6 +41,12 @@ export default {
return []
}
},
tagEnable: {
type: Boolean,
default() {
return false;
}
},
distinctTags: {
type: Array,
default() {
......@@ -56,7 +64,10 @@ export default {
data: {
text: this.$t('test_track.review_view.all_case'),
disable: true,
id: 'root',
id: "root",
type: 'node',
path: "",
tagEnable: this.tagEnable
},
children: []
},
......@@ -115,9 +126,14 @@ export default {
text: item.name,
id: item.id,
disable: true,
type: 'node',
path: root.data.path + "/" + item.name,
expandState:"collapse"
},
}
if (this.tagEnable) {
node.data.tagEnable = this.tagEnable;
}
root.children.push(node);
this.parse(node, item.children);
});
......@@ -127,6 +143,9 @@ export default {
this.$nextTick(() => {
this.isActive = true;
})
this.$nextTick(() => {
listenNodeSelected();
})
},
setJsonImport(data) {
this.importJson = data;
......@@ -147,6 +166,8 @@ export default {
text: nodeData.name,
id: nodeData.id,
disable: true,
tagEnable: this.tagEnable,
type: 'node'
},
children: []
},
......
<template>
<el-table-column width="1" :resizable="false" align="center">
<el-table-column v-if="isShow" width="1" :resizable="false" align="center">
<el-popover slot="header" placement="right" trigger="click" style="margin-right: 0px;">
<el-link @click.native.stop="$emit('selectAll')">{{$t('api_test.batch_menus.select_all_data',[total])}}</el-link>
<el-link
:class="{'selected-link': selectDataCounts === this.total}"
@click.native.stop="click('selectAll')"
ref="selectAllLink">
{{$t('api_test.batch_menus.select_all_data',[total])}}
</el-link>
<br/>
<el-link @click.native.stop="$emit('selectPageAll')">{{$t('api_test.batch_menus.select_show_data',[pageSize])}}</el-link>
<el-link
:class="{'selected-link': selectDataCounts === this.pageSize}"
@click.native.stop="click('selectPageAll')"
ref="selectPageAllLink">
{{$t('api_test.batch_menus.select_show_data',[pageSize])}}
</el-link>
<i class="el-icon-arrow-down" slot="reference"></i>
</el-popover>
</el-table-column>
......@@ -12,14 +24,35 @@
<script>
export default {
name: "MsTableSelectAll",
props: ['total', 'pageSize'],
props: ['total', 'pageSize', 'selectDataCounts'],
data() {
return {
isShow: true
};
},
watch: {
selectDataCounts() {
this.reload();
}
},
methods: {
click(even) {
this.$emit(even);
},
reload() {
this.isShow = false;
this.$nextTick(() => {
this.isShow = true;
});
}
}
}
</script>
<style scoped>
.selected-link{
color: #783887 !important;
}
</style>
......@@ -23,8 +23,8 @@
<el-form-item>
<el-radio v-model='radioValue' :label="4">
{{$t('schedule.cron.from')}}
<el-input-number v-model='average01' :min="0" :max="31" /> {{$t('schedule.cron.day_unit')}}{{$t('schedule.cron.start')}}{{$t('schedule.cron.every')}}
<el-input-number v-model='average02' :min="0" :max="31" /> {{$t('schedule.cron.day')}}{{$t('schedule.cron.execute_once')}}
<el-input-number v-model='average01' :min="1" :max="31" /> {{$t('schedule.cron.day_unit')}}{{$t('schedule.cron.start')}}{{$t('schedule.cron.every')}}
<el-input-number v-model='average02' :min="1" :max="31" /> {{$t('schedule.cron.day')}}{{$t('schedule.cron.execute_once')}}
</el-radio>
</el-form-item>
......
......@@ -17,8 +17,8 @@
<el-form-item>
<el-radio v-model='radioValue' :label="3">
{{$t('schedule.cron.from')}}
<el-input-number v-model='average01' :min="0" :max="24" /> {{$t('schedule.cron.hours')}}{{$t('schedule.cron.start')}}{{$t('schedule.cron.every')}}
<el-input-number v-model='average02' :min="0" :max="24" /> {{$t('schedule.cron.hours')}}{{$t('schedule.cron.execute_once')}}
<el-input-number v-model='average01' :min="1" :max="24" /> {{$t('schedule.cron.hours')}}{{$t('schedule.cron.start')}}{{$t('schedule.cron.every')}}
<el-input-number v-model='average02' :min="1" :max="24" /> {{$t('schedule.cron.hours')}}{{$t('schedule.cron.execute_once')}}
</el-radio>
</el-form-item>
......
......@@ -17,8 +17,8 @@
<el-form-item>
<el-radio v-model='radioValue' :label="3">
{{$t('schedule.cron.from')}}
<el-input-number v-model='average01' :min="0" :max="59" /> {{$t('schedule.cron.minutes')}}{{$t('schedule.cron.start')}}{{$t('schedule.cron.every')}}
<el-input-number v-model='average02' :min="0" :max="60" /> {{$t('schedule.cron.minutes')}}{{$t('schedule.cron.execute_once')}}
<el-input-number v-model='average01' :min="1" :max="59" /> {{$t('schedule.cron.minutes')}}{{$t('schedule.cron.start')}}{{$t('schedule.cron.every')}}
<el-input-number v-model='average02' :min="1" :max="60" /> {{$t('schedule.cron.minutes')}}{{$t('schedule.cron.execute_once')}}
</el-radio>
</el-form-item>
......
......@@ -17,8 +17,8 @@
<el-form-item>
<el-radio v-model='radioValue' :label="3">
{{$t('schedule.cron.from')}}
<el-input-number v-model='average01' :min="0" :max="59" /> {{$t('schedule.cron.seconds')}}{{$t('schedule.cron.start')}}{{$t('schedule.cron.every')}}
<el-input-number v-model='average02' :min="0" :max="60" /> {{$t('schedule.cron.seconds')}}{{$t('schedule.cron.execute_once')}}
<el-input-number v-model='average01' :min="1" :max="59" /> {{$t('schedule.cron.seconds')}}{{$t('schedule.cron.start')}}{{$t('schedule.cron.every')}}
<el-input-number v-model='average02' :min="1" :max="60" /> {{$t('schedule.cron.seconds')}}{{$t('schedule.cron.execute_once')}}
</el-radio>
</el-form-item>
......
......@@ -13,6 +13,7 @@
<ms-table-header-select-popover v-show="total>0"
:page-size="pageSize>total?total:pageSize"
:total="total"
:select-data-counts="selectDataCounts"
@selectPageAll="isSelectDataAll(false)"
@selectAll="isSelectDataAll(true)"/>
<el-table-column v-if="!referenced" width="30" min-width="30" :resizable="false" align="center">
......@@ -365,7 +366,7 @@
});
},
handleSelectAll(selection) {
_handleSelectAll(this, selection, this.tableData, this.selectRows);
_handleSelectAll(this, selection, this.tableData, this.selectRows, this.condition);
setUnSelectIds(this.tableData, this.condition, this.selectRows);
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
this.$emit('selection', selection);
......
......@@ -16,6 +16,7 @@
<ms-table-header-select-popover v-show="total>0"
:page-size="pageSize>total?total:pageSize"
:total="total"
:select-data-counts="selectDataCounts"
@selectPageAll="isSelectDataAll(false)"
@selectAll="isSelectDataAll(true)"/>
<el-table-column v-if="!referenced" width="30" min-width="30" :resizable="false" align="center">
......@@ -746,7 +747,7 @@ export default {
});
},
handleSelectAll(selection) {
_handleSelectAll(this, selection, this.tableData, this.selectRows);
_handleSelectAll(this, selection, this.tableData, this.selectRows, this.condition);
setUnSelectIds(this.tableData, this.condition, this.selectRows);
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
this.$emit('selection', selection);
......
......@@ -14,6 +14,7 @@
<ms-table-header-select-popover v-show="total>0"
:page-size="pageSize>total?total:pageSize"
:total="total"
:select-data-counts="selectDataCounts"
@selectPageAll="isSelectDataAll(false)"
@selectAll="isSelectDataAll(true)"/>
<el-table-column v-if="!referenced" width="30" min-width="30" :resizable="false" align="center">
......@@ -361,7 +362,7 @@
});
},
handleSelectAll(selection) {
_handleSelectAll(this, selection, this.tableData, this.selectRows);
_handleSelectAll(this, selection, this.tableData, this.selectRows, this.condition);
setUnSelectIds(this.tableData, this.condition, this.selectRows);
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
this.$emit('selection', selection);
......
......@@ -24,6 +24,7 @@
<ms-table-header-select-popover v-show="total>0"
:page-size="pageSize > total ? total : pageSize"
:total="total"
:select-data-counts="selectDataCounts"
@selectPageAll="isSelectDataAll(false)"
@selectAll="isSelectDataAll(true)"/>
......@@ -499,7 +500,7 @@ export default {
this.$emit('testCaseDetail', row);
},
handleSelectAll(selection) {
_handleSelectAll(this, selection, this.tableData, this.selectRows);
_handleSelectAll(this, selection, this.tableData, this.selectRows, this.condition);
setUnSelectIds(this.tableData, this.condition, this.selectRows);
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
},
......
......@@ -4,7 +4,10 @@
:tree-nodes="treeNodes"
:data-map="dataMap"
:tags="tags"
:distinct-tags="[...tags, $t('test_track.plan.plan_status_prepare')]"
:tag-enable="true"
:select-node="selectNode"
:distinct-tags="[...tags, this.$t('test_track.plan.plan_status_prepare')]"
@afterMount="handleAfterMount"
@save="save"
ref="minder"
/>
......@@ -12,7 +15,10 @@
<script>
import MsModuleMinder from "@/business/components/common/components/MsModuleMinder";
import {getTestCaseDataMap} from "@/business/components/track/common/minder/minderUtils";
import {
getTestCaseDataMap,
tagBatch,
} from "@/business/components/track/common/minder/minderUtils";
export default {
name: "TestPlanMinder",
components: {MsModuleMinder},
......@@ -63,6 +69,9 @@ name: "TestPlanMinder",
}
},
methods: {
handleAfterMount() {
tagBatch([...this.tags, this.$t('test_track.plan.plan_status_prepare')]);
},
getTestCases() {
if (this.projectId) {
this.result = this.$get('/test/plan/case/list/minder/' + this.planId, response => {
......
......@@ -4,7 +4,10 @@
:tree-nodes="treeNodes"
:data-map="dataMap"
:tags="tags"
:tag-enable="true"
:select-node="selectNode"
:distinct-tags="[...tags, $t('test_track.plan.plan_status_prepare')]"
@afterMount="handleAfterMount"
@save="save"
ref="minder"
/>
......@@ -12,7 +15,7 @@
<script>
import MsModuleMinder from "@/business/components/common/components/MsModuleMinder";
import {getTestCaseDataMap} from "@/business/components/track/common/minder/minderUtils";
import {getTestCaseDataMap, tagBatch} from "@/business/components/track/common/minder/minderUtils";
export default {
name: "TestReviewMinder",
components: {MsModuleMinder},
......@@ -63,6 +66,9 @@ name: "TestReviewMinder",
}
},
methods: {
handleAfterMount() {
tagBatch([...this.tags, this.$t('test_track.plan.plan_status_prepare')]);
},
getTestCases() {
if (this.projectId) {
let param = {
......
import {getUUID} from "@/common/js/utils";
import i18n from "@/i18n/i18n";
export function getTestCaseDataMap(testCase, isDisable, setParamCallback) {
let dataMap = new Map();
......@@ -25,7 +25,7 @@ export function parseCase(item, dataMap, isDisable, setParamCallback) {
id: item.id,
text: item.name,
priority: Number.parseInt(item.priority.substring(item.priority.length - 1 )) + 1,
resource: ["用例"],
resource: [i18n.t('api_test.definition.request.case')],
type: item.type,
method: item.method,
maintainer: item.maintainer
......@@ -53,7 +53,7 @@ export function parseCase(item, dataMap, isDisable, setParamCallback) {
function parseChildren(nodeItem, item, isDisable) {
nodeItem.children = [];
let children = [];
_parseChildren(children, item.prerequisite, "前置条件", isDisable);
_parseChildren(children, item.prerequisite, i18n.t('test_track.case.prerequisite'), isDisable);
if (item.steps) {
item.steps.forEach((step) => {
let descNode = _parseChildren(children, step.desc, undefined, isDisable);
......@@ -64,7 +64,7 @@ function parseChildren(nodeItem, item, isDisable) {
}
});
}
_parseChildren(children, item.remark, "备注", isDisable);
_parseChildren(children, item.remark, i18n.t('commons.remark'), isDisable);
nodeItem.children = children;
}
......@@ -85,6 +85,33 @@ function _parseChildren(children, k, v, isDisable) {
}
}
export function listenNodeSelected(callback) {
let minder = window.minder;
minder.on('selectionchange ', function (even) {
if (callback) {
callback(even);
}
});
}
export function listenNodeChange(callback) {
let minder = window.minder;
minder.on('contentchange ', function (even) {
if (callback) {
callback(even);
}
});
}
export function listenBeforeExecCommand(callback) {
let minder = window.minder;
minder.on('beforeExecCommand ', function (even) {
if (callback) {
callback(even);
}
});
}
export function appendChild(appendPid, root, node) {
if (root.data.id === appendPid) {
root.children.push(node);
......@@ -121,3 +148,85 @@ export function updateNode(root, node) {
}
}
}
export function tagChildren(node, resourceName, distinctTags) {
let children = node.children;
if (!children) {
children = [];
}
if (!resourceName || !/\S/.test(resourceName)) {return;}
children.forEach((item) => {
let isCaseNode = item.data.resource && item.data.resource.indexOf(i18n.t('api_test.definition.request.case')) > -1;
if (item.data.type === 'node' || isCaseNode) {
let origin = item.data.resource;
if (!origin) {
origin = [];
}
let index = origin.indexOf(resourceName);
// 先删除排他的标签
if (distinctTags.indexOf(resourceName) > -1) {
for (let i = 0; i < origin.length; i++) {
if (distinctTags.indexOf(origin[i]) > -1) {
origin.splice(i, 1);
i--;
}
}
}
if (index !== -1) {
origin.splice(index, 1);
} else {
origin.push(resourceName);
}
item.data.resource = origin;
if (isCaseNode) {
item.data.changed = true;
}
tagChildren(item, resourceName, distinctTags);
}
});
}
function modifyParentNodeTag(node, resourceName) {
let topNode = null;
while (node.parent) {
let pNode = node.parent;
let pResource = pNode.data.resource;
if (pResource && pResource.length > 0 && pResource.indexOf(resourceName) < 0) {
pNode.data.resource = [];
topNode = pNode;
}
node = pNode;
}
return topNode;
}
export function tagBatch(distinctTags) {
listenBeforeExecCommand((even) => {
let minder = window.minder;
let selectNodes = window.minder.getSelectedNodes();
let args = even.commandArgs;
if (selectNodes) {
selectNodes.forEach((node) => {
if (node.data.type === 'node' && even.commandName === 'resource') {
// let origin = minder.queryCommandValue('resource');
if (args && args.length > 0) {
let origin = args[0];
if (origin && origin.length > 0) {
let resourceName = origin[0];
tagChildren(node, resourceName, distinctTags);
let modifyTopNode = modifyParentNodeTag(node, resourceName);
if (modifyTopNode) {
modifyTopNode.renderTree();
} else {
node.renderTree();
}
minder.layout(600);
}
}
}
});
}
});
}
......@@ -15,6 +15,11 @@
:icon="status == 'Completed' ? 'el-icon-check' : ''"
@click="setStatus('Completed')"> {{$t('test_track.plan.plan_status_completed')}}</el-button>
</el-col>
<el-col>
<el-button type="warning" round size="mini"
:icon="status == 'Finished' ? 'el-icon-check' : ''"
@click="setStatus('Finished')"> {{$t('test_track.plan.plan_status_finished')}}</el-button>
</el-col>
</el-row>
</template>
......
......@@ -343,11 +343,11 @@ export default {
handleEdit(testPlan) {
this.$emit('testPlanEdit', testPlan);
},
statusChange(param) {
console.log(this.tableData);
let oldStatus = param.item.status;
let newStatus = param.status;
param = param.item;
statusChange(data) {
let oldStatus = data.item.status;
let newStatus = data.status;
let param = {};
param.id = data.item.id;
param.status = newStatus;
this.$post('/test/plan/edit', param, () => {
for (let i = 0; i < this.tableData.length; i++) {
......
......@@ -509,7 +509,7 @@ export default {
});
},
showDetail(row, event, column) {
this.isReadOnly = true;
this.isReadOnly = !this.isTestManagerOrTestUser;
this.$refs.testPlanTestCaseEdit.openTestCaseEdit(row);
},
refresh() {
......
import {getCurrentProjectID, getCurrentUser, humpToLine} from "@/common/js/utils";
import {TEST_CASE_LIST} from "@/common/js/constants";
export function _handleSelectAll(component, selection, tableData, selectRows) {
export function _handleSelectAll(component, selection, tableData, selectRows, condition) {
if (selection.length > 0) {
if (selection.length === 1) {
selection.hashTree = [];
......@@ -19,6 +18,9 @@ export function _handleSelectAll(component, selection, tableData, selectRows) {
component.$set(item, "showMore", false);
});
}
if (selectRows.size < 1 && condition) {
condition.selectAll = false;
}
}
export function _handleSelect(component, selection, row, selectRows) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册