fix(接口测试): 场景普通导出时数据补足
--bug=1047996 --user=宋天阳 【场景导入】-导入无引用关系的场景文件,CASE类型步骤的参数丢失 https://www.tapd.cn/55049933/s/1597504
This commit is contained in:
parent
e31dc32ec3
commit
be5ce9de72
|
@ -1,7 +1,5 @@
|
||||||
package io.metersphere.api.dto.export;
|
package io.metersphere.api.dto.export;
|
||||||
|
|
||||||
import io.metersphere.api.constants.ApiScenarioStepRefType;
|
|
||||||
import io.metersphere.api.constants.ApiScenarioStepType;
|
|
||||||
import io.metersphere.api.domain.ApiScenarioCsv;
|
import io.metersphere.api.domain.ApiScenarioCsv;
|
||||||
import io.metersphere.api.dto.converter.ApiDefinitionDetail;
|
import io.metersphere.api.dto.converter.ApiDefinitionDetail;
|
||||||
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
||||||
|
@ -9,7 +7,6 @@ import io.metersphere.api.dto.scenario.ApiScenarioDetail;
|
||||||
import io.metersphere.api.dto.scenario.ApiScenarioStepDTO;
|
import io.metersphere.api.dto.scenario.ApiScenarioStepDTO;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -55,20 +52,4 @@ public class MetersphereApiScenarioExportResponse extends ApiScenarioExportRespo
|
||||||
public void addExportScenario(ApiScenarioDetail apiScenarioDetail) {
|
public void addExportScenario(ApiScenarioDetail apiScenarioDetail) {
|
||||||
exportScenarioList.add(apiScenarioDetail);
|
exportScenarioList.add(apiScenarioDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStepTypeToCustomRequest() {
|
|
||||||
scenarioStepList.forEach(step -> {
|
|
||||||
if (StringUtils.equalsAnyIgnoreCase(step.getStepType(), ApiScenarioStepType.API.name(), ApiScenarioStepType.API_CASE.name())) {
|
|
||||||
step.setStepType(ApiScenarioStepType.CUSTOM_REQUEST.name());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRefTypeToCopy() {
|
|
||||||
scenarioStepList.forEach(step -> {
|
|
||||||
if (StringUtils.equalsAnyIgnoreCase(step.getStepType(), ApiScenarioStepType.API.name(), ApiScenarioStepType.API_SCENARIO.name(), ApiScenarioStepType.API_CASE.name())) {
|
|
||||||
step.setRefType(ApiScenarioStepRefType.COPY.name());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.api.service;
|
package io.metersphere.api.service;
|
||||||
|
|
||||||
import io.metersphere.api.constants.ApiDefinitionStatus;
|
import io.metersphere.api.constants.ApiDefinitionStatus;
|
||||||
|
import io.metersphere.api.constants.ApiScenarioStepRefType;
|
||||||
import io.metersphere.api.constants.ApiScenarioStepType;
|
import io.metersphere.api.constants.ApiScenarioStepType;
|
||||||
import io.metersphere.api.domain.*;
|
import io.metersphere.api.domain.*;
|
||||||
import io.metersphere.api.dto.ApiFile;
|
import io.metersphere.api.dto.ApiFile;
|
||||||
|
@ -179,7 +180,7 @@ public class ApiScenarioDataTransferService {
|
||||||
}
|
}
|
||||||
//解析
|
//解析
|
||||||
ApiScenarioPreImportAnalysisResult preImportAnalysisResult = this.importAnalysis(
|
ApiScenarioPreImportAnalysisResult preImportAnalysisResult = this.importAnalysis(
|
||||||
parseResult, request.getOperator(), request.getProjectId(), request.getModuleId(), apiScenarioModuleService.getTree(request.getProjectId()));
|
parseResult, request.getOperator(), request.getProjectId(), request.getModuleId(), apiScenarioModuleService.getImportTreeNodeList(request.getProjectId()));
|
||||||
//存储
|
//存储
|
||||||
this.save(preImportAnalysisResult, request.getProjectId(), request.getOperator(), request.isCoverData());
|
this.save(preImportAnalysisResult, request.getProjectId(), request.getOperator(), request.isCoverData());
|
||||||
}
|
}
|
||||||
|
@ -938,7 +939,7 @@ public class ApiScenarioDataTransferService {
|
||||||
{
|
{
|
||||||
for (Map.Entry<String, List<ApiScenarioImportDetail>> entry : projectScenarioMap.entrySet()) {
|
for (Map.Entry<String, List<ApiScenarioImportDetail>> entry : projectScenarioMap.entrySet()) {
|
||||||
String targetProjectId = entry.getKey();
|
String targetProjectId = entry.getKey();
|
||||||
List<BaseTreeNode> apiScenarioModules = apiScenarioModuleService.getTree(targetProjectId);
|
List<BaseTreeNode> apiScenarioModules = apiScenarioModuleService.getImportTreeNodeList(targetProjectId);
|
||||||
|
|
||||||
Map<String, String> moduleIdPathMap = apiScenarioModules.stream().collect(Collectors.toMap(BaseTreeNode::getId, BaseTreeNode::getPath));
|
Map<String, String> moduleIdPathMap = apiScenarioModules.stream().collect(Collectors.toMap(BaseTreeNode::getId, BaseTreeNode::getPath));
|
||||||
Map<String, BaseTreeNode> modulePathMap = apiScenarioModules.stream().collect(Collectors.toMap(BaseTreeNode::getPath, k -> k, (k1, k2) -> k1));
|
Map<String, BaseTreeNode> modulePathMap = apiScenarioModules.stream().collect(Collectors.toMap(BaseTreeNode::getPath, k -> k, (k1, k2) -> k1));
|
||||||
|
@ -1020,7 +1021,7 @@ public class ApiScenarioDataTransferService {
|
||||||
if (CollectionUtils.isEmpty(ids)) {
|
if (CollectionUtils.isEmpty(ids)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Map<String, String> moduleMap = this.apiScenarioModuleService.getTree(request.getProjectId()).stream().collect(Collectors.toMap(BaseTreeNode::getId, BaseTreeNode::getPath));
|
Map<String, String> moduleMap = this.apiScenarioModuleService.getImportTreeNodeList(request.getProjectId()).stream().collect(Collectors.toMap(BaseTreeNode::getId, BaseTreeNode::getPath));
|
||||||
|
|
||||||
String fileFolder = tmpDir.getPath() + File.separatorChar + request.getFileId();
|
String fileFolder = tmpDir.getPath() + File.separatorChar + request.getFileId();
|
||||||
AtomicInteger fileIndex = new AtomicInteger(1);
|
AtomicInteger fileIndex = new AtomicInteger(1);
|
||||||
|
@ -1150,9 +1151,47 @@ public class ApiScenarioDataTransferService {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// 普通导出,所有的引用都改为复制,并且Api、ApiCase改为CUSTOM_REQUEST
|
// 普通导出,所有的引用都改为复制,并且Api、ApiCase改为CUSTOM_REQUEST
|
||||||
response.setRefTypeToCopy();
|
Map<String, String> stepApiDefinitionMap = new HashMap<>();
|
||||||
response.setStepTypeToCustomRequest();
|
Map<String, String> stepApiCaseMap = new HashMap<>();
|
||||||
|
response.getScenarioStepList().forEach(step -> {
|
||||||
|
if (StringUtils.equalsAnyIgnoreCase(step.getStepType(), ApiScenarioStepType.API.name(), ApiScenarioStepType.API_SCENARIO.name(), ApiScenarioStepType.API_CASE.name())) {
|
||||||
|
// 引用的api、case转换为自定义步骤时,要对应的api、case也一并导出
|
||||||
|
if (!response.getScenarioStepBlobMap().containsKey(step.getId())) {
|
||||||
|
if (StringUtils.equalsIgnoreCase(step.getStepType(), ApiScenarioStepType.API.name())) {
|
||||||
|
stepApiDefinitionMap.put(step.getId(), step.getResourceId());
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(step.getStepType(), ApiScenarioStepType.API_CASE.name())) {
|
||||||
|
stepApiCaseMap.put(step.getId(), step.getResourceId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
step.setRefType(ApiScenarioStepRefType.COPY.name());
|
||||||
|
step.setStepType(ApiScenarioStepType.CUSTOM_REQUEST.name());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Map<String, String> appendBlobMap = new HashMap<>();
|
||||||
|
if (MapUtils.isNotEmpty(stepApiDefinitionMap)) {
|
||||||
|
List<ApiDefinitionWithBlob> apiDefinitionWithBlobs = extApiDefinitionMapper.selectApiDefinitionWithBlob(new ArrayList<>(stepApiDefinitionMap.values()));
|
||||||
|
Map<String, ApiDefinitionWithBlob> idMap = apiDefinitionWithBlobs.stream().collect(Collectors.toMap(ApiDefinitionWithBlob::getId, Function.identity()));
|
||||||
|
stepApiDefinitionMap.forEach((stepId, apiId) -> {
|
||||||
|
ApiDefinitionWithBlob api = idMap.get(apiId);
|
||||||
|
if (api != null) {
|
||||||
|
appendBlobMap.put(stepId, new String(api.getRequest(), StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (MapUtils.isNotEmpty(stepApiCaseMap)) {
|
||||||
|
List<ApiTestCaseWithBlob> apiTestCaseList = extApiTestCaseMapper.selectAllDetailByIds(new ArrayList<>(stepApiCaseMap.values()));
|
||||||
|
Map<String, ApiTestCaseWithBlob> idMap = apiTestCaseList.stream().collect(Collectors.toMap(ApiTestCaseWithBlob::getId, Function.identity()));
|
||||||
|
stepApiCaseMap.forEach((stepId, apiCaseId) -> {
|
||||||
|
ApiTestCaseWithBlob apiTestCase = idMap.get(apiCaseId);
|
||||||
|
if (apiTestCase != null) {
|
||||||
|
appendBlobMap.put(stepId, new String(apiTestCase.getRequest(), StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
response.getScenarioStepBlobMap().putAll(appendBlobMap);
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -65,12 +66,36 @@ public class ApiScenarioModuleService extends ModuleTreeService {
|
||||||
return super.buildTreeAndCountResource(fileModuleList, true, Translator.get(UNPLANNED_SCENARIO));
|
return super.buildTreeAndCountResource(fileModuleList, true, Translator.get(UNPLANNED_SCENARIO));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<BaseTreeNode> getTree(String projectId) {
|
public List<BaseTreeNode> getImportTreeNodeList(String projectId) {
|
||||||
|
|
||||||
//接口的树结构是 模块:子模块+接口 接口为非delete状态的
|
//接口的树结构是 模块:子模块+接口 接口为非delete状态的
|
||||||
List<BaseTreeNode> fileModuleList = extApiScenarioModuleMapper.selectBaseByRequest(new ApiScenarioModuleRequest() {{
|
List<BaseTreeNode> traverseList = extApiScenarioModuleMapper.selectBaseByRequest(new ApiScenarioModuleRequest() {{
|
||||||
this.setProjectId(projectId);
|
this.setProjectId(projectId);
|
||||||
}});
|
}});
|
||||||
return super.buildTreeAndCountResource(fileModuleList, true, Translator.get(UNPLANNED_SCENARIO));
|
|
||||||
|
List<BaseTreeNode> baseTreeNodeList = new ArrayList<>();
|
||||||
|
BaseTreeNode defaultNode = new BaseTreeNode(ModuleConstants.DEFAULT_NODE_ID, Translator.get(UNPLANNED_SCENARIO), ModuleConstants.NODE_TYPE_DEFAULT, ModuleConstants.ROOT_NODE_PARENT_ID);
|
||||||
|
defaultNode.setPath(StringUtils.join("/", defaultNode.getName()));
|
||||||
|
baseTreeNodeList.add(defaultNode);
|
||||||
|
int lastSize = 0;
|
||||||
|
Map<String, BaseTreeNode> baseTreeNodeMap = new HashMap<>();
|
||||||
|
while (CollectionUtils.isNotEmpty(traverseList) && traverseList.size() != lastSize) {
|
||||||
|
lastSize = traverseList.size();
|
||||||
|
List<BaseTreeNode> notMatchedList = new ArrayList<>();
|
||||||
|
for (BaseTreeNode treeNode : traverseList) {
|
||||||
|
if (!baseTreeNodeMap.containsKey(treeNode.getParentId()) && !StringUtils.equalsIgnoreCase(treeNode.getParentId(), ModuleConstants.ROOT_NODE_PARENT_ID)) {
|
||||||
|
notMatchedList.add(treeNode);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
BaseTreeNode node = new BaseTreeNode(treeNode.getId(), treeNode.getName(), treeNode.getType(), treeNode.getParentId());
|
||||||
|
node.genModulePath(baseTreeNodeMap.get(treeNode.getParentId()));
|
||||||
|
baseTreeNodeMap.put(treeNode.getId(), node);
|
||||||
|
|
||||||
|
baseTreeNodeList.add(node);
|
||||||
|
}
|
||||||
|
traverseList = notMatchedList;
|
||||||
|
}
|
||||||
|
return baseTreeNodeList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<BaseTreeNode> getTreeOnlyIdsAndResourceCount(ApiScenarioModuleRequest request, List<ModuleCountDTO> moduleCountDTOList) {
|
public List<BaseTreeNode> getTreeOnlyIdsAndResourceCount(ApiScenarioModuleRequest request, List<ModuleCountDTO> moduleCountDTOList) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package io.metersphere.api.controller;
|
package io.metersphere.api.controller;
|
||||||
|
|
||||||
import io.metersphere.api.dto.definition.ApiDefinitionBatchExportRequest;
|
import io.metersphere.api.dto.definition.ApiScenarioBatchExportRequest;
|
||||||
import io.metersphere.api.dto.export.MetersphereApiScenarioExportResponse;
|
import io.metersphere.api.dto.export.MetersphereApiScenarioExportResponse;
|
||||||
import io.metersphere.api.dto.scenario.ApiScenarioImportRequest;
|
import io.metersphere.api.dto.scenario.ApiScenarioImportRequest;
|
||||||
import io.metersphere.api.utils.ApiDataUtils;
|
import io.metersphere.api.utils.ApiDataUtils;
|
||||||
|
@ -34,6 +34,7 @@ import org.springframework.util.MultiValueMap;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@ -62,11 +63,6 @@ public class ApiScenarioControllerImportAndExportTests extends BaseTest {
|
||||||
initProject.setEnable(true);
|
initProject.setEnable(true);
|
||||||
initProject.setUserIds(List.of("admin"));
|
initProject.setUserIds(List.of("admin"));
|
||||||
project = commonProjectService.add(initProject, "admin", "/organization-project/add", OperationLogModule.SETTING_ORGANIZATION_PROJECT);
|
project = commonProjectService.add(initProject, "admin", "/organization-project/add", OperationLogModule.SETTING_ORGANIZATION_PROJECT);
|
||||||
// ArrayList<String> moduleList = new ArrayList<>(List.of("workstation", "testPlan", "bugManagement", "caseManagement", "apiTest", "uiTest", "loadTest"));
|
|
||||||
// Project updateProject = new Project();
|
|
||||||
// updateProject.setId(importProject.getId());
|
|
||||||
// updateProject.setModuleSetting(JSON.toJSONString(moduleList));
|
|
||||||
// projectMapper.updateByPrimaryKeySelective(updateProject);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,13 +97,17 @@ public class ApiScenarioControllerImportAndExportTests extends BaseTest {
|
||||||
public void testExport() throws Exception {
|
public void testExport() throws Exception {
|
||||||
MsFileUtils.deleteDir("/tmp/api-scenario-export/");
|
MsFileUtils.deleteDir("/tmp/api-scenario-export/");
|
||||||
|
|
||||||
ApiDefinitionBatchExportRequest exportRequest = new ApiDefinitionBatchExportRequest();
|
List<Boolean> exportAllRelatedData = new ArrayList<>() {{
|
||||||
|
this.add(true);
|
||||||
|
this.add(false);
|
||||||
|
}};
|
||||||
|
for (Boolean isAllRelatedData : exportAllRelatedData) {
|
||||||
|
ApiScenarioBatchExportRequest exportRequest = new ApiScenarioBatchExportRequest();
|
||||||
String fileId = IDGenerator.nextStr();
|
String fileId = IDGenerator.nextStr();
|
||||||
exportRequest.setProjectId(project.getId());
|
exportRequest.setProjectId(project.getId());
|
||||||
exportRequest.setFileId(fileId);
|
exportRequest.setFileId(fileId);
|
||||||
exportRequest.setSelectAll(true);
|
exportRequest.setSelectAll(true);
|
||||||
exportRequest.setExportApiCase(true);
|
exportRequest.setExportAllRelatedData(isAllRelatedData);
|
||||||
exportRequest.setExportApiMock(true);
|
|
||||||
MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_POST_EXPORT + "metersphere", exportRequest);
|
MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_POST_EXPORT + "metersphere", exportRequest);
|
||||||
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
@ -143,6 +143,7 @@ public class ApiScenarioControllerImportAndExportTests extends BaseTest {
|
||||||
|
|
||||||
MsFileUtils.deleteDir("/tmp/api-scenario-export/");
|
MsFileUtils.deleteDir("/tmp/api-scenario-export/");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private MvcResult download(String projectId, String fileId) throws Exception {
|
private MvcResult download(String projectId, String fileId) throws Exception {
|
||||||
return mockMvc.perform(MockMvcRequestBuilders.get("/api/scenario/download/file/" + projectId + "/" + fileId)
|
return mockMvc.perform(MockMvcRequestBuilders.get("/api/scenario/download/file/" + projectId + "/" + fileId)
|
||||||
|
|
Loading…
Reference in New Issue