From 4c32efb643a2ef96131accbf132d54b3a6ad0cb0 Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Mon, 1 Feb 2021 10:58:26 +0800 Subject: [PATCH 1/4] =?UTF-8?q?refactor:=20postman=E5=92=8C=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E5=AF=BC=E5=85=A5=E8=87=AA=E5=8A=A8=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/dto/parse/postman/PostmanEvent.java | 8 ++ .../api/dto/parse/postman/PostmanItem.java | 1 + .../api/dto/parse/postman/PostmanScript.java | 11 +++ .../io/metersphere/api/parse/MsParser.java | 2 + .../metersphere/api/parse/PostmanParser.java | 32 +++++++ .../api/service/ApiDefinitionService.java | 83 ++++++++++++++----- .../commons/constants/ApiImportPlatform.java | 2 +- 7 files changed, 117 insertions(+), 22 deletions(-) create mode 100644 backend/src/main/java/io/metersphere/api/dto/parse/postman/PostmanEvent.java create mode 100644 backend/src/main/java/io/metersphere/api/dto/parse/postman/PostmanScript.java 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/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 } From b02b1727ff344136677cda8e2d4930484f24617d Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Mon, 1 Feb 2021 11:57:02 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/automation/scenario/common/ApiBaseComponent.vue | 1 + 1 file changed, 1 insertion(+) 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 @@ +
From 5d167e10d5e88583093dd354970b53e81bcbcbcd Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Mon, 1 Feb 2021 13:40:57 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20query=E5=8F=82=E6=95=B0=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E4=BC=A0=E7=A9=BA=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/sampler/MsHTTPSamplerProxy.java | 12 ++++++++---- .../io/metersphere/api/dto/scenario/KeyValue.java | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) 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/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() { From 9752736e3a92d7bff1b4d99cf8dd1f78a5b7509d Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Mon, 1 Feb 2021 13:58:49 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=9B=BE=E7=89=87=E4=BD=8D=E7=BD=AE=E5=92=8C?= =?UTF-8?q?=E6=98=BE=E7=A4=BAtitle=E4=B8=8D=E5=AF=B9=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/business/components/xpack | 2 +- frontend/src/i18n/en-US.js | 4 ++-- frontend/src/i18n/zh-CN.js | 4 ++-- frontend/src/i18n/zh-TW.js | 4 ++-- frontend/src/login/Login.vue | 7 ++++--- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/frontend/src/business/components/xpack b/frontend/src/business/components/xpack index 53bd821bee..a3d469fd18 160000 --- a/frontend/src/business/components/xpack +++ b/frontend/src/business/components/xpack @@ -1 +1 @@ -Subproject commit 53bd821bee65be3374f1ccc9a299cef9ac44b985 +Subproject commit a3d469fd18f663d11e5c1c49f71ced6e3e4b292f diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index b57556fa94..3776b3b2ad 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -208,8 +208,8 @@ export default { display: { title: 'Theme', logo: 'System LOGO', - loginLogo: 'Picture on the right side of the login page', - loginImage: 'Login page upper left corner LOGO', + loginLogo: 'Login page upper left corner LOGO', + loginImage: 'Picture on the right side of the login page', loginTitle: 'Login page prompt information', pageTitle: 'Page Title', }, diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index 01c88a49b7..141ed507cd 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -209,8 +209,8 @@ export default { display: { title: '显示设置', logo: '系统 LOGO', - loginLogo: '登陆页面右侧图片', - loginImage: '登录页左上角 LOGO', + loginLogo: '登录页左上角 LOGO', + loginImage: '登陆页面右侧图片', loginTitle: '登陆页面提示信息', pageTitle: '页面 Title', }, diff --git a/frontend/src/i18n/zh-TW.js b/frontend/src/i18n/zh-TW.js index 6d81c01325..a109cf7d15 100644 --- a/frontend/src/i18n/zh-TW.js +++ b/frontend/src/i18n/zh-TW.js @@ -209,8 +209,8 @@ export default { display: { title: '顯示設置', logo: '系統 LOGO', - loginLogo: '登陸頁面右側圖片', - loginImage: '登錄頁左上角 LOGO', + loginLogo: '登錄頁左上角 LOGO', + loginImage: '登陸頁面右側圖片', loginTitle: '登陸頁面提示信息', pageTitle: '頁面 Title', }, diff --git a/frontend/src/login/Login.vue b/frontend/src/login/Login.vue index 73a287cc60..6dec041ed8 100644 --- a/frontend/src/login/Login.vue +++ b/frontend/src/login/Login.vue @@ -8,7 +8,7 @@
- {{ $t('commons.welcome') }} + {{ loginTitle }}
@@ -46,7 +46,7 @@
- + @@ -85,7 +85,7 @@ export default { msg: '', ready: false, openLdap: false, - loginTitle: this.$t("commons.login") + " MeterSphere", + loginTitle: this.$t("commons.welcome"), authSources: [], loginUrl: 'signin', } @@ -200,6 +200,7 @@ export default { .title img { width: 293px; + max-height: 60px; margin-top: 165px; }