diff --git a/backend/src/main/java/io/metersphere/api/dto/SaveAPITestRequest.java b/backend/src/main/java/io/metersphere/api/dto/SaveAPITestRequest.java index 8f93f2b0a8..ccddb708c7 100644 --- a/backend/src/main/java/io/metersphere/api/dto/SaveAPITestRequest.java +++ b/backend/src/main/java/io/metersphere/api/dto/SaveAPITestRequest.java @@ -1,8 +1,11 @@ package io.metersphere.api.dto; +import io.metersphere.api.dto.scenario.Scenario; import lombok.Getter; import lombok.Setter; +import java.util.List; + @Setter @Getter public class SaveAPITestRequest { @@ -13,5 +16,5 @@ public class SaveAPITestRequest { private String name; - private String scenarioDefinition; + private List scenarioDefinition; } diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java b/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java new file mode 100644 index 0000000000..63db961c19 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java @@ -0,0 +1,12 @@ +package io.metersphere.api.dto.scenario; + +import lombok.Data; + +import java.util.List; + +@Data +public class Body { + private String type; + private String raw; + private List kvs; +} 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 new file mode 100644 index 0000000000..26d1450608 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/KeyValue.java @@ -0,0 +1,9 @@ +package io.metersphere.api.dto.scenario; + +import lombok.Data; + +@Data +public class KeyValue { + private String name; + private String value; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/Request.java b/backend/src/main/java/io/metersphere/api/dto/scenario/Request.java new file mode 100644 index 0000000000..ce55174015 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/Request.java @@ -0,0 +1,19 @@ +package io.metersphere.api.dto.scenario; + +import io.metersphere.api.dto.scenario.assertions.Assertions; +import io.metersphere.api.dto.scenario.extract.Extract; +import lombok.Data; + +import java.util.List; + +@Data +public class Request { + private String name; + private String url; + private String method; + private List parameters; + private List headers; + private Body body; + private Assertions assertions; + private Extract extract; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/Scenario.java b/backend/src/main/java/io/metersphere/api/dto/scenario/Scenario.java new file mode 100644 index 0000000000..df60feb3b6 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/Scenario.java @@ -0,0 +1,14 @@ +package io.metersphere.api.dto.scenario; + +import lombok.Data; + +import java.util.List; + +@Data +public class Scenario { + private String name; + private String url; + private List variables; + private List headers; + private List requests; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/assertions/AssertionDuration.java b/backend/src/main/java/io/metersphere/api/dto/scenario/assertions/AssertionDuration.java new file mode 100644 index 0000000000..af9f5ebbf1 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/assertions/AssertionDuration.java @@ -0,0 +1,14 @@ +package io.metersphere.api.dto.scenario.assertions; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class AssertionDuration extends AssertionType { + private long value; + + public AssertionDuration() { + setType(AssertionType.DURATION); + } +} diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/assertions/AssertionRegex.java b/backend/src/main/java/io/metersphere/api/dto/scenario/assertions/AssertionRegex.java new file mode 100644 index 0000000000..8b787d5c1a --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/assertions/AssertionRegex.java @@ -0,0 +1,16 @@ +package io.metersphere.api.dto.scenario.assertions; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class AssertionRegex extends AssertionType { + private String subject; + private String expression; + private String description; + + public AssertionRegex() { + setType(AssertionType.REGEX); + } +} diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/assertions/AssertionType.java b/backend/src/main/java/io/metersphere/api/dto/scenario/assertions/AssertionType.java new file mode 100644 index 0000000000..5ae8414478 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/assertions/AssertionType.java @@ -0,0 +1,12 @@ +package io.metersphere.api.dto.scenario.assertions; + +import lombok.Data; + +@Data +public class AssertionType { + public final static String REGEX = "Regex"; + public final static String DURATION = "Duration"; + public final static String TEXT = "Text"; + + private String type; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/assertions/Assertions.java b/backend/src/main/java/io/metersphere/api/dto/scenario/assertions/Assertions.java new file mode 100644 index 0000000000..678fcdc0ce --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/assertions/Assertions.java @@ -0,0 +1,11 @@ +package io.metersphere.api.dto.scenario.assertions; + +import lombok.Data; + +import java.util.List; + +@Data +public class Assertions { + private List regex; + private AssertionDuration duration; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/extract/Extract.java b/backend/src/main/java/io/metersphere/api/dto/scenario/extract/Extract.java new file mode 100644 index 0000000000..3a390df6f1 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/extract/Extract.java @@ -0,0 +1,12 @@ +package io.metersphere.api.dto.scenario.extract; + +import lombok.Data; + +import java.util.List; + +@Data +public class Extract { + private List regex; + private List json; + private List xpath; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractCommon.java b/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractCommon.java new file mode 100644 index 0000000000..6757bc4cad --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractCommon.java @@ -0,0 +1,13 @@ +package io.metersphere.api.dto.scenario.extract; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class ExtractCommon extends ExtractType { + private String variable; + private String value; // value: ${variable} + private String expression; + private String description; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractJSONPath.java b/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractJSONPath.java new file mode 100644 index 0000000000..d151bf2118 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractJSONPath.java @@ -0,0 +1,12 @@ +package io.metersphere.api.dto.scenario.extract; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class ExtractJSONPath extends ExtractCommon { + public ExtractJSONPath() { + setType(ExtractType.JSON_PATH); + } +} diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractRegex.java b/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractRegex.java new file mode 100644 index 0000000000..3a2216fa27 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractRegex.java @@ -0,0 +1,12 @@ +package io.metersphere.api.dto.scenario.extract; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class ExtractRegex extends ExtractCommon { + public ExtractRegex() { + setType(ExtractType.REGEX); + } +} diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractType.java b/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractType.java new file mode 100644 index 0000000000..2df0b02e22 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractType.java @@ -0,0 +1,12 @@ +package io.metersphere.api.dto.scenario.extract; + +import lombok.Data; + +@Data +public class ExtractType { + public final static String REGEX = "Regex"; + public final static String JSON_PATH = "JSONPath"; + public final static String XPATH = "XPath"; + + private String type; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractXPath.java b/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractXPath.java new file mode 100644 index 0000000000..82e801b3b4 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/extract/ExtractXPath.java @@ -0,0 +1,12 @@ +package io.metersphere.api.dto.scenario.extract; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class ExtractXPath extends ExtractCommon { + public ExtractXPath() { + setType(ExtractType.XPATH); + } +} diff --git a/backend/src/main/java/io/metersphere/api/service/APITestService.java b/backend/src/main/java/io/metersphere/api/service/APITestService.java index e454d5afdd..9c1cdec6e0 100644 --- a/backend/src/main/java/io/metersphere/api/service/APITestService.java +++ b/backend/src/main/java/io/metersphere/api/service/APITestService.java @@ -1,5 +1,6 @@ package io.metersphere.api.service; +import com.alibaba.fastjson.JSONObject; import io.metersphere.api.dto.APITestResult; import io.metersphere.api.dto.QueryAPITestRequest; import io.metersphere.api.dto.SaveAPITestRequest; @@ -25,6 +26,7 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.List; import java.util.Objects; +import java.util.Random; import java.util.UUID; import java.util.stream.Collectors; @@ -73,10 +75,17 @@ public class APITestService { } public void copy(SaveAPITestRequest request) { + request.setName(request.getName() + " Copy"); + try { + checkNameExist(request); + } catch (Exception e) { + request.setName(request.getName() + " " + new Random().nextInt(1000)); + } + // copy test ApiTestWithBLOBs copy = get(request.getId()); copy.setId(UUID.randomUUID().toString()); - copy.setName(copy.getName() + " Copy"); + copy.setName(request.getName()); copy.setCreateTime(System.currentTimeMillis()); copy.setUpdateTime(System.currentTimeMillis()); copy.setStatus(APITestStatus.Saved.name()); @@ -96,6 +105,10 @@ public class APITestService { return apiTestMapper.selectByPrimaryKey(id); } + public List getApiTestByProjectId(String projectId) { + return extApiTestMapper.getApiTestByProjectId(projectId); + } + public void delete(String testId) { deleteFileByTestId(testId); apiReportService.deleteByTestId(testId); @@ -138,7 +151,7 @@ public class APITestService { test.setId(request.getId()); test.setName(request.getName()); test.setProjectId(request.getProjectId()); - test.setScenarioDefinition(request.getScenarioDefinition()); + test.setScenarioDefinition(JSONObject.toJSONString(request.getScenarioDefinition())); test.setUpdateTime(System.currentTimeMillis()); test.setStatus(APITestStatus.Saved.name()); apiTestMapper.updateByPrimaryKeySelective(test); @@ -151,7 +164,7 @@ public class APITestService { test.setId(request.getId()); test.setName(request.getName()); test.setProjectId(request.getProjectId()); - test.setScenarioDefinition(request.getScenarioDefinition()); + test.setScenarioDefinition(JSONObject.toJSONString(request.getScenarioDefinition())); test.setCreateTime(System.currentTimeMillis()); test.setUpdateTime(System.currentTimeMillis()); test.setStatus(APITestStatus.Saved.name()); @@ -194,7 +207,4 @@ public class APITestService { } } - public List getApiTestByProjectId(String projectId) { - return extApiTestMapper.getApiTestByProjectId(projectId); - } } diff --git a/frontend/src/business/components/api/test/ApiTestConfig.vue b/frontend/src/business/components/api/test/ApiTestConfig.vue index 1929790b1c..2605d077fd 100644 --- a/frontend/src/business/components/api/test/ApiTestConfig.vue +++ b/frontend/src/business/components/api/test/ApiTestConfig.vue @@ -5,7 +5,8 @@ - @@ -17,7 +18,8 @@ {{$t('commons.save')}} - + {{$t('load_test.save_and_run')}} @@ -25,7 +27,8 @@ {{$t('api_test.run')}} - {{$t('commons.cancel')}} + {{$t('commons.cancel')}} + @@ -165,13 +168,7 @@ }, getOptions(url) { let formData = new FormData(); - let request = { - id: this.test.id, - projectId: this.test.projectId, - name: this.test.name, - scenarioDefinition: JSON.stringify(this.test.scenarioDefinition) - } - let requestJson = JSON.stringify(request); + let requestJson = JSON.stringify(this.test); formData.append('request', new Blob([requestJson], { type: "application/json" diff --git a/frontend/src/business/components/api/test/ApiTestList.vue b/frontend/src/business/components/api/test/ApiTestList.vue index eac8067f29..7274cb5c94 100644 --- a/frontend/src/business/components/api/test/ApiTestList.vue +++ b/frontend/src/business/components/api/test/ApiTestList.vue @@ -143,7 +143,7 @@ }); }, handleCopy(test) { - this.result = this.$post("/api/copy", {id: test.id}, () => { + this.result = this.$post("/api/copy", {projectId: test.projectId, id: test.id, name: test.name}, () => { this.$success(this.$t('commons.copy_success')); this.search(); }); diff --git a/frontend/src/business/components/api/test/components/assertion/ApiAssertionResponseTime.vue b/frontend/src/business/components/api/test/components/assertion/ApiAssertionDuration.vue similarity index 91% rename from frontend/src/business/components/api/test/components/assertion/ApiAssertionResponseTime.vue rename to frontend/src/business/components/api/test/components/assertion/ApiAssertionDuration.vue index 1009ed163e..b992735f0b 100644 --- a/frontend/src/business/components/api/test/components/assertion/ApiAssertionResponseTime.vue +++ b/frontend/src/business/components/api/test/components/assertion/ApiAssertionDuration.vue @@ -15,13 +15,13 @@