feat(接口测试): 场景格式导入-普通导出的文件导入导出功能开发
This commit is contained in:
parent
e5ff245aa5
commit
fe96718b9b
|
@ -1,5 +1,6 @@
|
||||||
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.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;
|
||||||
|
@ -62,4 +63,12 @@ public class MetersphereApiScenarioExportResponse extends ApiScenarioExportRespo
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.dto.scenario;
|
package io.metersphere.api.dto.scenario;
|
||||||
|
|
||||||
import io.metersphere.api.domain.ApiScenario;
|
import io.metersphere.api.domain.ApiScenario;
|
||||||
|
import io.metersphere.api.domain.ApiScenarioCsv;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
@ -21,4 +22,13 @@ public class ApiScenarioImportDetail extends ApiScenario {
|
||||||
private Map<String, Object> stepDetails = new HashMap<>();
|
private Map<String, Object> stepDetails = new HashMap<>();
|
||||||
@Schema(description = "步骤集合")
|
@Schema(description = "步骤集合")
|
||||||
private List<ApiScenarioStepRequest> steps = new ArrayList<>();
|
private List<ApiScenarioStepRequest> steps = new ArrayList<>();
|
||||||
|
@Schema(description = "CSV相关信息")
|
||||||
|
private List<ApiScenarioCsv> apiScenarioCsvList = new ArrayList<>();
|
||||||
|
|
||||||
|
public void setApiScenarioCsvList(List<ApiScenarioCsv> apiScenarioCsvList) {
|
||||||
|
apiScenarioCsvList.forEach(csv -> {
|
||||||
|
csv.setScenarioId(this.getId());
|
||||||
|
});
|
||||||
|
this.apiScenarioCsvList = apiScenarioCsvList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ public interface ExtApiScenarioMapper {
|
||||||
|
|
||||||
List<ApiScenario> getListBySelectIds(@Param("projectId") String projectId, @Param("ids") List<String> ids, @Param("testPlanId") String testPlanId);
|
List<ApiScenario> getListBySelectIds(@Param("projectId") String projectId, @Param("ids") List<String> ids, @Param("testPlanId") String testPlanId);
|
||||||
|
|
||||||
List<ApiScenario> selectBaseInfoByModuleId(String id);
|
List<ApiScenario> selectBaseInfoByModuleIdAndProjectId(@Param("moduleId") String moduleId, @Param("projectId") String projectId);
|
||||||
|
|
||||||
List<ApiScenario> getNameInfo(@Param("ids") List<String> ids);
|
List<ApiScenario> getNameInfo(@Param("ids") List<String> ids);
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,10 +758,11 @@
|
||||||
#{id}
|
#{id}
|
||||||
</foreach>
|
</foreach>
|
||||||
</select>
|
</select>
|
||||||
<select id="selectBaseInfoByModuleId" resultType="io.metersphere.api.domain.ApiScenario">
|
<select id="selectBaseInfoByModuleIdAndProjectId" resultType="io.metersphere.api.domain.ApiScenario">
|
||||||
SELECT id, name
|
SELECT id, name
|
||||||
FROM api_scenario
|
FROM api_scenario
|
||||||
WHERE module_id = #{0}
|
WHERE module_id = #{moduleId}
|
||||||
|
AND project_id = #{projectId}
|
||||||
AND deleted = false
|
AND deleted = false
|
||||||
</select>
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.api.parser.api.dataimport;
|
package io.metersphere.api.parser.api.dataimport;
|
||||||
|
|
||||||
|
|
||||||
|
import io.metersphere.api.domain.ApiScenarioCsv;
|
||||||
import io.metersphere.api.dto.converter.ApiScenarioImportParseResult;
|
import io.metersphere.api.dto.converter.ApiScenarioImportParseResult;
|
||||||
import io.metersphere.api.dto.converter.ApiScenarioStepParseResult;
|
import io.metersphere.api.dto.converter.ApiScenarioStepParseResult;
|
||||||
import io.metersphere.api.dto.export.MetersphereApiScenarioExportResponse;
|
import io.metersphere.api.dto.export.MetersphereApiScenarioExportResponse;
|
||||||
|
@ -11,12 +12,10 @@ import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.util.BeanUtils;
|
import io.metersphere.sdk.util.BeanUtils;
|
||||||
import io.metersphere.sdk.util.LogUtils;
|
import io.metersphere.sdk.util.LogUtils;
|
||||||
import io.metersphere.system.uid.IDGenerator;
|
import io.metersphere.system.uid.IDGenerator;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
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;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -25,7 +24,7 @@ public class MetersphereParserApiScenario implements ApiScenarioImportParser {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiScenarioImportParseResult parse(InputStream source, ApiScenarioImportRequest request) throws Exception {
|
public ApiScenarioImportParseResult parse(InputStream source, ApiScenarioImportRequest request) throws Exception {
|
||||||
MetersphereApiScenarioExportResponse metersphereApiScenarioExportResponse = null;
|
MetersphereApiScenarioExportResponse metersphereApiScenarioExportResponse;
|
||||||
try {
|
try {
|
||||||
metersphereApiScenarioExportResponse = ApiDataUtils.parseObject(source, MetersphereApiScenarioExportResponse.class);
|
metersphereApiScenarioExportResponse = ApiDataUtils.parseObject(source, MetersphereApiScenarioExportResponse.class);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -35,84 +34,108 @@ public class MetersphereParserApiScenario implements ApiScenarioImportParser {
|
||||||
if (metersphereApiScenarioExportResponse == null) {
|
if (metersphereApiScenarioExportResponse == null) {
|
||||||
throw new MSException("解析失败,请确认是否是正确的文件");
|
throw new MSException("解析失败,请确认是否是正确的文件");
|
||||||
}
|
}
|
||||||
return this.genApiScenarioPreImportAnalysisResult(metersphereApiScenarioExportResponse);
|
return this.genApiScenarioPreImportAnalysisResult(request.getProjectId(), metersphereApiScenarioExportResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApiScenarioImportParseResult genApiScenarioPreImportAnalysisResult(MetersphereApiScenarioExportResponse metersphereApiScenarioExportResponse) {
|
private ApiScenarioImportParseResult genApiScenarioPreImportAnalysisResult(String projectId, MetersphereApiScenarioExportResponse metersphereApiScenarioExportResponse) {
|
||||||
ApiScenarioImportParseResult returnResult = new ApiScenarioImportParseResult();
|
ApiScenarioImportParseResult returnResult = new ApiScenarioImportParseResult();
|
||||||
|
|
||||||
returnResult.setRelatedApiDefinitions(metersphereApiScenarioExportResponse.getRelatedApiDefinitions());
|
returnResult.setRelatedApiDefinitions(metersphereApiScenarioExportResponse.getRelatedApiDefinitions());
|
||||||
returnResult.setRelatedApiTestCaseList(metersphereApiScenarioExportResponse.getRelatedApiTestCaseList());
|
returnResult.setRelatedApiTestCaseList(metersphereApiScenarioExportResponse.getRelatedApiTestCaseList());
|
||||||
returnResult.setApiScenarioCsvList(metersphereApiScenarioExportResponse.getApiScenarioCsvList());
|
returnResult.setApiScenarioCsvList(metersphereApiScenarioExportResponse.getApiScenarioCsvList());
|
||||||
|
|
||||||
|
|
||||||
List<ApiScenarioDetail> exportScenarioList = metersphereApiScenarioExportResponse.getExportScenarioList();
|
List<ApiScenarioDetail> exportScenarioList = metersphereApiScenarioExportResponse.getExportScenarioList();
|
||||||
List<ApiScenarioDetail> relatedScenarioList = metersphereApiScenarioExportResponse.getRelatedScenarioList();
|
List<ApiScenarioDetail> relatedScenarioList = metersphereApiScenarioExportResponse.getRelatedScenarioList();
|
||||||
Map<String, List<ApiScenarioStepDTO>> scenarioStepMap =
|
Map<String, List<ApiScenarioStepDTO>> scenarioStepMap =
|
||||||
metersphereApiScenarioExportResponse.getScenarioStepList().stream().collect(Collectors.groupingBy(ApiScenarioStepDTO::getScenarioId));
|
metersphereApiScenarioExportResponse.getScenarioStepList().stream().collect(Collectors.groupingBy(ApiScenarioStepDTO::getScenarioId));
|
||||||
Map<String, String> scenarioStepBlobMap = metersphereApiScenarioExportResponse.getScenarioStepBlobMap();
|
Map<String, String> scenarioStepBlobMap = metersphereApiScenarioExportResponse.getScenarioStepBlobMap();
|
||||||
|
Map<String, List<ApiScenarioCsv>> apiScenarioCsvMap =
|
||||||
|
metersphereApiScenarioExportResponse.getApiScenarioCsvList().stream().collect(Collectors.groupingBy(ApiScenarioCsv::getScenarioId));
|
||||||
|
|
||||||
|
|
||||||
for (ApiScenarioDetail apiScenarioDetail : exportScenarioList) {
|
for (ApiScenarioDetail apiScenarioDetail : exportScenarioList) {
|
||||||
returnResult.getImportScenarioList().add(
|
returnResult.getImportScenarioList().add(
|
||||||
this.parseApiScenarioStep(apiScenarioDetail, scenarioStepMap.getOrDefault(apiScenarioDetail.getId(), new ArrayList<>()), scenarioStepBlobMap));
|
this.parseApiScenario(projectId, apiScenarioDetail, scenarioStepMap, scenarioStepBlobMap, apiScenarioCsvMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ApiScenarioDetail apiScenarioDetail : relatedScenarioList) {
|
for (ApiScenarioDetail apiScenarioDetail : relatedScenarioList) {
|
||||||
returnResult.getRelatedScenarioList().add(
|
returnResult.getRelatedScenarioList().add(
|
||||||
this.parseApiScenarioStep(apiScenarioDetail, scenarioStepMap.getOrDefault(apiScenarioDetail.getId(), new ArrayList<>()), scenarioStepBlobMap));
|
this.parseApiScenario(projectId, apiScenarioDetail, scenarioStepMap, scenarioStepBlobMap, apiScenarioCsvMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnResult;
|
return returnResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApiScenarioImportDetail parseApiScenarioStep(ApiScenarioDetail apiScenarioDetail, List<ApiScenarioStepDTO> apiScenarioStepDTOList, Map<String, String> scenarioStepBlobMap) {
|
private ApiScenarioImportDetail parseApiScenario(String projectId,
|
||||||
|
ApiScenarioDetail apiScenarioDetail,
|
||||||
|
Map<String, List<ApiScenarioStepDTO>> apiScenarioStepMap,
|
||||||
|
Map<String, String> scenarioStepBlobMap,
|
||||||
|
Map<String, List<ApiScenarioCsv>> apiScenarioCsvMap) {
|
||||||
ApiScenarioImportDetail apiScenarioImportDetail = new ApiScenarioImportDetail();
|
ApiScenarioImportDetail apiScenarioImportDetail = new ApiScenarioImportDetail();
|
||||||
BeanUtils.copyBean(apiScenarioImportDetail, apiScenarioDetail);
|
BeanUtils.copyBean(apiScenarioImportDetail, apiScenarioDetail);
|
||||||
ApiScenarioStepParseResult parseResult = this.parseStepDetails(apiScenarioStepDTOList, scenarioStepBlobMap);
|
ApiScenarioStepParseResult parseResult = this.parseStepDetails(apiScenarioStepMap, apiScenarioDetail.getId(), scenarioStepBlobMap);
|
||||||
apiScenarioImportDetail.setSteps(parseResult.getStepList());
|
apiScenarioImportDetail.setSteps(parseResult.getStepList());
|
||||||
apiScenarioImportDetail.setStepDetails(parseResult.getStepDetails());
|
apiScenarioImportDetail.setStepDetails(parseResult.getStepDetails());
|
||||||
|
apiScenarioImportDetail.setProjectId(projectId);
|
||||||
|
apiScenarioImportDetail.setApiScenarioCsvList(apiScenarioCsvMap.getOrDefault(apiScenarioDetail.getId(), new ArrayList<>()));
|
||||||
return apiScenarioImportDetail;
|
return apiScenarioImportDetail;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApiScenarioStepParseResult parseStepDetails(List<ApiScenarioStepDTO> apiScenarioStepDTOList, Map<String, String> scenarioStepBlobMap) {
|
private ApiScenarioStepParseResult parseStepDetails(Map<String, List<ApiScenarioStepDTO>> apiScenarioStepMap, String scenarioId, Map<String, String> scenarioStepBlobMap) {
|
||||||
ApiScenarioStepParseResult apiScenarioStepParseResult = new ApiScenarioStepParseResult();
|
ApiScenarioStepParseResult apiScenarioStepParseResult = new ApiScenarioStepParseResult();
|
||||||
Map<String, ApiScenarioStepRequest> stepRequestIdMap = new HashMap<>();
|
|
||||||
|
|
||||||
int lastSize = 0;
|
List<ApiScenarioStepDTO> stepList = apiScenarioStepMap.getOrDefault(scenarioId, new ArrayList<>());
|
||||||
while (CollectionUtils.isNotEmpty(apiScenarioStepDTOList) && apiScenarioStepDTOList.size() != lastSize) {
|
for (ApiScenarioStepDTO stepDTO : stepList) {
|
||||||
lastSize = apiScenarioStepDTOList.size();
|
String oldStepId = stepDTO.getId();
|
||||||
List<ApiScenarioStepDTO> 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
|
ApiScenarioStepRequest stepRequest = new ApiScenarioStepRequest();
|
||||||
stepRequestIdMap.put(oldStepId, stepRequest);
|
BeanUtils.copyBean(stepRequest, stepDTO);
|
||||||
if (StringUtils.isBlank(stepDTO.getParentId())) {
|
// 赋值新ID防止和库内已有数据重复
|
||||||
apiScenarioStepParseResult.getStepList().add(stepRequest);
|
stepRequest.setId(IDGenerator.nextStr());
|
||||||
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)) {
|
||||||
if (scenarioStepBlobMap.containsKey(oldStepId)) {
|
apiScenarioStepParseResult.getStepDetails().put(stepRequest.getId(), scenarioStepBlobMap.get(oldStepId).getBytes());
|
||||||
apiScenarioStepParseResult.getStepDetails().put(stepRequest.getId(), scenarioStepBlobMap.get(oldStepId).getBytes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
apiScenarioStepDTOList = notMatchedList;
|
stepRequest.setChildren(this.buildTreeStep(this.getChildScenarioStep(oldStepId, apiScenarioStepMap),
|
||||||
|
apiScenarioStepMap, scenarioStepBlobMap, apiScenarioStepParseResult));
|
||||||
|
apiScenarioStepParseResult.getStepList().add(stepRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
return apiScenarioStepParseResult;
|
return apiScenarioStepParseResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<ApiScenarioStepRequest> buildTreeStep(
|
||||||
|
List<ApiScenarioStepDTO> childScenarioStep,
|
||||||
|
Map<String, List<ApiScenarioStepDTO>> allScenarioStepMap,
|
||||||
|
Map<String, String> scenarioStepBlobMap,
|
||||||
|
ApiScenarioStepParseResult apiScenarioStepParseResult) {
|
||||||
|
List<ApiScenarioStepRequest> returnList = new ArrayList<>();
|
||||||
|
for (ApiScenarioStepDTO childDTO : childScenarioStep) {
|
||||||
|
String oldChildId = childDTO.getId();
|
||||||
|
ApiScenarioStepRequest childRequest = new ApiScenarioStepRequest();
|
||||||
|
BeanUtils.copyBean(childRequest, childDTO);
|
||||||
|
// 赋值新ID防止和库内已有数据重复
|
||||||
|
childRequest.setId(IDGenerator.nextStr());
|
||||||
|
// 使用旧ID用于配置Tree
|
||||||
|
if (scenarioStepBlobMap.containsKey(oldChildId)) {
|
||||||
|
apiScenarioStepParseResult.getStepDetails().put(childRequest.getId(), scenarioStepBlobMap.get(oldChildId).getBytes());
|
||||||
|
}
|
||||||
|
childRequest.setChildren(this.buildTreeStep(this.getChildScenarioStep(oldChildId, allScenarioStepMap),
|
||||||
|
allScenarioStepMap, scenarioStepBlobMap, apiScenarioStepParseResult));
|
||||||
|
returnList.add(childRequest);
|
||||||
|
}
|
||||||
|
return returnList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ApiScenarioStepDTO> getChildScenarioStep(String parentId, Map<String, List<ApiScenarioStepDTO>> apiScenarioStepMap) {
|
||||||
|
List<ApiScenarioStepDTO> childStepList = new ArrayList<>();
|
||||||
|
apiScenarioStepMap.values().forEach(stepList -> {
|
||||||
|
for (ApiScenarioStepDTO stepDTO : stepList) {
|
||||||
|
if (StringUtils.equals(stepDTO.getParentId(), parentId)) {
|
||||||
|
childStepList.add(stepDTO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return childStepList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ public class ApiScenarioDataTransferService {
|
||||||
}
|
}
|
||||||
//解析
|
//解析
|
||||||
ApiScenarioPreImportAnalysisResult preImportAnalysisResult = this.importAnalysis(
|
ApiScenarioPreImportAnalysisResult preImportAnalysisResult = this.importAnalysis(
|
||||||
parseResult, request.getModuleId(), apiScenarioModuleService.getTree(request.getProjectId()));
|
parseResult, request.getProjectId(), request.getModuleId(), apiScenarioModuleService.getTree(request.getProjectId()));
|
||||||
|
|
||||||
//存储
|
//存储
|
||||||
this.save(preImportAnalysisResult, request.getProjectId(), request.getOperator(), request.isCoverData());
|
this.save(preImportAnalysisResult, request.getProjectId(), request.getOperator(), request.isCoverData());
|
||||||
|
@ -212,13 +212,11 @@ public class ApiScenarioDataTransferService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateScenarios(String projectId, String operator, List<ApiScenarioImportDetail> updateApiScenarioData, SqlSession sqlSession) {
|
private void updateScenarios(String projectId, String operator, List<ApiScenarioImportDetail> updateApiScenarioData, SqlSession sqlSession) {
|
||||||
// 创建场景
|
|
||||||
if (CollectionUtils.isEmpty(updateApiScenarioData)) {
|
if (CollectionUtils.isEmpty(updateApiScenarioData)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ApiScenarioMapper scenarioBatchMapper = sqlSession.getMapper(ApiScenarioMapper.class);
|
ApiScenarioMapper scenarioBatchMapper = sqlSession.getMapper(ApiScenarioMapper.class);
|
||||||
ApiScenarioBlobMapper scenarioBlobBatchMapper = sqlSession.getMapper(ApiScenarioBlobMapper.class);
|
ApiScenarioBlobMapper scenarioBlobBatchMapper = sqlSession.getMapper(ApiScenarioBlobMapper.class);
|
||||||
ApiScenarioCsvMapper csvBatchMapper = sqlSession.getMapper(ApiScenarioCsvMapper.class);
|
|
||||||
ApiScenarioCsvStepMapper csvStepBatchMapper = sqlSession.getMapper(ApiScenarioCsvStepMapper.class);
|
ApiScenarioCsvStepMapper csvStepBatchMapper = sqlSession.getMapper(ApiScenarioCsvStepMapper.class);
|
||||||
ApiScenarioStepMapper stepBatchMapper = sqlSession.getMapper(ApiScenarioStepMapper.class);
|
ApiScenarioStepMapper stepBatchMapper = sqlSession.getMapper(ApiScenarioStepMapper.class);
|
||||||
ApiScenarioStepBlobMapper stepBlobBatchMapper = sqlSession.getMapper(ApiScenarioStepBlobMapper.class);
|
ApiScenarioStepBlobMapper stepBlobBatchMapper = sqlSession.getMapper(ApiScenarioStepBlobMapper.class);
|
||||||
|
@ -520,7 +518,7 @@ public class ApiScenarioDataTransferService {
|
||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApiScenarioPreImportAnalysisResult importAnalysis(ApiScenarioImportParseResult parseResult, String moduleId, List<BaseTreeNode> apiScenarioModules) {
|
private ApiScenarioPreImportAnalysisResult importAnalysis(ApiScenarioImportParseResult parseResult, String projectId, String moduleId, List<BaseTreeNode> apiScenarioModules) {
|
||||||
ApiScenarioPreImportAnalysisResult analysisResult = new ApiScenarioPreImportAnalysisResult();
|
ApiScenarioPreImportAnalysisResult analysisResult = new ApiScenarioPreImportAnalysisResult();
|
||||||
|
|
||||||
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));
|
||||||
|
@ -549,7 +547,7 @@ public class ApiScenarioDataTransferService {
|
||||||
modulePath = "/" + modulePath;
|
modulePath = "/" + modulePath;
|
||||||
}
|
}
|
||||||
if (modulePathMap.containsKey(modulePath)) {
|
if (modulePathMap.containsKey(modulePath)) {
|
||||||
List<ApiScenario> existenceScenarios = extApiScenarioMapper.selectBaseInfoByModuleId(modulePathMap.get(modulePath).getId());
|
List<ApiScenario> existenceScenarios = extApiScenarioMapper.selectBaseInfoByModuleIdAndProjectId(modulePathMap.get(modulePath).getId(), projectId);
|
||||||
Map<String, String> existenceNameIdMap = existenceScenarios.stream().collect(Collectors.toMap(ApiScenario::getName, ApiScenario::getId, (k1, k2) -> k1));
|
Map<String, String> existenceNameIdMap = existenceScenarios.stream().collect(Collectors.toMap(ApiScenario::getName, ApiScenario::getId, (k1, k2) -> k1));
|
||||||
String finalModulePath = modulePath;
|
String finalModulePath = modulePath;
|
||||||
scenarios.forEach(scenario -> {
|
scenarios.forEach(scenario -> {
|
||||||
|
@ -611,6 +609,7 @@ public class ApiScenarioDataTransferService {
|
||||||
ExportWebSocketHandler.sendMessageSingle(
|
ExportWebSocketHandler.sendMessageSingle(
|
||||||
new ExportMsgDTO(request.getFileId(), taskId, ids.size(), true, MsgType.EXEC_RESULT.name())
|
new ExportMsgDTO(request.getFileId(), taskId, ids.size(), true, MsgType.EXEC_RESULT.name())
|
||||||
);
|
);
|
||||||
|
return taskId;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtils.error(e);
|
LogUtils.error(e);
|
||||||
List<ExportTask> exportTasks = exportTaskManager.getExportTasks(request.getProjectId(), ExportConstants.ExportType.API_SCENARIO.name(), ExportConstants.ExportState.PREPARED.toString(), userId, null);
|
List<ExportTask> exportTasks = exportTaskManager.getExportTasks(request.getProjectId(), ExportConstants.ExportType.API_SCENARIO.name(), ExportConstants.ExportState.PREPARED.toString(), userId, null);
|
||||||
|
@ -623,7 +622,6 @@ public class ApiScenarioDataTransferService {
|
||||||
} finally {
|
} finally {
|
||||||
MsFileUtils.deleteDir(tmpDir.getPath());
|
MsFileUtils.deleteDir(tmpDir.getPath());
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApiScenarioExportResponse genMetersphereExportResponse(ApiScenarioBatchExportRequest request, Map<String, String> moduleMap, String exportType, String userId) {
|
private ApiScenarioExportResponse genMetersphereExportResponse(ApiScenarioBatchExportRequest request, Map<String, String> moduleMap, String exportType, String userId) {
|
||||||
|
@ -712,6 +710,7 @@ public class ApiScenarioDataTransferService {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// 普通导出,所有的引用都改为复制,并且Api、ApiCase改为CUSTOM_REQUEST
|
// 普通导出,所有的引用都改为复制,并且Api、ApiCase改为CUSTOM_REQUEST
|
||||||
|
response.setRefTypeToCopy();
|
||||||
response.setStepTypeToCustomRequest();
|
response.setStepTypeToCustomRequest();
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
|
|
|
@ -1817,6 +1817,53 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
return steps;
|
return steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<ApiScenarioStepDTO> parseConfig(List<ApiScenarioStepDTO> steps, String parentId) {
|
||||||
|
List<ApiScenarioStepDTO> returnList = new ArrayList<>();
|
||||||
|
// 将 config 转换成对象
|
||||||
|
steps.forEach(dto -> {
|
||||||
|
ApiScenarioStepDTO returnDTO = new ApiScenarioStepDTO();
|
||||||
|
BeanUtils.copyBean(returnDTO, dto);
|
||||||
|
if (!StringUtils.equalsIgnoreCase(parentId, dto.getId())) {
|
||||||
|
returnDTO.setParentId(parentId);
|
||||||
|
}
|
||||||
|
if (returnDTO.getConfig() != null && StringUtils.isNotBlank(returnDTO.getConfig().toString())) {
|
||||||
|
if (returnDTO.getConfig() instanceof String configVal) {
|
||||||
|
returnDTO.setConfig(JSON.parseObject(configVal));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
returnList.add(returnDTO);
|
||||||
|
});
|
||||||
|
return returnList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归获取所有的场景步骤
|
||||||
|
*/
|
||||||
|
public List<ApiScenarioStepDTO> buildScenarioSteps(List<String> scenarioIds) {
|
||||||
|
List<ApiScenarioStepDTO> returnList = new ArrayList<>();
|
||||||
|
|
||||||
|
List<ApiScenarioStepDTO> steps = getStepDTOByScenarioIds(scenarioIds);
|
||||||
|
if (CollectionUtils.isEmpty(steps)) {
|
||||||
|
return returnList;
|
||||||
|
} else {
|
||||||
|
returnList.addAll(this.parseConfig(steps, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ApiScenarioStepDTO> refScenarioSteps = steps.stream().filter(this::isRefOrPartialScenario).toList();
|
||||||
|
while (CollectionUtils.isNotEmpty(refScenarioSteps)) {
|
||||||
|
List<ApiScenarioStepDTO> childStep = new ArrayList<>();
|
||||||
|
for (ApiScenarioStepDTO step : refScenarioSteps) {
|
||||||
|
childStep = getStepDTOByScenarioIds(Collections.singletonList(step.getResourceId()));
|
||||||
|
if (CollectionUtils.isNotEmpty(childStep)) {
|
||||||
|
returnList.addAll(this.parseConfig(childStep, step.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refScenarioSteps = childStep.stream().filter(this::isRefOrPartialScenario).toList();
|
||||||
|
}
|
||||||
|
// 嵌套获取引用的场景步骤
|
||||||
|
return returnList;
|
||||||
|
}
|
||||||
|
|
||||||
private List<ApiScenarioStepDTO> getStepDTOByScenarioIds(List<String> scenarioIds) {
|
private List<ApiScenarioStepDTO> getStepDTOByScenarioIds(List<String> scenarioIds) {
|
||||||
if (CollectionUtils.isEmpty(scenarioIds)) {
|
if (CollectionUtils.isEmpty(scenarioIds)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
@ -2487,7 +2534,7 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
List<ApiScenario> exportApiScenarios = apiScenarioMapper.selectByExample(scenarioExample);
|
List<ApiScenario> exportApiScenarios = apiScenarioMapper.selectByExample(scenarioExample);
|
||||||
|
|
||||||
// 获取所有步骤(包含引用的场景)
|
// 获取所有步骤(包含引用的场景)
|
||||||
List<ApiScenarioStepDTO> allSteps = getAllStepsByScenarioIds(scenarioIds)
|
List<ApiScenarioStepDTO> allSteps = buildScenarioSteps(scenarioIds)
|
||||||
.stream()
|
.stream()
|
||||||
.distinct() // 这里可能存在多次引用相同场景,步骤可能会重复,去重
|
.distinct() // 这里可能存在多次引用相同场景,步骤可能会重复,去重
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -5,6 +5,34 @@
|
||||||
"css_prefix_text": "icon-",
|
"css_prefix_text": "icon-",
|
||||||
"description": "",
|
"description": "",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "42178834",
|
||||||
|
"name": "icon_file_ms",
|
||||||
|
"font_class": "icon_file_ms",
|
||||||
|
"unicode": "e6da",
|
||||||
|
"unicode_decimal": 59098
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "42048031",
|
||||||
|
"name": "icon_disassociation",
|
||||||
|
"font_class": "icon_disassociation",
|
||||||
|
"unicode": "e6d9",
|
||||||
|
"unicode_decimal": 59097
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "42047679",
|
||||||
|
"name": "icon_update_rotatiorn",
|
||||||
|
"font_class": "icon_update_rotatiorn",
|
||||||
|
"unicode": "e6b1",
|
||||||
|
"unicode_decimal": 59057
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "41978752",
|
||||||
|
"name": "icon_download",
|
||||||
|
"font_class": "icon_download",
|
||||||
|
"unicode": "e6a7",
|
||||||
|
"unicode_decimal": 59047
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"icon_id": "32849821",
|
"icon_id": "32849821",
|
||||||
"name": "icon_expand-right_filled",
|
"name": "icon_expand-right_filled",
|
||||||
|
|
|
@ -14,6 +14,14 @@
|
||||||
/>
|
/>
|
||||||
<missing-glyph />
|
<missing-glyph />
|
||||||
|
|
||||||
|
<glyph glyph-name="icon_file_ms" unicode="" d="M648.533333 853.333333a42.666667 42.666667 0 0 0 33.322667-16l170.666667-213.333333 2.730666-3.925333 1.152-1.877334 1.664-3.242666 1.408-3.541334 0.981334-3.157333a41.258667 41.258667 0 0 0 1.109333-5.973333L861.866667 597.333333v-85.333333h42.666666a85.333333 85.333333 0 0 0 85.333334-85.333333v-298.666667a85.333333 85.333333 0 0 0-85.333334-85.333333h-42.666666v-85.333334a42.666667 42.666667 0 0 0-42.666667-42.666666h-597.333333a42.666667 42.666667 0 0 0-42.666667 42.666666v85.333334h-42.666667a85.333333 85.333333 0 0 0-85.333333 85.333333v298.666667a85.333333 85.333333 0 0 0 85.333333 85.333333h42.666667V810.666667a42.666667 42.666667 0 0 0 42.666667 42.666666h426.666666z m128-810.666666h-512v-42.666667h512v42.666667z m128 384h-768v-298.666667h768v298.666667z m-250.197333-38.570667c27.306667 0 48.128-5.077333 62.506667-15.232 14.336-10.154667 22.869333-26.325333 25.6-48.469333l-62.293334-3.669334c-1.664 9.642667-5.12 16.64-10.410666 20.992-5.333333 4.394667-12.629333 6.570667-21.973334 6.570667-7.68 0-13.44-1.621333-17.365333-4.864a14.933333 14.933333 0 0 1-5.802667-11.904c0-3.413333 1.578667-6.485333 4.778667-9.173333 3.114667-2.816 10.538667-5.461333 22.186667-7.893334 28.885333-6.229333 49.578667-12.501333 62.037333-18.901333 12.501333-6.357333 21.589333-14.250667 27.306667-23.68 5.674667-9.429333 8.533333-19.968 8.533333-31.658667 0-13.653333-3.84-26.325333-11.392-37.888a71.168 71.168 0 0 0-31.786667-26.325333c-13.653333-5.973333-30.762667-8.96-51.498666-8.96-36.352 0-61.525333 6.997333-75.52 20.992-13.994667 13.994667-21.930667 31.786667-23.765334 53.333333l62.848 3.968c1.365333-10.24 4.138667-18.005333 8.32-23.338666 6.784-8.661333 16.512-12.970667 29.141334-12.970667 9.429333 0 16.682667 2.218667 21.802666 6.613333a19.882667 19.882667 0 0 1 7.68 15.402667 19.626667 19.626667 0 0 1-7.296 14.890667c-4.864 4.352-16.170667 8.533333-33.834666 12.373333-29.013333 6.528-49.664 15.189333-61.994667 25.984a52.224 52.224 0 0 0-18.645333 41.258667c0 10.965333 3.157333 21.333333 9.514666 31.146666 6.4 9.770667 15.957333 17.450667 28.757334 23.04 12.8 5.546667 30.293333 8.362667 52.565333 8.362667z m-283.050667-3.626667l33.536-130.133333 33.408 130.133333h86.613334V170.666667h-53.973334v163.029333L429.056 170.666667H380.16l-41.685333 163.029333V170.666667H284.373333v213.76h86.912zM563.2 768h-298.666667v-256h512V554.666667h-170.666666a42.666667 42.666667 0 0 0-42.666667 42.666666V768z m85.333333-25.6V640h81.92L648.533333 742.4z" horiz-adv-x="1024" />
|
||||||
|
|
||||||
|
<glyph glyph-name="icon_disassociation" unicode="" d="M640 512a42.666667 42.666667 0 0 0 0-85.333333h-213.333333a128 128 0 1 1 0-256h341.333333a128 128 0 0 1 96 212.650666 42.666667 42.666667 0 0 0 64 56.490667A213.333333 213.333333 0 0 0 768 85.333333h-341.333333a213.333333 213.333333 0 1 0 0 426.666667h213.333333z m-42.666667 170.666667a213.333333 213.333333 0 1 0 0-426.666667H384a42.666667 42.666667 0 0 0 0 85.333333h213.333333a128 128 0 1 1 0 256H256a128 128 0 0 1-96-212.650666 42.666667 42.666667 0 1 0-64-56.490667A213.333333 213.333333 0 0 0 256 682.666667h341.333333z" horiz-adv-x="1024" />
|
||||||
|
|
||||||
|
<glyph glyph-name="icon_update_rotatiorn" unicode="" d="M512 853.333333c259.2 0 469.333333-210.133333 469.333333-469.333333s-210.133333-469.333333-469.333333-469.333333S42.666667 124.8 42.666667 384 252.8 853.333333 512 853.333333z m0-85.333333a384 384 0 1 1 0-768 384 384 0 0 1 0 768zM349.141333 332.8a170.752 170.752 0 0 1 325.717334 0 42.666667 42.666667 0 1 0 81.408-25.6 256.085333 256.085333 0 0 0-395.093334-130.048l-10.666666 8.234667-0.512-3.157334a42.666667 42.666667 0 0 0-36.565334-32.597333l-4.992-0.298667a42.666667 42.666667 0 0 0-42.666666 42.666667v128c0 48.810667 68.736 59.392 83.370666 12.8zM512 640c55.850667 0 108.202667-18.048 150.826667-49.152l10.624-8.192 0.597333 3.114667a42.666667 42.666667 0 0 0 36.565333 32.597333l4.949334 0.298667a42.666667 42.666667 0 0 0 42.666666-42.666667v-128c0-48.810667-68.693333-59.392-83.370666-12.8a170.752 170.752 0 0 1-325.717334 0 42.666667 42.666667 0 1 0-81.408 25.6A256.085333 256.085333 0 0 0 512 640z" horiz-adv-x="1024" />
|
||||||
|
|
||||||
|
<glyph glyph-name="icon_download" unicode="" d="M512.170667 810.666667a42.666667 42.666667 0 0 0 42.666666-42.666667v-494.122667l182.997334 182.954667a42.666667 42.666667 0 0 0 56.32 3.541333l4.010666-3.541333a42.666667 42.666667 0 0 0 0-60.330667l-256-256a42.666667 42.666667 0 0 0-60.330666 0l-256 256a42.666667 42.666667 0 0 0 60.330666 60.330667l183.338667-183.296V768a42.666667 42.666667 0 0 0 42.666667 42.666667zM768 42.666667a42.666667 42.666667 0 0 0 0-85.333334H256a42.666667 42.666667 0 0 0 0 85.333334h512z" horiz-adv-x="1024" />
|
||||||
|
|
||||||
<glyph glyph-name="icon_expand-right_filled1" unicode="" d="M797.994667 359.424L332.8-13.696a38.4 38.4 0 0 0-45.952 0 23.722667 23.722667 0 0 0-9.514667 18.389333V763.306667c0 14.378667 14.549333 26.026667 32.469334 26.026666 8.618667 0 16.853333-2.730667 22.954666-7.637333l465.237334-373.12c16.896-13.568 16.896-35.584 0-49.152z" horiz-adv-x="1024" />
|
<glyph glyph-name="icon_expand-right_filled1" unicode="" d="M797.994667 359.424L332.8-13.696a38.4 38.4 0 0 0-45.952 0 23.722667 23.722667 0 0 0-9.514667 18.389333V763.306667c0 14.378667 14.549333 26.026667 32.469334 26.026666 8.618667 0 16.853333-2.730667 22.954666-7.637333l465.237334-373.12c16.896-13.568 16.896-35.584 0-49.152z" horiz-adv-x="1024" />
|
||||||
|
|
||||||
<glyph glyph-name="icon_folder_outlined" unicode="" d="M42.666667 42.666667V725.333333a42.666667 42.666667 0 0 0 42.666666 42.666667h357.674667a42.666667 42.666667 0 0 0 38.144-23.594667L512 682.666667h424.618667C961.365333 682.666667 981.333333 663.552 981.333333 640v-597.333333c0-23.552-19.968-42.666667-44.672-42.666667H87.381333C62.72 0 42.666667 19.114667 42.666667 42.666667zM128 597.333333v-512h768V597.333333H128z" horiz-adv-x="1024" />
|
<glyph glyph-name="icon_folder_outlined" unicode="" d="M42.666667 42.666667V725.333333a42.666667 42.666667 0 0 0 42.666666 42.666667h357.674667a42.666667 42.666667 0 0 0 38.144-23.594667L512 682.666667h424.618667C961.365333 682.666667 981.333333 663.552 981.333333 640v-597.333333c0-23.552-19.968-42.666667-44.672-42.666667H87.381333C62.72 0 42.666667 19.114667 42.666667 42.666667zM128 597.333333v-512h768V597.333333H128z" horiz-adv-x="1024" />
|
||||||
|
|
Before Width: | Height: | Size: 403 KiB After Width: | Height: | Size: 408 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -84,6 +84,10 @@ export const FileIconMap: FileIconMapping = {
|
||||||
[UploadStatus.init]: 'icon-icon_file_har',
|
[UploadStatus.init]: 'icon-icon_file_har',
|
||||||
[UploadStatus.done]: 'icon-icon_file_har',
|
[UploadStatus.done]: 'icon-icon_file_har',
|
||||||
},
|
},
|
||||||
|
ms: {
|
||||||
|
[UploadStatus.init]: 'icon-icon_file_ms',
|
||||||
|
[UploadStatus.done]: 'icon-icon_file_ms',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,6 +18,7 @@ export enum UploadAcceptEnum {
|
||||||
json = '.json',
|
json = '.json',
|
||||||
jmx = '.jmx',
|
jmx = '.jmx',
|
||||||
har = '.har',
|
har = '.har',
|
||||||
|
ms = '.ms',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum UploadStatus {
|
export enum UploadStatus {
|
||||||
|
|
|
@ -145,7 +145,7 @@
|
||||||
const importForm = ref({ ...defaultForm });
|
const importForm = ref({ ...defaultForm });
|
||||||
const importFormRef = ref<FormInstance>();
|
const importFormRef = ref<FormInstance>();
|
||||||
const fileAccept = computed(() => {
|
const fileAccept = computed(() => {
|
||||||
return importForm.value.type === RequestImportFormat.MeterSphere ? 'json' : 'jmx';
|
return importForm.value.type === RequestImportFormat.MeterSphere ? 'ms' : 'jmx';
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
Loading…
Reference in New Issue