From 6cec903a59bde25f7d27ca39d5229466ad8c830c Mon Sep 17 00:00:00 2001 From: Jianguo-Genius Date: Fri, 18 Oct 2024 18:23:50 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):=20M?= =?UTF-8?q?etersphere=E5=9C=BA=E6=99=AF=E6=A0=BC=E5=BC=8F=E5=AF=BC?= =?UTF-8?q?=E5=85=A5-=E6=96=87=E4=BB=B6=E6=95=B0=E6=8D=AE=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ApiScenarioImportParseResult.java | 40 + .../ApiScenarioPreImportAnalysisResult.java | 5 +- .../converter/ApiScenarioStepParseResult.java | 15 + .../dto/scenario/ApiScenarioImportDetail.java | 6 +- .../api/parser/ApiScenarioImportParser.java | 5 +- .../dataimport/JmeterParserApiScenario.java | 14 +- .../MetersphereParserApiScenario.java | 119 +- .../ApiScenarioDataTransferService.java | 12 +- ...cenarioControllerImportAndExportTests.java | 44 +- .../file/import-scenario/metersphere/all.ms | 1018 +++++++++++++++++ 10 files changed, 1223 insertions(+), 55 deletions(-) create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/dto/converter/ApiScenarioImportParseResult.java create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/dto/converter/ApiScenarioStepParseResult.java create mode 100644 backend/services/api-test/src/test/resources/file/import-scenario/metersphere/all.ms diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/converter/ApiScenarioImportParseResult.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/converter/ApiScenarioImportParseResult.java new file mode 100644 index 0000000000..791c8886ea --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/converter/ApiScenarioImportParseResult.java @@ -0,0 +1,40 @@ +package io.metersphere.api.dto.converter; + +import io.metersphere.api.domain.ApiScenarioCsv; +import io.metersphere.api.dto.definition.ApiTestCaseDTO; +import io.metersphere.api.dto.scenario.ApiScenarioImportDetail; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 接口导入数据准备结果 + */ +@Data +public class ApiScenarioImportParseResult { + @Schema(description = "导入的场景") + List importScenarioList = new ArrayList<>(); + + @Schema(description = "有关联关系的场景") + List relatedScenarioList = new ArrayList<>(); + + + @Schema(description = "场景CSV相关的数据") + private List apiScenarioCsvList = new ArrayList<>(); + + + @Schema(description = "所有场景步骤内容") + private Map scenarioStepBlobMap = new HashMap<>(); + + + @Schema(description = "有关联的接口定义") + private List relatedApiDefinitions = new ArrayList<>(); + + @Schema(description = "有关联的接口用例") + private List relatedApiTestCaseList = new ArrayList<>(); + +} diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/converter/ApiScenarioPreImportAnalysisResult.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/converter/ApiScenarioPreImportAnalysisResult.java index e31b6b9e7a..13c84539b0 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/converter/ApiScenarioPreImportAnalysisResult.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/converter/ApiScenarioPreImportAnalysisResult.java @@ -8,9 +8,6 @@ import lombok.Data; import java.util.ArrayList; import java.util.List; -/** - * 接口导入数据准备结果 - */ @Data public class ApiScenarioPreImportAnalysisResult { @@ -23,4 +20,4 @@ public class ApiScenarioPreImportAnalysisResult { @Schema(description = "需要更新的场景") List updateApiScenarioData = new ArrayList<>(); -} +} \ No newline at end of file diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/converter/ApiScenarioStepParseResult.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/converter/ApiScenarioStepParseResult.java new file mode 100644 index 0000000000..cb4c325fe2 --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/converter/ApiScenarioStepParseResult.java @@ -0,0 +1,15 @@ +package io.metersphere.api.dto.converter; + +import io.metersphere.api.dto.scenario.ApiScenarioStepRequest; +import lombok.Data; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Data +public class ApiScenarioStepParseResult { + private List stepList = new ArrayList<>(); + private Map stepDetails = new HashMap<>(); +} \ No newline at end of file diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioImportDetail.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioImportDetail.java index 9fb6d94435..ee5f2158d4 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioImportDetail.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioImportDetail.java @@ -5,6 +5,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -16,7 +18,7 @@ public class ApiScenarioImportDetail extends ApiScenario { @Schema(description = "模块路径") private String modulePath; @Schema(description = "步骤详情") - private Map stepDetails; + private Map stepDetails = new HashMap<>(); @Schema(description = "步骤集合") - private List steps; + private List steps = new ArrayList<>(); } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/parser/ApiScenarioImportParser.java b/backend/services/api-test/src/main/java/io/metersphere/api/parser/ApiScenarioImportParser.java index 7cc7715ee8..8fb48b3509 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/parser/ApiScenarioImportParser.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/parser/ApiScenarioImportParser.java @@ -1,11 +1,10 @@ package io.metersphere.api.parser; -import io.metersphere.api.dto.scenario.ApiScenarioImportDetail; +import io.metersphere.api.dto.converter.ApiScenarioImportParseResult; import io.metersphere.api.dto.scenario.ApiScenarioImportRequest; import java.io.InputStream; -import java.util.List; public interface ApiScenarioImportParser { @@ -16,6 +15,6 @@ public interface ApiScenarioImportParser { * @param request 导入的请求参数 * @return 解析后的数据 */ - List parse(InputStream source, ApiScenarioImportRequest request) throws Exception; + ApiScenarioImportParseResult parse(InputStream source, ApiScenarioImportRequest request) throws Exception; } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/parser/api/dataimport/JmeterParserApiScenario.java b/backend/services/api-test/src/main/java/io/metersphere/api/parser/api/dataimport/JmeterParserApiScenario.java index 066e81233b..d9e3d5183b 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/parser/api/dataimport/JmeterParserApiScenario.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/parser/api/dataimport/JmeterParserApiScenario.java @@ -3,6 +3,8 @@ package io.metersphere.api.parser.api.dataimport; import io.metersphere.api.constants.ApiScenarioStatus; import io.metersphere.api.constants.ApiScenarioStepRefType; import io.metersphere.api.constants.ApiScenarioStepType; +import io.metersphere.api.dto.converter.ApiScenarioImportParseResult; +import io.metersphere.api.dto.converter.ApiScenarioStepParseResult; import io.metersphere.api.dto.request.MsJMeterComponent; import io.metersphere.api.dto.request.MsThreadGroup; import io.metersphere.api.dto.request.controller.*; @@ -19,7 +21,6 @@ import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.LogUtils; import io.metersphere.system.uid.IDGenerator; -import lombok.Data; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; @@ -36,14 +37,16 @@ public class JmeterParserApiScenario implements ApiScenarioImportParser { @Override - public List parse(InputStream inputSource, ApiScenarioImportRequest request) throws Exception { + public ApiScenarioImportParseResult parse(InputStream inputSource, ApiScenarioImportRequest request) throws Exception { try { Object scriptWrapper = MsSaveService.loadElement(inputSource); HashTree hashTree = this.getHashTree(scriptWrapper); MsTestElementParser parser = new MsTestElementParser(); AbstractMsTestElement msTestElement = parser.parse(hashTree); Map polymorphicNameMap = parser.getPolymorphicNameMap(request.getProjectId()); - return this.parseImportFile(request.getProjectId(), msTestElement, polymorphicNameMap); + return new ApiScenarioImportParseResult() {{ + this.setImportScenarioList(parseImportFile(request.getProjectId(), msTestElement, polymorphicNameMap)); + }}; } catch (Exception e) { LogUtils.error(e); throw new MSException("当前JMX版本不兼容"); @@ -184,11 +187,6 @@ public class JmeterParserApiScenario implements ApiScenarioImportParser { } } -@Data -class ApiScenarioStepParseResult { - private List stepList = new ArrayList<>(); - private Map stepDetails = new HashMap<>(); -} class ProtocolConfig { String id; 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 519e5e70fc..ef3df57325 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,29 +1,118 @@ package io.metersphere.api.parser.api.dataimport; -import io.metersphere.api.dto.scenario.ApiScenarioImportDetail; -import io.metersphere.api.dto.scenario.ApiScenarioImportRequest; +import io.metersphere.api.dto.converter.ApiScenarioImportParseResult; +import io.metersphere.api.dto.converter.ApiScenarioStepParseResult; +import io.metersphere.api.dto.export.MetersphereApiScenarioExportResponse; +import io.metersphere.api.dto.scenario.*; import io.metersphere.api.parser.ApiScenarioImportParser; +import io.metersphere.api.utils.ApiDataUtils; +import io.metersphere.sdk.exception.MSException; +import io.metersphere.sdk.util.BeanUtils; +import io.metersphere.sdk.util.LogUtils; +import io.metersphere.system.uid.IDGenerator; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; public class MetersphereParserApiScenario implements ApiScenarioImportParser { @Override - public List parse(InputStream source, ApiScenarioImportRequest request) throws Exception { - return null; - // MetersphereApiExportResponse metersphereApiExportResponse = null; - // try { - // metersphereApiExportResponse = ApiDataUtils.parseObject(source, MetersphereApiExportResponse.class); - // } catch (Exception e) { - // LogUtils.error(e.getMessage(), e); - // throw new MSException(e.getMessage()); - // } - // if (metersphereApiExportResponse == null) { - // throw new MSException("解析失败,请确认选择的是 Metersphere 格式!"); - // } - // return this.genApiDefinitionImport(metersphereApiExportResponse.getApiDefinitions()); + public ApiScenarioImportParseResult parse(InputStream source, ApiScenarioImportRequest request) throws Exception { + MetersphereApiScenarioExportResponse metersphereApiScenarioExportResponse = null; + try { + metersphereApiScenarioExportResponse = ApiDataUtils.parseObject(source, MetersphereApiScenarioExportResponse.class); + } catch (Exception e) { + LogUtils.error(e.getMessage(), e); + throw new MSException(e.getMessage()); + } + if (metersphereApiScenarioExportResponse == null) { + throw new MSException("解析失败,请确认是否是正确的文件"); + } + return this.genApiScenarioPreImportAnalysisResult(metersphereApiScenarioExportResponse); } + private ApiScenarioImportParseResult genApiScenarioPreImportAnalysisResult(MetersphereApiScenarioExportResponse metersphereApiScenarioExportResponse) { + ApiScenarioImportParseResult returnResult = new ApiScenarioImportParseResult(); + + returnResult.setRelatedApiDefinitions(metersphereApiScenarioExportResponse.getRelatedApiDefinitions()); + returnResult.setRelatedApiTestCaseList(metersphereApiScenarioExportResponse.getRelatedApiTestCaseList()); + returnResult.setApiScenarioCsvList(metersphereApiScenarioExportResponse.getApiScenarioCsvList()); + + + List exportScenarioList = metersphereApiScenarioExportResponse.getExportScenarioList(); + List relatedScenarioList = metersphereApiScenarioExportResponse.getRelatedScenarioList(); + Map> scenarioStepMap = + metersphereApiScenarioExportResponse.getScenarioStepList().stream().collect(Collectors.groupingBy(ApiScenarioStepDTO::getScenarioId)); + Map scenarioStepBlobMap = metersphereApiScenarioExportResponse.getScenarioStepBlobMap(); + + for (ApiScenarioDetail apiScenarioDetail : exportScenarioList) { + returnResult.getImportScenarioList().add( + this.parseApiScenarioStep(apiScenarioDetail, scenarioStepMap.getOrDefault(apiScenarioDetail.getId(), new ArrayList<>()), scenarioStepBlobMap)); + } + + for (ApiScenarioDetail apiScenarioDetail : relatedScenarioList) { + returnResult.getRelatedScenarioList().add( + this.parseApiScenarioStep(apiScenarioDetail, scenarioStepMap.getOrDefault(apiScenarioDetail.getId(), new ArrayList<>()), scenarioStepBlobMap)); + } + + return returnResult; + } + + private ApiScenarioImportDetail parseApiScenarioStep(ApiScenarioDetail apiScenarioDetail, List apiScenarioStepDTOList, Map scenarioStepBlobMap) { + ApiScenarioImportDetail apiScenarioImportDetail = new ApiScenarioImportDetail(); + BeanUtils.copyBean(apiScenarioImportDetail, apiScenarioDetail); + ApiScenarioStepParseResult parseResult = this.parseStepDetails(apiScenarioStepDTOList, scenarioStepBlobMap); + apiScenarioImportDetail.setSteps(parseResult.getStepList()); + apiScenarioImportDetail.setStepDetails(parseResult.getStepDetails()); + return apiScenarioImportDetail; + } + + private ApiScenarioStepParseResult parseStepDetails(List apiScenarioStepDTOList, Map scenarioStepBlobMap) { + ApiScenarioStepParseResult apiScenarioStepParseResult = new ApiScenarioStepParseResult(); + Map stepRequestIdMap = new HashMap<>(); + + int lastSize = 0; + while (CollectionUtils.isNotEmpty(apiScenarioStepDTOList) && apiScenarioStepDTOList.size() != lastSize) { + lastSize = apiScenarioStepDTOList.size(); + List notMatchedList = new ArrayList<>(); + for (ApiScenarioStepDTO stepDTO : apiScenarioStepDTOList) { + String oldStepId = stepDTO.getId(); + if (!stepRequestIdMap.containsKey(stepDTO.getParentId()) && StringUtils.isNotBlank(stepDTO.getParentId())) { + notMatchedList.add(stepDTO); + continue; + } + ApiScenarioStepRequest stepRequest = new ApiScenarioStepRequest(); + BeanUtils.copyBean(stepRequest, stepDTO); + // 赋值新ID防止和库内已有数据重复 + stepRequest.setId(IDGenerator.nextStr()); + + // 使用旧ID用于配置Tree + stepRequestIdMap.put(oldStepId, stepRequest); + if (StringUtils.isBlank(stepDTO.getParentId())) { + apiScenarioStepParseResult.getStepList().add(stepRequest); + if (scenarioStepBlobMap.containsKey(oldStepId)) { + apiScenarioStepParseResult.getStepDetails().put(stepRequest.getId(), scenarioStepBlobMap.get(oldStepId).getBytes()); + } + } else if (stepRequestIdMap.containsKey(stepDTO.getParentId())) { + if (stepRequestIdMap.get(stepDTO.getParentId()).getChildren() == null) { + stepRequestIdMap.get(stepDTO.getParentId()).setChildren(new ArrayList<>()); + } + + stepRequestIdMap.get(stepDTO.getParentId()).getChildren().add(stepRequest); + if (scenarioStepBlobMap.containsKey(oldStepId)) { + apiScenarioStepParseResult.getStepDetails().put(stepRequest.getId(), scenarioStepBlobMap.get(oldStepId).getBytes()); + } + } + } + apiScenarioStepDTOList = notMatchedList; + } + return apiScenarioStepParseResult; + } } 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 202aa8491a..aa2187fe84 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 @@ -5,6 +5,7 @@ import io.metersphere.api.constants.ApiScenarioStepType; import io.metersphere.api.domain.*; import io.metersphere.api.dto.ApiFile; import io.metersphere.api.dto.converter.ApiDefinitionExportDetail; +import io.metersphere.api.dto.converter.ApiScenarioImportParseResult; import io.metersphere.api.dto.converter.ApiScenarioPreImportAnalysisResult; import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.export.ApiScenarioExportResponse; @@ -140,21 +141,21 @@ public class ApiScenarioDataTransferService { public void importScenario(MultipartFile file, ApiScenarioImportRequest request) { ApiScenarioImportParser parser = ImportParserFactory.getApiScenarioImportParser(request.getType()); - List importScenarios; + ApiScenarioImportParseResult parseResult; try { assert parser != null; - importScenarios = parser.parse(file.getInputStream(), request); + parseResult = parser.parse(file.getInputStream(), request); } catch (Exception e) { LogUtils.error(e.getMessage(), e); throw new MSException(Translator.get("parse_data_error")); } - if (CollectionUtils.isEmpty(importScenarios)) { + if (CollectionUtils.isEmpty(parseResult.getImportScenarioList())) { throw new MSException(Translator.get("parse_empty_data")); } //解析 ApiScenarioPreImportAnalysisResult preImportAnalysisResult = this.importAnalysis( - importScenarios, request.getModuleId(), apiScenarioModuleService.getTree(request.getProjectId())); + parseResult, request.getModuleId(), apiScenarioModuleService.getTree(request.getProjectId())); //存储 this.save(preImportAnalysisResult, request.getProjectId(), request.getOperator(), request.isCoverData()); @@ -519,12 +520,13 @@ public class ApiScenarioDataTransferService { return order; } - private ApiScenarioPreImportAnalysisResult importAnalysis(List importScenarios, String moduleId, List apiScenarioModules) { + private ApiScenarioPreImportAnalysisResult importAnalysis(ApiScenarioImportParseResult parseResult, String moduleId, List apiScenarioModules) { ApiScenarioPreImportAnalysisResult analysisResult = new ApiScenarioPreImportAnalysisResult(); Map moduleIdPathMap = apiScenarioModules.stream().collect(Collectors.toMap(BaseTreeNode::getId, BaseTreeNode::getPath)); Map modulePathMap = apiScenarioModules.stream().collect(Collectors.toMap(BaseTreeNode::getPath, k -> k, (k1, k2) -> k1)); + List importScenarios = parseResult.getImportScenarioList(); for (ApiScenarioImportDetail importScenario : importScenarios) { if (StringUtils.isBlank(moduleId) || StringUtils.equalsIgnoreCase(moduleId, ModuleConstants.DEFAULT_NODE_ID) || !moduleIdPathMap.containsKey(moduleId)) { importScenario.setModuleId(ModuleConstants.DEFAULT_NODE_ID); 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 dba0e9a921..a268b56011 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 @@ -34,9 +34,7 @@ import org.springframework.util.MultiValueMap; import java.io.File; import java.io.FileInputStream; import java.nio.charset.StandardCharsets; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.Objects; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @@ -75,22 +73,17 @@ public class ApiScenarioControllerImportAndExportTests extends BaseTest { @Test @Order(1) public void testImport() throws Exception { - Map importTypeAndSuffix = new LinkedHashMap<>(); - // importTypeAndSuffix.put("metersphere", "json"); - importTypeAndSuffix.put("jmeter", "jmx"); - for (Map.Entry entry : importTypeAndSuffix.entrySet()) { - ApiScenarioImportRequest request = new ApiScenarioImportRequest(); - request.setProjectId(project.getId()); - request.setType(entry.getKey()); - String importType = entry.getKey(); - String fileSuffix = entry.getValue(); - FileInputStream inputStream = new FileInputStream(new File(Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/import-scenario/" + importType + "/simple." + fileSuffix)).getPath())); - MockMultipartFile file = new MockMultipartFile("file", "simple." + fileSuffix, MediaType.APPLICATION_OCTET_STREAM_VALUE, inputStream); - MultiValueMap paramMap = new LinkedMultiValueMap<>(); - paramMap.add("request", JSON.toJSONString(request)); - paramMap.add("file", file); - this.requestMultipartWithOkAndReturn(URL_POST_IMPORT, paramMap); - } + ApiScenarioImportRequest request = new ApiScenarioImportRequest(); + request.setProjectId(project.getId()); + request.setType("jmeter"); + String importType = "jmeter"; + String fileSuffix = "jmx"; + FileInputStream inputStream = new FileInputStream(new File(Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/import-scenario/" + importType + "/simple." + fileSuffix)).getPath())); + MockMultipartFile file = new MockMultipartFile("file", "simple." + fileSuffix, MediaType.APPLICATION_OCTET_STREAM_VALUE, inputStream); + MultiValueMap paramMap = new LinkedMultiValueMap<>(); + paramMap.add("request", JSON.toJSONString(request)); + paramMap.add("file", file); + this.requestMultipartWithOkAndReturn(URL_POST_IMPORT, paramMap); } @Resource @@ -144,6 +137,21 @@ public class ApiScenarioControllerImportAndExportTests extends BaseTest { MsFileUtils.deleteDir("/tmp/api-scenario-export/"); } + @Test + @Order(3) + public void testImportMs() throws Exception { + ApiScenarioImportRequest request = new ApiScenarioImportRequest(); + request.setProjectId(project.getId()); + request.setType("metersphere"); + String importType = "metersphere"; + FileInputStream inputStream = new FileInputStream(new File(Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/import-scenario/" + importType + "/all.ms")).getPath())); + MockMultipartFile file = new MockMultipartFile("file", "all.ms", MediaType.APPLICATION_OCTET_STREAM_VALUE, inputStream); + MultiValueMap paramMap = new LinkedMultiValueMap<>(); + paramMap.add("request", JSON.toJSONString(request)); + paramMap.add("file", file); + this.requestMultipartWithOkAndReturn(URL_POST_IMPORT, paramMap); + } + private MvcResult download(String projectId, String fileId) throws Exception { return mockMvc.perform(MockMvcRequestBuilders.get("/api/scenario/download/file/" + projectId + "/" + fileId) .header(SessionConstants.HEADER_TOKEN, sessionId) diff --git a/backend/services/api-test/src/test/resources/file/import-scenario/metersphere/all.ms b/backend/services/api-test/src/test/resources/file/import-scenario/metersphere/all.ms new file mode 100644 index 0000000000..8fcabac6bb --- /dev/null +++ b/backend/services/api-test/src/test/resources/file/import-scenario/metersphere/all.ms @@ -0,0 +1,1018 @@ +{ + "organizationId": "717345437786112", + "projectId": "997050905108480", + "exportScenarioList": + [ + { + "id": "950871430496256", + "name": "场景复制:复制引用场景二人组", + "priority": "P0", + "status": "UNDERWAY", + "stepTotal": 2, + "requestPassRate": "0", + "lastReportStatus": "", + "lastReportId": null, + "num": 100003, + "deleted": false, + "pos": 14798848, + "versionId": "997050905108527", + "refId": "950871430496256", + "latest": true, + "projectId": "997050905108480", + "moduleId": "661562424147968", + "description": "", + "tags": + [], + "grouped": false, + "environmentId": "997050905108481", + "createUser": "724938939965440", + "createTime": 1729236148336, + "deleteTime": null, + "deleteUser": null, + "updateUser": "724938939965440", + "updateTime": 1729236175161, + "modulePath": "/正经场景模块", + "scenarioConfig": + { + "variable": + { + "commonVariables": + [], + "csvVariables": + [] + }, + "preProcessorConfig": + { + "enableGlobal": true, + "processors": + [] + }, + "postProcessorConfig": + { + "enableGlobal": true, + "processors": + [] + }, + "assertionConfig": + { + "assertions": + [] + }, + "otherConfig": + { + "enableGlobalCookie": true, + "enableCookieShare": false, + "enableStepWait": false, + "failureStrategy": "CONTINUE" + } + }, + "steps": + [] + }, + { + "id": "951661704478720", + "name": "场景引用:复制引用场景二人组", + "priority": "P0", + "status": "UNDERWAY", + "stepTotal": 2, + "requestPassRate": "0", + "lastReportStatus": "", + "lastReportId": null, + "num": 100004, + "deleted": false, + "pos": 14802944, + "versionId": "997050905108527", + "refId": "951661704478720", + "latest": true, + "projectId": "997050905108480", + "moduleId": "661562424147968", + "description": "", + "tags": + [], + "grouped": false, + "environmentId": "997050905108481", + "createUser": "724938939965440", + "createTime": 1729236194110, + "deleteTime": null, + "deleteUser": null, + "updateUser": "724938939965440", + "updateTime": 1729236194110, + "modulePath": "/正经场景模块", + "scenarioConfig": + { + "variable": + { + "commonVariables": + [], + "csvVariables": + [] + }, + "preProcessorConfig": + { + "enableGlobal": true, + "processors": + [] + }, + "postProcessorConfig": + { + "enableGlobal": true, + "processors": + [] + }, + "assertionConfig": + { + "assertions": + [] + }, + "otherConfig": + { + "enableGlobalCookie": true, + "enableCookieShare": false, + "enableStepWait": false, + "failureStrategy": "CONTINUE" + } + }, + "steps": + [] + } + ], + "apiScenarioCsvList": + [], + "scenarioStepList": + [ + { + "id": "172923614497700000", + "enable": true, + "resourceId": "949101903970304", + "originProjectId": "997050905108480", + "stepType": "API_SCENARIO", + "refType": "COPY", + "config": + { + "id": "", + "name": "", + "enable": true, + "enableScenarioEnv": false, + "useOriginScenarioParamPreferential": true, + "useOriginScenarioParam": false + }, + "csvIds": null, + "projectId": "997050905108480", + "name": "场景引用复制接口定义", + "resourceNum": "100001", + "versionId": null, + "children": null, + "uniqueId": null, + "scenarioId": "950871430496256", + "sort": 1, + "parentId": null + }, + { + "id": "172923614497700001", + "enable": true, + "resourceId": "933073076830208", + "originProjectId": "997050905108480", + "stepType": "API", + "refType": "COPY", + "config": + { + "id": "", + "name": "", + "enable": true, + "protocol": "HTTP", + "method": "GET" + }, + "csvIds": null, + "projectId": "997050905108480", + "name": "可以正常执行的获取tapd-复制", + "resourceNum": "100003", + "versionId": null, + "children": null, + "uniqueId": null, + "scenarioId": "950871430496256", + "sort": 1, + "parentId": "172923614497700000" + }, + { + "id": "172923614497700002", + "enable": true, + "resourceId": "933073076830208", + "originProjectId": "997050905108480", + "stepType": "API", + "refType": "REF", + "config": + { + "id": "", + "name": "", + "enable": true, + "protocol": "HTTP", + "method": "GET" + }, + "csvIds": null, + "projectId": "997050905108480", + "name": "可以正常执行的获取tapd-引用", + "resourceNum": "100003", + "versionId": null, + "children": null, + "uniqueId": null, + "scenarioId": "950871430496256", + "sort": 2, + "parentId": "172923614497700000" + }, + { + "id": "172923614497800000", + "enable": true, + "resourceId": "950029616906240", + "originProjectId": "997050905108480", + "stepType": "API_SCENARIO", + "refType": "COPY", + "config": + { + "id": "", + "name": "", + "enable": true, + "enableScenarioEnv": false, + "useOriginScenarioParamPreferential": true, + "useOriginScenarioParam": false + }, + "csvIds": null, + "projectId": "997050905108480", + "name": "场景引用复制接口用例", + "resourceNum": "100002", + "versionId": null, + "children": null, + "uniqueId": null, + "scenarioId": "950871430496256", + "sort": 2, + "parentId": null + }, + { + "id": "172923614497800001", + "enable": true, + "resourceId": "933725911859200", + "originProjectId": "997050905108480", + "stepType": "API_CASE", + "refType": "COPY", + "config": + { + "id": "", + "name": "", + "enable": true, + "protocol": "HTTP", + "method": "GET" + }, + "csvIds": null, + "projectId": "997050905108480", + "name": "复制的用例", + "resourceNum": "100003001", + "versionId": null, + "children": null, + "uniqueId": null, + "scenarioId": "950871430496256", + "sort": 1, + "parentId": "172923614497800000" + }, + { + "id": "172923614497800002", + "enable": true, + "resourceId": "933725911859200", + "originProjectId": "997050905108480", + "stepType": "API_CASE", + "refType": "REF", + "config": + { + "id": "", + "name": "", + "enable": true, + "protocol": "HTTP", + "method": "GET" + }, + "csvIds": null, + "projectId": "997050905108480", + "name": "引用的用例", + "resourceNum": "100003001", + "versionId": null, + "children": null, + "uniqueId": null, + "scenarioId": "950871430496256", + "sort": 2, + "parentId": "172923614497800000" + }, + { + "id": "172923619228400000", + "enable": true, + "resourceId": "949101903970304", + "originProjectId": "997050905108480", + "stepType": "API_SCENARIO", + "refType": "REF", + "config": + { + "id": "", + "name": "", + "enable": true, + "enableScenarioEnv": false, + "useOriginScenarioParamPreferential": true, + "useOriginScenarioParam": false + }, + "csvIds": null, + "projectId": "997050905108480", + "name": "场景引用复制接口定义", + "resourceNum": "100001", + "versionId": null, + "children": null, + "uniqueId": null, + "scenarioId": "951661704478720", + "sort": 1, + "parentId": null + }, + { + "id": "172923619228400003", + "enable": true, + "resourceId": "950029616906240", + "originProjectId": "997050905108480", + "stepType": "API_SCENARIO", + "refType": "REF", + "config": + { + "id": "", + "name": "", + "enable": true, + "enableScenarioEnv": false, + "useOriginScenarioParamPreferential": true, + "useOriginScenarioParam": false + }, + "csvIds": null, + "projectId": "997050905108480", + "name": "场景引用复制接口用例", + "resourceNum": "100002", + "versionId": null, + "children": null, + "uniqueId": null, + "scenarioId": "951661704478720", + "sort": 2, + "parentId": null + }, + { + "id": "172923599832400000", + "enable": true, + "resourceId": "933073076830208", + "originProjectId": "997050905108480", + "stepType": "API", + "refType": "COPY", + "config": + { + "id": "", + "name": "", + "enable": true, + "protocol": "HTTP", + "method": "GET" + }, + "csvIds": null, + "projectId": "997050905108480", + "name": "可以正常执行的获取tapd-复制", + "resourceNum": "100003", + "versionId": null, + "children": null, + "uniqueId": null, + "scenarioId": "949101903970304", + "sort": 1, + "parentId": null + }, + { + "id": "172923601542900000", + "enable": true, + "resourceId": "933073076830208", + "originProjectId": "997050905108480", + "stepType": "API", + "refType": "REF", + "config": + { + "id": "", + "name": "", + "enable": true, + "protocol": "HTTP", + "method": "GET" + }, + "csvIds": null, + "projectId": "997050905108480", + "name": "可以正常执行的获取tapd-引用", + "resourceNum": "100003", + "versionId": null, + "children": null, + "uniqueId": null, + "scenarioId": "949101903970304", + "sort": 2, + "parentId": null + }, + { + "id": "172923607239900000", + "enable": true, + "resourceId": "933725911859200", + "originProjectId": "997050905108480", + "stepType": "API_CASE", + "refType": "COPY", + "config": + { + "id": "", + "name": "", + "enable": true, + "protocol": "HTTP", + "method": "GET" + }, + "csvIds": null, + "projectId": "997050905108480", + "name": "复制的用例", + "resourceNum": "100003001", + "versionId": null, + "children": null, + "uniqueId": null, + "scenarioId": "950029616906240", + "sort": 1, + "parentId": null + }, + { + "id": "172923609009900000", + "enable": true, + "resourceId": "933725911859200", + "originProjectId": "997050905108480", + "stepType": "API_CASE", + "refType": "REF", + "config": + { + "id": "", + "name": "", + "enable": true, + "protocol": "HTTP", + "method": "GET" + }, + "csvIds": null, + "projectId": "997050905108480", + "name": "引用的用例", + "resourceNum": "100003001", + "versionId": null, + "children": null, + "uniqueId": null, + "scenarioId": "950029616906240", + "sort": 2, + "parentId": null + } + ], + "scenarioStepBlobMap": + { + "172923599832400000": "{\"polymorphicName\":\"MsHTTPElement\",\"stepId\":null,\"resourceId\":null,\"projectId\":null,\"name\":\"https://api.tapd.cn/stories?workspace_id=55049933&id=1155049933001012963\",\"enable\":true,\"children\":[{\"polymorphicName\":\"MsCommonElement\",\"stepId\":null,\"resourceId\":null,\"projectId\":null,\"name\":null,\"enable\":true,\"children\":null,\"parent\":null,\"csvIds\":null,\"preProcessorConfig\":{\"enableGlobal\":true,\"processors\":[]},\"postProcessorConfig\":{\"enableGlobal\":true,\"processors\":[]},\"assertionConfig\":{\"enableGlobal\":true,\"assertions\":[]}}],\"parent\":null,\"csvIds\":null,\"customizeRequest\":false,\"customizeRequestEnvEnable\":false,\"path\":\"/stories\",\"method\":\"GET\",\"body\":{\"bodyType\":\"NONE\",\"noneBody\":{},\"formDataBody\":{\"formValues\":[]},\"wwwFormBody\":{\"formValues\":[]},\"jsonBody\":{\"enableJsonSchema\":false,\"jsonValue\":null,\"jsonSchema\":null},\"xmlBody\":{\"value\":null},\"rawBody\":{\"value\":null},\"binaryBody\":{\"description\":null,\"file\":null},\"bodyClassByType\":\"io.metersphere.api.dto.request.http.body.NoneBody\",\"bodyDataByType\":{}},\"headers\":[],\"rest\":[],\"query\":[{\"key\":\"workspace_id\",\"value\":\"55049933\",\"enable\":true,\"description\":\"\",\"paramType\":\"string\",\"required\":false,\"minLength\":null,\"maxLength\":null,\"encode\":false,\"valid\":true,\"notBlankValue\":true},{\"key\":\"id\",\"value\":\"1155049933001012963\",\"enable\":true,\"description\":\"\",\"paramType\":\"string\",\"required\":false,\"minLength\":null,\"maxLength\":null,\"encode\":false,\"valid\":true,\"notBlankValue\":true}],\"otherConfig\":{\"connectTimeout\":60000,\"responseTimeout\":60000,\"certificateAlias\":null,\"followRedirects\":false,\"autoRedirects\":true},\"authConfig\":{\"authType\":\"BASIC\",\"basicAuth\":{\"userName\":\"oOjrikkm\",\"password\":\"9CD9AB02-7497-0B85-2C4F-45CC3EA763F8\",\"valid\":true},\"digestAuth\":{\"userName\":null,\"password\":null,\"valid\":false},\"httpauthValid\":true},\"moduleId\":null,\"num\":null,\"mockNum\":null}", + "172923614497800001": "{\"authConfig\":{\"authType\":\"BASIC\",\"basicAuth\":{\"userName\":\"oOjrikkm\",\"password\":\"9CD9AB02-7497-0B85-2C4F-45CC3EA763F8\"},\"digestAuth\":{\"userName\":\"\",\"password\":\"\"}},\"body\":{\"bodyType\":\"NONE\",\"formDataBody\":{\"formValues\":[]},\"wwwFormBody\":{\"formValues\":[]},\"jsonBody\":{\"jsonValue\":\"\",\"enableJsonSchema\":true},\"xmlBody\":{\"value\":\"\"},\"rawBody\":{\"value\":\"\"},\"binaryBody\":{\"description\":\"\",\"sendAsBody\":false}},\"headers\":[],\"method\":\"GET\",\"otherConfig\":{\"connectTimeout\":60000,\"responseTimeout\":60000,\"certificateAlias\":\"\",\"followRedirects\":true,\"autoRedirects\":false},\"path\":\"/stories\",\"query\":[{\"id\":\"172059506570200000\",\"enable\":true,\"key\":\"workspace_id\",\"value\":\"55049933\",\"paramType\":\"string\",\"description\":\"\",\"required\":false,\"encode\":false},{\"id\":\"172059506675100000\",\"enable\":true,\"key\":\"id\",\"value\":\"1155049933001012963\",\"paramType\":\"string\",\"description\":\"\",\"required\":false,\"encode\":false}],\"rest\":[],\"url\":\"/stories\",\"polymorphicName\":\"MsHTTPElement\",\"name\":\"正常执行的但是断言失败的\",\"children\":[{\"polymorphicName\":\"MsCommonElement\",\"assertionConfig\":{\"enableGlobal\":true,\"assertions\":[{\"name\":\"响应体\",\"assertionType\":\"RESPONSE_BODY\",\"id\":\"1720595131649\",\"enable\":true,\"assertionBodyType\":\"JSON_PATH\",\"jsonPathAssertion\":{\"assertions\":[{\"id\":\"172059513165900000\",\"enable\":true,\"variableName\":\"\",\"variableType\":\"TEMPORARY\",\"extractScope\":\"BODY\",\"expression\":\"$.data[0].Story.id\",\"condition\":\"EQUALS\",\"extractType\":\"JSON_PATH\",\"expressionMatchingRule\":\"EXPRESSION\",\"resultMatchingRule\":\"RANDOM\",\"resultMatchingRuleNum\":1,\"responseFormat\":\"XML\",\"moreSettingPopoverVisible\":false,\"expectedValue\":\"aaaavbbb\"}]},\"xpathAssertion\":{\"responseFormat\":\"XML\",\"assertions\":[]},\"regexAssertion\":{\"assertions\":[]},\"bodyAssertionDataByType\":{\"assertions\":[]}}]},\"postProcessorConfig\":{\"enableGlobal\":true,\"processors\":[]},\"preProcessorConfig\":{\"enableGlobal\":true,\"processors\":[]}}]}", + "172923601542900000": "{\"polymorphicName\":\"MsHTTPElement\",\"stepId\":null,\"resourceId\":null,\"projectId\":null,\"name\":\"https://api.tapd.cn/stories?workspace_id=55049933&id=1155049933001012963\",\"enable\":true,\"children\":[{\"polymorphicName\":\"MsCommonElement\",\"stepId\":null,\"resourceId\":null,\"projectId\":null,\"name\":null,\"enable\":true,\"children\":null,\"parent\":null,\"csvIds\":null,\"preProcessorConfig\":{\"enableGlobal\":true,\"processors\":[]},\"postProcessorConfig\":{\"enableGlobal\":true,\"processors\":[]},\"assertionConfig\":{\"enableGlobal\":true,\"assertions\":[]}}],\"parent\":null,\"csvIds\":null,\"customizeRequest\":false,\"customizeRequestEnvEnable\":false,\"path\":\"/stories\",\"method\":\"GET\",\"body\":{\"bodyType\":\"NONE\",\"noneBody\":{},\"formDataBody\":{\"formValues\":[]},\"wwwFormBody\":{\"formValues\":[]},\"jsonBody\":{\"enableJsonSchema\":false,\"jsonValue\":null,\"jsonSchema\":null},\"xmlBody\":{\"value\":null},\"rawBody\":{\"value\":null},\"binaryBody\":{\"description\":null,\"file\":null},\"bodyClassByType\":\"io.metersphere.api.dto.request.http.body.NoneBody\",\"bodyDataByType\":{}},\"headers\":[],\"rest\":[],\"query\":[{\"key\":\"workspace_id\",\"value\":\"55049933\",\"enable\":true,\"description\":\"\",\"paramType\":\"string\",\"required\":false,\"minLength\":null,\"maxLength\":null,\"encode\":false,\"valid\":true,\"notBlankValue\":true},{\"key\":\"id\",\"value\":\"1155049933001012963\",\"enable\":true,\"description\":\"\",\"paramType\":\"string\",\"required\":false,\"minLength\":null,\"maxLength\":null,\"encode\":false,\"valid\":true,\"notBlankValue\":true}],\"otherConfig\":{\"connectTimeout\":60000,\"responseTimeout\":60000,\"certificateAlias\":null,\"followRedirects\":false,\"autoRedirects\":true},\"authConfig\":{\"authType\":\"BASIC\",\"basicAuth\":{\"userName\":\"oOjrikkm\",\"password\":\"9CD9AB02-7497-0B85-2C4F-45CC3EA763F8\",\"valid\":true},\"digestAuth\":{\"userName\":null,\"password\":null,\"valid\":false},\"httpauthValid\":true},\"moduleId\":null,\"num\":null,\"mockNum\":null}", + "172923607239900000": "{\"authConfig\":{\"authType\":\"BASIC\",\"basicAuth\":{\"userName\":\"oOjrikkm\",\"password\":\"9CD9AB02-7497-0B85-2C4F-45CC3EA763F8\"},\"digestAuth\":{\"userName\":\"\",\"password\":\"\"}},\"body\":{\"bodyType\":\"NONE\",\"formDataBody\":{\"formValues\":[]},\"wwwFormBody\":{\"formValues\":[]},\"jsonBody\":{\"jsonValue\":\"\",\"enableJsonSchema\":true},\"xmlBody\":{\"value\":\"\"},\"rawBody\":{\"value\":\"\"},\"binaryBody\":{\"description\":\"\",\"sendAsBody\":false}},\"headers\":[],\"method\":\"GET\",\"otherConfig\":{\"connectTimeout\":60000,\"responseTimeout\":60000,\"certificateAlias\":\"\",\"followRedirects\":true,\"autoRedirects\":false},\"path\":\"/stories\",\"query\":[{\"id\":\"172059506570200000\",\"enable\":true,\"key\":\"workspace_id\",\"value\":\"55049933\",\"paramType\":\"string\",\"description\":\"\",\"required\":false,\"encode\":false},{\"id\":\"172059506675100000\",\"enable\":true,\"key\":\"id\",\"value\":\"1155049933001012963\",\"paramType\":\"string\",\"description\":\"\",\"required\":false,\"encode\":false}],\"rest\":[],\"url\":\"/stories\",\"polymorphicName\":\"MsHTTPElement\",\"name\":\"正常执行的但是断言失败的\",\"children\":[{\"polymorphicName\":\"MsCommonElement\",\"assertionConfig\":{\"enableGlobal\":true,\"assertions\":[{\"name\":\"响应体\",\"assertionType\":\"RESPONSE_BODY\",\"id\":\"1720595131649\",\"enable\":true,\"assertionBodyType\":\"JSON_PATH\",\"jsonPathAssertion\":{\"assertions\":[{\"id\":\"172059513165900000\",\"enable\":true,\"variableName\":\"\",\"variableType\":\"TEMPORARY\",\"extractScope\":\"BODY\",\"expression\":\"$.data[0].Story.id\",\"condition\":\"EQUALS\",\"extractType\":\"JSON_PATH\",\"expressionMatchingRule\":\"EXPRESSION\",\"resultMatchingRule\":\"RANDOM\",\"resultMatchingRuleNum\":1,\"responseFormat\":\"XML\",\"moreSettingPopoverVisible\":false,\"expectedValue\":\"aaaavbbb\"}]},\"xpathAssertion\":{\"responseFormat\":\"XML\",\"assertions\":[]},\"regexAssertion\":{\"assertions\":[]},\"bodyAssertionDataByType\":{\"assertions\":[]}}]},\"postProcessorConfig\":{\"enableGlobal\":true,\"processors\":[]},\"preProcessorConfig\":{\"enableGlobal\":true,\"processors\":[]}}]}", + "172923614497700002": "{\"polymorphicName\":\"MsHTTPElement\",\"stepId\":null,\"resourceId\":null,\"projectId\":null,\"name\":\"https://api.tapd.cn/stories?workspace_id=55049933&id=1155049933001012963\",\"enable\":true,\"children\":[{\"polymorphicName\":\"MsCommonElement\",\"stepId\":null,\"resourceId\":null,\"projectId\":null,\"name\":null,\"enable\":true,\"children\":null,\"parent\":null,\"csvIds\":null,\"preProcessorConfig\":{\"enableGlobal\":true,\"processors\":[]},\"postProcessorConfig\":{\"enableGlobal\":true,\"processors\":[]},\"assertionConfig\":{\"enableGlobal\":true,\"assertions\":[]}}],\"parent\":null,\"csvIds\":null,\"customizeRequest\":false,\"customizeRequestEnvEnable\":false,\"path\":\"/stories\",\"method\":\"GET\",\"body\":{\"bodyType\":\"NONE\",\"noneBody\":{},\"formDataBody\":{\"formValues\":[]},\"wwwFormBody\":{\"formValues\":[]},\"jsonBody\":{\"enableJsonSchema\":false,\"jsonValue\":null,\"jsonSchema\":null},\"xmlBody\":{\"value\":null},\"rawBody\":{\"value\":null},\"binaryBody\":{\"description\":null,\"file\":null},\"bodyClassByType\":\"io.metersphere.api.dto.request.http.body.NoneBody\",\"bodyDataByType\":{}},\"headers\":[],\"rest\":[],\"query\":[{\"key\":\"workspace_id\",\"value\":\"55049933\",\"enable\":true,\"description\":\"\",\"paramType\":\"string\",\"required\":false,\"minLength\":null,\"maxLength\":null,\"encode\":false,\"valid\":true,\"notBlankValue\":true},{\"key\":\"id\",\"value\":\"1155049933001012963\",\"enable\":true,\"description\":\"\",\"paramType\":\"string\",\"required\":false,\"minLength\":null,\"maxLength\":null,\"encode\":false,\"valid\":true,\"notBlankValue\":true}],\"otherConfig\":{\"connectTimeout\":60000,\"responseTimeout\":60000,\"certificateAlias\":null,\"followRedirects\":false,\"autoRedirects\":true},\"authConfig\":{\"authType\":\"BASIC\",\"basicAuth\":{\"userName\":\"oOjrikkm\",\"password\":\"9CD9AB02-7497-0B85-2C4F-45CC3EA763F8\",\"valid\":true},\"digestAuth\":{\"userName\":null,\"password\":null,\"valid\":false},\"httpauthValid\":true},\"moduleId\":null,\"num\":null,\"mockNum\":null}", + "172923614497700001": "{\"polymorphicName\":\"MsHTTPElement\",\"stepId\":null,\"resourceId\":null,\"projectId\":null,\"name\":\"https://api.tapd.cn/stories?workspace_id=55049933&id=1155049933001012963\",\"enable\":true,\"children\":[{\"polymorphicName\":\"MsCommonElement\",\"stepId\":null,\"resourceId\":null,\"projectId\":null,\"name\":null,\"enable\":true,\"children\":null,\"parent\":null,\"csvIds\":null,\"preProcessorConfig\":{\"enableGlobal\":true,\"processors\":[]},\"postProcessorConfig\":{\"enableGlobal\":true,\"processors\":[]},\"assertionConfig\":{\"enableGlobal\":true,\"assertions\":[]}}],\"parent\":null,\"csvIds\":null,\"customizeRequest\":false,\"customizeRequestEnvEnable\":false,\"path\":\"/stories\",\"method\":\"GET\",\"body\":{\"bodyType\":\"NONE\",\"noneBody\":{},\"formDataBody\":{\"formValues\":[]},\"wwwFormBody\":{\"formValues\":[]},\"jsonBody\":{\"enableJsonSchema\":false,\"jsonValue\":null,\"jsonSchema\":null},\"xmlBody\":{\"value\":null},\"rawBody\":{\"value\":null},\"binaryBody\":{\"description\":null,\"file\":null},\"bodyClassByType\":\"io.metersphere.api.dto.request.http.body.NoneBody\",\"bodyDataByType\":{}},\"headers\":[],\"rest\":[],\"query\":[{\"key\":\"workspace_id\",\"value\":\"55049933\",\"enable\":true,\"description\":\"\",\"paramType\":\"string\",\"required\":false,\"minLength\":null,\"maxLength\":null,\"encode\":false,\"valid\":true,\"notBlankValue\":true},{\"key\":\"id\",\"value\":\"1155049933001012963\",\"enable\":true,\"description\":\"\",\"paramType\":\"string\",\"required\":false,\"minLength\":null,\"maxLength\":null,\"encode\":false,\"valid\":true,\"notBlankValue\":true}],\"otherConfig\":{\"connectTimeout\":60000,\"responseTimeout\":60000,\"certificateAlias\":null,\"followRedirects\":false,\"autoRedirects\":true},\"authConfig\":{\"authType\":\"BASIC\",\"basicAuth\":{\"userName\":\"oOjrikkm\",\"password\":\"9CD9AB02-7497-0B85-2C4F-45CC3EA763F8\",\"valid\":true},\"digestAuth\":{\"userName\":null,\"password\":null,\"valid\":false},\"httpauthValid\":true},\"moduleId\":null,\"num\":null,\"mockNum\":null}" + }, + "relatedApiDefinitions": + [ + { + "id": null, + "name": "可以正常执行的获取tapd", + "protocol": "HTTP", + "method": "GET", + "path": "/stories", + "status": "PROCESSING", + "num": null, + "tags": + [], + "pos": 12288, + "projectId": null, + "moduleId": "root", + "latest": null, + "versionId": null, + "refId": null, + "description": "", + "createTime": null, + "createUser": null, + "updateTime": null, + "updateUser": null, + "deleteUser": null, + "deleteTime": null, + "deleted": null, + "request": + { + "polymorphicName": "MsHTTPElement", + "stepId": null, + "resourceId": null, + "projectId": null, + "name": "https://api.tapd.cn/stories?workspace_id=55049933&id=1155049933001012963", + "enable": true, + "children": + [ + { + "polymorphicName": "MsCommonElement", + "stepId": null, + "resourceId": null, + "projectId": null, + "name": null, + "enable": true, + "children": null, + "parent": null, + "csvIds": null, + "preProcessorConfig": + { + "enableGlobal": true, + "processors": + [] + }, + "postProcessorConfig": + { + "enableGlobal": true, + "processors": + [] + }, + "assertionConfig": + { + "enableGlobal": true, + "assertions": + [] + } + } + ], + "parent": null, + "csvIds": null, + "customizeRequest": false, + "customizeRequestEnvEnable": false, + "path": "/stories", + "method": "GET", + "body": + { + "bodyType": "NONE", + "noneBody": + {}, + "formDataBody": + { + "formValues": + [] + }, + "wwwFormBody": + { + "formValues": + [] + }, + "jsonBody": + { + "enableJsonSchema": false, + "jsonValue": null, + "jsonSchema": null + }, + "xmlBody": + { + "value": null + }, + "rawBody": + { + "value": null + }, + "binaryBody": + { + "description": null, + "file": null + }, + "bodyClassByType": "io.metersphere.api.dto.request.http.body.NoneBody", + "bodyDataByType": + {} + }, + "headers": + [], + "rest": + [], + "query": + [ + { + "key": "workspace_id", + "value": "55049933", + "enable": true, + "description": "", + "paramType": "string", + "required": false, + "minLength": null, + "maxLength": null, + "encode": false, + "valid": true, + "notBlankValue": true + }, + { + "key": "id", + "value": "1155049933001012963", + "enable": true, + "description": "", + "paramType": "string", + "required": false, + "minLength": null, + "maxLength": null, + "encode": false, + "valid": true, + "notBlankValue": true + } + ], + "otherConfig": + { + "connectTimeout": 60000, + "responseTimeout": 60000, + "certificateAlias": null, + "followRedirects": false, + "autoRedirects": true + }, + "authConfig": + { + "authType": "BASIC", + "basicAuth": + { + "userName": "oOjrikkm", + "password": "9CD9AB02-7497-0B85-2C4F-45CC3EA763F8", + "valid": true + }, + "digestAuth": + { + "userName": null, + "password": null, + "valid": false + }, + "httpauthValid": true + }, + "moduleId": null, + "num": null, + "mockNum": null + }, + "response": + [], + "modulePath": "未规划接口", + "apiTestCaseList": + [], + "apiMockList": + [] + } + ], + "relatedApiTestCaseList": + [ + { + "id": null, + "name": "正常执行的但是断言失败的", + "priority": "P0", + "num": null, + "status": "PROCESSING", + "lastReportStatus": null, + "lastReportId": null, + "projectId": null, + "apiDefinitionId": null, + "apiDefinitionNum": null, + "apiDefinitionName": null, + "environmentId": null, + "createTime": null, + "createUser": null, + "updateTime": null, + "updateUser": null, + "deleteTime": null, + "deleteUser": null, + "follow": null, + "method": null, + "path": null, + "environmentName": null, + "createName": null, + "updateName": null, + "deleteName": null, + "tags": + [], + "passRate": null, + "request": + { + "polymorphicName": "MsHTTPElement", + "stepId": null, + "resourceId": null, + "projectId": null, + "name": "正常执行的但是断言失败的", + "enable": true, + "children": + [ + { + "polymorphicName": "MsCommonElement", + "stepId": null, + "resourceId": null, + "projectId": null, + "name": null, + "enable": true, + "children": + [], + "parent": null, + "csvIds": null, + "preProcessorConfig": + { + "enableGlobal": true, + "processors": + [] + }, + "postProcessorConfig": + { + "enableGlobal": true, + "processors": + [] + }, + "assertionConfig": + { + "enableGlobal": true, + "assertions": + [ + { + "assertionType": "RESPONSE_BODY", + "enable": true, + "name": "响应体", + "id": "1720595131649", + "projectId": null, + "assertionBodyType": "JSON_PATH", + "jsonPathAssertion": + { + "assertions": + [ + { + "enable": true, + "expression": "$.data[0].Story.id", + "condition": "EQUALS", + "expectedValue": "aaaavbbb", + "valid": true + } + ] + }, + "xpathAssertion": + { + "responseFormat": "XML", + "assertions": + [] + }, + "documentAssertion": null, + "regexAssertion": + { + "assertions": + [] + }, + "bodyAssertionClassByType": "io.metersphere.project.api.assertion.body.MsJSONPathAssertion", + "bodyAssertionDataByType": + { + "assertions": + [ + { + "enable": true, + "expression": "$.data[0].Story.id", + "condition": "EQUALS", + "expectedValue": "aaaavbbb", + "valid": true + } + ] + } + } + ] + } + } + ], + "parent": null, + "csvIds": null, + "customizeRequest": false, + "customizeRequestEnvEnable": false, + "path": "/stories", + "method": "GET", + "body": + { + "bodyType": "NONE", + "noneBody": null, + "formDataBody": + { + "formValues": + [] + }, + "wwwFormBody": + { + "formValues": + [] + }, + "jsonBody": + { + "enableJsonSchema": true, + "jsonValue": "", + "jsonSchema": null + }, + "xmlBody": + { + "value": "" + }, + "rawBody": + { + "value": "" + }, + "binaryBody": + { + "description": "", + "file": null + }, + "bodyClassByType": "io.metersphere.api.dto.request.http.body.NoneBody", + "bodyDataByType": null + }, + "headers": + [], + "rest": + [], + "query": + [ + { + "key": "workspace_id", + "value": "55049933", + "enable": true, + "description": "", + "paramType": "string", + "required": false, + "minLength": null, + "maxLength": null, + "encode": false, + "valid": true, + "notBlankValue": true + }, + { + "key": "id", + "value": "1155049933001012963", + "enable": true, + "description": "", + "paramType": "string", + "required": false, + "minLength": null, + "maxLength": null, + "encode": false, + "valid": true, + "notBlankValue": true + } + ], + "otherConfig": + { + "connectTimeout": 60000, + "responseTimeout": 60000, + "certificateAlias": "", + "followRedirects": true, + "autoRedirects": false + }, + "authConfig": + { + "authType": "BASIC", + "basicAuth": + { + "userName": "oOjrikkm", + "password": "9CD9AB02-7497-0B85-2C4F-45CC3EA763F8", + "valid": true + }, + "digestAuth": + { + "userName": "", + "password": "", + "valid": false + }, + "httpauthValid": true + }, + "moduleId": null, + "num": null, + "mockNum": null + }, + "modulePath": null, + "moduleId": null, + "protocol": null, + "apiChange": null, + "inconsistentWithApi": null, + "ignoreApiDiff": null, + "ignoreApiChange": null + } + ], + "relatedScenarioList": + [ + { + "id": "949101903970304", + "name": "场景引用复制接口定义", + "priority": "P0", + "status": "UNDERWAY", + "stepTotal": 2, + "requestPassRate": "0", + "lastReportStatus": "", + "lastReportId": null, + "num": 100001, + "deleted": false, + "pos": 14790656, + "versionId": "997050905108527", + "refId": "949101903970304", + "latest": true, + "projectId": "997050905108480", + "moduleId": "661562424147968", + "description": "", + "tags": + [], + "grouped": false, + "environmentId": "997050905108481", + "createUser": "724938939965440", + "createTime": 1729236045861, + "deleteTime": null, + "deleteUser": null, + "updateUser": "724938939965440", + "updateTime": 1729236045861, + "modulePath": "/正经场景模块", + "scenarioConfig": + { + "variable": + { + "commonVariables": + [], + "csvVariables": + [] + }, + "preProcessorConfig": + { + "enableGlobal": true, + "processors": + [] + }, + "postProcessorConfig": + { + "enableGlobal": true, + "processors": + [] + }, + "assertionConfig": + { + "assertions": + [] + }, + "otherConfig": + { + "enableGlobalCookie": true, + "enableCookieShare": false, + "enableStepWait": false, + "failureStrategy": "CONTINUE" + } + }, + "steps": + [] + }, + { + "id": "950029616906240", + "name": "场景引用复制接口用例", + "priority": "P0", + "status": "UNDERWAY", + "stepTotal": 2, + "requestPassRate": "0", + "lastReportStatus": "", + "lastReportId": null, + "num": 100002, + "deleted": false, + "pos": 14794752, + "versionId": "997050905108527", + "refId": "950029616906240", + "latest": true, + "projectId": "997050905108480", + "moduleId": "661562424147968", + "description": "", + "tags": + [], + "grouped": false, + "environmentId": "997050905108481", + "createUser": "724938939965440", + "createTime": 1729236099525, + "deleteTime": null, + "deleteUser": null, + "updateUser": "724938939965440", + "updateTime": 1729236099525, + "modulePath": "/正经场景模块", + "scenarioConfig": + { + "variable": + { + "commonVariables": + [], + "csvVariables": + [] + }, + "preProcessorConfig": + { + "enableGlobal": true, + "processors": + [] + }, + "postProcessorConfig": + { + "enableGlobal": true, + "processors": + [] + }, + "assertionConfig": + { + "assertions": + [] + }, + "otherConfig": + { + "enableGlobalCookie": true, + "enableCookieShare": false, + "enableStepWait": false, + "failureStrategy": "CONTINUE" + } + }, + "steps": + [] + } + ] +} \ No newline at end of file