From 1e4c6911b955494bfd0fce699bee8a05d38fa33c Mon Sep 17 00:00:00 2001 From: wxg0103 <727495428@qq.com> Date: Tue, 16 Jan 2024 10:01:31 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9C=BA=E6=99=AF=E7=9B=B8=E5=85=B3=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../metersphere/api/domain/ApiScenario.java | 25 +- .../api/domain/ApiScenarioEnvironment.java | 12 - .../domain/ApiScenarioEnvironmentExample.java | 140 ------ .../api/domain/ApiScenarioExample.java | 118 ++++- .../api/domain/ApiScenarioStep.java | 12 +- .../mapper/ApiScenarioEnvironmentMapper.java | 4 +- .../mapper/ApiScenarioEnvironmentMapper.xml | 67 +-- .../api/mapper/ApiScenarioMapper.xml | 83 ++-- .../3.0.0/ddl/V3.0.0_5__api_test.sql | 15 +- .../src/main/resources/i18n/api.properties | 13 +- .../main/resources/i18n/api_en_US.properties | 13 +- .../main/resources/i18n/api_zh_CN.properties | 13 +- .../main/resources/i18n/api_zh_TW.properties | 13 +- .../main/resources/i18n/commons.properties | 3 + .../resources/i18n/commons_en_US.properties | 3 + .../resources/i18n/commons_zh_CN.properties | 3 + .../resources/i18n/commons_zh_TW.properties | 3 + .../scenario/ApiScenarioController.java | 68 +++ .../scenario/ApiScenarioModuleController.java | 2 +- .../definition/ApiCaseBatchEditRequest.java | 2 + .../dto/definition/ApiTestCaseAddRequest.java | 1 + .../definition/ApiTestCaseUpdateRequest.java | 1 + .../scenario/ApiScenarioBatchEditRequest.java | 49 ++ .../dto/scenario/ApiScenarioBatchRequest.java | 36 ++ .../api/dto/scenario/ApiScenarioDTO.java | 25 +- .../ApiScenarioModuleRequest.java | 2 +- .../dto/scenario/ApiScenarioPageRequest.java | 38 ++ .../mapper/ExtApiDefinitionModuleMapper.xml | 4 +- .../api/mapper/ExtApiScenarioMapper.java | 20 + .../api/mapper/ExtApiScenarioMapper.xml | 266 ++++++++++ .../mapper/ExtApiScenarioModuleMapper.java | 2 +- .../api/mapper/ExtApiTestCaseMapper.java | 4 +- .../api/mapper/ExtApiTestCaseMapper.xml | 16 + .../ApiDefinitionImportUtilService.java | 3 +- .../definition/ApiTestCaseService.java | 34 +- .../scenario/ApiScenarioLogService.java | 100 ++++ .../scenario/ApiScenarioModuleService.java | 2 +- .../service/scenario/ApiScenarioService.java | 281 +++++++++++ .../ApiScenarioControllerTests.java | 455 ++++++++++++++++++ .../ApiScenarioModuleControllerTests.java | 2 +- .../log/constants/OperationLogModule.java | 1 + 41 files changed, 1629 insertions(+), 325 deletions(-) create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/controller/scenario/ApiScenarioController.java create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioBatchEditRequest.java create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioBatchRequest.java rename backend/services/api-test/src/main/java/io/metersphere/api/dto/{definition => scenario}/ApiScenarioModuleRequest.java (95%) create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioPageRequest.java create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioMapper.java create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioMapper.xml create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioLogService.java create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java create mode 100644 backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java diff --git a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenario.java b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenario.java index acc71d0b2a..78bb2929c0 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenario.java +++ b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenario.java @@ -1,13 +1,16 @@ package io.metersphere.api.domain; -import io.metersphere.validation.groups.*; +import io.metersphere.validation.groups.Created; +import io.metersphere.validation.groups.Updated; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.*; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; + import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; -import java.util.List; -import lombok.Data; @Data public class ApiScenario implements Serializable { @@ -35,9 +38,14 @@ public class ApiScenario implements Serializable { @NotNull(message = "{api_scenario.step_total.not_blank}", groups = {Created.class}) private Integer stepTotal; + @Schema(description = "请求执行率", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{api_scenario.request_execution_rate.not_blank}", groups = {Created.class}) + @Size(min = 1, max = 255, message = "{api_scenario.request_execution_rate.length_range}", groups = {Created.class, Updated.class}) + private String requestExecutionRate; + @Schema(description = "通过率", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "{api_scenario.pass_rate.not_blank}", groups = {Created.class}) - private Long passRate; + @NotNull(message = "{api_scenario.request_pass_rate.not_blank}", groups = {Created.class}) + private Long requestPassRate; @Schema(description = "最后一次执行的结果状态") private String lastReportStatus; @@ -116,7 +124,8 @@ public class ApiScenario implements Serializable { priority("priority", "priority", "VARCHAR", false), status("status", "status", "VARCHAR", true), stepTotal("step_total", "stepTotal", "INTEGER", false), - passRate("pass_rate", "passRate", "BIGINT", false), + requestExecutionRate("request_execution_rate", "requestExecutionRate", "VARCHAR", false), + requestPassRate("request_pass_rate", "requestPassRate", "BIGINT", false), lastReportStatus("last_report_status", "lastReportStatus", "VARCHAR", false), lastReportId("last_report_id", "lastReportId", "VARCHAR", false), num("num", "num", "BIGINT", false), @@ -180,7 +189,7 @@ public class ApiScenario implements Serializable { return this.getEscapedColumnName() + " ASC"; } - public static Column[] excludes(Column ... excludes) { + public static Column[] excludes(Column... excludes) { ArrayList columns = new ArrayList<>(Arrays.asList(Column.values())); if (excludes != null && excludes.length > 0) { columns.removeAll(new ArrayList<>(Arrays.asList(excludes))); diff --git a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioEnvironment.java b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioEnvironment.java index 03a4b69bd1..29e5cd91ab 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioEnvironment.java +++ b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioEnvironment.java @@ -10,21 +10,11 @@ import lombok.Data; @Data public class ApiScenarioEnvironment implements Serializable { - @Schema(description = "场景环境pk", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "{api_scenario_environment.id.not_blank}", groups = {Updated.class}) - @Size(min = 1, max = 50, message = "{api_scenario_environment.id.length_range}", groups = {Created.class, Updated.class}) - private String id; - @Schema(description = "场景fk", requiredMode = Schema.RequiredMode.REQUIRED) @NotBlank(message = "{api_scenario_environment.api_scenario_id.not_blank}", groups = {Created.class}) @Size(min = 1, max = 50, message = "{api_scenario_environment.api_scenario_id.length_range}", groups = {Created.class, Updated.class}) private String apiScenarioId; - @Schema(description = "项目fk", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "{api_scenario_environment.project_id.not_blank}", groups = {Created.class}) - @Size(min = 1, max = 50, message = "{api_scenario_environment.project_id.length_range}", groups = {Created.class, Updated.class}) - private String projectId; - @Schema(description = "环境fk") private String environmentId; @@ -34,9 +24,7 @@ public class ApiScenarioEnvironment implements Serializable { private static final long serialVersionUID = 1L; public enum Column { - id("id", "id", "VARCHAR", false), apiScenarioId("api_scenario_id", "apiScenarioId", "VARCHAR", false), - projectId("project_id", "projectId", "VARCHAR", false), environmentId("environment_id", "environmentId", "VARCHAR", false), environmentGroupId("environment_group_id", "environmentGroupId", "VARCHAR", false); diff --git a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioEnvironmentExample.java b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioEnvironmentExample.java index 2a1d23e279..c028cb54cd 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioEnvironmentExample.java +++ b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioEnvironmentExample.java @@ -104,76 +104,6 @@ public class ApiScenarioEnvironmentExample { criteria.add(new Criterion(condition, value1, value2)); } - public Criteria andIdIsNull() { - addCriterion("id is null"); - return (Criteria) this; - } - - public Criteria andIdIsNotNull() { - addCriterion("id is not null"); - return (Criteria) this; - } - - public Criteria andIdEqualTo(String value) { - addCriterion("id =", value, "id"); - return (Criteria) this; - } - - public Criteria andIdNotEqualTo(String value) { - addCriterion("id <>", value, "id"); - return (Criteria) this; - } - - public Criteria andIdGreaterThan(String value) { - addCriterion("id >", value, "id"); - return (Criteria) this; - } - - public Criteria andIdGreaterThanOrEqualTo(String value) { - addCriterion("id >=", value, "id"); - return (Criteria) this; - } - - public Criteria andIdLessThan(String value) { - addCriterion("id <", value, "id"); - return (Criteria) this; - } - - public Criteria andIdLessThanOrEqualTo(String value) { - addCriterion("id <=", value, "id"); - return (Criteria) this; - } - - public Criteria andIdLike(String value) { - addCriterion("id like", value, "id"); - return (Criteria) this; - } - - public Criteria andIdNotLike(String value) { - addCriterion("id not like", value, "id"); - return (Criteria) this; - } - - public Criteria andIdIn(List values) { - addCriterion("id in", values, "id"); - return (Criteria) this; - } - - public Criteria andIdNotIn(List values) { - addCriterion("id not in", values, "id"); - return (Criteria) this; - } - - public Criteria andIdBetween(String value1, String value2) { - addCriterion("id between", value1, value2, "id"); - return (Criteria) this; - } - - public Criteria andIdNotBetween(String value1, String value2) { - addCriterion("id not between", value1, value2, "id"); - return (Criteria) this; - } - public Criteria andApiScenarioIdIsNull() { addCriterion("api_scenario_id is null"); return (Criteria) this; @@ -244,76 +174,6 @@ public class ApiScenarioEnvironmentExample { return (Criteria) this; } - public Criteria andProjectIdIsNull() { - addCriterion("project_id is null"); - return (Criteria) this; - } - - public Criteria andProjectIdIsNotNull() { - addCriterion("project_id is not null"); - return (Criteria) this; - } - - public Criteria andProjectIdEqualTo(String value) { - addCriterion("project_id =", value, "projectId"); - return (Criteria) this; - } - - public Criteria andProjectIdNotEqualTo(String value) { - addCriterion("project_id <>", value, "projectId"); - return (Criteria) this; - } - - public Criteria andProjectIdGreaterThan(String value) { - addCriterion("project_id >", value, "projectId"); - return (Criteria) this; - } - - public Criteria andProjectIdGreaterThanOrEqualTo(String value) { - addCriterion("project_id >=", value, "projectId"); - return (Criteria) this; - } - - public Criteria andProjectIdLessThan(String value) { - addCriterion("project_id <", value, "projectId"); - return (Criteria) this; - } - - public Criteria andProjectIdLessThanOrEqualTo(String value) { - addCriterion("project_id <=", value, "projectId"); - return (Criteria) this; - } - - public Criteria andProjectIdLike(String value) { - addCriterion("project_id like", value, "projectId"); - return (Criteria) this; - } - - public Criteria andProjectIdNotLike(String value) { - addCriterion("project_id not like", value, "projectId"); - return (Criteria) this; - } - - public Criteria andProjectIdIn(List values) { - addCriterion("project_id in", values, "projectId"); - return (Criteria) this; - } - - public Criteria andProjectIdNotIn(List values) { - addCriterion("project_id not in", values, "projectId"); - return (Criteria) this; - } - - public Criteria andProjectIdBetween(String value1, String value2) { - addCriterion("project_id between", value1, value2, "projectId"); - return (Criteria) this; - } - - public Criteria andProjectIdNotBetween(String value1, String value2) { - addCriterion("project_id not between", value1, value2, "projectId"); - return (Criteria) this; - } - public Criteria andEnvironmentIdIsNull() { addCriterion("environment_id is null"); return (Criteria) this; diff --git a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioExample.java b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioExample.java index 4faedfac2f..e4a7ab6ee5 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioExample.java +++ b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioExample.java @@ -478,63 +478,133 @@ public class ApiScenarioExample { return (Criteria) this; } - public Criteria andPassRateIsNull() { - addCriterion("pass_rate is null"); + public Criteria andRequestExecutionRateIsNull() { + addCriterion("request_execution_rate is null"); return (Criteria) this; } - public Criteria andPassRateIsNotNull() { - addCriterion("pass_rate is not null"); + public Criteria andRequestExecutionRateIsNotNull() { + addCriterion("request_execution_rate is not null"); return (Criteria) this; } - public Criteria andPassRateEqualTo(Long value) { - addCriterion("pass_rate =", value, "passRate"); + public Criteria andRequestExecutionRateEqualTo(String value) { + addCriterion("request_execution_rate =", value, "requestExecutionRate"); return (Criteria) this; } - public Criteria andPassRateNotEqualTo(Long value) { - addCriterion("pass_rate <>", value, "passRate"); + public Criteria andRequestExecutionRateNotEqualTo(String value) { + addCriterion("request_execution_rate <>", value, "requestExecutionRate"); return (Criteria) this; } - public Criteria andPassRateGreaterThan(Long value) { - addCriterion("pass_rate >", value, "passRate"); + public Criteria andRequestExecutionRateGreaterThan(String value) { + addCriterion("request_execution_rate >", value, "requestExecutionRate"); return (Criteria) this; } - public Criteria andPassRateGreaterThanOrEqualTo(Long value) { - addCriterion("pass_rate >=", value, "passRate"); + public Criteria andRequestExecutionRateGreaterThanOrEqualTo(String value) { + addCriterion("request_execution_rate >=", value, "requestExecutionRate"); return (Criteria) this; } - public Criteria andPassRateLessThan(Long value) { - addCriterion("pass_rate <", value, "passRate"); + public Criteria andRequestExecutionRateLessThan(String value) { + addCriterion("request_execution_rate <", value, "requestExecutionRate"); return (Criteria) this; } - public Criteria andPassRateLessThanOrEqualTo(Long value) { - addCriterion("pass_rate <=", value, "passRate"); + public Criteria andRequestExecutionRateLessThanOrEqualTo(String value) { + addCriterion("request_execution_rate <=", value, "requestExecutionRate"); return (Criteria) this; } - public Criteria andPassRateIn(List values) { - addCriterion("pass_rate in", values, "passRate"); + public Criteria andRequestExecutionRateLike(String value) { + addCriterion("request_execution_rate like", value, "requestExecutionRate"); return (Criteria) this; } - public Criteria andPassRateNotIn(List values) { - addCriterion("pass_rate not in", values, "passRate"); + public Criteria andRequestExecutionRateNotLike(String value) { + addCriterion("request_execution_rate not like", value, "requestExecutionRate"); return (Criteria) this; } - public Criteria andPassRateBetween(Long value1, Long value2) { - addCriterion("pass_rate between", value1, value2, "passRate"); + public Criteria andRequestExecutionRateIn(List values) { + addCriterion("request_execution_rate in", values, "requestExecutionRate"); return (Criteria) this; } - public Criteria andPassRateNotBetween(Long value1, Long value2) { - addCriterion("pass_rate not between", value1, value2, "passRate"); + public Criteria andRequestExecutionRateNotIn(List values) { + addCriterion("request_execution_rate not in", values, "requestExecutionRate"); + return (Criteria) this; + } + + public Criteria andRequestExecutionRateBetween(String value1, String value2) { + addCriterion("request_execution_rate between", value1, value2, "requestExecutionRate"); + return (Criteria) this; + } + + public Criteria andRequestExecutionRateNotBetween(String value1, String value2) { + addCriterion("request_execution_rate not between", value1, value2, "requestExecutionRate"); + return (Criteria) this; + } + + public Criteria andRequestPassRateIsNull() { + addCriterion("request_pass_rate is null"); + return (Criteria) this; + } + + public Criteria andRequestPassRateIsNotNull() { + addCriterion("request_pass_rate is not null"); + return (Criteria) this; + } + + public Criteria andRequestPassRateEqualTo(Long value) { + addCriterion("request_pass_rate =", value, "requestPassRate"); + return (Criteria) this; + } + + public Criteria andRequestPassRateNotEqualTo(Long value) { + addCriterion("request_pass_rate <>", value, "requestPassRate"); + return (Criteria) this; + } + + public Criteria andRequestPassRateGreaterThan(Long value) { + addCriterion("request_pass_rate >", value, "requestPassRate"); + return (Criteria) this; + } + + public Criteria andRequestPassRateGreaterThanOrEqualTo(Long value) { + addCriterion("request_pass_rate >=", value, "requestPassRate"); + return (Criteria) this; + } + + public Criteria andRequestPassRateLessThan(Long value) { + addCriterion("request_pass_rate <", value, "requestPassRate"); + return (Criteria) this; + } + + public Criteria andRequestPassRateLessThanOrEqualTo(Long value) { + addCriterion("request_pass_rate <=", value, "requestPassRate"); + return (Criteria) this; + } + + public Criteria andRequestPassRateIn(List values) { + addCriterion("request_pass_rate in", values, "requestPassRate"); + return (Criteria) this; + } + + public Criteria andRequestPassRateNotIn(List values) { + addCriterion("request_pass_rate not in", values, "requestPassRate"); + return (Criteria) this; + } + + public Criteria andRequestPassRateBetween(Long value1, Long value2) { + addCriterion("request_pass_rate between", value1, value2, "requestPassRate"); + return (Criteria) this; + } + + public Criteria andRequestPassRateNotBetween(Long value1, Long value2) { + addCriterion("request_pass_rate not between", value1, value2, "requestPassRate"); return (Criteria) this; } diff --git a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioStep.java b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioStep.java index a989de4ec0..848e2fc501 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioStep.java +++ b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioStep.java @@ -1,12 +1,16 @@ package io.metersphere.api.domain; -import io.metersphere.validation.groups.*; +import io.metersphere.validation.groups.Created; +import io.metersphere.validation.groups.Updated; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.*; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; + import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; -import lombok.Data; @Data public class ApiScenarioStep implements Serializable { @@ -114,7 +118,7 @@ public class ApiScenarioStep implements Serializable { return this.getEscapedColumnName() + " ASC"; } - public static Column[] excludes(Column ... excludes) { + public static Column[] excludes(Column... excludes) { ArrayList columns = new ArrayList<>(Arrays.asList(Column.values())); if (excludes != null && excludes.length > 0) { columns.removeAll(new ArrayList<>(Arrays.asList(excludes))); diff --git a/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioEnvironmentMapper.java b/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioEnvironmentMapper.java index a3f024e2ff..78c2238ed6 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioEnvironmentMapper.java +++ b/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioEnvironmentMapper.java @@ -10,7 +10,7 @@ public interface ApiScenarioEnvironmentMapper { int deleteByExample(ApiScenarioEnvironmentExample example); - int deleteByPrimaryKey(String id); + int deleteByPrimaryKey(String apiScenarioId); int insert(ApiScenarioEnvironment record); @@ -18,7 +18,7 @@ public interface ApiScenarioEnvironmentMapper { List selectByExample(ApiScenarioEnvironmentExample example); - ApiScenarioEnvironment selectByPrimaryKey(String id); + ApiScenarioEnvironment selectByPrimaryKey(String apiScenarioId); int updateByExampleSelective(@Param("record") ApiScenarioEnvironment record, @Param("example") ApiScenarioEnvironmentExample example); diff --git a/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioEnvironmentMapper.xml b/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioEnvironmentMapper.xml index 0230dd2d1b..020e39eff7 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioEnvironmentMapper.xml +++ b/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioEnvironmentMapper.xml @@ -2,9 +2,7 @@ - - - + @@ -67,7 +65,7 @@ - id, api_scenario_id, project_id, environment_id, environment_group_id + api_scenario_id, environment_id, environment_group_id delete from api_scenario_environment - where id = #{id,jdbcType=VARCHAR} + where api_scenario_id = #{apiScenarioId,jdbcType=VARCHAR} delete from api_scenario_environment @@ -100,23 +98,17 @@ - insert into api_scenario_environment (id, api_scenario_id, project_id, - environment_id, environment_group_id) - values (#{id,jdbcType=VARCHAR}, #{apiScenarioId,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, - #{environmentId,jdbcType=VARCHAR}, #{environmentGroupId,jdbcType=VARCHAR}) + insert into api_scenario_environment (api_scenario_id, environment_id, environment_group_id + ) + values (#{apiScenarioId,jdbcType=VARCHAR}, #{environmentId,jdbcType=VARCHAR}, #{environmentGroupId,jdbcType=VARCHAR} + ) insert into api_scenario_environment - - id, - api_scenario_id, - - project_id, - environment_id, @@ -125,15 +117,9 @@ - - #{id,jdbcType=VARCHAR}, - #{apiScenarioId,jdbcType=VARCHAR}, - - #{projectId,jdbcType=VARCHAR}, - #{environmentId,jdbcType=VARCHAR}, @@ -151,15 +137,9 @@ update api_scenario_environment - - id = #{record.id,jdbcType=VARCHAR}, - api_scenario_id = #{record.apiScenarioId,jdbcType=VARCHAR}, - - project_id = #{record.projectId,jdbcType=VARCHAR}, - environment_id = #{record.environmentId,jdbcType=VARCHAR}, @@ -173,9 +153,7 @@ update api_scenario_environment - set id = #{record.id,jdbcType=VARCHAR}, - api_scenario_id = #{record.apiScenarioId,jdbcType=VARCHAR}, - project_id = #{record.projectId,jdbcType=VARCHAR}, + set api_scenario_id = #{record.apiScenarioId,jdbcType=VARCHAR}, environment_id = #{record.environmentId,jdbcType=VARCHAR}, environment_group_id = #{record.environmentGroupId,jdbcType=VARCHAR} @@ -185,12 +163,6 @@ update api_scenario_environment - - api_scenario_id = #{apiScenarioId,jdbcType=VARCHAR}, - - - project_id = #{projectId,jdbcType=VARCHAR}, - environment_id = #{environmentId,jdbcType=VARCHAR}, @@ -198,24 +170,21 @@ environment_group_id = #{environmentGroupId,jdbcType=VARCHAR}, - where id = #{id,jdbcType=VARCHAR} + where api_scenario_id = #{apiScenarioId,jdbcType=VARCHAR} update api_scenario_environment - set api_scenario_id = #{apiScenarioId,jdbcType=VARCHAR}, - project_id = #{projectId,jdbcType=VARCHAR}, - environment_id = #{environmentId,jdbcType=VARCHAR}, + set environment_id = #{environmentId,jdbcType=VARCHAR}, environment_group_id = #{environmentGroupId,jdbcType=VARCHAR} - where id = #{id,jdbcType=VARCHAR} + where api_scenario_id = #{apiScenarioId,jdbcType=VARCHAR} insert into api_scenario_environment - (id, api_scenario_id, project_id, environment_id, environment_group_id) + (api_scenario_id, environment_id, environment_group_id) values - (#{item.id,jdbcType=VARCHAR}, #{item.apiScenarioId,jdbcType=VARCHAR}, #{item.projectId,jdbcType=VARCHAR}, - #{item.environmentId,jdbcType=VARCHAR}, #{item.environmentGroupId,jdbcType=VARCHAR} - ) + (#{item.apiScenarioId,jdbcType=VARCHAR}, #{item.environmentId,jdbcType=VARCHAR}, + #{item.environmentGroupId,jdbcType=VARCHAR}) @@ -228,15 +197,9 @@ ( - - #{item.id,jdbcType=VARCHAR} - #{item.apiScenarioId,jdbcType=VARCHAR} - - #{item.projectId,jdbcType=VARCHAR} - #{item.environmentId,jdbcType=VARCHAR} diff --git a/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioMapper.xml b/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioMapper.xml index 26a2f3abf6..df2fea7464 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioMapper.xml +++ b/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioMapper.xml @@ -7,7 +7,8 @@ - + + @@ -125,9 +126,10 @@ - id, `name`, priority, `status`, step_total, pass_rate, last_report_status, last_report_id, - num, deleted, pos, version_id, ref_id, latest, project_id, module_id, description, - tags, grouped, create_user, create_time, delete_time, delete_user, update_user, update_time + id, `name`, priority, `status`, step_total, request_execution_rate, request_pass_rate, + last_report_status, last_report_id, num, deleted, pos, version_id, ref_id, latest, + project_id, module_id, description, tags, grouped, create_user, create_time, delete_time, + delete_user, update_user, update_time + select + api_scenario.id, api_scenario.`name`,api_scenario.priority, + api_scenario.step_total,api_scenario.request_pass_rate,api_scenario.last_report_status, + api_scenario.request_execution_rate, + api_scenario.last_report_id,api_scenario.grouped, + api_scenario.`status`, api_scenario.num, api_scenario.tags, api_scenario.pos, + api_scenario.project_id, api_scenario.module_id, api_scenario.latest, api_scenario.version_id, + api_scenario.ref_id, api_scenario.create_time, api_scenario.create_user, + api_scenario.update_time, api_scenario.update_user, api_scenario.delete_user, api_scenario.delete_time, + api_scenario.deleted, project_version.name as version_name + from api_scenario + LEFT JOIN project_version ON project_version.id = api_scenario.version_id + where api_scenario.deleted = #{request.deleted} + + + + + + + + + + + + + + + + and ( + api_scenario.num like concat('%', #{request.keyword},'%') + or api_scenario.name like concat('%', #{request.keyword},'%') + or api_scenario.tags like JSON_CONTAINS(tags, concat('["',#{request.keyword},'"]')) + ) + + + + + + + + + and ( + api_scenario.num like concat('%', #{request.keyword},'%') + or api_scenario.name like concat('%', #{request.keyword},'%') + or api_scenario.tags like JSON_CONTAINS(tags, concat('["',#{request.keyword},'"]')) + ) + + + and api_scenario.project_id = #{request.projectId} + + + and api_scenario.id = #{request.scenarioId} + + + and api_scenario.module_id in + + #{nodeId} + + + + + + + + + + + + + + + + + + + + + + + + + + + and api_scenario.status in + + + + and api_scenario.create_user in + + + + and api_scenario.version_id in + + + + and api_scenario.priority in + + + + and api_scenario.id in ( + select api_id from api_definition_custom_field where concat('custom_single_', field_id) = + #{key} + and trim(both '"' from `value`) in + + ) + + + and api_scenario.id in ( + select api_id from api_definition_custom_field where concat('custom_multiple_', field_id) = + #{key} + and + + ) + + + + + + + + + + and api_scenario.name + + + + + + + and api_scenario.num + + + + + + + and api_scenario.update_time + + + + + + + and api_scenario.create_time + + + + + + + and api_scenario.status + + + + + + + and (api_scenario.tags is null or api_scenario.tags + + + + ) + + + + and api_scenario.tags + + + + + + + + + + and api_scenario.id not in ( + + + and api_scenario.id in ( + + select api_id from api_definition_custom_field where field_id = #{custom.id} + + + and `value` + + + + + + and ${custom.value} + + + and left(replace(unix_timestamp(trim(both '"' from `value`)), '.', ''), 13) + + + + + + and trim(both '"' from `value`) + + + + + + ) + + + + + + + + and ${versionTable}.version_id = #{request.versionId} + + + and ${versionTable}.ref_id = #{request.refId} + + + AND ${versionTable}.latest = 1 + + + + + and ${versionTable}.version_id = #{request.versionId} + + + AND ${versionTable}.latest = 1 + + + + + diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioModuleMapper.java b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioModuleMapper.java index 588fddf3eb..bc2ac48ec6 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioModuleMapper.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioModuleMapper.java @@ -1,6 +1,6 @@ package io.metersphere.api.mapper; -import io.metersphere.api.dto.definition.ApiScenarioModuleRequest; +import io.metersphere.api.dto.scenario.ApiScenarioModuleRequest; import io.metersphere.project.dto.ModuleCountDTO; import io.metersphere.project.dto.NodeSortQueryParam; import io.metersphere.system.dto.sdk.BaseModule; diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.java b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.java index e61ab0863b..45169cd337 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.java @@ -7,8 +7,8 @@ import io.metersphere.api.dto.definition.ApiTestCaseDTO; import io.metersphere.api.dto.definition.ApiTestCasePageRequest; import io.metersphere.api.dto.definition.CasePassDTO; import io.metersphere.dto.TestCaseProviderDTO; -import io.metersphere.request.TestCasePageProviderRequest; import io.metersphere.request.AssociateOtherCaseRequest; +import io.metersphere.request.TestCasePageProviderRequest; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -50,4 +50,6 @@ public interface ExtApiTestCaseMapper { List getTestCaseByProvider(@Param("request") AssociateOtherCaseRequest request, @Param("deleted") boolean deleted); + List getTagsByIds(@Param("ids") List ids, @Param("deleted") boolean deleted); + } \ No newline at end of file diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.xml b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.xml index 92a6bf4045..42cf4a3377 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.xml +++ b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.xml @@ -9,6 +9,10 @@ + + + + UPDATE api_test_case SET deleted = 1, @@ -191,6 +195,18 @@ WHERE t1.deleted =#{deleted} + diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionImportUtilService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionImportUtilService.java index 1ddd6e591c..d65667949d 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionImportUtilService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionImportUtilService.java @@ -1,5 +1,6 @@ package io.metersphere.api.service.definition; +import io.metersphere.api.constants.ApiDefinitionStatus; import io.metersphere.api.constants.ApiImportPlatform; import io.metersphere.api.domain.ApiDefinition; import io.metersphere.api.domain.ApiDefinitionBlob; @@ -327,7 +328,7 @@ public class ApiDefinitionImportUtilService { apiDefinition.setUpdateTime(System.currentTimeMillis()); apiDefinition.setNum(NumGenerator.nextNum(request.getProjectId(), ApplicationNumScope.API_DEFINITION)); apiDefinition.setLatest(true); - apiDefinition.setStatus("Underway"); + apiDefinition.setStatus(ApiDefinitionStatus.UNDERWAY.name()); apiDefinition.setRefId(apiDefinition.getId()); apiDefinition.setVersionId(request.getVersionId()); apiMapper.insertSelective(apiDefinition); diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java index a9261216ef..270f8db367 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java @@ -41,6 +41,7 @@ import org.springframework.web.multipart.MultipartFile; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.stream.Collectors; @Service @@ -413,8 +414,7 @@ public class ApiTestCaseService { switch (request.getType()) { case PRIORITY -> batchUpdatePriority(example, updateCase, request.getPriority()); case STATUS -> batchUpdateStatus(example, updateCase, request.getStatus()); - case TAGS -> - batchUpdateTags(example, updateCase, request.getTags(), request.isAppendTag(), sqlSession, mapper); + case TAGS -> batchUpdateTags(example, updateCase, request, ids, sqlSession, mapper); case ENVIRONMENT -> batchUpdateEnvironment(example, updateCase, request.getEnvId()); default -> throw new MSException(Translator.get("batch_edit_type_error")); } @@ -435,23 +435,27 @@ public class ApiTestCaseService { } private void batchUpdateTags(ApiTestCaseExample example, ApiTestCase updateCase, - List tags, boolean appendTag, + ApiCaseBatchEditRequest request, List ids, SqlSession sqlSession, ApiTestCaseMapper mapper) { - if (CollectionUtils.isEmpty(tags)) { + if (CollectionUtils.isEmpty(request.getTags())) { throw new MSException(Translator.get("tags_is_null")); } - if (appendTag) { - List caseList = apiTestCaseMapper.selectByExample(example); - if (CollectionUtils.isNotEmpty(caseList)) { - caseList.forEach(apiTestCase -> { - if (CollectionUtils.isNotEmpty(apiTestCase.getTags())) { - List orgTags = apiTestCase.getTags(); - orgTags.addAll(tags); - apiTestCase.setTags(orgTags); + if (request.isAppendTag()) { + Map caseMap = extApiTestCaseMapper.getTagsByIds(ids, false) + .stream() + .collect(Collectors.toMap(ApiTestCase::getId, Function.identity())); + if (MapUtils.isNotEmpty(caseMap)) { + caseMap.forEach((k, v) -> { + if (CollectionUtils.isNotEmpty(v.getTags())) { + List orgTags = v.getTags(); + orgTags.addAll(request.getTags()); + v.setTags(orgTags.stream().distinct().toList()); } else { - apiTestCase.setTags(tags); + v.setTags(request.getTags()); } - mapper.updateByPrimaryKey(apiTestCase); + v.setUpdateTime(updateCase.getUpdateTime()); + v.setUpdateUser(updateCase.getUpdateUser()); + mapper.updateByPrimaryKeySelective(v); }); sqlSession.flushStatements(); if (sqlSessionFactory != null) { @@ -459,7 +463,7 @@ public class ApiTestCaseService { } } } else { - updateCase.setTags(tags); + updateCase.setTags(request.getTags()); apiTestCaseMapper.updateByExampleSelective(updateCase, example); } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioLogService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioLogService.java new file mode 100644 index 0000000000..ee7feaadba --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioLogService.java @@ -0,0 +1,100 @@ +package io.metersphere.api.service.scenario; + +import io.metersphere.api.domain.ApiScenario; +import io.metersphere.api.domain.ApiScenarioExample; +import io.metersphere.api.mapper.ApiScenarioMapper; +import io.metersphere.project.domain.Project; +import io.metersphere.project.mapper.ProjectMapper; +import io.metersphere.sdk.constants.HttpMethodConstants; +import io.metersphere.sdk.util.JSON; +import io.metersphere.sdk.util.Translator; +import io.metersphere.system.dto.builder.LogDTOBuilder; +import io.metersphere.system.log.constants.OperationLogModule; +import io.metersphere.system.log.constants.OperationLogType; +import io.metersphere.system.log.dto.LogDTO; +import io.metersphere.system.log.service.OperationLogService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +@Service +public class ApiScenarioLogService { + + @Resource + private ProjectMapper projectMapper; + @Resource + private OperationLogService operationLogService; + @Resource + private ApiScenarioMapper apiScenarioMapper; + + public void batchEditLog(List scenarioList, String operator, String projectId) { + saveBatchLog(projectId, scenarioList, "/api/scenario/batch/edit", operator, OperationLogType.UPDATE.name(), false); + } + + + private void saveBatchLog(String projectId, List scenarioList, String path, String operator, String operationType, boolean isHistory) { + Project project = projectMapper.selectByPrimaryKey(projectId); + //取出apiTestCases所有的id为新的list + List scenarioIds = scenarioList.stream().map(ApiScenario::getId).distinct().toList(); + ApiScenarioExample example = new ApiScenarioExample(); + example.createCriteria().andIdIn(scenarioIds); + List apiScenarioList = apiScenarioMapper.selectByExample(example); + List logs = new ArrayList<>(); + apiScenarioList.forEach(item -> { + LogDTO dto = LogDTOBuilder.builder() + .projectId(project.getId()) + .organizationId(project.getOrganizationId()) + .type(operationType) + .module(OperationLogModule.API_SCENARIO) + .method(HttpMethodConstants.POST.name()) + .path(path) + .sourceId(item.getId()) + .content(item.getName()) + .createUser(operator) + .originalValue(JSON.toJSONBytes(item)) + .build().getLogDTO(); + dto.setHistory(isHistory); + logs.add(dto); + } + ); + operationLogService.batchAdd(logs); + } + + public void followLog(String id, String operator) { + ApiScenario scenario = apiScenarioMapper.selectByPrimaryKey(id); + Project project = projectMapper.selectByPrimaryKey(scenario.getProjectId()); + LogDTO dto = new LogDTO( + scenario.getProjectId(), + project.getOrganizationId(), + id, + operator, + OperationLogType.UPDATE.name(), + OperationLogModule.API_SCENARIO, + Translator.get("follow") + scenario.getName()); + + dto.setPath("/api/scenario/follow/" + id); + dto.setMethod(HttpMethodConstants.GET.name()); + dto.setOriginalValue(JSON.toJSONBytes(scenario)); + operationLogService.add(dto); + } + + public void unfollowLog(String id, String operator) { + ApiScenario apiTestCase = apiScenarioMapper.selectByPrimaryKey(id); + Project project = projectMapper.selectByPrimaryKey(apiTestCase.getProjectId()); + LogDTO dto = new LogDTO( + apiTestCase.getProjectId(), + project.getOrganizationId(), + id, + operator, + OperationLogType.UPDATE.name(), + OperationLogModule.API_SCENARIO, + Translator.get("unfollow") + apiTestCase.getName()); + + dto.setPath("/api/scenario/follow/" + id); + dto.setMethod(HttpMethodConstants.GET.name()); + dto.setOriginalValue(JSON.toJSONBytes(apiTestCase)); + operationLogService.add(dto); + } +} diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioModuleService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioModuleService.java index f50677c531..b5ba6310b8 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioModuleService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioModuleService.java @@ -8,7 +8,7 @@ import io.metersphere.api.domain.ApiScenarioModuleExample; import io.metersphere.api.dto.debug.ModuleCreateRequest; import io.metersphere.api.dto.debug.ModuleUpdateRequest; import io.metersphere.api.dto.definition.ApiModuleRequest; -import io.metersphere.api.dto.definition.ApiScenarioModuleRequest; +import io.metersphere.api.dto.scenario.ApiScenarioModuleRequest; import io.metersphere.api.mapper.ApiScenarioMapper; import io.metersphere.api.mapper.ApiScenarioModuleMapper; import io.metersphere.api.mapper.ExtApiScenarioModuleMapper; diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java new file mode 100644 index 0000000000..9a65b74573 --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java @@ -0,0 +1,281 @@ +package io.metersphere.api.service.scenario; + +import com.alibaba.excel.util.BooleanUtils; +import io.metersphere.api.domain.*; +import io.metersphere.api.dto.scenario.ApiScenarioBatchEditRequest; +import io.metersphere.api.dto.scenario.ApiScenarioDTO; +import io.metersphere.api.dto.scenario.ApiScenarioPageRequest; +import io.metersphere.api.mapper.*; +import io.metersphere.sdk.domain.Environment; +import io.metersphere.sdk.domain.EnvironmentExample; +import io.metersphere.sdk.domain.EnvironmentGroup; +import io.metersphere.sdk.domain.EnvironmentGroupExample; +import io.metersphere.sdk.exception.MSException; +import io.metersphere.sdk.mapper.EnvironmentGroupMapper; +import io.metersphere.sdk.mapper.EnvironmentMapper; +import io.metersphere.sdk.util.SubListUtils; +import io.metersphere.sdk.util.Translator; +import io.metersphere.system.service.UserLoginService; +import jakarta.annotation.Resource; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Service +@Transactional(rollbackFor = Exception.class) +public class ApiScenarioService { + + public static final Long ORDER_STEP = 5000L; + + @Resource + private ApiScenarioMapper apiScenarioMapper; + + @Resource + private ExtApiScenarioMapper extApiScenarioMapper; + + @Resource + private UserLoginService userLoginService; + @Resource + private ApiScenarioEnvironmentMapper apiScenarioEnvironmentMapper; + @Resource + private ApiScenarioModuleMapper apiScenarioModuleMapper; + @Resource + private EnvironmentMapper environmentMapper; + @Resource + private EnvironmentGroupMapper environmentGroupMapper; + @Resource + private ApiScenarioLogService apiScenarioLogService; + @Resource + private ApiScenarioFollowerMapper apiScenarioFollowerMapper; + @Resource + private SqlSessionFactory sqlSessionFactory; + public static final String PRIORITY = "Priority"; + public static final String STATUS = "Status"; + public static final String TAGS = "Tags"; + public static final String ENVIRONMENT = "Environment"; + + + public List getScenarioPage(ApiScenarioPageRequest request) { + //CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request, userId); + //TODO 场景的自定义字段 等设计 不一定会有 + List list = extApiScenarioMapper.list(request); + if (!CollectionUtils.isEmpty(list)) { + processApiScenario(list); + } + return list; + } + + private void processApiScenario(List scenarioLists) { + Set userIds = extractUserIds(scenarioLists); + Map userMap = userLoginService.getUserNameMap(new ArrayList<>(userIds)); + //取出所有的apiId + List scenarioIds = scenarioLists.stream().map(ApiScenarioDTO::getId).distinct().toList(); + ApiScenarioEnvironmentExample scenarioEnvironmentExample = new ApiScenarioEnvironmentExample(); + scenarioEnvironmentExample.createCriteria().andApiScenarioIdIn(scenarioIds); + List apiScenarioEnvironments = apiScenarioEnvironmentMapper.selectByExample(scenarioEnvironmentExample); + //生成map key为id value为ApiScenarioEnvironment + Map environmentMap = apiScenarioEnvironments.stream().collect(Collectors.toMap(ApiScenarioEnvironment::getApiScenarioId, item -> item)); + List envIds = apiScenarioEnvironments.stream().map(ApiScenarioEnvironment::getEnvironmentId).toList(); + EnvironmentExample environmentExample = new EnvironmentExample(); + environmentExample.createCriteria().andIdIn(envIds); + List environments = environmentMapper.selectByExample(environmentExample); + Map envMap = environments.stream().collect(Collectors.toMap(Environment::getId, Environment::getName)); + List envGroupIds = apiScenarioEnvironments.stream().map(ApiScenarioEnvironment::getEnvironmentGroupId).toList(); + EnvironmentGroupExample groupExample = new EnvironmentGroupExample(); + groupExample.createCriteria().andIdIn(envGroupIds); + List environmentGroups = environmentGroupMapper.selectByExample(groupExample); + Map groupMap = environmentGroups.stream().collect(Collectors.toMap(EnvironmentGroup::getId, EnvironmentGroup::getName)); + //取模块id为新的set + List moduleIds = scenarioLists.stream().map(ApiScenarioDTO::getModuleId).distinct().toList(); + ApiScenarioModuleExample moduleExample = new ApiScenarioModuleExample(); + moduleExample.createCriteria().andIdIn(moduleIds); + List modules = apiScenarioModuleMapper.selectByExample(moduleExample); + //生成map key为id value为name + Map moduleMap = modules.stream().collect(Collectors.toMap(ApiScenarioModule::getId, ApiScenarioModule::getName)); + scenarioLists.forEach(item -> { + item.setCreateUserName(userMap.get(item.getCreateUser())); + item.setDeleteUserName(userMap.get(item.getDeleteUser())); + item.setUpdateUserName(userMap.get(item.getUpdateUser())); + item.setModulePath(StringUtils.isNotBlank(moduleMap.get(item.getModuleId())) ? moduleMap.get(item.getModuleId()) : Translator.get("api_unplanned_scenario")); + if (!item.getGrouped() && environmentMap.containsKey(item.getId()) && + StringUtils.isNotBlank(environmentMap.get(item.getId()).getEnvironmentId()) && + envMap.containsKey(environmentMap.get(item.getId()).getEnvironmentId())) { + item.setEnvironmentName(environmentMap.get(item.getId()).getEnvironmentId()); + } else if (item.getGrouped() && environmentMap.containsKey(item.getId()) && + StringUtils.isNotBlank(environmentMap.get(item.getId()).getEnvironmentGroupId()) && + groupMap.containsKey(environmentMap.get(item.getId()).getEnvironmentGroupId())) { + item.setEnvironmentName(groupMap.get(item.getId())); + } + }); + } + + private Set extractUserIds(List list) { + return list.stream() + .flatMap(apiDefinition -> Stream.of(apiDefinition.getUpdateUser(), apiDefinition.getDeleteUser(), apiDefinition.getCreateUser())) + .collect(Collectors.toSet()); + } + + public void batchEdit(ApiScenarioBatchEditRequest request, String userId) { + List ids = doSelectIds(request, false); + if (CollectionUtils.isEmpty(ids)) { + return; + } + SubListUtils.dealForSubList(ids, 500, subList -> batchEditByType(request, subList, userId, request.getProjectId())); + } + + private void batchEditByType(ApiScenarioBatchEditRequest request, List ids, String userId, String projectId) { + ApiScenarioExample example = new ApiScenarioExample(); + example.createCriteria().andIdIn(ids); + ApiScenario updateScenario = new ApiScenario(); + updateScenario.setUpdateUser(userId); + updateScenario.setUpdateTime(System.currentTimeMillis()); + SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); + ApiScenarioMapper mapper = sqlSession.getMapper(ApiScenarioMapper.class); + + switch (request.getType()) { + case PRIORITY -> batchUpdatePriority(example, updateScenario, request.getPriority()); + case STATUS -> batchUpdateStatus(example, updateScenario, request.getStatus()); + case TAGS -> batchUpdateTags(example, updateScenario, request, ids, sqlSession, mapper); + case ENVIRONMENT -> batchUpdateEnvironment(example, updateScenario, request, ids); + default -> throw new MSException(Translator.get("batch_edit_type_error")); + } + List scenarioInfoByIds = extApiScenarioMapper.getInfoByIds(ids, false); + apiScenarioLogService.batchEditLog(scenarioInfoByIds, userId, projectId); + } + + private void batchUpdateEnvironment(ApiScenarioExample example, ApiScenario updateScenario, + ApiScenarioBatchEditRequest request, + List ids) { + if (BooleanUtils.isFalse(request.isGrouped())) { + if (StringUtils.isBlank(request.getEnvId())) { + throw new MSException(Translator.get("environment_id_is_null")); + } + Environment environment = environmentMapper.selectByPrimaryKey(request.getEnvId()); + if (environment == null) { + throw new MSException(Translator.get("environment_is_not_exist")); + } + updateScenario.setGrouped(false); + ApiScenarioEnvironment apiScenarioEnvironment = new ApiScenarioEnvironment(); + apiScenarioEnvironment.setEnvironmentId(request.getEnvId()); + ApiScenarioEnvironmentExample environmentExample = new ApiScenarioEnvironmentExample(); + environmentExample.createCriteria().andApiScenarioIdIn(ids); + apiScenarioEnvironmentMapper.updateByExampleSelective(apiScenarioEnvironment, environmentExample); + } else { + if (StringUtils.isBlank(request.getGroupId())) { + throw new MSException(Translator.get("environment_group_id_is_null")); + } + EnvironmentGroup environmentGroup = environmentGroupMapper.selectByPrimaryKey(request.getGroupId()); + if (environmentGroup == null) { + throw new MSException(Translator.get("environment_group_is_not_exist")); + } + updateScenario.setGrouped(true); + ApiScenarioEnvironment apiScenarioEnvironment = new ApiScenarioEnvironment(); + apiScenarioEnvironment.setEnvironmentGroupId(request.getGroupId()); + ApiScenarioEnvironmentExample environmentExample = new ApiScenarioEnvironmentExample(); + environmentExample.createCriteria().andApiScenarioIdIn(ids); + apiScenarioEnvironmentMapper.updateByExampleSelective(apiScenarioEnvironment, environmentExample); + } + apiScenarioMapper.updateByExampleSelective(updateScenario, example); + + } + + private void batchUpdateTags(ApiScenarioExample example, ApiScenario updateScenario, + ApiScenarioBatchEditRequest request, List ids, + SqlSession sqlSession, ApiScenarioMapper mapper) { + if (CollectionUtils.isEmpty(request.getTags())) { + throw new MSException(Translator.get("tags_is_null")); + } + if (request.isAppendTag()) { + Map scenarioMap = extApiScenarioMapper.getTagsByIds(ids, false) + .stream() + .collect(Collectors.toMap(ApiScenario::getId, Function.identity())); + if (MapUtils.isNotEmpty(scenarioMap)) { + scenarioMap.forEach((k, v) -> { + if (CollectionUtils.isNotEmpty(v.getTags())) { + List orgTags = v.getTags(); + orgTags.addAll(request.getTags()); + v.setTags(orgTags.stream().distinct().toList()); + } else { + v.setTags(request.getTags()); + } + v.setUpdateTime(updateScenario.getUpdateTime()); + v.setUpdateUser(updateScenario.getUpdateUser()); + mapper.updateByPrimaryKeySelective(v); + }); + sqlSession.flushStatements(); + if (sqlSessionFactory != null) { + SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory); + } + } + } else { + updateScenario.setTags(request.getTags()); + apiScenarioMapper.updateByExampleSelective(updateScenario, example); + } + } + + private void batchUpdateStatus(ApiScenarioExample example, ApiScenario updateScenario, String status) { + if (StringUtils.isBlank(status)) { + throw new MSException(Translator.get("status_is_null")); + } + updateScenario.setStatus(status); + apiScenarioMapper.updateByExampleSelective(updateScenario, example); + } + + private void batchUpdatePriority(ApiScenarioExample example, ApiScenario updateScenario, String priority) { + if (StringUtils.isBlank(priority)) { + throw new MSException(Translator.get("priority_is_null")); + } + updateScenario.setPriority(priority); + apiScenarioMapper.updateByExampleSelective(updateScenario, example); + } + + public List doSelectIds(ApiScenarioBatchEditRequest request, boolean deleted) { + if (request.isSelectAll()) { + List ids = extApiScenarioMapper.getIds(request, deleted); + if (CollectionUtils.isNotEmpty(request.getExcludeIds())) { + ids.removeAll(request.getExcludeIds()); + } + return ids; + } else { + return request.getSelectIds(); + } + } + + public void follow(String id, String userId) { + checkApiScenario(id); + ApiScenarioFollowerExample example = new ApiScenarioFollowerExample(); + example.createCriteria().andApiScenarioIdEqualTo(id).andUserIdEqualTo(userId); + if (apiScenarioFollowerMapper.countByExample(example) > 0) { + apiScenarioFollowerMapper.deleteByPrimaryKey(id, userId); + apiScenarioLogService.unfollowLog(id, userId); + } else { + ApiScenarioFollower apiScenarioFollower = new ApiScenarioFollower(); + apiScenarioFollower.setApiScenarioId(id); + apiScenarioFollower.setUserId(userId); + apiScenarioFollowerMapper.insertSelective(apiScenarioFollower); + apiScenarioLogService.followLog(id, userId); + } + } + + private ApiScenario checkApiScenario(String id) { + ApiScenario apiScenario = apiScenarioMapper.selectByPrimaryKey(id); + if (apiScenario == null) { + throw new MSException(Translator.get("api_scenario_is_not_exist")); + } + return apiScenario; + } +} diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java new file mode 100644 index 0000000000..a58e8428b6 --- /dev/null +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java @@ -0,0 +1,455 @@ +package io.metersphere.api.controller; + +import io.metersphere.api.domain.*; +import io.metersphere.api.dto.scenario.ApiScenarioBatchEditRequest; +import io.metersphere.api.dto.scenario.ApiScenarioDTO; +import io.metersphere.api.dto.scenario.ApiScenarioPageRequest; +import io.metersphere.api.mapper.*; +import io.metersphere.sdk.constants.ApplicationNumScope; +import io.metersphere.sdk.constants.PermissionConstants; +import io.metersphere.sdk.constants.SessionConstants; +import io.metersphere.sdk.domain.Environment; +import io.metersphere.sdk.domain.EnvironmentExample; +import io.metersphere.sdk.domain.EnvironmentGroup; +import io.metersphere.sdk.mapper.EnvironmentGroupMapper; +import io.metersphere.sdk.mapper.EnvironmentMapper; +import io.metersphere.sdk.util.JSON; +import io.metersphere.system.base.BaseTest; +import io.metersphere.system.controller.handler.ResultHolder; +import io.metersphere.system.log.constants.OperationLogType; +import io.metersphere.system.uid.NumGenerator; +import io.metersphere.system.utils.Pager; +import jakarta.annotation.Resource; +import org.apache.commons.collections.CollectionUtils; +import org.junit.jupiter.api.*; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultMatcher; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; + +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class ApiScenarioControllerTests extends BaseTest { + private static final String BASE_PATH = "/api/scenario/"; + private static final String PAGE = BASE_PATH + "page"; + private static final String TRASH_PAGE = BASE_PATH + "trash/page"; + private static final String BATCH_EDIT = BASE_PATH + "batch/edit"; + private static final String FOLLOW = BASE_PATH + "follow/"; + + private static final ResultMatcher ERROR_REQUEST_MATCHER = status().is5xxServerError(); + @Resource + private ApiScenarioMapper apiScenarioMapper; + @Resource + private ApiScenarioModuleMapper apiScenarioModuleMapper; + @Resource + private ExtApiScenarioMapper extApiScenarioMapper; + @Resource + private ApiScenarioEnvironmentMapper apiScenarioEnvironmentMapper; + @Resource + private EnvironmentMapper environmentMapper; + @Resource + private ApiScenarioFollowerMapper apiScenarioFollowerMapper; + @Resource + private EnvironmentGroupMapper environmentGroupMapper; + + public static T parseObjectFromMvcResult(MvcResult mvcResult, Class parseClass) { + try { + String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); + ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class); + //返回请求正常 + Assertions.assertNotNull(resultHolder); + return JSON.parseObject(JSON.toJSONString(resultHolder.getData()), parseClass); + } catch (Exception ignore) { + } + return null; + } + + private MvcResult responsePost(String url, Object param) throws Exception { + return mockMvc.perform(MockMvcRequestBuilders.post(url) + .header(SessionConstants.HEADER_TOKEN, sessionId) + .header(SessionConstants.CSRF_TOKEN, csrfToken) + .content(JSON.toJSONString(param)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn(); + } + + public void initApiScenario() { + ApiScenarioModule apiScenarioModule = new ApiScenarioModule(); + apiScenarioModule.setId("scenario-moduleId"); + apiScenarioModule.setProjectId(DEFAULT_PROJECT_ID); + apiScenarioModule.setName("场景模块"); + apiScenarioModule.setCreateTime(System.currentTimeMillis()); + apiScenarioModule.setUpdateTime(System.currentTimeMillis()); + apiScenarioModule.setCreateUser("admin"); + apiScenarioModule.setUpdateUser("admin"); + apiScenarioModule.setPos(0L); + apiScenarioModuleMapper.insertSelective(apiScenarioModule); + + // 创建环境组 + EnvironmentGroup environmentGroup = new EnvironmentGroup(); + environmentGroup.setId("scenario-environment-group-id"); + environmentGroup.setProjectId(DEFAULT_PROJECT_ID); + environmentGroup.setName("环境组"); + environmentGroup.setCreateTime(System.currentTimeMillis()); + environmentGroup.setUpdateTime(System.currentTimeMillis()); + environmentGroup.setCreateUser("admin"); + environmentGroup.setUpdateUser("admin"); + environmentGroup.setPos(0L); + environmentGroupMapper.insertSelective(environmentGroup); + + EnvironmentExample environmentExample = new EnvironmentExample(); + environmentExample.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID).andMockEqualTo(true); + List environments = environmentMapper.selectByExample(environmentExample); + + for (int i = 0; i < 10; i++) { + ApiScenario apiScenario = new ApiScenario(); + apiScenario.setId("api-scenario-id" + i); + apiScenario.setProjectId(DEFAULT_PROJECT_ID); + apiScenario.setName(StringUtils.join("接口场景", apiScenario.getId())); + apiScenario.setModuleId("scenario-moduleId"); + apiScenario.setStatus("未规划"); + apiScenario.setNum(NumGenerator.nextNum(DEFAULT_PROJECT_ID, ApplicationNumScope.API_SCENARIO)); + apiScenario.setPos(0L); + apiScenario.setPriority("P0"); + apiScenario.setLatest(true); + apiScenario.setVersionId("1.0"); + apiScenario.setRefId(apiScenario.getId()); + apiScenario.setCreateTime(System.currentTimeMillis()); + apiScenario.setUpdateTime(System.currentTimeMillis()); + apiScenario.setCreateUser("admin"); + apiScenario.setUpdateUser("admin"); + ApiScenarioEnvironment apiScenarioEnvironment = new ApiScenarioEnvironment(); + apiScenarioEnvironment.setApiScenarioId(apiScenario.getId()); + if (i % 2 == 0) { + apiScenario.setTags(new ArrayList<>(List.of("tag1", "tag2"))); + apiScenario.setGrouped(true); + apiScenarioEnvironment.setEnvironmentGroupId("scenario-environment-group-id"); + } else { + apiScenario.setGrouped(false); + apiScenarioEnvironment.setEnvironmentId(environments.get(0).getId()); + } + apiScenarioMapper.insertSelective(apiScenario); + apiScenarioEnvironmentMapper.insertSelective(apiScenarioEnvironment); + } + } + + public void initApiScenarioTrash() { + ApiScenarioModule apiScenarioModule = new ApiScenarioModule(); + apiScenarioModule.setId("scenario-moduleId-trash"); + apiScenarioModule.setProjectId(DEFAULT_PROJECT_ID); + apiScenarioModule.setName("场景模块-trash"); + apiScenarioModule.setCreateTime(System.currentTimeMillis()); + apiScenarioModule.setUpdateTime(System.currentTimeMillis()); + apiScenarioModule.setCreateUser("admin"); + apiScenarioModule.setUpdateUser("admin"); + apiScenarioModule.setPos(0L); + apiScenarioModuleMapper.insertSelective(apiScenarioModule); + for (int i = 0; i < 10; i++) { + ApiScenario apiScenario = new ApiScenario(); + apiScenario.setId("trash-api-scenario-id" + i); + apiScenario.setProjectId(DEFAULT_PROJECT_ID); + apiScenario.setName(StringUtils.join("接口场景-回收站", apiScenario.getId())); + apiScenario.setModuleId("scenario-moduleId-trash"); + apiScenario.setStatus("未规划"); + apiScenario.setNum(NumGenerator.nextNum(DEFAULT_PROJECT_ID, ApplicationNumScope.API_SCENARIO)); + apiScenario.setPos(0L); + apiScenario.setLatest(true); + apiScenario.setPriority("P0"); + apiScenario.setVersionId("1.0"); + apiScenario.setRefId(apiScenario.getId()); + apiScenario.setCreateTime(System.currentTimeMillis()); + apiScenario.setUpdateTime(System.currentTimeMillis()); + apiScenario.setCreateUser("admin"); + apiScenario.setUpdateUser("admin"); + apiScenarioMapper.insertSelective(apiScenario); + ApiScenarioEnvironment apiScenarioEnvironment = new ApiScenarioEnvironment(); + apiScenarioEnvironment.setApiScenarioId(apiScenario.getId()); + apiScenarioEnvironmentMapper.insertSelective(apiScenarioEnvironment); + } + } + + @Test + @Order(11) + public void page() throws Exception { + // @@请求成功 + initApiScenario(); + ApiScenarioPageRequest pageRequest = new ApiScenarioPageRequest(); + pageRequest.setProjectId(DEFAULT_PROJECT_ID); + pageRequest.setPageSize(10); + pageRequest.setCurrent(1); + MvcResult mvcResult = responsePost(PAGE, pageRequest); + Pager returnPager = parseObjectFromMvcResult(mvcResult, Pager.class); + //返回值不为空 + Assertions.assertNotNull(returnPager); + //返回值的页码和当前页码相同 + Assertions.assertEquals(returnPager.getCurrent(), pageRequest.getCurrent()); + //返回的数据量不超过规定要返回的数据量相同 + Assertions.assertTrue(((List) returnPager.getList()).size() <= pageRequest.getPageSize()); + + //查询api-scenario-id1的数据 + pageRequest.setScenarioId("api-scenario-id1"); + mvcResult = responsePost(PAGE, pageRequest); + returnPager = parseObjectFromMvcResult(mvcResult, Pager.class); + //返回值不为空 + Assertions.assertNotNull(returnPager); + //返回值的页码和当前页码相同 + Assertions.assertEquals(returnPager.getCurrent(), pageRequest.getCurrent()); + + List scenarioDTOS = JSON.parseArray(JSON.toJSONString(returnPager.getList()), ApiScenarioDTO.class); + scenarioDTOS.forEach(caseDTO -> Assertions.assertEquals(caseDTO.getId(), "api-scenario-id1")); + + //查询模块为moduleId1的数据 + pageRequest.setScenarioId(null); + pageRequest.setModuleIds(List.of("scenario-moduleId")); + mvcResult = responsePost(PAGE, pageRequest); + returnPager = parseObjectFromMvcResult(mvcResult, Pager.class); + //返回值不为空 + Assertions.assertNotNull(returnPager); + //返回值的页码和当前页码相同 + Assertions.assertEquals(returnPager.getCurrent(), pageRequest.getCurrent()); + scenarioDTOS = JSON.parseArray(JSON.toJSONString(returnPager.getList()), ApiScenarioDTO.class); + scenarioDTOS.forEach(scenario -> Assertions.assertEquals(scenario.getModuleId(), "scenario-moduleId")); + + pageRequest.setModuleIds(null); + pageRequest.setSort(new HashMap<>() {{ + put("createTime", "asc"); + }}); + responsePost(PAGE, pageRequest); + + pageRequest = new ApiScenarioPageRequest(); + pageRequest.setProjectId(DEFAULT_PROJECT_ID); + pageRequest.setPageSize(10); + pageRequest.setCurrent(1); + pageRequest.setModuleIds(List.of("scenario-moduleId")); + pageRequest.setFilter(new HashMap<>() {{ + put("priority", List.of("P0")); + }}); + mvcResult = responsePost(PAGE, pageRequest); + returnPager = parseObjectFromMvcResult(mvcResult, Pager.class); + //返回值不为空 + Assertions.assertNotNull(returnPager); + //返回值的页码和当前页码相同 + Assertions.assertEquals(returnPager.getCurrent(), pageRequest.getCurrent()); + scenarioDTOS = JSON.parseArray(JSON.toJSONString(returnPager.getList()), ApiScenarioDTO.class); + scenarioDTOS.forEach(scenario -> Assertions.assertEquals(scenario.getPriority(), "P0")); + + //校验权限 + requestPostPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_READ, PAGE, pageRequest); + } + + @Test + @Order(12) + public void follow() throws Exception { + // @@请求成功 + this.requestGetWithOk(FOLLOW + "api-scenario-id1"); + ApiScenarioFollowerExample example = new ApiScenarioFollowerExample(); + example.createCriteria().andApiScenarioIdEqualTo("api-scenario-id1").andUserIdEqualTo("admin"); + List followers = apiScenarioFollowerMapper.selectByExample(example); + Assertions.assertTrue(CollectionUtils.isNotEmpty(followers)); + // @@校验日志 + checkLog("api-scenario-id1", OperationLogType.UPDATE); + this.requestGet(FOLLOW + "111").andExpect(ERROR_REQUEST_MATCHER); + // @@校验权限 + requestGetPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_UPDATE, FOLLOW + "api-scenario-id1"); + + // @@请求成功 + this.requestGetWithOk(FOLLOW + "api-scenario-id1"); + example = new ApiScenarioFollowerExample(); + example.createCriteria().andApiScenarioIdEqualTo("api-scenario-id1").andUserIdEqualTo("admin"); + followers = apiScenarioFollowerMapper.selectByExample(example); + Assertions.assertTrue(CollectionUtils.isEmpty(followers)); + // @@校验日志 + checkLog("api-scenario-id1", OperationLogType.UPDATE); + this.requestGet(FOLLOW + "111").andExpect(ERROR_REQUEST_MATCHER); + + } + + + @Test + @Order(13) + public void batchEdit() throws Exception { + // 追加标签 + ApiScenarioBatchEditRequest request = new ApiScenarioBatchEditRequest(); + request.setProjectId(DEFAULT_PROJECT_ID); + request.setType("Tags"); + request.setAppendTag(true); + request.setSelectAll(true); + request.setTags(new LinkedHashSet<>(List.of("tag1", "tag3", "tag4"))); + responsePost(BATCH_EDIT, request); + ApiScenarioExample example = new ApiScenarioExample(); + List ids = extApiScenarioMapper.getIds(request, false); + example.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID).andDeletedEqualTo(false).andIdIn(ids); + apiScenarioMapper.selectByExample(example).forEach(apiTestCase -> { + Assertions.assertTrue(apiTestCase.getTags().contains("tag1")); + Assertions.assertTrue(apiTestCase.getTags().contains("tag3")); + Assertions.assertTrue(apiTestCase.getTags().contains("tag4")); + }); + //覆盖标签 + request.setTags(new LinkedHashSet<>(List.of("tag1"))); + request.setAppendTag(false); + responsePost(BATCH_EDIT, request); + apiScenarioMapper.selectByExample(example).forEach(scenario -> { + Assertions.assertEquals(scenario.getTags(), List.of("tag1")); + }); + //标签为空 报错 + request.setTags(new LinkedHashSet<>()); + this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER); + //ids为空的时候 + request.setTags(new LinkedHashSet<>(List.of("tag1"))); + request.setSelectAll(true); + List apiScenarioList = apiScenarioMapper.selectByExample(example); + //提取所有的id + List apiIdList = apiScenarioList.stream().map(ApiScenario::getId).toList(); + request.setSelectIds(apiIdList); + request.setExcludeIds(apiIdList); + responsePost(BATCH_EDIT, request); + + //优先级 + request.setTags(new LinkedHashSet<>()); + request.setSelectAll(true); + request.setType("Priority"); + request.setModuleIds(List.of("scenario-moduleId")); + request.setPriority("P3"); + request.setExcludeIds(new ArrayList<>()); + responsePost(BATCH_EDIT, request); + //判断数据的优先级是不是P3 + example.clear(); + example.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID).andDeletedEqualTo(false); + List apiScenarios = apiScenarioMapper.selectByExample(example); + + apiScenarios.forEach(apiTestCase -> Assertions.assertEquals(apiTestCase.getPriority(), "P3")); + //优先级数据为空 + request.setPriority(null); + this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER); + //ids为空的时候 + request.setPriority("P3"); + request.setSelectAll(false); + request.setSelectIds(List.of("api-scenario-id1")); + request.setExcludeIds(List.of("api-scenario-id1")); + responsePost(BATCH_EDIT, request); + //状态 + request.setPriority(null); + request.setType("Status"); + request.setStatus("Completed"); + request.setSelectAll(true); + request.setExcludeIds(new ArrayList<>()); + responsePost(BATCH_EDIT, request); + //判断数据的状态是不是Completed + apiScenarios = apiScenarioMapper.selectByExample(example); + apiScenarios.forEach(apiTestCase -> Assertions.assertEquals(apiTestCase.getStatus(), "Completed")); + //状态数据为空 + request.setStatus(null); + this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER); + //环境 + request.setStatus(null); + request.setType("Environment"); + EnvironmentExample environmentExample = new EnvironmentExample(); + environmentExample.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID).andMockEqualTo(true); + List environments = environmentMapper.selectByExample(environmentExample); + request.setEnvId(environments.get(0).getId()); + responsePost(BATCH_EDIT, request); + //取所有的ids + List scenarioIds = apiScenarios.stream().map(ApiScenario::getId).toList(); + //判断数据的环境是不是environments.get(0).getId() + ApiScenarioEnvironmentExample apiScenarioEnvironmentExample = new ApiScenarioEnvironmentExample(); + apiScenarioEnvironmentExample.createCriteria().andApiScenarioIdIn(scenarioIds); + List apiScenarioEnvironments = apiScenarioEnvironmentMapper.selectByExample(apiScenarioEnvironmentExample); + apiScenarioEnvironments.forEach(apiTestCase -> Assertions.assertEquals(apiTestCase.getEnvironmentId(), environments.get(0).getId())); + + //环境数据为空 + request.setEnvId(null); + this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER); + //环境不存在 + request.setEnvId("111"); + this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER); + //环境组 + request.setGrouped(true); + request.setGroupId("scenario-environment-group-id"); + responsePost(BATCH_EDIT, request); + apiScenarioEnvironments = apiScenarioEnvironmentMapper.selectByExample(apiScenarioEnvironmentExample); + apiScenarioEnvironments.forEach(apiTestCase -> Assertions.assertEquals(apiTestCase.getEnvironmentGroupId(), "scenario-environment-group-id")); + apiScenarios = apiScenarioMapper.selectByExample(example); + apiScenarios.forEach(apiTestCase -> Assertions.assertEquals(apiTestCase.getGrouped(), true)); + + //环境组数据为空 + request.setGroupId(null); + this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER); + //环境组不存在 + request.setGroupId("111"); + this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER); + //类型错误 + request.setType("111"); + this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER); + + //校验权限 + requestPostPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_UPDATE, BATCH_EDIT, request); + + } + + @Test + @Order(15) + public void trashPage() throws Exception { + // @@请求成功 + initApiScenarioTrash(); + ApiScenarioPageRequest pageRequest = new ApiScenarioPageRequest(); + pageRequest.setProjectId(DEFAULT_PROJECT_ID); + pageRequest.setPageSize(10); + pageRequest.setCurrent(1); + MvcResult mvcResult = responsePost(TRASH_PAGE, pageRequest); + Pager returnPager = parseObjectFromMvcResult(mvcResult, Pager.class); + //返回值不为空 + Assertions.assertNotNull(returnPager); + //返回值的页码和当前页码相同 + Assertions.assertEquals(returnPager.getCurrent(), pageRequest.getCurrent()); + //返回的数据量不超过规定要返回的数据量相同 + Assertions.assertTrue(((List) returnPager.getList()).size() <= pageRequest.getPageSize()); + + //查询api-scenario-id1的数据 + pageRequest.setScenarioId("trash-api-scenario-id1"); + mvcResult = responsePost(TRASH_PAGE, pageRequest); + returnPager = parseObjectFromMvcResult(mvcResult, Pager.class); + //返回值不为空 + Assertions.assertNotNull(returnPager); + //返回值的页码和当前页码相同 + Assertions.assertEquals(returnPager.getCurrent(), pageRequest.getCurrent()); + + List scenarioDTOS = JSON.parseArray(JSON.toJSONString(returnPager.getList()), ApiScenarioDTO.class); + scenarioDTOS.forEach(caseDTO -> Assertions.assertEquals(caseDTO.getId(), "trash-api-scenario-id1")); + + //查询模块为moduleId1的数据 + pageRequest.setScenarioId(null); + pageRequest.setModuleIds(List.of("scenario-moduleId-trash")); + mvcResult = responsePost(TRASH_PAGE, pageRequest); + returnPager = parseObjectFromMvcResult(mvcResult, Pager.class); + //返回值不为空 + Assertions.assertNotNull(returnPager); + //返回值的页码和当前页码相同 + Assertions.assertEquals(returnPager.getCurrent(), pageRequest.getCurrent()); + scenarioDTOS = JSON.parseArray(JSON.toJSONString(returnPager.getList()), ApiScenarioDTO.class); + scenarioDTOS.forEach(scenario -> Assertions.assertEquals(scenario.getModuleId(), "scenario-moduleId-trash")); + + pageRequest.setModuleIds(null); + pageRequest.setSort(new HashMap<>() {{ + put("createTime", "asc"); + }}); + responsePost(TRASH_PAGE, pageRequest); + //校验权限 + requestPostPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_READ, TRASH_PAGE, pageRequest); + } + + +} \ No newline at end of file diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioModuleControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioModuleControllerTests.java index 3ae19e1526..e3ae69d295 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioModuleControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioModuleControllerTests.java @@ -6,7 +6,7 @@ import io.metersphere.api.domain.ApiScenarioModule; import io.metersphere.api.domain.ApiScenarioModuleExample; import io.metersphere.api.dto.debug.ModuleCreateRequest; import io.metersphere.api.dto.debug.ModuleUpdateRequest; -import io.metersphere.api.dto.definition.ApiScenarioModuleRequest; +import io.metersphere.api.dto.scenario.ApiScenarioModuleRequest; import io.metersphere.api.mapper.ApiScenarioMapper; import io.metersphere.api.mapper.ApiScenarioModuleMapper; import io.metersphere.api.service.scenario.ApiScenarioModuleService; diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/log/constants/OperationLogModule.java b/backend/services/system-setting/src/main/java/io/metersphere/system/log/constants/OperationLogModule.java index 085758c03b..3d58cd1d50 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/log/constants/OperationLogModule.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/log/constants/OperationLogModule.java @@ -21,6 +21,7 @@ public class OperationLogModule { public static final String API_DEFINITION = "API_DEFINITION"; public static final String API_DEFINITION_MOCK = "API_DEFINITION_MOCK"; public static final String API_DEFINITION_CASE = "API_DEFINITION_CASE"; + public static final String API_SCENARIO = "API_SCENARIO"; public static final String AUTH_TITLE = "AUTH_TITLE"; public static final String PROJECT_ENVIRONMENT_SETTING = "PROJECT_ENVIRONMENT_SETTING"; public static final String PROJECT_PROJECT_MANAGER = "PROJECT_PROJECT_MANAGER";