diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImport.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImport.java index b1f3ddba8d..a92d0d1bf8 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImport.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImport.java @@ -2,6 +2,7 @@ package io.metersphere.api.dto.definition.parse; import io.metersphere.api.dto.definition.request.MsScenario; import io.metersphere.base.domain.ApiDefinitionWithBLOBs; +import io.metersphere.base.domain.ApiScenarioWithBLOBs; import io.metersphere.base.domain.ApiTestCaseWithBLOBs; import lombok.Data; @@ -15,6 +16,7 @@ public class ApiDefinitionImport { //导入场景 private MsScenario scenarioDefinition; + private List scenarioDefinitionData; // 新版本带用例导出 private List cases; diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java index 3686898bde..6f56557fa4 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java @@ -20,6 +20,8 @@ import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.jmeter.config.Arguments; +import org.apache.jmeter.protocol.http.control.Header; +import org.apache.jmeter.protocol.http.control.HeaderManager; import org.apache.jmeter.save.SaveService; import org.apache.jmeter.testelement.TestElement; import org.apache.jorphan.collections.HashTree; @@ -100,6 +102,9 @@ public class MsScenario extends MsTestElement { el.toHashTree(tree, el.getHashTree(), config); } } + if (CollectionUtils.isNotEmpty(this.headers)) { + setHeader(tree, this.headers); + } } public void setOldVariables(List oldVariables) { @@ -109,6 +114,20 @@ public class MsScenario extends MsTestElement { } } + public void setHeader(HashTree tree, List headers) { + if (CollectionUtils.isNotEmpty(headers)) { + HeaderManager headerManager = new HeaderManager(); + headerManager.setEnabled(true); + headerManager.setName(this.getName() + "场景Headers"); + headerManager.setProperty(TestElement.TEST_CLASS, HeaderManager.class.getName()); + headerManager.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("HeaderPanel")); + headers.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> + headerManager.add(new Header(keyValue.getName(), keyValue.getValue())) + ); + tree.add(headerManager); + } + } + private Arguments arguments(ParameterConfig config) { Arguments arguments = new Arguments(); arguments.setEnabled(true); @@ -134,11 +153,6 @@ public class MsScenario extends MsTestElement { arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") ); } - if (CollectionUtils.isNotEmpty(this.headers)) { - this.headers.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> - arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") - ); - } return arguments; } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsLoopController.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsLoopController.java index b22949ed2a..350db02e11 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsLoopController.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsLoopController.java @@ -102,7 +102,7 @@ public class MsLoopController extends MsTestElement { return counterConfig; } - private LoopController loopController() { + private LoopController initLoopController() { LoopController loopController = new LoopController(); loopController.setEnabled(true); loopController.setName("LoopController"); @@ -113,7 +113,7 @@ public class MsLoopController extends MsTestElement { return loopController; } - public String getCondition() { + private String getCondition() { String variable = "\"" + this.whileController.getVariable() + "\""; String operator = this.whileController.getOperator(); String value = "\"" + this.whileController.getValue() + "\""; @@ -136,7 +136,7 @@ public class MsLoopController extends MsTestElement { return "${__jexl3(" + variable + operator + value + ")}"; } - private WhileController whileController() { + private WhileController initWhileController() { String condition = getCondition(); if (StringUtils.isEmpty(condition)) { return null; @@ -150,7 +150,7 @@ public class MsLoopController extends MsTestElement { return controller; } - private ForeachController foreachController() { + private ForeachController initForeachController() { ForeachController controller = new ForeachController(); controller.setEnabled(true); controller.setName("ForeachController"); @@ -175,13 +175,13 @@ public class MsLoopController extends MsTestElement { runTime.setRuntime(timeout); // 添加超时处理,防止死循环 HashTree hashTree = tree.add(runTime); - return hashTree.add(whileController()); + return hashTree.add(initWhileController()); } if (StringUtils.equals(this.loopType, LoopConstants.FOREACH.name()) && this.forEachController != null) { - return tree.add(foreachController()); + return tree.add(initForeachController()); } if (StringUtils.equals(this.loopType, LoopConstants.LOOP_COUNT.name()) && this.countController != null) { - return tree.add(loopController()); + return tree.add(initLoopController()); } return null; } 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 7b939a84af..e8b69e112c 100644 --- a/backend/src/main/java/io/metersphere/api/parse/MsParser.java +++ b/backend/src/main/java/io/metersphere/api/parse/MsParser.java @@ -39,7 +39,7 @@ public class MsParser extends ApiImportAbstractParser { return parseMsFormat(testStr, request); } else { request.setPlatform(ApiImportPlatform.Plugin.name()); - return parsePluginFormat(testObject, request); + return parsePluginFormat(testObject, request, true); } } @@ -65,17 +65,20 @@ public class MsParser extends ApiImportAbstractParser { apiDefinition.setRequest(JSONObject.toJSONString(requestObj)); } - private ApiDefinitionImport parsePluginFormat(JSONObject testObject, ApiTestImportRequest importRequest) { + protected ApiDefinitionImport parsePluginFormat(JSONObject testObject, ApiTestImportRequest importRequest, Boolean isCreateModule) { List results = new ArrayList<>(); ApiDefinitionImport apiImport = new ApiDefinitionImport(); apiImport.setProtocol(RequestType.HTTP); apiImport.setData(results); testObject.keySet().forEach(tag -> { - ApiModule parentModule = getSelectModule(importRequest.getModuleId()); - ApiModule module = buildModule(parentModule, tag); - + ApiModule module = null; + if (isCreateModule) { + module = buildModule(getSelectModule(importRequest.getModuleId()), tag); + } JSONObject requests = testObject.getJSONObject(tag); + String moduleId = module.getId(); + requests.keySet().forEach(requestName -> { JSONObject requestObject = requests.getJSONObject(requestName); @@ -84,7 +87,7 @@ public class MsParser extends ApiImportAbstractParser { MsHTTPSamplerProxy request = buildRequest(requestName, path, method); ApiDefinitionWithBLOBs apiDefinition = buildApiDefinition(request.getId(), requestName, path, method,importRequest); - apiDefinition.setModuleId(module.getId()); + apiDefinition.setModuleId(moduleId); apiDefinition.setProjectId(this.projectId); parseBody(requestObject, request.getBody()); parseHeader(requestObject, request.getHeaders()); diff --git a/backend/src/main/java/io/metersphere/api/parse/ScenarioMsParser.java b/backend/src/main/java/io/metersphere/api/parse/ScenarioMsParser.java new file mode 100644 index 0000000000..29a6f4c244 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/parse/ScenarioMsParser.java @@ -0,0 +1,71 @@ +package io.metersphere.api.parse; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.parser.Feature; +import io.metersphere.api.dto.ApiTestImportRequest; +import io.metersphere.api.dto.automation.ApiScenrioExportResult; +import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; +import io.metersphere.api.dto.definition.request.MsScenario; +import io.metersphere.api.dto.definition.request.MsTestElement; +import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; +import io.metersphere.api.service.ApiModuleService; +import io.metersphere.base.domain.ApiScenarioWithBLOBs; +import io.metersphere.commons.constants.ApiImportPlatform; +import io.metersphere.commons.utils.CommonBeanFactory; +import org.apache.commons.lang3.StringUtils; + +import java.io.InputStream; +import java.util.LinkedList; +import java.util.UUID; + +public class ScenarioMsParser extends MsParser { + + @Override + public ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request) { + String testStr = getApiTestStr(source); + JSONObject testObject = JSONObject.parseObject(testStr, Feature.OrderedField); + apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); + this.projectId = request.getProjectId(); + if (testObject.get("projectId") != null) { + return parseMsFormat(testStr, request); + } else { + request.setPlatform(ApiImportPlatform.Plugin.name()); + ApiDefinitionImport apiDefinitionImport = parsePluginFormat(testObject, request, false); + MsScenario msScenario = new MsScenario(); + LinkedList msHTTPSamplerProxies = new LinkedList<>(); + apiDefinitionImport.getData().forEach(res -> { + msHTTPSamplerProxies.add(JSONObject.parseObject(res.getRequest(), MsHTTPSamplerProxy.class)); + }); + msScenario.setHashTree(msHTTPSamplerProxies); + msScenario.setType("scenario"); + msScenario.setName("test"); + apiDefinitionImport.setScenarioDefinition(msScenario); + return apiDefinitionImport; + } + } + + private ApiDefinitionImport parseMsFormat(String testStr, ApiTestImportRequest importRequest) { + ApiScenrioExportResult apiScenrioExportResult = JSON.parseObject(testStr, ApiScenrioExportResult.class); + apiScenrioExportResult.getData().forEach(scenario -> { + parseApiDefinition(scenario, importRequest); + }); + ApiDefinitionImport apiDefinitionImport = new ApiDefinitionImport(); + apiDefinitionImport.setScenarioDefinitionData(apiScenrioExportResult.getData()); + return apiDefinitionImport; + } + + private void parseApiDefinition(ApiScenarioWithBLOBs scenario, ApiTestImportRequest importRequest) { + String id = UUID.randomUUID().toString(); + if (StringUtils.isBlank(scenario.getModulePath())) { + scenario.setApiScenarioModuleId(null); + } +// parseModule(scenario, importRequest); + scenario.setId(id); + scenario.setProjectId(this.projectId); + String scenarioDefinition = scenario.getScenarioDefinition(); + JSONObject scenarioDefinitionObj = JSONObject.parseObject(scenarioDefinition); + scenarioDefinitionObj.put("id", id); + scenario.setScenarioDefinition(JSONObject.toJSONString(scenarioDefinitionObj)); + } +} diff --git a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java index 1f7f2d26c2..a82f7baa79 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -10,7 +10,6 @@ import io.metersphere.api.dto.DeleteAPIReportRequest; import io.metersphere.api.dto.JmxInfoDTO; import io.metersphere.api.dto.automation.*; import io.metersphere.api.dto.datacount.ApiDataCountResult; -import io.metersphere.api.dto.definition.ApiExportResult; import io.metersphere.api.dto.definition.RunDefinitionRequest; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; import io.metersphere.api.dto.definition.request.*; 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 2a89c74dad..6e1577576e 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -44,7 +44,7 @@ import org.springframework.web.multipart.MultipartFile; import sun.security.util.Cache; import javax.annotation.Resource; -import java.io.*; +import java.io.File; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; diff --git a/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java b/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java index 7fe11b1bca..ea4e2d8074 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java @@ -29,6 +29,7 @@ import io.metersphere.service.FileService; import io.metersphere.service.QuotaService; import io.metersphere.service.UserService; import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.SqlSession; @@ -38,11 +39,10 @@ import org.apache.jorphan.collections.ListedHashTree; import org.aspectj.util.FileUtil; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.apache.commons.collections.CollectionUtils; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; -import java.io.*; +import java.io.File; import java.util.*; import java.util.stream.Collectors; diff --git a/backend/src/main/java/io/metersphere/track/service/TestCaseNodeService.java b/backend/src/main/java/io/metersphere/track/service/TestCaseNodeService.java index e8058ea0f8..6322147321 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestCaseNodeService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestCaseNodeService.java @@ -407,6 +407,10 @@ public class TestCaseNodeService extends NodeTreeService { TestCaseNodeDTO nodeTree = request.getNodeTree(); + if (nodeTree == null) { + return; + } + List updateNodes = new ArrayList<>(); buildUpdateTestCase(nodeTree, testCases, updateNodes, "/", "0", 1); diff --git a/backend/src/main/java/io/metersphere/xmind/XmindCaseParser.java b/backend/src/main/java/io/metersphere/xmind/XmindCaseParser.java index a2e5645e8c..8829d61ba0 100644 --- a/backend/src/main/java/io/metersphere/xmind/XmindCaseParser.java +++ b/backend/src/main/java/io/metersphere/xmind/XmindCaseParser.java @@ -276,22 +276,19 @@ public class XmindCaseParser { testCase.setType("functional"); String tc = title.replace(":", ":"); - String[] tcArr = tc.split(":"); - if (tcArr.length < 1) { + String[] tcArrs = tc.split(":"); + if (tcArrs.length < 1) { process.add(Translator.get("test_case_name") + Translator.get("incorrect_format"), title); return; } // 用例名称 - StringBuffer name = new StringBuffer(); - for (int i = 1; i < tcArr.length; i++) { - name.append(tcArr[i]); - } - testCase.setName(name.toString()); + String name = title.replace(tcArrs[0] + ":", "").replace(tcArrs[0] + ":", ""); + testCase.setName(name); testCase.setNodePath(nodePath); // 用例等级和用例性质处理 - if (tcArr[0].indexOf("-") != -1) { - for (String item : tcArr[0].split("-")) { + if (tcArrs[0].indexOf("-") != -1) { + for (String item : tcArrs[0].split("-")) { if (isAvailable(item, TC_REGEX)) { continue; } else if (item.toUpperCase().startsWith("P")) { diff --git a/backend/src/main/resources/db/migration/V74__modify_schedule_message_task.sql b/backend/src/main/resources/db/migration/V74__modify_schedule_message_task.sql index 0acb8fc2cd..695c6b2f11 100644 --- a/backend/src/main/resources/db/migration/V74__modify_schedule_message_task.sql +++ b/backend/src/main/resources/db/migration/V74__modify_schedule_message_task.sql @@ -1,4 +1,4 @@ ALTER TABLE schedule - MODIFY COLUMN id VARCHAR(255); + MODIFY COLUMN id VARCHAR (255); ALTER TABLE message_task - MODIFY COLUMN id VARCHAR(255); + MODIFY COLUMN id VARCHAR (255); diff --git a/backend/src/main/resources/db/migration/V75__modify_schedule_message_task_test_id.sql b/backend/src/main/resources/db/migration/V75__modify_schedule_message_task_test_id.sql index eaa6402348..b1092b7e3f 100644 --- a/backend/src/main/resources/db/migration/V75__modify_schedule_message_task_test_id.sql +++ b/backend/src/main/resources/db/migration/V75__modify_schedule_message_task_test_id.sql @@ -1,4 +1,4 @@ ALTER TABLE schedule - MODIFY COLUMN resource_id VARCHAR(255); + MODIFY COLUMN resource_id VARCHAR (255); ALTER TABLE message_task - MODIFY COLUMN test_id VARCHAR(255); + MODIFY COLUMN test_id VARCHAR (255); diff --git a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue index cfc4671a5e..d769d6c275 100644 --- a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue +++ b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue @@ -106,7 +106,7 @@ {{$t('api_test.automation.scenario_total')}} - :{{getVariableSize()}} + :{{ getVariableSize() }} 共享cookie @@ -204,37 +204,44 @@ diff --git a/frontend/src/business/components/api/definition/components/assertion/ApiAssertions.vue b/frontend/src/business/components/api/definition/components/assertion/ApiAssertions.vue index d825f5cb74..3bf78dbd8c 100644 --- a/frontend/src/business/components/api/definition/components/assertion/ApiAssertions.vue +++ b/frontend/src/business/components/api/definition/components/assertion/ApiAssertions.vue @@ -52,31 +52,31 @@