diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java index 22c78ad384..702d3326a4 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java @@ -272,10 +272,14 @@ public class MsHTTPSamplerProxy extends MsTestElement { StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append(path); stringBuffer.append("?"); - this.getArguments().stream().filter(KeyValue::isEnable).filter(KeyValue::isValid).forEach(keyValue -> - stringBuffer.append(keyValue.getName()).append("=").append(keyValue.getValue() != null && keyValue.getValue().startsWith("@") ? - ScriptEngineUtils.calculate(keyValue.getValue()) : keyValue.getValue()).append("&") - ); + this.getArguments().stream().filter(KeyValue::isEnable).filter(KeyValue::isValid).forEach(keyValue -> { + stringBuffer.append(keyValue.getName()); + if (keyValue.getValue() != null) { + stringBuffer.append("=").append(keyValue.getValue().startsWith("@") ? + ScriptEngineUtils.calculate(keyValue.getValue()) : keyValue.getValue()); + } + stringBuffer.append("&"); + }); return stringBuffer.substring(0, stringBuffer.length() - 1); } diff --git a/backend/src/main/java/io/metersphere/api/dto/parse/postman/PostmanEvent.java b/backend/src/main/java/io/metersphere/api/dto/parse/postman/PostmanEvent.java new file mode 100644 index 0000000000..9003ec4267 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/parse/postman/PostmanEvent.java @@ -0,0 +1,8 @@ +package io.metersphere.api.dto.parse.postman; + +import lombok.Data; +@Data +public class PostmanEvent { + private String listen; + private PostmanScript script; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/parse/postman/PostmanItem.java b/backend/src/main/java/io/metersphere/api/dto/parse/postman/PostmanItem.java index 49ccae955e..b1de1b7512 100644 --- a/backend/src/main/java/io/metersphere/api/dto/parse/postman/PostmanItem.java +++ b/backend/src/main/java/io/metersphere/api/dto/parse/postman/PostmanItem.java @@ -7,6 +7,7 @@ import java.util.List; @Data public class PostmanItem { private String name; + private List event; private PostmanRequest request; private List item; } diff --git a/backend/src/main/java/io/metersphere/api/dto/parse/postman/PostmanScript.java b/backend/src/main/java/io/metersphere/api/dto/parse/postman/PostmanScript.java new file mode 100644 index 0000000000..1c0f4c2cae --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/parse/postman/PostmanScript.java @@ -0,0 +1,11 @@ +package io.metersphere.api.dto.parse.postman; + +import lombok.Data; + +import java.util.List; + +@Data +public class PostmanScript { + private List exec; + private String type; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/KeyValue.java b/backend/src/main/java/io/metersphere/api/dto/scenario/KeyValue.java index 85153d2bcd..9cb1e08033 100644 --- a/backend/src/main/java/io/metersphere/api/dto/scenario/KeyValue.java +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/KeyValue.java @@ -57,7 +57,7 @@ public class KeyValue { } public boolean isValid() { - return ((StringUtils.isNotBlank(name) && StringUtils.isNotBlank(value)) || "JSON-SCHEMA".equals(type)) && !StringUtils.equalsIgnoreCase(type, "file"); + return (StringUtils.isNotBlank(name) || "JSON-SCHEMA".equals(type)) && !StringUtils.equalsIgnoreCase(type, "file"); } public boolean isFile() { diff --git a/backend/src/main/java/io/metersphere/api/parse/MsParser.java b/backend/src/main/java/io/metersphere/api/parse/MsParser.java index db9727b8e5..7cf9ca65f0 100644 --- a/backend/src/main/java/io/metersphere/api/parse/MsParser.java +++ b/backend/src/main/java/io/metersphere/api/parse/MsParser.java @@ -13,6 +13,7 @@ import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.request.RequestType; import io.metersphere.api.service.ApiModuleService; import io.metersphere.base.domain.ApiModule; +import io.metersphere.commons.constants.ApiImportPlatform; import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.LogUtil; import org.apache.commons.collections.CollectionUtils; @@ -34,6 +35,7 @@ public class MsParser extends ApiImportAbstractParser { if (testObject.get("projectName") != null) { return parseMsFormat(testStr, request); } else { + request.setPlatform(ApiImportPlatform.Plugin.name()); return parsePluginFormat(testObject, request); } } diff --git a/backend/src/main/java/io/metersphere/api/parse/PostmanParser.java b/backend/src/main/java/io/metersphere/api/parse/PostmanParser.java index 30ee6907b1..a1db04246b 100644 --- a/backend/src/main/java/io/metersphere/api/parse/PostmanParser.java +++ b/backend/src/main/java/io/metersphere/api/parse/PostmanParser.java @@ -5,6 +5,8 @@ import com.alibaba.fastjson.JSONObject; import io.metersphere.api.dto.ApiTestImportRequest; import io.metersphere.api.dto.definition.ApiDefinitionResult; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; +import io.metersphere.api.dto.definition.request.MsTestElement; +import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.parse.postman.*; import io.metersphere.api.dto.scenario.Body; @@ -12,11 +14,14 @@ import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.base.domain.ApiModule; import io.metersphere.commons.constants.MsRequestBodyType; import io.metersphere.commons.constants.PostmanRequestBodyMode; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import java.io.InputStream; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; +import java.util.stream.Collectors; public class PostmanParser extends ApiImportAbstractParser { @@ -75,10 +80,37 @@ public class PostmanParser extends ApiImportAbstractParser { request.setArguments(parseKeyValue(url.getQuery())); request.setHeaders(parseKeyValue(requestDesc.getHeader())); addBodyHeader(request); + addPreScript(request, requestItem.getEvent()); apiDefinition.setRequest(JSON.toJSONString(request)); return apiDefinition; } + private void addPreScript(MsHTTPSamplerProxy request, List event) { + if (CollectionUtils.isNotEmpty(event)) { + StringBuilder scriptStr = new StringBuilder(); + event = event.stream() + .filter(item -> item.getScript() != null) + .collect(Collectors.toList()); + event.forEach(item -> { + PostmanScript script = item.getScript(); + List exec = script.getExec(); + if (CollectionUtils.isNotEmpty(exec)) { + exec.forEach(col -> { + scriptStr.append(col + "/n"); + }); + } + }); + if (StringUtils.isNotBlank(scriptStr)) { + MsJSR223PreProcessor jsr223PreProcessor = new MsJSR223PreProcessor(); + jsr223PreProcessor.setScriptLanguage("javascript"); + jsr223PreProcessor.setScript(scriptStr.toString()); + LinkedList hashTree = new LinkedList<>(); + hashTree.add(jsr223PreProcessor); + request.setHashTree(hashTree); + } + } + } + private List parseKeyValue(List postmanKeyValues) { if (postmanKeyValues == null) { return null; diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java index e9c2a1f9c0..50a4671755 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -10,6 +10,7 @@ import io.metersphere.api.dto.datacount.ApiDataCountResult; import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; import io.metersphere.api.dto.definition.request.ScheduleInfoSwaggerUrlRequest; +import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.scenario.request.RequestType; import io.metersphere.api.dto.swaggerurl.SwaggerTaskResult; import io.metersphere.api.dto.swaggerurl.SwaggerUrlRequest; @@ -21,10 +22,7 @@ import io.metersphere.api.parse.ApiImportParserFactory; import io.metersphere.base.domain.*; import io.metersphere.base.mapper.*; import io.metersphere.base.mapper.ext.*; -import io.metersphere.commons.constants.APITestStatus; -import io.metersphere.commons.constants.ApiRunMode; -import io.metersphere.commons.constants.ScheduleGroup; -import io.metersphere.commons.constants.ScheduleType; +import io.metersphere.commons.constants.*; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.utils.*; import io.metersphere.i18n.Translator; @@ -300,7 +298,7 @@ public class ApiDefinitionService { } } - private ApiDefinition importCreate(ApiDefinitionResult request, ApiDefinitionMapper batchMapper, ApiTestImportRequest apiTestImportRequest) { + private ApiDefinition importCreate(ApiDefinitionResult request, ApiDefinitionMapper batchMapper, ApiTestCaseMapper apiTestCaseMapper, ApiTestImportRequest apiTestImportRequest) { SaveApiDefinitionRequest saveReq = new SaveApiDefinitionRequest(); BeanUtils.copyBean(saveReq, request); final ApiDefinitionWithBLOBs apiDefinition = new ApiDefinitionWithBLOBs(); @@ -317,30 +315,72 @@ public class ApiDefinitionService { List sameRequest = getSameRequest(saveReq); if (StringUtils.equals("fullCoverage", apiTestImportRequest.getModeId())) { - if (CollectionUtils.isEmpty(sameRequest)) { - batchMapper.insert(apiDefinition); - } else { - //如果存在则修改 - apiDefinition.setId(sameRequest.get(0).getId()); - apiDefinitionMapper.updateByPrimaryKeyWithBLOBs(apiDefinition); - } + _importCreate(sameRequest, batchMapper, apiDefinition, apiTestCaseMapper, apiTestImportRequest); } else if (StringUtils.equals("incrementalMerge", apiTestImportRequest.getModeId())) { if (CollectionUtils.isEmpty(sameRequest)) { + //postman 可能含有前置脚本,接口定义去掉脚本 + String requestStr = setImportHashTree(apiDefinition); batchMapper.insert(apiDefinition); + apiDefinition.setRequest(requestStr); + importApiCase(apiDefinition, apiTestCaseMapper, apiTestImportRequest, true); } } else { - if (CollectionUtils.isEmpty(sameRequest)) { - batchMapper.insert(apiDefinition); - } else { - //如果存在则修改 - apiDefinition.setId(sameRequest.get(0).getId()); - apiDefinitionMapper.updateByPrimaryKeyWithBLOBs(apiDefinition); - } + _importCreate(sameRequest, batchMapper, apiDefinition, apiTestCaseMapper, apiTestImportRequest); } - return apiDefinition; } + private void _importCreate(List sameRequest, ApiDefinitionMapper batchMapper, ApiDefinitionWithBLOBs apiDefinition, + ApiTestCaseMapper apiTestCaseMapper, ApiTestImportRequest apiTestImportRequest) { + if (CollectionUtils.isEmpty(sameRequest)) { + String request = setImportHashTree(apiDefinition); + batchMapper.insert(apiDefinition); + apiDefinition.setRequest(request); + importApiCase(apiDefinition, apiTestCaseMapper, apiTestImportRequest, true); + } else { + //如果存在则修改 + apiDefinition.setId(sameRequest.get(0).getId()); + String request = setImportHashTree(apiDefinition); + apiDefinitionMapper.updateByPrimaryKeyWithBLOBs(apiDefinition); + apiDefinition.setRequest(request); + importApiCase(apiDefinition, apiTestCaseMapper, apiTestImportRequest, false); + } + } + + private String setImportHashTree(ApiDefinitionWithBLOBs apiDefinition) { + String request = apiDefinition.getRequest(); + MsHTTPSamplerProxy msHTTPSamplerProxy = JSONObject.parseObject(request, MsHTTPSamplerProxy.class); + msHTTPSamplerProxy.setHashTree(null); + apiDefinition.setRequest(JSONObject.toJSONString(msHTTPSamplerProxy)); + return request; + } + + /** + * 导入是插件或者postman时创建用例 + * postman考虑是否有前置脚本 + */ + private void importApiCase(ApiDefinitionWithBLOBs apiDefinition, ApiTestCaseMapper apiTestCaseMapper, + ApiTestImportRequest apiTestImportRequest, Boolean isInsert) { + try { + if (StringUtils.equalsAnyIgnoreCase(apiTestImportRequest.getPlatform(), ApiImportPlatform.Plugin.name(), ApiImportPlatform.Postman.name())) { + ApiTestCaseWithBLOBs apiTestCase = new ApiTestCaseWithBLOBs(); + BeanUtils.copyBean(apiTestCase, apiDefinition); + apiTestCase.setId(UUID.randomUUID().toString()); + apiTestCase.setApiDefinitionId(apiDefinition.getId()); + apiTestCase.setCreateTime(System.currentTimeMillis()); + apiTestCase.setUpdateTime(System.currentTimeMillis()); + apiTestCase.setCreateUserId(SessionUtils.getUserId()); + apiTestCase.setUpdateUserId(SessionUtils.getUserId()); + apiTestCase.setPriority("P0"); + if (!isInsert) { + apiTestCase.setName(apiTestCase.getName() + "_" + apiTestCase.getId().substring(0, 5)); + } + apiTestCaseMapper.insert(apiTestCase); + } + } catch (Exception e) { + LogUtil.error("导入创建用例异常", e); + } + } private void deleteFileByTestId(String apiId) { ApiTestFileExample apiTestFileExample = new ApiTestFileExample(); @@ -457,6 +497,7 @@ public class ApiDefinitionService { private void importApi(ApiTestImportRequest request, ApiDefinitionImport apiImport) { SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); ApiDefinitionMapper batchMapper = sqlSession.getMapper(ApiDefinitionMapper.class); + ApiTestCaseMapper apiTestCaseMapper = sqlSession.getMapper(ApiTestCaseMapper.class); List data = apiImport.getData(); int num = 0; if (!CollectionUtils.isEmpty(data) && data.get(0) != null && data.get(0).getProjectId() != null) { @@ -468,7 +509,7 @@ public class ApiDefinitionService { item.setName(item.getName().substring(0, 255)); } item.setNum(num++); - importCreate(item, batchMapper, request); + importCreate(item, batchMapper, apiTestCaseMapper, request); if (i % 300 == 0) { sqlSession.flushStatements(); } diff --git a/backend/src/main/java/io/metersphere/commons/constants/ApiImportPlatform.java b/backend/src/main/java/io/metersphere/commons/constants/ApiImportPlatform.java index a417f3913a..ae9d45396f 100644 --- a/backend/src/main/java/io/metersphere/commons/constants/ApiImportPlatform.java +++ b/backend/src/main/java/io/metersphere/commons/constants/ApiImportPlatform.java @@ -1,5 +1,5 @@ package io.metersphere.commons.constants; public enum ApiImportPlatform { - Metersphere, Postman, Swagger2 + Metersphere, Postman, Swagger2, Plugin } diff --git a/frontend/src/business/components/api/automation/scenario/common/ApiBaseComponent.vue b/frontend/src/business/components/api/automation/scenario/common/ApiBaseComponent.vue index 6b15f37c90..d2a439c0f7 100644 --- a/frontend/src/business/components/api/automation/scenario/common/ApiBaseComponent.vue +++ b/frontend/src/business/components/api/automation/scenario/common/ApiBaseComponent.vue @@ -37,6 +37,7 @@ +
diff --git a/frontend/src/business/components/api/definition/components/list/ApiCaseSimpleList.vue b/frontend/src/business/components/api/definition/components/list/ApiCaseSimpleList.vue index 6a4c72a57b..b0142763ab 100644 --- a/frontend/src/business/components/api/definition/components/list/ApiCaseSimpleList.vue +++ b/frontend/src/business/components/api/definition/components/list/ApiCaseSimpleList.vue @@ -31,19 +31,21 @@ - + - + +