diff --git a/README.md b/README.md index 23dccbda7d..11ca993285 100755 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ > [English](README-EN.md) | 中文 -| Developer Wanted | +| 下载持续测试白皮书 | | ------------------------------------------------------------------------------------------------------------ | -| 我们正在寻找开发者,欢迎加入我们共同打造更好用、更强大的 MeterSphere。联系我们: [metersphere@fit2cloud.com](mailto:metersphere@fit2cloud.com) | +| 《持续测试白皮书 v1.0》由“软件质量报道”公众号和MeterSphere开源项目组共同编写而成。采用贴近企业实践的视角进行组织,编写团队结合自身对软件测试发展历程以及持续测试理念的理解,并积极听取行业内其他专家理念,在此基础上编写而成。全文从持续测试产生的背景和价值、企业如何实践持续测试以及持续测试成熟度模型这三个方面展开,分别介绍了持续测试产生的原因、持续测试落地的关键要素和持续测试成熟度模型的构成、评判等方面内容。下载链接: [https://jinshuju.net/f/KqFUhq](https://jinshuju.net/f/KqFUhq) | MeterSphere 是一站式开源持续测试平台,涵盖测试跟踪、接口测试、性能测试、团队协作等功能,兼容JMeter 等开源标准,有效助力开发和测试团队充分利用云弹性进行高度可扩展的自动化测试,加速高质量软件的交付。 diff --git a/backend/pom.xml b/backend/pom.xml index 3bae3d6a29..74617336e4 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -212,7 +212,7 @@ org.apache.zookeeper zookeeper - 3.4.13 + 3.4.14 org.apache.curator @@ -341,6 +341,11 @@ jaxen 1.2.0 + + net.sourceforge.htmlcleaner + htmlcleaner + 2.24 + org.json diff --git a/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenarioRequest.java b/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenarioRequest.java index 2eb30e0f64..12b85d5a13 100644 --- a/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenarioRequest.java +++ b/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenarioRequest.java @@ -21,7 +21,7 @@ public class ApiScenarioRequest { private String planId; private boolean recent = false; private List orders; - private List filters; + private Map> filters; private Map combine; private List ids; private boolean isSelectThisWeedData; diff --git a/backend/src/main/java/io/metersphere/api/dto/automation/RunScenarioRequest.java b/backend/src/main/java/io/metersphere/api/dto/automation/RunScenarioRequest.java index 83aff1371a..217787ffe0 100644 --- a/backend/src/main/java/io/metersphere/api/dto/automation/RunScenarioRequest.java +++ b/backend/src/main/java/io/metersphere/api/dto/automation/RunScenarioRequest.java @@ -45,7 +45,7 @@ public class RunScenarioRequest { */ private boolean isSelectAllDate; - private List filters; + private Map> filters; private String name; diff --git a/backend/src/main/java/io/metersphere/api/dto/automation/SaveApiPlanRequest.java b/backend/src/main/java/io/metersphere/api/dto/automation/SaveApiPlanRequest.java index 44fc3d8e17..516efd56e8 100644 --- a/backend/src/main/java/io/metersphere/api/dto/automation/SaveApiPlanRequest.java +++ b/backend/src/main/java/io/metersphere/api/dto/automation/SaveApiPlanRequest.java @@ -4,6 +4,7 @@ import lombok.Getter; import lombok.Setter; import java.util.List; +import java.util.Map; @Getter @Setter @@ -23,7 +24,7 @@ public class SaveApiPlanRequest { */ private boolean isSelectAllDate; - private List filters; + private Map> filters; private String name; diff --git a/backend/src/main/java/io/metersphere/api/dto/automation/SaveApiScenarioRequest.java b/backend/src/main/java/io/metersphere/api/dto/automation/SaveApiScenarioRequest.java index 1f73ee1804..bdfa94144b 100644 --- a/backend/src/main/java/io/metersphere/api/dto/automation/SaveApiScenarioRequest.java +++ b/backend/src/main/java/io/metersphere/api/dto/automation/SaveApiScenarioRequest.java @@ -5,6 +5,7 @@ import lombok.Getter; import lombok.Setter; import java.util.List; +import java.util.Map; @Setter @Getter @@ -47,7 +48,7 @@ public class SaveApiScenarioRequest { private boolean isSelectAllDate; - private List filters; + private Map> filters; private List moduleIds; 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 d6b73cc520..54ac08e65a 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 @@ -60,7 +60,7 @@ public class MsScenario extends MsTestElement { return; } config.setStep(this.name); - + config.setStepType("SCENARIO"); config.setEnableCookieShare(enableCookieShare); if (StringUtils.isNotEmpty(environmentId)) { ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class); @@ -121,6 +121,14 @@ public class MsScenario extends MsTestElement { variables.stream().filter(ScenarioVariable::isConstantValid).forEach(keyValue -> arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") ); + + List variableList = variables.stream().filter(ScenarioVariable::isListValid).collect(Collectors.toList()); + variableList.forEach(item -> { + String[] arrays = item.getValue().split(","); + for (int i = 0; i < arrays.length; i++) { + arguments.addArgument(item.getName() + "_" + (i + 1), arrays[i], "="); + } + }); } if (config != null && config.getConfig() != null && config.getConfig().getCommonConfig() != null && CollectionUtils.isNotEmpty(config.getConfig().getCommonConfig().getVariables())) { diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/ParameterConfig.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/ParameterConfig.java index 6f75a54fb6..345d80efcd 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/ParameterConfig.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/ParameterConfig.java @@ -17,6 +17,6 @@ public class ParameterConfig { // 步骤 private String step; - private final String stepType = "STEP_GROUP"; + private String stepType; } 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 14acd921f6..c2c38fa3b3 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 @@ -12,7 +12,11 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.jmeter.control.*; +import org.apache.jmeter.control.ForeachController; +import org.apache.jmeter.control.LoopController; +import org.apache.jmeter.control.RunTime; +import org.apache.jmeter.control.WhileController; +import org.apache.jmeter.modifiers.CounterConfig; import org.apache.jmeter.reporters.ResultAction; import org.apache.jmeter.save.SaveService; import org.apache.jmeter.testelement.TestElement; @@ -43,8 +47,21 @@ public class MsLoopController extends MsTestElement { if (!this.isEnable()) { return; } - final HashTree groupTree = controller(tree); + if (StringUtils.equals(this.loopType, LoopConstants.WHILE.name()) && this.whileController != null) { + config.setStep("While 循环"); + } + if (StringUtils.equals(this.loopType, LoopConstants.FOREACH.name()) && this.forEachController != null) { + config.setStep("ForEach 循环"); + } + if (StringUtils.equals(this.loopType, LoopConstants.LOOP_COUNT.name()) && this.countController != null) { + config.setStep("次数循环"); + } + config.setStepType("LOOP"); + + final HashTree groupTree = controller(tree); + // 循环下都增加一个计数器,用于结果统计 + groupTree.add(addCounterConfig()); // 不打开执行成功后轮询功能,则成功后就停止循环 if (StringUtils.equals(this.loopType, LoopConstants.LOOP_COUNT.name()) && this.countController != null && !countController.isProceed()) { ResultAction resultAction = new ResultAction(); @@ -65,6 +82,18 @@ public class MsLoopController extends MsTestElement { } } + private CounterConfig addCounterConfig() { + CounterConfig counterConfig = new CounterConfig(); + counterConfig.setVarName("LoopCounterConfigXXX"); + counterConfig.setName("LoopCounterConfigXXX"); + counterConfig.setEnabled(true); + counterConfig.setProperty(TestElement.TEST_CLASS, CounterConfig.class.getName()); + counterConfig.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("CounterConfigGui")); + counterConfig.setStart(1L); + counterConfig.setIncrement(1L); + return counterConfig; + } + private LoopController loopController() { LoopController loopController = new LoopController(); loopController.setEnabled(true); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/loop/CountController.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/loop/CountController.java index 808b67cc9e..c55db9540d 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/loop/CountController.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/loop/CountController.java @@ -7,4 +7,6 @@ public class CountController { private int loops; private int interval; private boolean proceed; + private Object requestResult; + } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/loop/MsForEachController.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/loop/MsForEachController.java index 30a4a59e7f..8e97a204f2 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/loop/MsForEachController.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/loop/MsForEachController.java @@ -7,4 +7,6 @@ public class MsForEachController { private String inputVal; private String returnVal; private String interval; + private Object requestResult; + } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/loop/MsWhileController.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/loop/MsWhileController.java index 7781abbb0b..4ed9a8cc67 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/loop/MsWhileController.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/loop/MsWhileController.java @@ -8,4 +8,5 @@ public class MsWhileController { private String operator; private String value; private int timeout; + private Object requestResult; } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/MsJSR223Processor.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/MsJSR223Processor.java index d83998137f..af9da5e11f 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/MsJSR223Processor.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/MsJSR223Processor.java @@ -40,7 +40,11 @@ public class MsJSR223Processor extends MsTestElement { processor.setName("JSR223Processor"); } if (config != null && StringUtils.isNotEmpty(config.getStep())) { - processor.setName(this.getName() + "<->" + config.getStep()); + if ("SCENARIO".equals(config.getStepType())) { + processor.setName(this.getName() + "<->" + config.getStep()); + } else { + processor.setName(this.getName() + "<->" + config.getStep() + "-" + "${LoopCounterConfigXXX}"); + } } processor.setProperty(TestElement.TEST_CLASS, JSR223Sampler.class.getName()); processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI")); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java index d59d5fff20..df146c68c6 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java @@ -78,7 +78,11 @@ public class MsDubboSampler extends MsTestElement { DubboSample sampler = new DubboSample(); sampler.setName(this.getName()); if (config != null && StringUtils.isNotEmpty(config.getStep())) { - sampler.setName(this.getName() + "<->" + config.getStep()); + if ("SCENARIO".equals(config.getStepType())) { + sampler.setName(this.getName() + "<->" + config.getStep()); + } else { + sampler.setName(this.getName() + "<->" + config.getStep() + "-" + "${LoopCounterConfigXXX}"); + } } sampler.setProperty(TestElement.TEST_CLASS, DubboSample.class.getName()); sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("DubboSampleGui")); 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 65d1031b47..6611ae1462 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 @@ -97,7 +97,11 @@ public class MsHTTPSamplerProxy extends MsTestElement { sampler.setEnabled(true); sampler.setName(this.getName()); if (config != null && StringUtils.isNotEmpty(config.getStep())) { - sampler.setName(this.getName() + "<->" + config.getStep()); + if ("SCENARIO".equals(config.getStepType())) { + sampler.setName(this.getName() + "<->" + config.getStep()); + } else { + sampler.setName(this.getName() + "<->" + config.getStep() + "-" + "${LoopCounterConfigXXX}"); + } } sampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName()); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsJDBCSampler.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsJDBCSampler.java index bb253cad2d..a918fd4589 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsJDBCSampler.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsJDBCSampler.java @@ -50,6 +50,8 @@ public class MsJDBCSampler extends MsTestElement { private Object requestResult; @JSONField(ordinal = 28) private String dataSourceId; + @JSONField(ordinal = 29) + private String protocol="SQL"; @Override public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { @@ -107,7 +109,11 @@ public class MsJDBCSampler extends MsTestElement { JDBCSampler sampler = new JDBCSampler(); sampler.setName(this.getName()); if (config != null && StringUtils.isNotEmpty(config.getStep())) { - sampler.setName(this.getName() + "<->" + config.getStep()); + if ("SCENARIO".equals(config.getStepType())) { + sampler.setName(this.getName() + "<->" + config.getStep()); + } else { + sampler.setName(this.getName() + "<->" + config.getStep() + "-" + "${LoopCounterConfigXXX}"); + } } sampler.setProperty(TestElement.TEST_CLASS, JDBCSampler.class.getName()); sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI")); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsTCPSampler.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsTCPSampler.java index d2d10d6f28..4131860918 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsTCPSampler.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsTCPSampler.java @@ -65,6 +65,8 @@ public class MsTCPSampler extends MsTestElement { private String useEnvironment; @JSONField(ordinal = 37) private MsJSR223PreProcessor tcpPreProcessor; + @JSONField(ordinal = 38) + private String protocol = "TCP"; @Override public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { @@ -99,7 +101,11 @@ public class MsTCPSampler extends MsTestElement { TCPSampler tcpSampler = new TCPSampler(); tcpSampler.setName(this.getName()); if (config != null && StringUtils.isNotEmpty(config.getStep())) { - tcpSampler.setName(this.getName() + "<->" + config.getStep()); + if ("SCENARIO".equals(config.getStepType())) { + tcpSampler.setName(this.getName() + "<->" + config.getStep()); + } else { + tcpSampler.setName(this.getName() + "<->" + config.getStep() + "-" + "${LoopCounterConfigXXX}"); + } } tcpSampler.setProperty(TestElement.TEST_CLASS, TCPSampler.class.getName()); @@ -128,10 +134,12 @@ public class MsTCPSampler extends MsTestElement { userParameters.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("UserParametersGui")); List names = new ArrayList<>(); List threadValues = new ArrayList<>(); - this.parameters.forEach(item -> { - names.add(new StringProperty(new Integer(new Random().nextInt(1000000)).toString(), item.getName())); - threadValues.add(new StringProperty(new Integer(new Random().nextInt(1000000)).toString(), item.getValue())); - }); + if (CollectionUtils.isNotEmpty(this.parameters)) { + this.parameters.forEach(item -> { + names.add(new StringProperty(new Integer(new Random().nextInt(1000000)).toString(), item.getName())); + threadValues.add(new StringProperty(new Integer(new Random().nextInt(1000000)).toString(), item.getValue())); + }); + } userParameters.setNames(new CollectionProperty(UserParameters.NAMES, names)); List collectionPropertyList = new ArrayList<>(); collectionPropertyList.add(new CollectionProperty(new Integer(new Random().nextInt(1000000)).toString(), threadValues)); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/variable/ScenarioVariable.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/variable/ScenarioVariable.java index b255aa8457..417711dfa2 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/variable/ScenarioVariable.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/variable/ScenarioVariable.java @@ -41,8 +41,7 @@ public class ScenarioVariable { private String maxNumber; public boolean isConstantValid() { - if ((StringUtils.equals(this.type, VariableTypeConstants.CONSTANT.name()) - || StringUtils.equals(this.type, VariableTypeConstants.LIST.name())) && StringUtils.isNotEmpty(name) && StringUtils.isNotEmpty(value)) { + if (StringUtils.equals(this.type, VariableTypeConstants.CONSTANT.name()) && StringUtils.isNotEmpty(name) && StringUtils.isNotEmpty(value)) { return true; } return false; @@ -55,6 +54,13 @@ public class ScenarioVariable { return false; } + public boolean isListValid() { + if (StringUtils.equals(this.type, VariableTypeConstants.LIST.name()) && StringUtils.isNotEmpty(name) && StringUtils.isNotEmpty(value) && value.indexOf(",") != -1) { + return true; + } + return false; + } + public boolean isCounterValid() { if (StringUtils.equals(this.type, VariableTypeConstants.COUNTER.name()) && StringUtils.isNotEmpty(name)) { return true; diff --git a/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java b/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java index 7fec48540f..9d9087dafb 100644 --- a/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java +++ b/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java @@ -126,6 +126,34 @@ public abstract class ApiImportAbstractParser implements ApiImportParser { } protected ApiDefinitionResult buildApiDefinition(String id, String name, String path, String method,ApiTestImportRequest importRequest) { + protected void addBodyHeader(MsHTTPSamplerProxy request) { + String contentType = ""; + if (request.getBody() != null && StringUtils.isNotBlank(request.getBody().getType())) { + switch (request.getBody().getType()) { + case Body.WWW_FROM: + contentType = "application/x-www-form-urlencoded"; + break; + case Body.JSON: + contentType = "application/json"; + break; + case Body.XML: + contentType = "application/xml"; + break; + case Body.BINARY: + contentType = "application/octet-stream"; + break; + } + List headers = request.getHeaders(); + if (headers == null) { + headers = new ArrayList<>(); + request.setHeaders(headers); + } + addContentType(request.getHeaders(), contentType); + + } + } + + protected ApiDefinitionResult buildApiDefinition(String id, String name, String path, String method) { ApiDefinitionResult apiDefinition = new ApiDefinitionResult(); apiDefinition.setName(name); apiDefinition.setPath(formatPath(path)); @@ -172,8 +200,8 @@ public abstract class ApiImportAbstractParser implements ApiImportParser { return request; } - protected void addContentType(HttpRequest request, String contentType) { -// addHeader(request, "Content-Type", contentType); + protected void addContentType(List headers, String contentType) { + addHeader(headers, "Content-Type", contentType); } protected void addCookie(List headers, String key, String value) { 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 e30127233c..30ee6907b1 100644 --- a/backend/src/main/java/io/metersphere/api/parse/PostmanParser.java +++ b/backend/src/main/java/io/metersphere/api/parse/PostmanParser.java @@ -74,6 +74,7 @@ public class PostmanParser extends ApiImportAbstractParser { parseBody(request.getBody(), requestDesc); request.setArguments(parseKeyValue(url.getQuery())); request.setHeaders(parseKeyValue(requestDesc.getHeader())); + addBodyHeader(request); apiDefinition.setRequest(JSON.toJSONString(request)); return apiDefinition; } diff --git a/backend/src/main/java/io/metersphere/api/parse/Swagger2Parser.java b/backend/src/main/java/io/metersphere/api/parse/Swagger2Parser.java index 80c18fce35..62fcf926be 100644 --- a/backend/src/main/java/io/metersphere/api/parse/Swagger2Parser.java +++ b/backend/src/main/java/io/metersphere/api/parse/Swagger2Parser.java @@ -68,6 +68,7 @@ public class Swagger2Parser extends SwaggerAbstractParser { MsHTTPSamplerProxy request = buildRequest(operation, pathName, method.name()); ApiDefinitionResult apiDefinition = buildApiDefinition(request.getId(), operation, pathName, method.name(),importRequest); parseParameters(operation, request); + addBodyHeader(request); apiDefinition.setRequest(JSON.toJSONString(request)); apiDefinition.setResponse(JSON.toJSONString(parseResponse(operation, operation.getResponses()))); buildModule(parentNode, apiDefinition, operation.getTags(), importRequest.isSaved()); @@ -275,7 +276,6 @@ public class Swagger2Parser extends SwaggerAbstractParser { } else { propertyList.add(new JSONObject()); } - jsonObject.put(key, propertyList); } else { jsonObject.put(key, new ArrayList<>()); diff --git a/backend/src/main/java/io/metersphere/api/parse/Swagger3Parser.java b/backend/src/main/java/io/metersphere/api/parse/Swagger3Parser.java index 1fd4033d76..62335c3c25 100644 --- a/backend/src/main/java/io/metersphere/api/parse/Swagger3Parser.java +++ b/backend/src/main/java/io/metersphere/api/parse/Swagger3Parser.java @@ -100,6 +100,7 @@ public class Swagger3Parser extends SwaggerAbstractParser { ApiDefinitionResult apiDefinition = buildApiDefinition(request.getId(), operation, pathName, method,importRequest); parseParameters(operation, request); parseRequestBody(operation.getRequestBody(), request.getBody()); + addBodyHeader(request); apiDefinition.setRequest(JSON.toJSONString(request)); apiDefinition.setResponse(JSON.toJSONString(parseResponse(operation.getResponses()))); buildModule(parentNode, apiDefinition, operation.getTags(), importRequest.isSaved()); 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 6805899a82..96278e134a 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -464,7 +464,7 @@ public class ApiAutomationService { * @param unSelectIds 未勾选ID_前台没有勾选的ID * @return */ - private List getAllScenarioIdsByFontedSelect(List moduleIds, String name, String projectId, List filters, List unSelectIds) { + private List getAllScenarioIdsByFontedSelect(List moduleIds, String name, String projectId, Map> filters, List unSelectIds) { ApiScenarioRequest selectRequest = new ApiScenarioRequest(); selectRequest.setModuleIds(moduleIds); selectRequest.setName(name); diff --git a/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java b/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java index 489f5b5133..6bfe58d770 100644 --- a/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java +++ b/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java @@ -65,6 +65,15 @@ public class HistoricalDataUpgradeService { } } + private MsScenario createScenarioByTest(ApiTest test) { + MsScenario scenario = new MsScenario(); + scenario.setName(test.getName()); + scenario.setReferenced("Upgrade"); + scenario.setResourceId(UUID.randomUUID().toString()); + scenario.setId(test.getId()); + return scenario; + } + private MsScenario createScenario(Scenario oldScenario) { MsScenario scenario = new MsScenario(); scenario.setOldVariables(oldScenario.getVariables()); @@ -147,6 +156,9 @@ public class HistoricalDataUpgradeService { BeanUtils.copyBean(element, request1); ((MsHTTPSamplerProxy) element).setProtocol(RequestType.HTTP); ((MsHTTPSamplerProxy) element).setArguments(request1.getParameters()); + List keyValues = new LinkedList<>(); + keyValues.add(new KeyValue("", "")); + ((MsHTTPSamplerProxy) element).setRest(keyValues); if (StringUtils.isEmpty(element.getName())) { element.setName(request1.getPath()); } @@ -185,6 +197,9 @@ public class HistoricalDataUpgradeService { CollectionUtils.isNotEmpty(request.getAssertions().getRegex()) || CollectionUtils.isNotEmpty(request.getAssertions().getXpath2()))) { String assertions = JSON.toJSONString(request.getAssertions()); MsAssertions msAssertions = JSON.parseObject(assertions, MsAssertions.class); + if (StringUtils.isEmpty(msAssertions.getName())) { + msAssertions.setName("Assertions"); + } msAssertions.setType("Assertions"); msAssertions.setIndex(index + ""); msAssertions.setResourceId(UUID.randomUUID().toString()); @@ -196,6 +211,9 @@ public class HistoricalDataUpgradeService { CollectionUtils.isNotEmpty(request.getExtract().getRegex()) || CollectionUtils.isNotEmpty(request.getExtract().getXpath()))) { String extractJson = JSON.toJSONString(request.getExtract()); MsExtract extract = JSON.parseObject(extractJson, MsExtract.class); + if (StringUtils.isEmpty(extract.getName())) { + extract.setName("Extract"); + } extract.setType("Extract"); extract.setIndex(index + ""); extract.setHashTree(new LinkedList<>()); @@ -206,6 +224,9 @@ public class HistoricalDataUpgradeService { if (request.getJsr223PreProcessor() != null && StringUtils.isNotEmpty(request.getJsr223PreProcessor().getScript())) { String preJson = JSON.toJSONString(request.getJsr223PreProcessor()); MsJSR223PreProcessor preProcessor = JSON.parseObject(preJson, MsJSR223PreProcessor.class); + if (StringUtils.isEmpty(preProcessor.getName())) { + preProcessor.setName("JSR223PreProcessor"); + } preProcessor.setType("JSR223PreProcessor"); preProcessor.setIndex(index + ""); preProcessor.setHashTree(new LinkedList<>()); @@ -216,6 +237,9 @@ public class HistoricalDataUpgradeService { if (request.getJsr223PostProcessor() != null && StringUtils.isNotEmpty(request.getJsr223PostProcessor().getScript())) { String preJson = JSON.toJSONString(request.getJsr223PostProcessor()); MsJSR223PostProcessor preProcessor = JSON.parseObject(preJson, MsJSR223PostProcessor.class); + if (StringUtils.isEmpty(preProcessor.getName())) { + preProcessor.setName("JSR223PostProcessor"); + } preProcessor.setType("JSR223PostProcessor"); preProcessor.setIndex(index + ""); preProcessor.setHashTree(new LinkedList<>()); @@ -239,9 +263,9 @@ public class HistoricalDataUpgradeService { return scenario; } - private ApiScenarioWithBLOBs checkNameExist(Scenario oldScenario, String projectId, ApiScenarioMapper mapper) { + private ApiScenarioWithBLOBs getScenario(String oldScenarioId, ApiScenarioMapper mapper) { ApiScenarioExample example = new ApiScenarioExample(); - example.createCriteria().andIdEqualTo(oldScenario.getId()); + example.createCriteria().andIdEqualTo(oldScenarioId); List list = mapper.selectByExampleWithBLOBs(example); if (list.size() > 0) { return list.get(0); @@ -321,20 +345,20 @@ public class HistoricalDataUpgradeService { copyDir(dir, BODY_FILE_DIR); } - private void createApiScenarioWithBLOBs(SaveHistoricalDataUpgrade saveHistoricalDataUpgrade, Scenario oldScenario, String scenarioDefinition, ApiScenarioMapper mapper, int num) { - if (StringUtils.isEmpty(oldScenario.getName())) { - oldScenario.setName("默认名称-" + DateUtils.getTimeStr(System.currentTimeMillis())); + private void createApiScenarioWithBLOBs(SaveHistoricalDataUpgrade saveHistoricalDataUpgrade, String id, String name, int total, String scenarioDefinition, ApiScenarioMapper mapper, int num) { + if (StringUtils.isEmpty(name)) { + name = "默认名称-" + DateUtils.getTimeStr(System.currentTimeMillis()); } - ApiScenarioWithBLOBs scenario = checkNameExist(oldScenario, saveHistoricalDataUpgrade.getProjectId(), mapper); + ApiScenarioWithBLOBs scenario = getScenario(id, mapper); if (scenario != null) { - scenario.setName(oldScenario.getName()); + scenario.setName(name); scenario.setProjectId(saveHistoricalDataUpgrade.getProjectId()); scenario.setTags(scenario.getTags()); scenario.setLevel("P0"); scenario.setModulePath(saveHistoricalDataUpgrade.getModulePath()); scenario.setApiScenarioModuleId(saveHistoricalDataUpgrade.getModuleId()); scenario.setPrincipal(Objects.requireNonNull(SessionUtils.getUser()).getId()); - scenario.setStepTotal(oldScenario.getRequests().size()); + scenario.setStepTotal(total); scenario.setScenarioDefinition(scenarioDefinition); scenario.setUpdateTime(System.currentTimeMillis()); scenario.setStatus(ScenarioStatus.Underway.name()); @@ -342,15 +366,15 @@ public class HistoricalDataUpgradeService { mapper.updateByPrimaryKeySelective(scenario); } else { scenario = new ApiScenarioWithBLOBs(); - scenario.setId(oldScenario.getId()); - scenario.setName(oldScenario.getName()); + scenario.setId(id); + scenario.setName(name); scenario.setProjectId(saveHistoricalDataUpgrade.getProjectId()); scenario.setTags(scenario.getTags()); scenario.setLevel("P0"); scenario.setModulePath(saveHistoricalDataUpgrade.getModulePath()); scenario.setApiScenarioModuleId(saveHistoricalDataUpgrade.getModuleId()); scenario.setPrincipal(Objects.requireNonNull(SessionUtils.getUser()).getId()); - scenario.setStepTotal(oldScenario.getRequests().size()); + scenario.setStepTotal(total); scenario.setScenarioDefinition(scenarioDefinition); scenario.setCreateTime(System.currentTimeMillis()); scenario.setUpdateTime(System.currentTimeMillis()); @@ -374,7 +398,9 @@ public class HistoricalDataUpgradeService { for (ApiTest test : blobs) { // 附件迁移 createBodyFiles(test.getId()); - + // 把test 生成一个场景,旧场景数据变成引用步骤 + MsScenario scenarioTest = createScenarioByTest(test); + LinkedList listSteps = new LinkedList<>(); List scenarios = JSON.parseArray(test.getScenarioDefinition(), Scenario.class); if (CollectionUtils.isNotEmpty(scenarios)) { // 批量处理 @@ -382,9 +408,20 @@ public class HistoricalDataUpgradeService { MsScenario scenario1 = createScenario(scenario); String scenarioDefinition = JSON.toJSONString(scenario1); num++; - createApiScenarioWithBLOBs(saveHistoricalDataUpgrade, scenario, scenarioDefinition, mapper, num); + createApiScenarioWithBLOBs(saveHistoricalDataUpgrade, scenario.getId(), scenario.getName(), scenario.getRequests().size(), scenarioDefinition, mapper, num); + MsScenario step = new MsScenario(); + step.setId(scenario1.getId()); + step.setName(scenario1.getName()); + step.setType("scenario"); + step.setResourceId(UUID.randomUUID().toString()); + step.setReferenced("REF"); + listSteps.add(step); } } + num++; + scenarioTest.setHashTree(listSteps); + String scenarioDefinition = JSON.toJSONString(scenarioTest); + createApiScenarioWithBLOBs(saveHistoricalDataUpgrade, scenarioTest.getId(), scenarioTest.getName(), listSteps.size(), scenarioDefinition, mapper, num); } sqlSession.flushStatements(); return null; diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml index c0089a1413..56556c85dd 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml @@ -150,9 +150,35 @@ - and api_scenario.status in - - #{value} + + + + + and api_scenario.status in + + #{value} + + + + and api_scenario.user_id in + + #{value} + + + + and api_scenario.level in + + #{value} + + + + and api_scenario.last_result in + + #{value} + + + + diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.java index fad4c49e32..2cb340e72f 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.java @@ -11,4 +11,5 @@ public interface ExtTestPlanLoadCaseMapper { List selectIdsNotInPlan(@Param("projectId") String projectId, @Param("planId") String planId); List selectTestPlanLoadCaseList(@Param("request") LoadCaseRequest request); void updateCaseStatus(@Param("reportId") String reportId, @Param("status") String status); + List getStatusByTestPlanId(@Param("planId") String planId); } diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.xml index 8c8e030dc9..d46688f5e1 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.xml @@ -40,6 +40,29 @@ and (lt.name like CONCAT('%', #{request.name},'%') or lt.num like CONCAT('%', #{request.name},'%')) + + + + + + and lt.status in + + #{value} + + + + + + + + order by + + tplc.${order.name} ${order.type} + + + + \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanMapper.java index ff54fa5a9b..c29727c077 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanMapper.java @@ -1,5 +1,6 @@ package io.metersphere.base.mapper.ext; +import io.metersphere.base.domain.TestPlan; import io.metersphere.track.dto.TestPlanDTO; import io.metersphere.track.dto.TestPlanDTOWithMetric; import io.metersphere.track.request.testcase.QueryTestPlanRequest; @@ -32,4 +33,6 @@ public interface ExtTestPlanMapper { String findScheduleCreateUserById(String testPlanId); List findIdByPerformanceReportId(String reportId); + + List listRecent(@Param("userId") String userId, @Param("projectId") String currentProjectId); } diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanMapper.xml index 53d54f2994..85d112f388 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanMapper.xml @@ -240,5 +240,16 @@ WHERE reportData.performance_info like CONCAT('%', #{0},'%') AND report.is_performance_executing = true; + \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanReportMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanReportMapper.xml index c461efcb04..fb5e0b81ba 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanReportMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanReportMapper.xml @@ -4,9 +4,10 @@ + + + + - - - + + + + - - - - + - + - + + + + + - - - - - + + + + + - - - - - + + + - - - + - + - + + + - - - + + + + - - - - - - - - + + + - - - + + @@ -94,11 +92,11 @@ import MsApiVariableAdvance from "./ApiVariableAdvance"; import MsApiBodyFileUpload from "./body/ApiBodyFileUpload"; import {REQUIRED} from "../model/JsonData"; - import MsDraggable from 'vuedraggable' + import Vue from 'vue'; export default { name: "MsApiVariable", - components: {MsApiBodyFileUpload, MsApiVariableAdvance, MsDraggable}, + components: {MsApiBodyFileUpload, MsApiVariableAdvance}, props: { keyPlaceholder: String, valuePlaceholder: String, @@ -125,7 +123,6 @@ return { currentItem: null, requireds: REQUIRED, - keyValues: [], } }, computed: { @@ -137,6 +134,25 @@ } }, methods: { + moveBottom(index) { + if (this.parameters.length < 2 || index === this.parameters.length - 2) { + return; + } + let thisRow = this.parameters[index]; + let nextRow = this.parameters[index + 1]; + Vue.set(this.parameters, index + 1, thisRow); + Vue.set(this.parameters, index, nextRow) + }, + moveTop(index) { + if (index === 0) { + return; + } + let thisRow = this.parameters[index]; + let lastRow = this.parameters[index - 1]; + Vue.set(this.parameters, index - 1, thisRow); + Vue.set(this.parameters, index, lastRow) + + }, remove: function (index) { // 移除整行输入控件及内容 this.parameters.splice(index, 1); @@ -204,21 +220,6 @@ item.contentType = 'text/plain'; } }, - endChange(env) { - if (env.newIndex == env.oldIndex) { - return; - } - let newItem = this.keyValues[env.newIndex]; - let oldItem = this.keyValues[env.oldIndex]; - this.$set(this.keyValues, env.oldIndex, oldItem); - this.$set(this.keyValues, env.newIndex, newItem) - this.parameters.forEach(item => { - this.parameters.splice(0); - }) - this.keyValues.forEach(item => { - this.parameters.push(item); - }) - } }, created() { if (this.parameters.length === 0 || this.parameters[this.parameters.length - 1].name) { @@ -230,7 +231,6 @@ contentType: 'text/plain' })); } - this.keyValues = this.parameters; } } diff --git a/frontend/src/business/components/api/definition/components/case/ApiCaseItem.vue b/frontend/src/business/components/api/definition/components/case/ApiCaseItem.vue index e1cfe6c7e5..2d6a40ffbe 100644 --- a/frontend/src/business/components/api/definition/components/case/ApiCaseItem.vue +++ b/frontend/src/business/components/api/definition/components/case/ApiCaseItem.vue @@ -85,7 +85,7 @@

{{ $t('api_test.definition.request.req_param') }}

- + diff --git a/frontend/src/business/components/api/definition/components/debug/DebugHttpPage.vue b/frontend/src/business/components/api/definition/components/debug/DebugHttpPage.vue index 10b5287bec..7bef849ff2 100644 --- a/frontend/src/business/components/api/definition/components/debug/DebugHttpPage.vue +++ b/frontend/src/business/components/api/definition/components/debug/DebugHttpPage.vue @@ -26,7 +26,7 @@

{{$t('api_test.definition.request.req_param')}}

- +

{{$t('api_test.definition.request.res_param')}}

diff --git a/frontend/src/business/components/api/definition/components/environment/EnvironmentHttpConfig.vue b/frontend/src/business/components/api/definition/components/environment/EnvironmentHttpConfig.vue index 91b4d256f9..6f98ce26ac 100644 --- a/frontend/src/business/components/api/definition/components/environment/EnvironmentHttpConfig.vue +++ b/frontend/src/business/components/api/definition/components/environment/EnvironmentHttpConfig.vue @@ -49,8 +49,13 @@ }, methods: { validateSocket(socket) { - // if (!socket) return true; - if (socket !== ''){ + if (!socket) { + this.httpConfig.domain = socket; + this.httpConfig.port = ''; + this.httpConfig.socket = socket; + return true; + } + let urlStr = this.httpConfig.protocol + '://' + socket; let url = {}; try { @@ -67,13 +72,6 @@ this.httpConfig.socket = this.httpConfig.domain + path; } return true; - }else { - this.httpConfig.domain = socket; - this.httpConfig.port = ''; - this.httpConfig.socket = socket; - return true; - } - }, validate() { let isValidate = false; diff --git a/frontend/src/business/components/api/definition/components/list/ApiList.vue b/frontend/src/business/components/api/definition/components/list/ApiList.vue index 429e4aaee0..fed69a9dc9 100644 --- a/frontend/src/business/components/api/definition/components/list/ApiList.vue +++ b/frontend/src/business/components/api/definition/components/list/ApiList.vue @@ -317,6 +317,15 @@ case 'coverage': this.condition.apiCaseCoverage = 'coverage'; break; + case 'Prepare': + this.condition.filters.status = [this.selectDataRange]; + break; + case 'Completed': + this.condition.filters.status = [this.selectDataRange]; + break; + case 'Underway': + this.condition.filters.status = [this.selectDataRange]; + break; } if (this.condition.projectId) { this.result = this.$post("/api/definition/list/" + this.currentPage + "/" + this.pageSize, this.condition, response => { diff --git a/frontend/src/business/components/api/definition/components/list/ApiStatus.vue b/frontend/src/business/components/api/definition/components/list/ApiStatus.vue index 5b5cfe132d..5e039365b5 100644 --- a/frontend/src/business/components/api/definition/components/list/ApiStatus.vue +++ b/frontend/src/business/components/api/definition/components/list/ApiStatus.vue @@ -3,7 +3,7 @@ - + diff --git a/frontend/src/business/components/api/definition/components/runtest/RunTestHTTPPage.vue b/frontend/src/business/components/api/definition/components/runtest/RunTestHTTPPage.vue index 363ad44b8c..3104935d8a 100644 --- a/frontend/src/business/components/api/definition/components/runtest/RunTestHTTPPage.vue +++ b/frontend/src/business/components/api/definition/components/runtest/RunTestHTTPPage.vue @@ -43,7 +43,7 @@

{{$t('api_test.definition.request.req_param')}}

- + diff --git a/frontend/src/business/components/api/definition/model/ApiTestModel.js b/frontend/src/business/components/api/definition/model/ApiTestModel.js index 236c002008..8136994191 100644 --- a/frontend/src/business/components/api/definition/model/ApiTestModel.js +++ b/frontend/src/business/components/api/definition/model/ApiTestModel.js @@ -1024,9 +1024,9 @@ export class LoopController extends Controller { this.type = "LoopController"; this.active = false; this.loopType = "LOOP_COUNT"; - this.countController = {loops: 0, interval: 0, proceed: true}; - this.forEachController = {inputVal: "", returnVal: "", interval: 0}; - this.whileController = {variable: "", operator: "", value: "", timeout: 0}; + this.countController = {loops: 0, interval: 0, proceed: true, requestResult: {}}; + this.forEachController = {inputVal: "", returnVal: "", interval: 0, requestResult: {}}; + this.whileController = {variable: "", operator: "", value: "", timeout: 0, requestResult: {}}; this.hashTree = []; this.set(options); } diff --git a/frontend/src/business/components/api/definition/model/EnvironmentModel.js b/frontend/src/business/components/api/definition/model/EnvironmentModel.js index 2be5d57666..0462553e13 100644 --- a/frontend/src/business/components/api/definition/model/EnvironmentModel.js +++ b/frontend/src/business/components/api/definition/model/EnvironmentModel.js @@ -64,11 +64,11 @@ export class HttpConfig extends BaseConfig { constructor(options = {}) { super(); - this.socket = undefined; - this.domain = undefined; + this.socket = ''; + this.domain = ''; this.headers = []; this.protocol = 'https'; - this.port = undefined; + this.port = ''; this.set(options); this.sets({headers: KeyValue}, options); diff --git a/frontend/src/business/components/api/test/components/processor/Jsr233Processor.vue b/frontend/src/business/components/api/test/components/processor/Jsr233Processor.vue index fd86a3a750..7cd6c957b0 100644 --- a/frontend/src/business/components/api/test/components/processor/Jsr233Processor.vue +++ b/frontend/src/business/components/api/test/components/processor/Jsr233Processor.vue @@ -93,11 +93,13 @@ export default { ], isCodeEditAlive: true, languages: [ - 'beanshell', "python" + 'beanshell', "python", "groovy", "javascript" ], codeEditModeMap: { beanshell: 'java', - python: 'python' + python: 'python', + groovy: 'java', + javascript: 'javascript', } } }, diff --git a/frontend/src/business/components/api/test/components/request/ApiDubboRequestForm.vue b/frontend/src/business/components/api/test/components/request/ApiDubboRequestForm.vue index eda7204d61..9cc19b2f99 100644 --- a/frontend/src/business/components/api/test/components/request/ApiDubboRequestForm.vue +++ b/frontend/src/business/components/api/test/components/request/ApiDubboRequestForm.vue @@ -65,7 +65,7 @@ import MsDubboRegistryCenter from "@/business/components/api/test/components/request/dubbo/RegistryCenter"; import MsDubboConfigCenter from "@/business/components/api/test/components/request/dubbo/ConfigCenter"; import MsDubboConsumerService from "@/business/components/api/test/components/request/dubbo/ConsumerAndService"; - import MsJsr233Processor from "../../../automation/scenario/component/Jsr233Processor"; + import MsJsr233Processor from "../processor/Jsr233Processor"; export default { name: "MsApiDubboRequestForm", diff --git a/frontend/src/business/components/api/test/components/request/ApiHttpRequestForm.vue b/frontend/src/business/components/api/test/components/request/ApiHttpRequestForm.vue index 989cf34dfe..be5323ec39 100644 --- a/frontend/src/business/components/api/test/components/request/ApiHttpRequestForm.vue +++ b/frontend/src/business/components/api/test/components/request/ApiHttpRequestForm.vue @@ -94,7 +94,7 @@ import ApiRequestMethodSelect from "../collapse/ApiRequestMethodSelect"; import {REQUEST_HEADERS} from "@/common/js/constants"; import MsApiVariable from "@/business/components/api/test/components/ApiVariable"; import MsApiAdvancedConfig from "../ApiAdvancedConfig"; -import MsJsr233Processor from "../../../automation/scenario/component/Jsr233Processor"; +import MsJsr233Processor from "../processor/Jsr233Processor"; export default { name: "MsApiHttpRequestForm", diff --git a/frontend/src/business/components/api/test/components/request/ApiSqlRequestForm.vue b/frontend/src/business/components/api/test/components/request/ApiSqlRequestForm.vue index 32a7d9574f..d0f23d63b0 100644 --- a/frontend/src/business/components/api/test/components/request/ApiSqlRequestForm.vue +++ b/frontend/src/business/components/api/test/components/request/ApiSqlRequestForm.vue @@ -78,7 +78,7 @@ import MsDubboConsumerService from "@/business/components/api/test/components/request/dubbo/ConsumerAndService"; import MsCodeEdit from "../../../../common/components/MsCodeEdit"; import MsApiScenarioVariables from "../ApiScenarioVariables"; - import MsJsr233Processor from "../../../automation/scenario/component/Jsr233Processor"; + import MsJsr233Processor from "../processor/Jsr233Processor"; export default { name: "MsApiSqlRequestForm", diff --git a/frontend/src/business/components/api/test/components/request/ApiTcpRequestForm.vue b/frontend/src/business/components/api/test/components/request/ApiTcpRequestForm.vue index e2b43d9901..c46815d06c 100644 --- a/frontend/src/business/components/api/test/components/request/ApiTcpRequestForm.vue +++ b/frontend/src/business/components/api/test/components/request/ApiTcpRequestForm.vue @@ -120,7 +120,7 @@ import {Scenario, TCPConfig, TCPRequest} from "@/business/components/api/test/mo import MsApiAssertions from "@/business/components/api/test/components/assertion/ApiAssertions"; import MsApiExtract from "@/business/components/api/test/components/extract/ApiExtract"; import MsCodeEdit from "@/business/components/common/components/MsCodeEdit"; -import MsJsr233Processor from "../../../automation/scenario/component/Jsr233Processor"; +import MsJsr233Processor from "../processor/Jsr233Processor"; export default { name: "MsApiTcpRequestForm", diff --git a/frontend/src/business/components/track/case/components/TestCaseEdit.vue b/frontend/src/business/components/track/case/components/TestCaseEdit.vue index e98c8ff9c1..b517936329 100644 --- a/frontend/src/business/components/track/case/components/TestCaseEdit.vue +++ b/frontend/src/business/components/track/case/components/TestCaseEdit.vue @@ -9,7 +9,9 @@ - {{operationType == 'edit' ? ( readOnly ? $t('test_track.case.view_case') : $t('test_track.case.edit_case')) : $t('test_track.case.create')}} + {{ + operationType == 'edit' ? (readOnly ? $t('test_track.case.view_case') : $t('test_track.case.edit_case')) : $t('test_track.case.create') + }} @@ -82,7 +84,7 @@ - + @@ -318,6 +320,7 @@ export default { result: '' }], remark: '', + tags: [], }, moduleOptions: [], maintainerOptions: [], @@ -350,7 +353,8 @@ export default { ], testCase: {}, testCases: [], - index: 0 + index: 0, + showInputTag: true, }; }, props: { @@ -416,6 +420,7 @@ export default { this.form.type = 'functional'; this.form.method = 'manual'; this.form.maintainer = user.id; + this.form.tags = []; this.getSelectOptions(); this.reload(); } @@ -441,6 +446,7 @@ export default { }); }, getTestCase(index) { + this.showInputTag = false; let testCase = this.testCases[index]; this.result = this.$get('/test/case/get/' + testCase.id, response => { let testCase = response.data; @@ -448,6 +454,9 @@ export default { this.setTestCaseExtInfo(testCase); this.getSelectOptions(); this.reload(); + this.$nextTick(() => { + this.showInputTag = true + }) }) }, setFormData(testCase) { @@ -459,7 +468,7 @@ export default { this.form.module = testCase.nodeId; this.getFileMetaData(testCase); }, - setTestCaseExtInfo (testCase) { + setTestCaseExtInfo(testCase) { this.testCase = {}; if (testCase) { // 复制 不查询评论 diff --git a/frontend/src/business/components/track/common/NodeTree.vue b/frontend/src/business/components/track/common/NodeTree.vue index 4100d799e8..5bc8e3c02e 100644 --- a/frontend/src/business/components/track/common/NodeTree.vue +++ b/frontend/src/business/components/track/common/NodeTree.vue @@ -137,12 +137,6 @@ export default { return false; }, filter(val) { - if (!val) { - val = this.filterText; - } else { - // 记录condition 的 filterText - this.filterText = val; - } this.$nextTick(() => { this.$refs.tree.filter(val); }); diff --git a/frontend/src/business/components/track/common/tableItems/plan/PlanStatusTableItem.vue b/frontend/src/business/components/track/common/tableItems/plan/PlanStatusTableItem.vue index 0721190c41..786cb030cc 100644 --- a/frontend/src/business/components/track/common/tableItems/plan/PlanStatusTableItem.vue +++ b/frontend/src/business/components/track/common/tableItems/plan/PlanStatusTableItem.vue @@ -3,12 +3,14 @@ + @@ -164,4 +278,22 @@ export default { .el-table { cursor: pointer; } + +.operate-button > div { + display: inline-block; + margin-left: 10px; +} + +.request-method { + padding: 0 5px; + color: #1E90FF; +} + +.ms-select-all >>> th:first-child { + margin-top: 20px; +} + +.ms-select-all >>> th:nth-child(2) .el-icon-arrow-down { + top: -2px; +} diff --git a/frontend/src/business/components/xpack b/frontend/src/business/components/xpack index 8a6a9ae708..5abe43dc1f 160000 --- a/frontend/src/business/components/xpack +++ b/frontend/src/business/components/xpack @@ -1 +1 @@ -Subproject commit 8a6a9ae708306eaf436f35394b71927cec075b0e +Subproject commit 5abe43dc1f65b529ad59c17bfdc58aea33d23cad diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index 0cee15ed36..ecc7f370f6 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -129,6 +129,7 @@ export default { validate: "Validate", batch_add: "Batch add", check_project_tip: "Create or select the project first", + auth_redirect_tip: 'Jump to the authentication source page for authentication', table: { select_tip: "Item {0} data is selected" }, @@ -831,8 +832,8 @@ export default { swagger_export_tip: "Export jSON-formatted files via Swagger website", suffixFormatErr: "The file format does not meet the requirements", swagger_url_import: "Import using URL", - timing_synchronization:"Timing synchronization", - next_synchronization_time:"Next synchronization time", + timing_synchronization: "Timing synchronization", + next_synchronization_time: "Next synchronization time", }, home_page: { @@ -1493,6 +1494,6 @@ export default { format: "Output format", }, auth_source: { - delete_prompt:'This operation will delete the authentication source, do you want to continue? ' + delete_prompt: 'This operation will delete the authentication source, do you want to continue? ' } }; diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index badbaab6d0..85d73e703d 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -129,6 +129,7 @@ export default { validate: "校验", batch_add: "批量添加", check_project_tip: "请先创建或选择项目", + auth_redirect_tip: '即将跳转到认证源页面进行认证', table: { select_tip: "已选中 {0} 条数据" }, @@ -833,8 +834,8 @@ export default { swagger_export_tip: "通过 Swagger 页面导出", suffixFormatErr: "文件格式不符合要求", swagger_url_import: "使用URL导入", - timing_synchronization:"定时同步", - next_synchronization_time:"下次同步时间" + timing_synchronization: "定时同步", + next_synchronization_time: "下次同步时间" }, diff --git a/frontend/src/i18n/zh-TW.js b/frontend/src/i18n/zh-TW.js index bc2a68bd91..47ede5346e 100644 --- a/frontend/src/i18n/zh-TW.js +++ b/frontend/src/i18n/zh-TW.js @@ -129,6 +129,7 @@ export default { validate: "校驗", batch_add: "批量添加", check_project_tip: "請先創建或選擇項目", + auth_redirect_tip: '即將跳轉到認證源頁面進行認證', table: { select_tip: "已选中 {0} 条数据" }, @@ -256,8 +257,8 @@ export default { nail_robot: '釘釘機器人', enterprise_wechat_robot: '企業微信機器人', notes: '1.釘釘和企業群裏新建壹個自定義機器人,然後復制 webhook 地址在我們平臺上;\n' + - ' 2.機器人選擇為群機器人,安全驗證選擇“自定義關鍵詞” :"任務通知";\n' + - ' 3.選擇接收人時必須是妳所建的群裏包含的人,接收人手機號為必填項且為釘釘企業所使用的手機號,', + ' 2.機器人選擇為群機器人,安全驗證選擇“自定義關鍵詞” :"任務通知";\n' + + ' 3.選擇接收人時必須是妳所建的群裏包含的人,接收人手機號為必填項且為釘釘企業所使用的手機號,', message: '事件,接收人,接收方式為必填項', message_webhook: '接收方式為釘釘和企業機器人時,webhook為必填項', template: "模版" @@ -832,8 +833,8 @@ export default { swagger_export_tip: "通過 Swagger 頁面導出", suffixFormatErr: "文件格式不符合要求", swagger_url_import: "使用URL導入", - timing_synchronization:"定時同步", - next_synchronization_time:"下次同步時間", + timing_synchronization: "定時同步", + next_synchronization_time: "下次同步時間", }, home_page: { diff --git a/frontend/src/login/Login.vue b/frontend/src/login/Login.vue index 8a957c3720..50a9a14d0a 100644 --- a/frontend/src/login/Login.vue +++ b/frontend/src/login/Login.vue @@ -15,7 +15,7 @@
- + LDAP 普通登录 {{ auth.type }} {{ auth.name }} @@ -172,6 +172,11 @@ export default { } else { window.location.href = "/" } + }, + redirectAuth(authId) { + if (auth.default) { + auth.default.redirectAuth(this, authId); + } } } }