diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/export/MetersphereApiScenarioExportResponse.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/export/MetersphereApiScenarioExportResponse.java index 0db43aebbb..9b2c185c45 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/export/MetersphereApiScenarioExportResponse.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/export/MetersphereApiScenarioExportResponse.java @@ -18,7 +18,8 @@ import java.util.Map; */ @Data public class MetersphereApiScenarioExportResponse extends ApiScenarioExportResponse { - + @Schema(description = "是否包含关联资源") + private boolean hasRelatedResource; @Schema(description = "导出的场景") private List exportScenarioList = new ArrayList<>(); diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioDetail.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioDetail.java index 3dc34805c7..ffce61214a 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioDetail.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioDetail.java @@ -1,6 +1,7 @@ package io.metersphere.api.dto.scenario; import io.metersphere.api.domain.ApiScenario; +import io.metersphere.system.uid.IDGenerator; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -16,4 +17,14 @@ public class ApiScenarioDetail extends ApiScenario { private ScenarioConfig scenarioConfig = new ScenarioConfig(); @Schema(description = "步骤") private List steps; + + public void resetConfigCsvId() { + if (scenarioConfig == null || scenarioConfig.getVariable() == null || scenarioConfig.getVariable().getCsvVariables() == null) { + return; + } + + scenarioConfig.getVariable().getCsvVariables().forEach(csvVariable -> { + csvVariable.setId(IDGenerator.nextStr()); + }); + } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/parser/api/dataimport/MetersphereParserApiScenario.java b/backend/services/api-test/src/main/java/io/metersphere/api/parser/api/dataimport/MetersphereParserApiScenario.java index cac989ead5..1488ed54aa 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/parser/api/dataimport/MetersphereParserApiScenario.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/parser/api/dataimport/MetersphereParserApiScenario.java @@ -1,6 +1,7 @@ package io.metersphere.api.parser.api.dataimport; +import io.metersphere.api.constants.ApiScenarioStepType; import io.metersphere.api.domain.ApiScenarioCsv; import io.metersphere.api.dto.converter.ApiScenarioImportParseResult; import io.metersphere.api.dto.converter.ApiScenarioStepParseResult; @@ -55,26 +56,31 @@ public class MetersphereParserApiScenario implements ApiScenarioImportParser { for (ApiScenarioDetail apiScenarioDetail : exportScenarioList) { + apiScenarioDetail.resetConfigCsvId(); returnResult.getImportScenarioList().add( - this.parseApiScenario(projectId, apiScenarioDetail, scenarioStepMap, scenarioStepBlobMap, apiScenarioCsvMap)); + this.parseApiScenario(projectId, metersphereApiScenarioExportResponse.isHasRelatedResource(), apiScenarioDetail, scenarioStepMap, scenarioStepBlobMap, apiScenarioCsvMap)); } - for (ApiScenarioDetail apiScenarioDetail : relatedScenarioList) { - returnResult.getRelatedScenarioList().add( - this.parseApiScenario(projectId, apiScenarioDetail, scenarioStepMap, scenarioStepBlobMap, apiScenarioCsvMap)); + if (metersphereApiScenarioExportResponse.isHasRelatedResource()) { + for (ApiScenarioDetail apiScenarioDetail : relatedScenarioList) { + apiScenarioDetail.resetConfigCsvId(); + returnResult.getRelatedScenarioList().add( + this.parseApiScenario(projectId, true, apiScenarioDetail, scenarioStepMap, scenarioStepBlobMap, apiScenarioCsvMap)); + } } return returnResult; } private ApiScenarioImportDetail parseApiScenario(String projectId, + boolean hasRelatedData, ApiScenarioDetail apiScenarioDetail, Map> apiScenarioStepMap, Map scenarioStepBlobMap, Map> apiScenarioCsvMap) { ApiScenarioImportDetail apiScenarioImportDetail = new ApiScenarioImportDetail(); BeanUtils.copyBean(apiScenarioImportDetail, apiScenarioDetail); - ApiScenarioStepParseResult parseResult = this.parseStepDetails(apiScenarioStepMap, apiScenarioDetail.getId(), scenarioStepBlobMap); + ApiScenarioStepParseResult parseResult = this.parseStepDetails(apiScenarioStepMap, apiScenarioDetail.getId(), hasRelatedData, scenarioStepBlobMap); apiScenarioImportDetail.setSteps(parseResult.getStepList()); apiScenarioImportDetail.setStepDetails(parseResult.getStepDetails()); apiScenarioImportDetail.setProjectId(projectId); @@ -82,7 +88,7 @@ public class MetersphereParserApiScenario implements ApiScenarioImportParser { return apiScenarioImportDetail; } - private ApiScenarioStepParseResult parseStepDetails(Map> apiScenarioStepMap, String scenarioId, Map scenarioStepBlobMap) { + private ApiScenarioStepParseResult parseStepDetails(Map> apiScenarioStepMap, String scenarioId, boolean hasRelatedData, Map scenarioStepBlobMap) { ApiScenarioStepParseResult apiScenarioStepParseResult = new ApiScenarioStepParseResult(); List stepList = apiScenarioStepMap.getOrDefault(scenarioId, new ArrayList<>()); @@ -109,8 +115,8 @@ public class MetersphereParserApiScenario implements ApiScenarioImportParser { if (scenarioStepBlobMap.containsKey(oldStepId)) { apiScenarioStepParseResult.getStepDetails().put(stepRequest.getId(), scenarioStepBlobMap.get(oldStepId).getBytes()); } - stepRequest.setChildren(this.buildTreeStep(this.getChildScenarioStep(oldStepId, apiScenarioStepMap), - apiScenarioStepMap, scenarioStepBlobMap, apiScenarioStepParseResult)); + stepRequest.setChildren(this.buildTreeStep(this.getChildScenarioStep(oldStepId, stepDTO.getStepType(), stepDTO.getScenarioId(), hasRelatedData, apiScenarioStepMap), + hasRelatedData, apiScenarioStepMap, scenarioStepBlobMap, apiScenarioStepParseResult)); apiScenarioStepParseResult.getStepList().add(stepRequest); } @@ -119,6 +125,7 @@ public class MetersphereParserApiScenario implements ApiScenarioImportParser { private List buildTreeStep( List childScenarioStep, + boolean hasRelatedData, Map> allScenarioStepMap, Map scenarioStepBlobMap, ApiScenarioStepParseResult apiScenarioStepParseResult) { @@ -133,22 +140,36 @@ public class MetersphereParserApiScenario implements ApiScenarioImportParser { if (scenarioStepBlobMap.containsKey(oldChildId)) { apiScenarioStepParseResult.getStepDetails().put(childRequest.getId(), scenarioStepBlobMap.get(oldChildId).getBytes()); } - childRequest.setChildren(this.buildTreeStep(this.getChildScenarioStep(oldChildId, allScenarioStepMap), - allScenarioStepMap, scenarioStepBlobMap, apiScenarioStepParseResult)); + childRequest.setChildren(this.buildTreeStep(this.getChildScenarioStep(oldChildId, childDTO.getStepType(), childDTO.getScenarioId(), hasRelatedData, allScenarioStepMap), + hasRelatedData, allScenarioStepMap, scenarioStepBlobMap, apiScenarioStepParseResult)); returnList.add(childRequest); } return returnList; } - private List getChildScenarioStep(String parentId, Map> apiScenarioStepMap) { + private List getChildScenarioStep(String parentId, String parentStepType, String scenarioId, boolean hasRelatedData, Map> apiScenarioStepMap) { List childStepList = new ArrayList<>(); - apiScenarioStepMap.values().forEach(stepList -> { - for (ApiScenarioStepDTO stepDTO : stepList) { + List allScenarioStepList = apiScenarioStepMap.get(scenarioId); + if (CollectionUtils.isNotEmpty(allScenarioStepList)) { + allScenarioStepList.forEach(stepDTO -> { if (StringUtils.equals(stepDTO.getParentId(), parentId)) { childStepList.add(stepDTO); } - } - }); + }); + } + if (CollectionUtils.isEmpty(childStepList) && StringUtils.equalsIgnoreCase(parentStepType, ApiScenarioStepType.API_SCENARIO.name()) && !hasRelatedData) { + //如果没有找到场景步骤,并且文件是不导出关联关系的配置,则可能这是一个引用的场景,我们要去所有场景步骤中找 + apiScenarioStepMap.forEach((otherScenarioId, v) -> { + if (StringUtils.equals(otherScenarioId, scenarioId)) { + return; + } + v.forEach(stepDTO -> { + if (StringUtils.equals(stepDTO.getParentId(), parentId)) { + childStepList.add(stepDTO); + } + }); + }); + } return childStepList; } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiScenarioDataTransferService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiScenarioDataTransferService.java index 5e60f85704..0d3c93c7a9 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiScenarioDataTransferService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiScenarioDataTransferService.java @@ -1145,7 +1145,7 @@ public class ApiScenarioDataTransferService { MetersphereApiScenarioExportResponse response = apiScenarioService.selectAndSortScenarioDetailWithIds(request.getSelectIds(), moduleMap); response.setProjectId(project.getId()); response.setOrganizationId(project.getOrganizationId()); - + response.setHasRelatedResource(request.isExportAllRelatedData()); if (request.isExportAllRelatedData()) { // 全量导出,导出引用的api、apiCase List apiDefinitionIdList = new ArrayList<>(); diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java index c09073f3d5..80d0092906 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java @@ -1824,7 +1824,9 @@ public class ApiScenarioService extends MoveNodeService { ApiScenarioStepDTO returnDTO = new ApiScenarioStepDTO(); BeanUtils.copyBean(returnDTO, dto); if (StringUtils.isNotBlank(parentId) && !StringUtils.equalsIgnoreCase(parentId, dto.getId())) { - returnDTO.setParentId(parentId); + if (StringUtils.isBlank(returnDTO.getParentId())) { + returnDTO.setParentId(parentId); + } } if (returnDTO.getConfig() != null && StringUtils.isNotBlank(returnDTO.getConfig().toString())) { if (returnDTO.getConfig() instanceof String configVal) { diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerImportAndExportTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerImportAndExportTests.java index 721192cdea..e0549686fd 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerImportAndExportTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerImportAndExportTests.java @@ -165,7 +165,7 @@ public class ApiScenarioControllerImportAndExportTests extends BaseTest { MetersphereApiScenarioExportResponse exportResponse = ApiDataUtils.parseObject(fileContent, MetersphereApiScenarioExportResponse.class); - Assertions.assertEquals(exportResponse.getExportScenarioList().size(), 8); + Assertions.assertEquals(exportResponse.getExportScenarioList().size(), 6); MsFileUtils.deleteDir("/tmp/api-scenario-export/"); }