diff --git a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioCsvStep.java b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioCsvStep.java index 59e90b586b..bac7dea3d7 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioCsvStep.java +++ b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioCsvStep.java @@ -25,12 +25,18 @@ public class ApiScenarioCsvStep implements Serializable { @Size(min = 1, max = 50, message = "{api_scenario_csv_step.step_id.length_range}", groups = {Created.class, Updated.class}) private String stepId; + @Schema(description = "场景ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{api_scenario_csv_step.scenario_id.not_blank}", groups = {Created.class}) + @Size(min = 1, max = 50, message = "{api_scenario_csv_step.scenario_id.length_range}", groups = {Created.class, Updated.class}) + private String scenarioId; + private static final long serialVersionUID = 1L; public enum Column { id("id", "id", "VARCHAR", false), fileId("file_id", "fileId", "VARCHAR", false), - stepId("step_id", "stepId", "VARCHAR", false); + stepId("step_id", "stepId", "VARCHAR", false), + scenarioId("scenario_id", "scenarioId", "VARCHAR", false); private static final String BEGINNING_DELIMITER = "`"; diff --git a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioCsvStepExample.java b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioCsvStepExample.java index b408b74427..9feaa2d97d 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioCsvStepExample.java +++ b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiScenarioCsvStepExample.java @@ -313,6 +313,76 @@ public class ApiScenarioCsvStepExample { addCriterion("step_id not between", value1, value2, "stepId"); return (Criteria) this; } + + public Criteria andScenarioIdIsNull() { + addCriterion("scenario_id is null"); + return (Criteria) this; + } + + public Criteria andScenarioIdIsNotNull() { + addCriterion("scenario_id is not null"); + return (Criteria) this; + } + + public Criteria andScenarioIdEqualTo(String value) { + addCriterion("scenario_id =", value, "scenarioId"); + return (Criteria) this; + } + + public Criteria andScenarioIdNotEqualTo(String value) { + addCriterion("scenario_id <>", value, "scenarioId"); + return (Criteria) this; + } + + public Criteria andScenarioIdGreaterThan(String value) { + addCriterion("scenario_id >", value, "scenarioId"); + return (Criteria) this; + } + + public Criteria andScenarioIdGreaterThanOrEqualTo(String value) { + addCriterion("scenario_id >=", value, "scenarioId"); + return (Criteria) this; + } + + public Criteria andScenarioIdLessThan(String value) { + addCriterion("scenario_id <", value, "scenarioId"); + return (Criteria) this; + } + + public Criteria andScenarioIdLessThanOrEqualTo(String value) { + addCriterion("scenario_id <=", value, "scenarioId"); + return (Criteria) this; + } + + public Criteria andScenarioIdLike(String value) { + addCriterion("scenario_id like", value, "scenarioId"); + return (Criteria) this; + } + + public Criteria andScenarioIdNotLike(String value) { + addCriterion("scenario_id not like", value, "scenarioId"); + return (Criteria) this; + } + + public Criteria andScenarioIdIn(List values) { + addCriterion("scenario_id in", values, "scenarioId"); + return (Criteria) this; + } + + public Criteria andScenarioIdNotIn(List values) { + addCriterion("scenario_id not in", values, "scenarioId"); + return (Criteria) this; + } + + public Criteria andScenarioIdBetween(String value1, String value2) { + addCriterion("scenario_id between", value1, value2, "scenarioId"); + return (Criteria) this; + } + + public Criteria andScenarioIdNotBetween(String value1, String value2) { + addCriterion("scenario_id not between", value1, value2, "scenarioId"); + return (Criteria) this; + } } public static class Criteria extends GeneratedCriteria { diff --git a/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioCsvStepMapper.xml b/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioCsvStepMapper.xml index 7572a00ad3..26827ce23c 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioCsvStepMapper.xml +++ b/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiScenarioCsvStepMapper.xml @@ -5,6 +5,7 @@ + @@ -65,7 +66,7 @@ - id, file_id, step_id + id, file_id, step_id, scenario_id @@ -146,6 +153,9 @@ step_id = #{record.stepId,jdbcType=VARCHAR}, + + scenario_id = #{record.scenarioId,jdbcType=VARCHAR}, + @@ -155,7 +165,8 @@ update api_scenario_csv_step set id = #{record.id,jdbcType=VARCHAR}, file_id = #{record.fileId,jdbcType=VARCHAR}, - step_id = #{record.stepId,jdbcType=VARCHAR} + step_id = #{record.stepId,jdbcType=VARCHAR}, + scenario_id = #{record.scenarioId,jdbcType=VARCHAR} @@ -169,22 +180,26 @@ step_id = #{stepId,jdbcType=VARCHAR}, + + scenario_id = #{scenarioId,jdbcType=VARCHAR}, + where id = #{id,jdbcType=VARCHAR} update api_scenario_csv_step set file_id = #{fileId,jdbcType=VARCHAR}, - step_id = #{stepId,jdbcType=VARCHAR} + step_id = #{stepId,jdbcType=VARCHAR}, + scenario_id = #{scenarioId,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR} insert into api_scenario_csv_step - (id, file_id, step_id) + (id, file_id, step_id, scenario_id) values - (#{item.id,jdbcType=VARCHAR}, #{item.fileId,jdbcType=VARCHAR}, #{item.stepId,jdbcType=VARCHAR} - ) + (#{item.id,jdbcType=VARCHAR}, #{item.fileId,jdbcType=VARCHAR}, #{item.stepId,jdbcType=VARCHAR}, + #{item.scenarioId,jdbcType=VARCHAR}) @@ -206,6 +221,9 @@ #{item.stepId,jdbcType=VARCHAR} + + #{item.scenarioId,jdbcType=VARCHAR} + ) diff --git a/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_12__beta_ddl.sql b/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_12__beta_ddl.sql index f1c5565c43..1f9dc33b10 100644 --- a/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_12__beta_ddl.sql +++ b/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_12__beta_ddl.sql @@ -127,6 +127,10 @@ CREATE TABLE IF NOT EXISTS test_plan_report_bug( CREATE UNIQUE INDEX idx_test_plan_report_id ON test_plan_report_bug(test_plan_report_id); +-- 场景步骤 csv 表增加场景ID字段 +ALTER TABLE api_scenario_csv_step ADD scenario_id varchar(50) NOT NULL COMMENT '场景ID'; +CREATE INDEX idx_scenario_id USING BTREE ON api_scenario_csv_step (scenario_id); + -- set innodb lock wait timeout to default SET SESSION innodb_lock_wait_timeout = DEFAULT; diff --git a/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractJmeterElementConverter.java b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractJmeterElementConverter.java index 893458a032..cdbb05f827 100644 --- a/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractJmeterElementConverter.java +++ b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractJmeterElementConverter.java @@ -9,6 +9,8 @@ import org.apache.jorphan.collections.HashTree; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; import java.util.function.Function; /** @@ -22,10 +24,25 @@ public abstract class AbstractJmeterElementConverter im /** * 获取转换器的函数 - * 主应用在实例化转换器的时候会设置 */ @Setter - private Function, AbstractJmeterElementConverter> getConverterFunc; + private static Function, AbstractJmeterElementConverter> getConverterFunc; + /** + * 解析子步骤前的前置处理函数 + */ + private static List childPreConverters = new ArrayList<>(); + /** + * 解析子步骤前的前置处理函数 + */ + private static List childPostConverters = new ArrayList<>(); + + public static void registerChildPreConverters(AbstractJmeterElementConverter converter) { + childPreConverters.add(converter); + } + + public static void registerChildPostConverters(AbstractJmeterElementConverter converter) { + childPostConverters.add(converter); + } public AbstractJmeterElementConverter() { Type genericSuperclass = getClass().getGenericSuperclass(); @@ -45,10 +62,14 @@ public abstract class AbstractJmeterElementConverter im */ public void parseChild(HashTree tree, AbstractMsTestElement element, ParameterConfig config) { if (element != null && element.getChildren() != null) { + // 解析子步骤前的前置处理函数 + childPreConverters.forEach(processor -> processor.toHashTree(tree, element, config)); element.getChildren().forEach(child -> { child.setParent(element); getConverterFunc.apply(child.getClass()).toHashTree(tree, child, config); }); + // 解析子步骤后的后置处理函数 + childPostConverters.forEach(processor -> processor.toHashTree(tree, element, config)); } } diff --git a/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractMsTestElement.java b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractMsTestElement.java index d2a9ecf6e0..310f08ab7d 100644 --- a/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractMsTestElement.java +++ b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractMsTestElement.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.Data; import java.util.LinkedList; +import java.util.List; /** * @@ -50,4 +51,8 @@ public abstract class AbstractMsTestElement implements MsTestElement { * 父组件 */ private AbstractMsTestElement parent; + /** + * 关联的 csv ID + */ + private List csvIds; } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiParamConfig.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiParamConfig.java index 77416a8dd1..36f5f05f26 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiParamConfig.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiParamConfig.java @@ -1,5 +1,6 @@ package io.metersphere.api.dto; +import io.metersphere.api.dto.scenario.CsvVariable; import io.metersphere.plugin.api.dto.ParameterConfig; import io.metersphere.plugin.api.spi.AbstractMsTestElement; import io.metersphere.project.dto.environment.EnvironmentInfoDTO; @@ -80,4 +81,13 @@ public class ApiParamConfig extends ParameterConfig { public EnvironmentInfoDTO getEnvConfig(String projectId) { return getEnvConfig(); } + + /** + * 获取 csv 信息 + * @param csvId + * @return + */ + public CsvVariable getCsvVariable(String csvId) { + return null; + } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiScenarioParamConfig.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiScenarioParamConfig.java index 0b8ac983cf..af9151710f 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiScenarioParamConfig.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiScenarioParamConfig.java @@ -1,11 +1,13 @@ package io.metersphere.api.dto; +import io.metersphere.api.dto.scenario.CsvVariable; import io.metersphere.api.dto.scenario.ScenarioConfig; import io.metersphere.plugin.api.spi.AbstractMsTestElement; import io.metersphere.project.dto.environment.EnvironmentInfoDTO; import lombok.Data; import org.apache.commons.lang3.BooleanUtils; +import java.util.HashMap; import java.util.Map; /** @@ -31,6 +33,13 @@ public class ApiScenarioParamConfig extends ApiParamConfig { */ private Boolean grouped; + /** + * csv Map + * key 为 csv 的 ID + * value 为 csv 的信息 + */ + private Map csvMap = new HashMap<>(0); + @Override public Map getProtocolEnvConfig(AbstractMsTestElement msTestElement) { if (BooleanUtils.isTrue(grouped)) { @@ -53,4 +62,14 @@ public class ApiScenarioParamConfig extends ApiParamConfig { return getEnvConfig(); } } + + /** + * 获取 csv 信息 + * @param csvId + * @return + */ + @Override + public CsvVariable getCsvVariable(String csvId) { + return csvMap.get(csvId); + } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioAddRequest.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioAddRequest.java index db0a93444c..8f04f48263 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioAddRequest.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioAddRequest.java @@ -59,6 +59,7 @@ public class ApiScenarioAddRequest { private String environmentId; @Schema(description = "场景的通用配置") + @Valid private ScenarioConfig scenarioConfig = new ScenarioConfig(); @Schema(description = "步骤集合") @@ -80,10 +81,4 @@ public class ApiScenarioAddRequest { */ @Schema(description = "步骤文件操作相关参数") private Map stepFileParam; - - /** - * 步骤文件操作相关参数 - */ - @Schema(description = "场景文件操作相关参数") - private ResourceAddFileParam fileParam; } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioDetail.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioDetail.java index e11e64b927..0f3201c684 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioDetail.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioDetail.java @@ -11,7 +11,7 @@ import java.util.List; @EqualsAndHashCode(callSuper = false) public class ApiScenarioDetail extends ApiScenario { @Schema(description = "场景的通用配置") - private ScenarioConfig scenarioConfig; + private ScenarioConfig scenarioConfig = new ScenarioConfig(); @Schema(description = "步骤") private List steps; } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioStepCommonDTO.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioStepCommonDTO.java index d7074ad9f8..4ea97092e2 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioStepCommonDTO.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioStepCommonDTO.java @@ -56,8 +56,8 @@ public class ApiScenarioStepCommonDTO { @Schema(description = "循环等组件基础数据") private Object config; - @Schema(description = "csv文件id集合") - private List csvFileIds; + @Schema(description = "csv id集合") + private List csvIds; @Schema(description = "项目fk") @NotBlank diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioUpdateRequest.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioUpdateRequest.java index 231465aff7..8d660faf02 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioUpdateRequest.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioUpdateRequest.java @@ -83,10 +83,4 @@ public class ApiScenarioUpdateRequest { */ @Schema(description = "步骤文件操作相关参数") private Map stepFileParam; - - /** - * 步骤文件操作相关参数 - */ - @Schema(description = "场景文件操作相关参数") - private ResourceUpdateFileParam fileParam; } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/CsvVariable.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/CsvVariable.java index b6aa35687e..bb742c46fc 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/CsvVariable.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/CsvVariable.java @@ -1,5 +1,7 @@ package io.metersphere.api.dto.scenario; +import io.metersphere.sdk.constants.ValueEnum; +import io.metersphere.system.valid.EnumValue; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; @@ -14,50 +16,51 @@ import lombok.Data; public class CsvVariable { @Schema(description = "id") + @NotBlank + @Size(max = 50) private String id; @Schema(description = "文件id/引用文件id", requiredMode = Schema.RequiredMode.REQUIRED) - @Size(min = 1, max = 50, message = "{api_scenario_csv.file_id.length_range}") + @Size(max = 50, message = "{api_scenario_csv.file_id.length_range}") + @NotBlank private String fileId; - @Schema(description = "场景id", requiredMode = Schema.RequiredMode.REQUIRED) - @Size(min = 1, max = 50, message = "{api_scenario_csv.scenario_id.length_range}") - private String scenarioId; - - @Schema(description = "csv变量名称", requiredMode = Schema.RequiredMode.REQUIRED) - @Size(min = 1, max = 255, message = "{api_scenario_csv.name.length_range}") - private String name; - @Schema(description = "文件名称") + @NotBlank private String fileName; - @Schema(description = "作用域 SCENARIO/STEP") + @Schema(description = "是否是关联文件") + private Boolean association = false; + + @Schema(description = "csv变量名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Size(max = 255, message = "{api_scenario_csv.name.length_range}") + private String name; + /** * @see CsvVariableScope */ + @Schema(description = "作用域 SCENARIO/STEP") @NotBlank(message = "{api_scenario_csv.scope.not_blank}") @Size(min = 1, max = 50, message = "{api_scenario_csv.scope.length_range}") - private String scope; + @EnumValue(enumClass = CsvVariableScope.class) + private String scope = CsvVariableScope.SCENARIO.name(); @Schema(description = "启用/禁用") private Boolean enable = true; - @Schema(description = "是否引用") - private Boolean association = false; - - @Schema(description = "文件编码") /** * 文件编码 - * * @see CsvEncodingType */ + @Schema(description = "文件编码 UTF-8/UTF-16/ISO-8859-15/US-ASCII") @Size(max = 50, message = "{api_scenario_csv.encoding.length_range}") - private String encoding; + @EnumValue(enumClass = CsvEncodingType.class) + private String encoding = CsvEncodingType.UTF8.getValue(); @Schema(description = "是否随机") private Boolean random = false; - @Schema(description = "变量名称(西文逗号间隔)") + @Schema(description = "变量名称(英文逗号间隔)") @Size(max = 255, message = "{api_scenario_csv.variable_names.length_range}") private String variableNames; @@ -78,7 +81,7 @@ public class CsvVariable { private Boolean stopThreadOnEof = false; - public enum CsvEncodingType { + public enum CsvEncodingType implements ValueEnum { UTF8("UTF-8"), UFT16("UTF-16"), ISO885915("ISO-8859-15"), US_ASCII("US-ASCII"); private String value; @@ -86,6 +89,7 @@ public class CsvVariable { this.value = value; } + @Override public String getValue() { return value; } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ScenarioConfig.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ScenarioConfig.java index 0b16a3ddf4..06af094763 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ScenarioConfig.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ScenarioConfig.java @@ -2,6 +2,7 @@ package io.metersphere.api.dto.scenario; import io.metersphere.api.dto.assertion.MsScenarioAssertionConfig; import io.metersphere.api.dto.request.processors.MsProcessorConfig; +import jakarta.validation.Valid; import lombok.Data; /** @@ -13,6 +14,7 @@ public class ScenarioConfig { /** * 场景变量 */ + @Valid private ScenarioVariable variable = new ScenarioVariable(); /** * 前置处理器配置 diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ScenarioVariable.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ScenarioVariable.java index e8dea5e2ba..99e21ed056 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ScenarioVariable.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ScenarioVariable.java @@ -1,6 +1,7 @@ package io.metersphere.api.dto.scenario; import io.metersphere.project.dto.environment.variables.CommonVariables; +import jakarta.validation.Valid; import lombok.Data; import java.util.ArrayList; @@ -15,9 +16,11 @@ public class ScenarioVariable { /** * 普通变量 */ + @Valid private List commonVariables = new ArrayList<>(0); /** * csv变量 */ + @Valid private List csvVariables = new ArrayList<>(0); } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioStepMapper.java b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioStepMapper.java index fa5b03cfcb..5dd0897b54 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioStepMapper.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioStepMapper.java @@ -18,7 +18,7 @@ public interface ExtApiScenarioStepMapper { List getCsvVariableByScenarioId(@Param("id") String id); - List getCsvStepByStepIds(@Param("ids") List stepIds); + List getCsvStepByScenarioId(@Param("scenarioId") String scenarioId); /** * 查询有步骤详情的请求类型的步骤 diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioStepMapper.xml b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioStepMapper.xml index 47573296f9..e77eab3616 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioStepMapper.xml +++ b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioStepMapper.xml @@ -18,13 +18,10 @@ from api_scenario_csv where scenario_id = #{id} - select - from api_scenario_csv_step where step_id in - - #{id} - + from api_scenario_csv_step where scenario_id = #{scenarioId}