feat(接口测试): 场景csv功能
This commit is contained in:
parent
21fbfee0b4
commit
b74eef8a6c
|
@ -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})
|
@Size(min = 1, max = 50, message = "{api_scenario_csv_step.step_id.length_range}", groups = {Created.class, Updated.class})
|
||||||
private String stepId;
|
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;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public enum Column {
|
public enum Column {
|
||||||
id("id", "id", "VARCHAR", false),
|
id("id", "id", "VARCHAR", false),
|
||||||
fileId("file_id", "fileId", "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 = "`";
|
private static final String BEGINNING_DELIMITER = "`";
|
||||||
|
|
||||||
|
|
|
@ -313,6 +313,76 @@ public class ApiScenarioCsvStepExample {
|
||||||
addCriterion("step_id not between", value1, value2, "stepId");
|
addCriterion("step_id not between", value1, value2, "stepId");
|
||||||
return (Criteria) this;
|
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<String> values) {
|
||||||
|
addCriterion("scenario_id in", values, "scenarioId");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andScenarioIdNotIn(List<String> 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 {
|
public static class Criteria extends GeneratedCriteria {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<id column="id" jdbcType="VARCHAR" property="id" />
|
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||||
<result column="file_id" jdbcType="VARCHAR" property="fileId" />
|
<result column="file_id" jdbcType="VARCHAR" property="fileId" />
|
||||||
<result column="step_id" jdbcType="VARCHAR" property="stepId" />
|
<result column="step_id" jdbcType="VARCHAR" property="stepId" />
|
||||||
|
<result column="scenario_id" jdbcType="VARCHAR" property="scenarioId" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
<sql id="Example_Where_Clause">
|
<sql id="Example_Where_Clause">
|
||||||
<where>
|
<where>
|
||||||
|
@ -65,7 +66,7 @@
|
||||||
</where>
|
</where>
|
||||||
</sql>
|
</sql>
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
id, file_id, step_id
|
id, file_id, step_id, scenario_id
|
||||||
</sql>
|
</sql>
|
||||||
<select id="selectByExample" parameterType="io.metersphere.api.domain.ApiScenarioCsvStepExample" resultMap="BaseResultMap">
|
<select id="selectByExample" parameterType="io.metersphere.api.domain.ApiScenarioCsvStepExample" resultMap="BaseResultMap">
|
||||||
select
|
select
|
||||||
|
@ -98,10 +99,10 @@
|
||||||
</if>
|
</if>
|
||||||
</delete>
|
</delete>
|
||||||
<insert id="insert" parameterType="io.metersphere.api.domain.ApiScenarioCsvStep">
|
<insert id="insert" parameterType="io.metersphere.api.domain.ApiScenarioCsvStep">
|
||||||
insert into api_scenario_csv_step (id, file_id, step_id
|
insert into api_scenario_csv_step (id, file_id, step_id,
|
||||||
)
|
scenario_id)
|
||||||
values (#{id,jdbcType=VARCHAR}, #{fileId,jdbcType=VARCHAR}, #{stepId,jdbcType=VARCHAR}
|
values (#{id,jdbcType=VARCHAR}, #{fileId,jdbcType=VARCHAR}, #{stepId,jdbcType=VARCHAR},
|
||||||
)
|
#{scenarioId,jdbcType=VARCHAR})
|
||||||
</insert>
|
</insert>
|
||||||
<insert id="insertSelective" parameterType="io.metersphere.api.domain.ApiScenarioCsvStep">
|
<insert id="insertSelective" parameterType="io.metersphere.api.domain.ApiScenarioCsvStep">
|
||||||
insert into api_scenario_csv_step
|
insert into api_scenario_csv_step
|
||||||
|
@ -115,6 +116,9 @@
|
||||||
<if test="stepId != null">
|
<if test="stepId != null">
|
||||||
step_id,
|
step_id,
|
||||||
</if>
|
</if>
|
||||||
|
<if test="scenarioId != null">
|
||||||
|
scenario_id,
|
||||||
|
</if>
|
||||||
</trim>
|
</trim>
|
||||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
<if test="id != null">
|
<if test="id != null">
|
||||||
|
@ -126,6 +130,9 @@
|
||||||
<if test="stepId != null">
|
<if test="stepId != null">
|
||||||
#{stepId,jdbcType=VARCHAR},
|
#{stepId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="scenarioId != null">
|
||||||
|
#{scenarioId,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
</trim>
|
</trim>
|
||||||
</insert>
|
</insert>
|
||||||
<select id="countByExample" parameterType="io.metersphere.api.domain.ApiScenarioCsvStepExample" resultType="java.lang.Long">
|
<select id="countByExample" parameterType="io.metersphere.api.domain.ApiScenarioCsvStepExample" resultType="java.lang.Long">
|
||||||
|
@ -146,6 +153,9 @@
|
||||||
<if test="record.stepId != null">
|
<if test="record.stepId != null">
|
||||||
step_id = #{record.stepId,jdbcType=VARCHAR},
|
step_id = #{record.stepId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="record.scenarioId != null">
|
||||||
|
scenario_id = #{record.scenarioId,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
</set>
|
</set>
|
||||||
<if test="_parameter != null">
|
<if test="_parameter != null">
|
||||||
<include refid="Update_By_Example_Where_Clause" />
|
<include refid="Update_By_Example_Where_Clause" />
|
||||||
|
@ -155,7 +165,8 @@
|
||||||
update api_scenario_csv_step
|
update api_scenario_csv_step
|
||||||
set id = #{record.id,jdbcType=VARCHAR},
|
set id = #{record.id,jdbcType=VARCHAR},
|
||||||
file_id = #{record.fileId,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}
|
||||||
<if test="_parameter != null">
|
<if test="_parameter != null">
|
||||||
<include refid="Update_By_Example_Where_Clause" />
|
<include refid="Update_By_Example_Where_Clause" />
|
||||||
</if>
|
</if>
|
||||||
|
@ -169,22 +180,26 @@
|
||||||
<if test="stepId != null">
|
<if test="stepId != null">
|
||||||
step_id = #{stepId,jdbcType=VARCHAR},
|
step_id = #{stepId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="scenarioId != null">
|
||||||
|
scenario_id = #{scenarioId,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
</set>
|
</set>
|
||||||
where id = #{id,jdbcType=VARCHAR}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.api.domain.ApiScenarioCsvStep">
|
<update id="updateByPrimaryKey" parameterType="io.metersphere.api.domain.ApiScenarioCsvStep">
|
||||||
update api_scenario_csv_step
|
update api_scenario_csv_step
|
||||||
set file_id = #{fileId,jdbcType=VARCHAR},
|
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}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
<insert id="batchInsert" parameterType="map">
|
<insert id="batchInsert" parameterType="map">
|
||||||
insert into api_scenario_csv_step
|
insert into api_scenario_csv_step
|
||||||
(id, file_id, step_id)
|
(id, file_id, step_id, scenario_id)
|
||||||
values
|
values
|
||||||
<foreach collection="list" item="item" separator=",">
|
<foreach collection="list" item="item" separator=",">
|
||||||
(#{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})
|
||||||
</foreach>
|
</foreach>
|
||||||
</insert>
|
</insert>
|
||||||
<insert id="batchInsertSelective" parameterType="map">
|
<insert id="batchInsertSelective" parameterType="map">
|
||||||
|
@ -206,6 +221,9 @@
|
||||||
<if test="'step_id'.toString() == column.value">
|
<if test="'step_id'.toString() == column.value">
|
||||||
#{item.stepId,jdbcType=VARCHAR}
|
#{item.stepId,jdbcType=VARCHAR}
|
||||||
</if>
|
</if>
|
||||||
|
<if test="'scenario_id'.toString() == column.value">
|
||||||
|
#{item.scenarioId,jdbcType=VARCHAR}
|
||||||
|
</if>
|
||||||
</foreach>
|
</foreach>
|
||||||
)
|
)
|
||||||
</foreach>
|
</foreach>
|
||||||
|
|
|
@ -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);
|
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 innodb lock wait timeout to default
|
||||||
SET SESSION innodb_lock_wait_timeout = DEFAULT;
|
SET SESSION innodb_lock_wait_timeout = DEFAULT;
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@ import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,10 +24,25 @@ public abstract class AbstractJmeterElementConverter<T extends MsTestElement> im
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取转换器的函数
|
* 获取转换器的函数
|
||||||
* 主应用在实例化转换器的时候会设置
|
|
||||||
*/
|
*/
|
||||||
@Setter
|
@Setter
|
||||||
private Function<Class<? extends MsTestElement>, AbstractJmeterElementConverter> getConverterFunc;
|
private static Function<Class<? extends MsTestElement>, AbstractJmeterElementConverter> getConverterFunc;
|
||||||
|
/**
|
||||||
|
* 解析子步骤前的前置处理函数
|
||||||
|
*/
|
||||||
|
private static List<AbstractJmeterElementConverter> childPreConverters = new ArrayList<>();
|
||||||
|
/**
|
||||||
|
* 解析子步骤前的前置处理函数
|
||||||
|
*/
|
||||||
|
private static List<AbstractJmeterElementConverter> childPostConverters = new ArrayList<>();
|
||||||
|
|
||||||
|
public static void registerChildPreConverters(AbstractJmeterElementConverter converter) {
|
||||||
|
childPreConverters.add(converter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerChildPostConverters(AbstractJmeterElementConverter converter) {
|
||||||
|
childPostConverters.add(converter);
|
||||||
|
}
|
||||||
|
|
||||||
public AbstractJmeterElementConverter() {
|
public AbstractJmeterElementConverter() {
|
||||||
Type genericSuperclass = getClass().getGenericSuperclass();
|
Type genericSuperclass = getClass().getGenericSuperclass();
|
||||||
|
@ -45,10 +62,14 @@ public abstract class AbstractJmeterElementConverter<T extends MsTestElement> im
|
||||||
*/
|
*/
|
||||||
public void parseChild(HashTree tree, AbstractMsTestElement element, ParameterConfig config) {
|
public void parseChild(HashTree tree, AbstractMsTestElement element, ParameterConfig config) {
|
||||||
if (element != null && element.getChildren() != null) {
|
if (element != null && element.getChildren() != null) {
|
||||||
|
// 解析子步骤前的前置处理函数
|
||||||
|
childPreConverters.forEach(processor -> processor.toHashTree(tree, element, config));
|
||||||
element.getChildren().forEach(child -> {
|
element.getChildren().forEach(child -> {
|
||||||
child.setParent(element);
|
child.setParent(element);
|
||||||
getConverterFunc.apply(child.getClass()).toHashTree(tree, child, config);
|
getConverterFunc.apply(child.getClass()).toHashTree(tree, child, config);
|
||||||
});
|
});
|
||||||
|
// 解析子步骤后的后置处理函数
|
||||||
|
childPostConverters.forEach(processor -> processor.toHashTree(tree, element, config));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -50,4 +51,8 @@ public abstract class AbstractMsTestElement implements MsTestElement {
|
||||||
* 父组件
|
* 父组件
|
||||||
*/
|
*/
|
||||||
private AbstractMsTestElement parent;
|
private AbstractMsTestElement parent;
|
||||||
|
/**
|
||||||
|
* 关联的 csv ID
|
||||||
|
*/
|
||||||
|
private List<String> csvIds;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.metersphere.api.dto;
|
package io.metersphere.api.dto;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.scenario.CsvVariable;
|
||||||
import io.metersphere.plugin.api.dto.ParameterConfig;
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
|
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
|
||||||
|
@ -80,4 +81,13 @@ public class ApiParamConfig extends ParameterConfig {
|
||||||
public EnvironmentInfoDTO getEnvConfig(String projectId) {
|
public EnvironmentInfoDTO getEnvConfig(String projectId) {
|
||||||
return getEnvConfig();
|
return getEnvConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 csv 信息
|
||||||
|
* @param csvId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public CsvVariable getCsvVariable(String csvId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
package io.metersphere.api.dto;
|
package io.metersphere.api.dto;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.scenario.CsvVariable;
|
||||||
import io.metersphere.api.dto.scenario.ScenarioConfig;
|
import io.metersphere.api.dto.scenario.ScenarioConfig;
|
||||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
|
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,6 +33,13 @@ public class ApiScenarioParamConfig extends ApiParamConfig {
|
||||||
*/
|
*/
|
||||||
private Boolean grouped;
|
private Boolean grouped;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* csv Map
|
||||||
|
* key 为 csv 的 ID
|
||||||
|
* value 为 csv 的信息
|
||||||
|
*/
|
||||||
|
private Map<String, CsvVariable> csvMap = new HashMap<>(0);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> getProtocolEnvConfig(AbstractMsTestElement msTestElement) {
|
public Map<String, Object> getProtocolEnvConfig(AbstractMsTestElement msTestElement) {
|
||||||
if (BooleanUtils.isTrue(grouped)) {
|
if (BooleanUtils.isTrue(grouped)) {
|
||||||
|
@ -53,4 +62,14 @@ public class ApiScenarioParamConfig extends ApiParamConfig {
|
||||||
return getEnvConfig();
|
return getEnvConfig();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 csv 信息
|
||||||
|
* @param csvId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public CsvVariable getCsvVariable(String csvId) {
|
||||||
|
return csvMap.get(csvId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ public class ApiScenarioAddRequest {
|
||||||
private String environmentId;
|
private String environmentId;
|
||||||
|
|
||||||
@Schema(description = "场景的通用配置")
|
@Schema(description = "场景的通用配置")
|
||||||
|
@Valid
|
||||||
private ScenarioConfig scenarioConfig = new ScenarioConfig();
|
private ScenarioConfig scenarioConfig = new ScenarioConfig();
|
||||||
|
|
||||||
@Schema(description = "步骤集合")
|
@Schema(description = "步骤集合")
|
||||||
|
@ -80,10 +81,4 @@ public class ApiScenarioAddRequest {
|
||||||
*/
|
*/
|
||||||
@Schema(description = "步骤文件操作相关参数")
|
@Schema(description = "步骤文件操作相关参数")
|
||||||
private Map<String, ResourceAddFileParam> stepFileParam;
|
private Map<String, ResourceAddFileParam> stepFileParam;
|
||||||
|
|
||||||
/**
|
|
||||||
* 步骤文件操作相关参数
|
|
||||||
*/
|
|
||||||
@Schema(description = "场景文件操作相关参数")
|
|
||||||
private ResourceAddFileParam fileParam;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import java.util.List;
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
public class ApiScenarioDetail extends ApiScenario {
|
public class ApiScenarioDetail extends ApiScenario {
|
||||||
@Schema(description = "场景的通用配置")
|
@Schema(description = "场景的通用配置")
|
||||||
private ScenarioConfig scenarioConfig;
|
private ScenarioConfig scenarioConfig = new ScenarioConfig();
|
||||||
@Schema(description = "步骤")
|
@Schema(description = "步骤")
|
||||||
private List<ApiScenarioStepDTO> steps;
|
private List<ApiScenarioStepDTO> steps;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,8 +56,8 @@ public class ApiScenarioStepCommonDTO<T extends ApiScenarioStepCommonDTO> {
|
||||||
@Schema(description = "循环等组件基础数据")
|
@Schema(description = "循环等组件基础数据")
|
||||||
private Object config;
|
private Object config;
|
||||||
|
|
||||||
@Schema(description = "csv文件id集合")
|
@Schema(description = "csv id集合")
|
||||||
private List<String> csvFileIds;
|
private List<String> csvIds;
|
||||||
|
|
||||||
@Schema(description = "项目fk")
|
@Schema(description = "项目fk")
|
||||||
@NotBlank
|
@NotBlank
|
||||||
|
|
|
@ -83,10 +83,4 @@ public class ApiScenarioUpdateRequest {
|
||||||
*/
|
*/
|
||||||
@Schema(description = "步骤文件操作相关参数")
|
@Schema(description = "步骤文件操作相关参数")
|
||||||
private Map<String, ResourceUpdateFileParam> stepFileParam;
|
private Map<String, ResourceUpdateFileParam> stepFileParam;
|
||||||
|
|
||||||
/**
|
|
||||||
* 步骤文件操作相关参数
|
|
||||||
*/
|
|
||||||
@Schema(description = "场景文件操作相关参数")
|
|
||||||
private ResourceUpdateFileParam fileParam;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package io.metersphere.api.dto.scenario;
|
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 io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
|
@ -14,50 +16,51 @@ import lombok.Data;
|
||||||
public class CsvVariable {
|
public class CsvVariable {
|
||||||
|
|
||||||
@Schema(description = "id")
|
@Schema(description = "id")
|
||||||
|
@NotBlank
|
||||||
|
@Size(max = 50)
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
@Schema(description = "文件id/引用文件id", requiredMode = Schema.RequiredMode.REQUIRED)
|
@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;
|
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 = "文件名称")
|
@Schema(description = "文件名称")
|
||||||
|
@NotBlank
|
||||||
private String fileName;
|
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
|
* @see CsvVariableScope
|
||||||
*/
|
*/
|
||||||
|
@Schema(description = "作用域 SCENARIO/STEP")
|
||||||
@NotBlank(message = "{api_scenario_csv.scope.not_blank}")
|
@NotBlank(message = "{api_scenario_csv.scope.not_blank}")
|
||||||
@Size(min = 1, max = 50, message = "{api_scenario_csv.scope.length_range}")
|
@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 = "启用/禁用")
|
@Schema(description = "启用/禁用")
|
||||||
private Boolean enable = true;
|
private Boolean enable = true;
|
||||||
|
|
||||||
@Schema(description = "是否引用")
|
|
||||||
private Boolean association = false;
|
|
||||||
|
|
||||||
@Schema(description = "文件编码")
|
|
||||||
/**
|
/**
|
||||||
* 文件编码
|
* 文件编码
|
||||||
*
|
|
||||||
* @see CsvEncodingType
|
* @see CsvEncodingType
|
||||||
*/
|
*/
|
||||||
|
@Schema(description = "文件编码 UTF-8/UTF-16/ISO-8859-15/US-ASCII")
|
||||||
@Size(max = 50, message = "{api_scenario_csv.encoding.length_range}")
|
@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 = "是否随机")
|
@Schema(description = "是否随机")
|
||||||
private Boolean random = false;
|
private Boolean random = false;
|
||||||
|
|
||||||
@Schema(description = "变量名称(西文逗号间隔)")
|
@Schema(description = "变量名称(英文逗号间隔)")
|
||||||
@Size(max = 255, message = "{api_scenario_csv.variable_names.length_range}")
|
@Size(max = 255, message = "{api_scenario_csv.variable_names.length_range}")
|
||||||
private String variableNames;
|
private String variableNames;
|
||||||
|
|
||||||
|
@ -78,7 +81,7 @@ public class CsvVariable {
|
||||||
private Boolean stopThreadOnEof = false;
|
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");
|
UTF8("UTF-8"), UFT16("UTF-16"), ISO885915("ISO-8859-15"), US_ASCII("US-ASCII");
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
|
@ -86,6 +89,7 @@ public class CsvVariable {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getValue() {
|
public String getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.api.dto.scenario;
|
||||||
|
|
||||||
import io.metersphere.api.dto.assertion.MsScenarioAssertionConfig;
|
import io.metersphere.api.dto.assertion.MsScenarioAssertionConfig;
|
||||||
import io.metersphere.api.dto.request.processors.MsProcessorConfig;
|
import io.metersphere.api.dto.request.processors.MsProcessorConfig;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,6 +14,7 @@ public class ScenarioConfig {
|
||||||
/**
|
/**
|
||||||
* 场景变量
|
* 场景变量
|
||||||
*/
|
*/
|
||||||
|
@Valid
|
||||||
private ScenarioVariable variable = new ScenarioVariable();
|
private ScenarioVariable variable = new ScenarioVariable();
|
||||||
/**
|
/**
|
||||||
* 前置处理器配置
|
* 前置处理器配置
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.api.dto.scenario;
|
package io.metersphere.api.dto.scenario;
|
||||||
|
|
||||||
import io.metersphere.project.dto.environment.variables.CommonVariables;
|
import io.metersphere.project.dto.environment.variables.CommonVariables;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -15,9 +16,11 @@ public class ScenarioVariable {
|
||||||
/**
|
/**
|
||||||
* 普通变量
|
* 普通变量
|
||||||
*/
|
*/
|
||||||
|
@Valid
|
||||||
private List<CommonVariables> commonVariables = new ArrayList<>(0);
|
private List<CommonVariables> commonVariables = new ArrayList<>(0);
|
||||||
/**
|
/**
|
||||||
* csv变量
|
* csv变量
|
||||||
*/
|
*/
|
||||||
|
@Valid
|
||||||
private List<CsvVariable> csvVariables = new ArrayList<>(0);
|
private List<CsvVariable> csvVariables = new ArrayList<>(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ public interface ExtApiScenarioStepMapper {
|
||||||
|
|
||||||
List<CsvVariable> getCsvVariableByScenarioId(@Param("id") String id);
|
List<CsvVariable> getCsvVariableByScenarioId(@Param("id") String id);
|
||||||
|
|
||||||
List<ApiScenarioCsvStep> getCsvStepByStepIds(@Param("ids") List<String> stepIds);
|
List<ApiScenarioCsvStep> getCsvStepByScenarioId(@Param("scenarioId") String scenarioId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询有步骤详情的请求类型的步骤
|
* 查询有步骤详情的请求类型的步骤
|
||||||
|
|
|
@ -18,13 +18,10 @@
|
||||||
<include refid="io.metersphere.api.mapper.ApiScenarioCsvMapper.Base_Column_List"/>
|
<include refid="io.metersphere.api.mapper.ApiScenarioCsvMapper.Base_Column_List"/>
|
||||||
from api_scenario_csv where scenario_id = #{id}
|
from api_scenario_csv where scenario_id = #{id}
|
||||||
</select>
|
</select>
|
||||||
<select id="getCsvStepByStepIds" resultType="io.metersphere.api.domain.ApiScenarioCsvStep">
|
<select id="getCsvStepByScenarioId" resultType="io.metersphere.api.domain.ApiScenarioCsvStep">
|
||||||
select
|
select
|
||||||
<include refid="io.metersphere.api.mapper.ApiScenarioCsvStepMapper.Base_Column_List"/>
|
<include refid="io.metersphere.api.mapper.ApiScenarioCsvStepMapper.Base_Column_List"/>
|
||||||
from api_scenario_csv_step where step_id in
|
from api_scenario_csv_step where scenario_id = #{scenarioId}
|
||||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
|
||||||
#{id}
|
|
||||||
</foreach>
|
|
||||||
</select>
|
</select>
|
||||||
<select id="getHasBlobRequestStepIds" resultType="java.lang.String">
|
<select id="getHasBlobRequestStepIds" resultType="java.lang.String">
|
||||||
select id
|
select id
|
||||||
|
|
|
@ -5,10 +5,13 @@ import io.metersphere.api.constants.ApiScenarioStepRefType;
|
||||||
import io.metersphere.api.dto.ApiScenarioParamConfig;
|
import io.metersphere.api.dto.ApiScenarioParamConfig;
|
||||||
import io.metersphere.api.dto.request.MsScenario;
|
import io.metersphere.api.dto.request.MsScenario;
|
||||||
import io.metersphere.api.dto.request.processors.MsProcessorConfig;
|
import io.metersphere.api.dto.request.processors.MsProcessorConfig;
|
||||||
|
import io.metersphere.api.dto.scenario.CsvVariable;
|
||||||
import io.metersphere.api.dto.scenario.ScenarioConfig;
|
import io.metersphere.api.dto.scenario.ScenarioConfig;
|
||||||
import io.metersphere.api.dto.scenario.ScenarioStepConfig;
|
import io.metersphere.api.dto.scenario.ScenarioStepConfig;
|
||||||
import io.metersphere.api.dto.scenario.ScenarioVariable;
|
import io.metersphere.api.dto.scenario.ScenarioVariable;
|
||||||
|
import io.metersphere.api.parser.jmeter.child.MsCsvChildPreConverter;
|
||||||
import io.metersphere.api.parser.jmeter.constants.JmeterAlias;
|
import io.metersphere.api.parser.jmeter.constants.JmeterAlias;
|
||||||
|
import io.metersphere.api.parser.jmeter.constants.JmeterProperty;
|
||||||
import io.metersphere.api.parser.jmeter.processor.MsProcessorConverter;
|
import io.metersphere.api.parser.jmeter.processor.MsProcessorConverter;
|
||||||
import io.metersphere.api.parser.jmeter.processor.MsProcessorConverterFactory;
|
import io.metersphere.api.parser.jmeter.processor.MsProcessorConverterFactory;
|
||||||
import io.metersphere.api.parser.jmeter.processor.assertion.AssertionConverterFactory;
|
import io.metersphere.api.parser.jmeter.processor.assertion.AssertionConverterFactory;
|
||||||
|
@ -65,6 +68,9 @@ public class MsScenarioConverter extends AbstractJmeterElementConverter<MsScenar
|
||||||
tree.add(getCookieManager());
|
tree.add(getCookieManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加 csv 数据集
|
||||||
|
addCsvDataSet(tree, msScenario.getScenarioConfig());
|
||||||
|
|
||||||
// 添加场景和环境变量
|
// 添加场景和环境变量
|
||||||
addUserParameters(tree, msScenario, envInfo, config);
|
addUserParameters(tree, msScenario, envInfo, config);
|
||||||
|
|
||||||
|
@ -85,8 +91,17 @@ public class MsScenarioConverter extends AbstractJmeterElementConverter<MsScenar
|
||||||
addScenarioAssertions(tree, msScenario, config);
|
addScenarioAssertions(tree, msScenario, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addCsvDataSet(HashTree tree, ScenarioConfig scenarioConfig) {
|
||||||
|
if (scenarioConfig == null || scenarioConfig.getVariable() == null || CollectionUtils.isEmpty(scenarioConfig.getVariable().getCsvVariables())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<CsvVariable> csvVariables = scenarioConfig.getVariable().getCsvVariables();
|
||||||
|
MsCsvChildPreConverter.addCsvDataSet(tree, JmeterProperty.CSVDataSetProperty.SHARE_MODE_GROUP, csvVariables);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加临界控制器,解决变量冲突
|
* 添加临界控制器,解决变量冲突
|
||||||
|
*
|
||||||
* @param tree
|
* @param tree
|
||||||
* @param msScenario
|
* @param msScenario
|
||||||
* @return
|
* @return
|
||||||
|
@ -270,9 +285,9 @@ public class MsScenarioConverter extends AbstractJmeterElementConverter<MsScenar
|
||||||
envScenarioProcessors.stream()
|
envScenarioProcessors.stream()
|
||||||
.filter(MsProcessor::getEnable)
|
.filter(MsProcessor::getEnable)
|
||||||
.forEach(processor -> {
|
.forEach(processor -> {
|
||||||
processor.setProjectId(msScenario.getProjectId());
|
processor.setProjectId(msScenario.getProjectId());
|
||||||
getConverterFunc.apply(processor.getClass()).parse(tree, processor, config);
|
getConverterFunc.apply(processor.getClass()).parse(tree, processor, config);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -319,9 +334,9 @@ public class MsScenarioConverter extends AbstractJmeterElementConverter<MsScenar
|
||||||
scenarioPreProcessors.stream()
|
scenarioPreProcessors.stream()
|
||||||
.filter(MsProcessor::getEnable)
|
.filter(MsProcessor::getEnable)
|
||||||
.forEach(processor -> {
|
.forEach(processor -> {
|
||||||
processor.setProjectId(msScenario.getProjectId());
|
processor.setProjectId(msScenario.getProjectId());
|
||||||
getConverterFunc.apply(processor.getClass()).parse(tree, processor, config);
|
getConverterFunc.apply(processor.getClass()).parse(tree, processor, config);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isRef(String refType) {
|
private boolean isRef(String refType) {
|
||||||
|
@ -347,6 +362,9 @@ public class MsScenarioConverter extends AbstractJmeterElementConverter<MsScenar
|
||||||
private ApiScenarioParamConfig getEnableConfig(MsScenario msScenario, ApiScenarioParamConfig config) {
|
private ApiScenarioParamConfig getEnableConfig(MsScenario msScenario, ApiScenarioParamConfig config) {
|
||||||
ApiScenarioParamConfig enableConfig = config;
|
ApiScenarioParamConfig enableConfig = config;
|
||||||
if (!isRef(msScenario.getRefType())) {
|
if (!isRef(msScenario.getRefType())) {
|
||||||
|
if (isRootScenario(msScenario.getRefType())) {
|
||||||
|
setScenarioConfig(msScenario, enableConfig);
|
||||||
|
}
|
||||||
// 非引用的场景,使用当前环境参数
|
// 非引用的场景,使用当前环境参数
|
||||||
return enableConfig;
|
return enableConfig;
|
||||||
}
|
}
|
||||||
|
@ -369,13 +387,24 @@ public class MsScenarioConverter extends AbstractJmeterElementConverter<MsScenar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setScenarioConfig(msScenario, enableConfig);
|
||||||
|
|
||||||
|
return enableConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setScenarioConfig(MsScenario msScenario, ApiScenarioParamConfig enableConfig) {
|
||||||
ScenarioConfig scenarioConfig = msScenario.getScenarioConfig();
|
ScenarioConfig scenarioConfig = msScenario.getScenarioConfig();
|
||||||
if (scenarioConfig != null) {
|
if (scenarioConfig != null) {
|
||||||
// 设置是否使用全局cookie
|
// 设置是否使用全局cookie
|
||||||
enableConfig.setEnableGlobalCookie(scenarioConfig.getOtherConfig().getEnableCookieShare());
|
enableConfig.setEnableGlobalCookie(scenarioConfig.getOtherConfig().getEnableCookieShare());
|
||||||
}
|
|
||||||
|
|
||||||
return enableConfig;
|
ScenarioVariable variable = scenarioConfig.getVariable();
|
||||||
|
if (variable != null && variable.getCsvVariables() != null) {
|
||||||
|
for (CsvVariable csvVariable : variable.getCsvVariables()) {
|
||||||
|
enableConfig.getCsvMap().put(csvVariable.getId(), csvVariable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private CookieManager getCookieManager() {
|
private CookieManager getCookieManager() {
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
package io.metersphere.api.parser.jmeter.child;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.ApiParamConfig;
|
||||||
|
import io.metersphere.api.dto.scenario.CsvVariable;
|
||||||
|
import io.metersphere.api.parser.jmeter.constants.JmeterAlias;
|
||||||
|
import io.metersphere.api.parser.jmeter.constants.JmeterProperty;
|
||||||
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractJmeterElementConverter;
|
||||||
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
import io.metersphere.sdk.constants.LocalRepositoryDir;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.jmeter.config.CSVDataSet;
|
||||||
|
import org.apache.jmeter.save.SaveService;
|
||||||
|
import org.apache.jmeter.testelement.TestElement;
|
||||||
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析 csv 文件
|
||||||
|
* 在解析子步骤前,先添加 csv 配置
|
||||||
|
* @Author: jianxing
|
||||||
|
* @CreateTime: 2024-05-15 11:32
|
||||||
|
*/
|
||||||
|
public class MsCsvChildPreConverter extends AbstractJmeterElementConverter<AbstractMsTestElement> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toHashTree(HashTree tree, AbstractMsTestElement element, ParameterConfig config) {
|
||||||
|
List<String> csvIds = element.getCsvIds();
|
||||||
|
ApiParamConfig apiParamConfig = (ApiParamConfig) config;
|
||||||
|
if (CollectionUtils.isEmpty(csvIds)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
csvIds.forEach(csvId -> {
|
||||||
|
CsvVariable csvVariable = apiParamConfig.getCsvVariable(csvId);
|
||||||
|
if (csvVariable != null) {
|
||||||
|
String shareMode = StringUtils.equals(csvVariable.getScope(), CsvVariable.CsvVariableScope.SCENARIO.name()) ?
|
||||||
|
JmeterProperty.CSVDataSetProperty.SHARE_MODE_GROUP : JmeterProperty.CSVDataSetProperty.SHARE_MODE_THREAD;
|
||||||
|
addCsvDataSet(tree, shareMode, csvVariable);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addCsvDataSet(HashTree tree, String shareMode, List<CsvVariable> list) {
|
||||||
|
list.forEach(item -> addCsvDataSet(tree, shareMode, item));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addCsvDataSet(HashTree tree, String shareMode, CsvVariable csvVariable) {
|
||||||
|
// 执行机执行文件存放的缓存目录
|
||||||
|
String path = LocalRepositoryDir.getSystemCacheDir() + "/" + csvVariable.getFileId() + "/" + csvVariable.getFileName();
|
||||||
|
if (!StringUtils.equals(File.separator, "/")) {
|
||||||
|
// windows 系统下运行,将 / 转换为 \,否则jmeter报错
|
||||||
|
path = path.replace("/", File.separator);
|
||||||
|
}
|
||||||
|
CSVDataSet csvDataSet = new CSVDataSet();
|
||||||
|
csvDataSet.setEnabled(true);
|
||||||
|
csvDataSet.setIgnoreFirstLine(false);
|
||||||
|
csvDataSet.setProperty(TestElement.TEST_CLASS, CSVDataSet.class.getName());
|
||||||
|
csvDataSet.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass(JmeterAlias.TEST_BEAN_GUI));
|
||||||
|
csvDataSet.setName(StringUtils.isEmpty(csvVariable.getName()) ? CSVDataSet.class.getSimpleName() : csvVariable.getName());
|
||||||
|
csvDataSet.setProperty(JmeterProperty.FILE_ENCODING, StringUtils.isEmpty(csvVariable.getEncoding()) ? StandardCharsets.UTF_8.name() : csvVariable.getEncoding());
|
||||||
|
csvDataSet.setProperty(JmeterProperty.CSVDataSetProperty.FILE_NAME, path);
|
||||||
|
csvDataSet.setProperty(JmeterProperty.CSVDataSetProperty.SHARE_MODE, shareMode);
|
||||||
|
csvDataSet.setProperty(JmeterProperty.CSVDataSetProperty.RECYCLE, true);
|
||||||
|
csvDataSet.setProperty(JmeterProperty.CSVDataSetProperty.DELIMITER, csvVariable.getDelimiter());
|
||||||
|
csvDataSet.setProperty(JmeterProperty.CSVDataSetProperty.QUOTED_DATA, csvVariable.getAllowQuotedData());
|
||||||
|
tree.add(csvDataSet);
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,4 +11,16 @@ public class JmeterProperty {
|
||||||
public final static String ASS_OPTION = "ASS_OPTION";
|
public final static String ASS_OPTION = "ASS_OPTION";
|
||||||
public final static String BEAN_SHELL_ASSERTION_QUERY = "BeanShellAssertion.query";
|
public final static String BEAN_SHELL_ASSERTION_QUERY = "BeanShellAssertion.query";
|
||||||
public final static String BEAN_SHELL_SAMPLER_QUERY = "BeanShellSampler.query";
|
public final static String BEAN_SHELL_SAMPLER_QUERY = "BeanShellSampler.query";
|
||||||
|
public final static String FILE_ENCODING = "fileEncoding";
|
||||||
|
|
||||||
|
public class CSVDataSetProperty {
|
||||||
|
public static final String FILE_NAME = "filename";
|
||||||
|
public static final String SHARE_MODE = "shareMode";
|
||||||
|
public static final String RECYCLE = "recycle";
|
||||||
|
public static final String DELIMITER = "delimiter";
|
||||||
|
public static final String QUOTED_DATA = "quotedData";
|
||||||
|
public static final String SHARE_MODE_GROUP = "shareMode.group";
|
||||||
|
public static final String SHARE_MODE_THREAD = "shareMode.thread";
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package io.metersphere.api.parser.jmeter;
|
package io.metersphere.api.parser.jmeter.controller;
|
||||||
|
|
||||||
import io.metersphere.api.dto.request.controller.MsConstantTimerController;
|
import io.metersphere.api.dto.request.controller.MsConstantTimerController;
|
||||||
import io.metersphere.api.parser.jmeter.processor.ScenarioTimeWaitingProcessorConverter;
|
import io.metersphere.api.parser.jmeter.processor.ScenarioTimeWaitingProcessorConverter;
|
|
@ -1,4 +1,4 @@
|
||||||
package io.metersphere.api.parser.jmeter;
|
package io.metersphere.api.parser.jmeter.controller;
|
||||||
|
|
||||||
import io.metersphere.api.dto.request.controller.MsIfController;
|
import io.metersphere.api.dto.request.controller.MsIfController;
|
||||||
import io.metersphere.plugin.api.dto.ParameterConfig;
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
|
@ -21,12 +21,9 @@ public class MsIfControllerConverter extends AbstractJmeterElementConverter<MsIf
|
||||||
LogUtils.info("MsIfController is disabled");
|
LogUtils.info("MsIfController is disabled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//TODO 这里需要处理csv文件
|
|
||||||
|
|
||||||
|
|
||||||
HashTree groupTree = tree.add(ifController(element));
|
HashTree groupTree = tree.add(ifController(element));
|
||||||
parseChild(groupTree, element, config);
|
parseChild(groupTree, element, config);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IfController ifController(MsIfController element) {
|
private IfController ifController(MsIfController element) {
|
|
@ -1,4 +1,4 @@
|
||||||
package io.metersphere.api.parser.jmeter;
|
package io.metersphere.api.parser.jmeter.controller;
|
||||||
|
|
||||||
import io.metersphere.api.dto.request.controller.LoopType;
|
import io.metersphere.api.dto.request.controller.LoopType;
|
||||||
import io.metersphere.api.dto.request.controller.MsLoopController;
|
import io.metersphere.api.dto.request.controller.MsLoopController;
|
||||||
|
@ -27,7 +27,6 @@ public class MsLoopControllerConverter extends AbstractJmeterElementConverter<Ms
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final HashTree groupTree = controller(tree, element);
|
final HashTree groupTree = controller(tree, element);
|
||||||
//TODO 这里需要处理csv文件 场景变量
|
|
||||||
|
|
||||||
if (groupTree == null) {
|
if (groupTree == null) {
|
||||||
return;
|
return;
|
|
@ -1,4 +1,4 @@
|
||||||
package io.metersphere.api.parser.jmeter;
|
package io.metersphere.api.parser.jmeter.controller;
|
||||||
|
|
||||||
import io.metersphere.api.dto.request.controller.MsOnceOnlyController;
|
import io.metersphere.api.dto.request.controller.MsOnceOnlyController;
|
||||||
import io.metersphere.plugin.api.dto.ParameterConfig;
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
|
@ -20,7 +20,6 @@ public class MsOnceOnlyControllerConverter extends AbstractJmeterElementConverte
|
||||||
LogUtils.info("MsOnceOnlyController is disabled");
|
LogUtils.info("MsOnceOnlyController is disabled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//TODO 这里需要处理csv文件
|
|
||||||
|
|
||||||
HashTree groupTree = tree.add(onceOnlyController(element));
|
HashTree groupTree = tree.add(onceOnlyController(element));
|
||||||
parseChild(groupTree, element, config);
|
parseChild(groupTree, element, config);
|
|
@ -237,8 +237,8 @@ public class ApiFileResourceService {
|
||||||
/**
|
/**
|
||||||
* 删除资源下所有的文件或者关联关系
|
* 删除资源下所有的文件或者关联关系
|
||||||
*
|
*
|
||||||
* @param dirPrefix 本地上传文件目录前缀
|
* @param dirPrefix 本地上传文件目录前缀
|
||||||
* @param resourceIds 资源ID
|
* @param resourceIds 资源ID
|
||||||
* @param projectId 项目ID
|
* @param projectId 项目ID
|
||||||
* @param operator 操作人
|
* @param operator 操作人
|
||||||
*/
|
*/
|
||||||
|
@ -402,18 +402,27 @@ public class ApiFileResourceService {
|
||||||
fileRequest.setFileName(fileName);
|
fileRequest.setFileName(fileName);
|
||||||
fileRequest.setStorage(StorageType.MINIO.name());
|
fileRequest.setStorage(StorageType.MINIO.name());
|
||||||
|
|
||||||
|
byte[] bytes;
|
||||||
try {
|
try {
|
||||||
fileId = fileMetadataService.transferFile(request.getFileName(), request.getOriginalName(), request.getProjectId(), request.getModuleId(), currentUser, fileService.download(fileRequest));
|
bytes = fileService.download(fileRequest);
|
||||||
if (CollectionUtils.isEmpty(apiFileResources)) {
|
|
||||||
// 删除临时文件
|
|
||||||
FileRequest deleteRequest = new FileRequest();
|
|
||||||
deleteRequest.setFolder(folder);
|
|
||||||
FileCenter.getDefaultRepository().deleteFolder(deleteRequest);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtils.error(e);
|
LogUtils.error(e);
|
||||||
throw new MSException(Translator.get("file.transfer.failed"));
|
throw new MSException(Translator.get("file.transfer.failed"), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileId = fileMetadataService.transferFile(request.getFileName(), request.getOriginalName(), request.getProjectId(), request.getModuleId(), currentUser, bytes);
|
||||||
|
if (CollectionUtils.isEmpty(apiFileResources)) {
|
||||||
|
// 删除临时文件
|
||||||
|
FileRequest deleteRequest = new FileRequest();
|
||||||
|
deleteRequest.setFolder(folder);
|
||||||
|
try {
|
||||||
|
FileCenter.getDefaultRepository().deleteFolder(deleteRequest);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.error(e);
|
||||||
|
throw new MSException(Translator.get("file.transfer.failed"), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return fileId;
|
return fileId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package io.metersphere.api.service.scenario;
|
package io.metersphere.api.service.scenario;
|
||||||
|
|
||||||
import io.metersphere.sdk.constants.ApiFileResourceType;
|
|
||||||
import io.metersphere.api.constants.ApiResourceType;
|
import io.metersphere.api.constants.ApiResourceType;
|
||||||
import io.metersphere.api.constants.ApiScenarioStepRefType;
|
import io.metersphere.api.constants.ApiScenarioStepRefType;
|
||||||
import io.metersphere.api.constants.ApiScenarioStepType;
|
import io.metersphere.api.constants.ApiScenarioStepType;
|
||||||
|
@ -51,9 +50,7 @@ import io.metersphere.sdk.domain.EnvironmentGroupExample;
|
||||||
import io.metersphere.sdk.dto.api.task.ApiRunModeConfigDTO;
|
import io.metersphere.sdk.dto.api.task.ApiRunModeConfigDTO;
|
||||||
import io.metersphere.sdk.dto.api.task.TaskRequestDTO;
|
import io.metersphere.sdk.dto.api.task.TaskRequestDTO;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.file.FileCenter;
|
|
||||||
import io.metersphere.sdk.file.FileCopyRequest;
|
import io.metersphere.sdk.file.FileCopyRequest;
|
||||||
import io.metersphere.sdk.file.FileRequest;
|
|
||||||
import io.metersphere.sdk.file.MinioRepository;
|
import io.metersphere.sdk.file.MinioRepository;
|
||||||
import io.metersphere.sdk.mapper.EnvironmentGroupMapper;
|
import io.metersphere.sdk.mapper.EnvironmentGroupMapper;
|
||||||
import io.metersphere.sdk.mapper.EnvironmentMapper;
|
import io.metersphere.sdk.mapper.EnvironmentMapper;
|
||||||
|
@ -152,10 +149,6 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
@Resource
|
@Resource
|
||||||
private ApiTestCaseService apiTestCaseService;
|
private ApiTestCaseService apiTestCaseService;
|
||||||
@Resource
|
@Resource
|
||||||
private FileAssociationService fileAssociationService;
|
|
||||||
@Resource
|
|
||||||
private FileMetadataService fileMetadataService;
|
|
||||||
@Resource
|
|
||||||
private ApiScenarioCsvMapper apiScenarioCsvMapper;
|
private ApiScenarioCsvMapper apiScenarioCsvMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private ApiScenarioCsvStepMapper apiScenarioCsvStepMapper;
|
private ApiScenarioCsvStepMapper apiScenarioCsvStepMapper;
|
||||||
|
@ -442,6 +435,18 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
apiScenarioBlob.setConfig(JSON.toJSONString(request.getScenarioConfig()).getBytes());
|
apiScenarioBlob.setConfig(JSON.toJSONString(request.getScenarioConfig()).getBytes());
|
||||||
apiScenarioBlobMapper.insert(apiScenarioBlob);
|
apiScenarioBlobMapper.insert(apiScenarioBlob);
|
||||||
|
|
||||||
|
// 处理csv文件
|
||||||
|
handCsvFilesAdd(request, creator, scenario);
|
||||||
|
|
||||||
|
// 处理添加的步骤
|
||||||
|
handleStepAdd(request, scenario);
|
||||||
|
|
||||||
|
// 处理步骤文件
|
||||||
|
handleStepFilesAdd(request, creator, scenario);
|
||||||
|
return scenario;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleStepAdd(ApiScenarioAddRequest request, ApiScenario scenario) {
|
||||||
// 插入步骤
|
// 插入步骤
|
||||||
if (CollectionUtils.isNotEmpty(request.getSteps())) {
|
if (CollectionUtils.isNotEmpty(request.getSteps())) {
|
||||||
checkCircularRef(scenario.getId(), request.getSteps());
|
checkCircularRef(scenario.getId(), request.getSteps());
|
||||||
|
@ -462,33 +467,25 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
apiScenarioStepBlobMapper.batchInsert(apiScenarioStepBlobs);
|
apiScenarioStepBlobMapper.batchInsert(apiScenarioStepBlobs);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveStepCsv(steps, csvSteps);
|
csvSteps.forEach(step -> step.setScenarioId(scenario.getId()));
|
||||||
|
saveStepCsv(scenario.getId(), steps, csvSteps);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理步骤文件
|
|
||||||
handleStepFiles(request, creator, scenario);
|
|
||||||
|
|
||||||
// 处理场景文件,csv等
|
|
||||||
handScenarioFiles(request, creator, scenario);
|
|
||||||
return scenario;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handScenarioFiles(ApiScenarioAddRequest request, String creator, ApiScenario scenario) {
|
private void handCsvFilesAdd(ApiScenarioAddRequest request, String creator, ApiScenario scenario) {
|
||||||
ResourceAddFileParam fileParam = request.getFileParam();
|
if (request.getScenarioConfig() == null || request.getScenarioConfig().getVariable() == null || request.getScenarioConfig().getVariable().getCsvVariables() == null) {
|
||||||
if (fileParam == null) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(scenario.getId(), scenario.getProjectId(), creator);
|
List<CsvVariable> csvVariables = request.getScenarioConfig().getVariable().getCsvVariables();
|
||||||
resourceUpdateRequest.setUploadFileIds(fileParam.getUploadFileIds());
|
|
||||||
resourceUpdateRequest.setLinkFileIds(fileParam.getLinkFileIds());
|
// 处理 csv 相关数据表
|
||||||
apiFileResourceService.addFileResource(resourceUpdateRequest);
|
handleCsvDataUpdate(csvVariables, scenario, List.of());
|
||||||
if (request.getScenarioConfig() != null
|
|
||||||
&& request.getScenarioConfig().getVariable() != null) {
|
// 处理文件的上传
|
||||||
saveCsv(request.getScenarioConfig().getVariable().getCsvVariables(), resourceUpdateRequest);
|
handleCsvFileUpdate(csvVariables, List.of(), scenario, creator);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleStepFiles(ApiScenarioAddRequest request, String creator, ApiScenario scenario) {
|
private void handleStepFilesAdd(ApiScenarioAddRequest request, String creator, ApiScenario scenario) {
|
||||||
Map<String, ResourceAddFileParam> stepFileParam = request.getStepFileParam();
|
Map<String, ResourceAddFileParam> stepFileParam = request.getStepFileParam();
|
||||||
if (MapUtils.isNotEmpty(stepFileParam)) {
|
if (MapUtils.isNotEmpty(stepFileParam)) {
|
||||||
stepFileParam.forEach((stepId, fileParam) -> {
|
stepFileParam.forEach((stepId, fileParam) -> {
|
||||||
|
@ -499,7 +496,7 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleStepFiles(ApiScenarioUpdateRequest request, String updater, ApiScenario scenario) {
|
private void handleStepFilesUpdate(ApiScenarioUpdateRequest request, String updater, ApiScenario scenario) {
|
||||||
Map<String, ResourceUpdateFileParam> stepFileParam = request.getStepFileParam();
|
Map<String, ResourceUpdateFileParam> stepFileParam = request.getStepFileParam();
|
||||||
if (MapUtils.isNotEmpty(stepFileParam)) {
|
if (MapUtils.isNotEmpty(stepFileParam)) {
|
||||||
stepFileParam.forEach((stepId, fileParam) -> {
|
stepFileParam.forEach((stepId, fileParam) -> {
|
||||||
|
@ -520,156 +517,126 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
return resourceUpdateRequest;
|
return resourceUpdateRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveStepCsv(List<ApiScenarioStep> steps, List<ApiScenarioCsvStep> csvSteps) {
|
private void saveStepCsv(String scenarioId, List<ApiScenarioStep> steps, List<ApiScenarioCsvStep> csvSteps) {
|
||||||
//获取所有的步骤id 然后删掉历史的关联关系
|
// 先删除
|
||||||
List<String> stepIds = steps.stream().map(ApiScenarioStep::getId).toList();
|
ApiScenarioCsvStepExample csvStepExample = new ApiScenarioCsvStepExample();
|
||||||
SubListUtils.dealForSubList(stepIds, 500, subList -> {
|
csvStepExample.createCriteria().andScenarioIdEqualTo(scenarioId);
|
||||||
ApiScenarioCsvStepExample csvStepExample = new ApiScenarioCsvStepExample();
|
apiScenarioCsvStepMapper.deleteByExample(csvStepExample);
|
||||||
csvStepExample.createCriteria().andStepIdIn(subList);
|
|
||||||
apiScenarioCsvStepMapper.deleteByExample(csvStepExample);
|
// 再添加
|
||||||
});
|
|
||||||
//插入csv步骤
|
|
||||||
if (CollectionUtils.isNotEmpty(csvSteps)) {
|
if (CollectionUtils.isNotEmpty(csvSteps)) {
|
||||||
SubListUtils.dealForSubList(csvSteps, 100, subList -> apiScenarioCsvStepMapper.batchInsert(subList));
|
SubListUtils.dealForSubList(csvSteps, 100, subList -> apiScenarioCsvStepMapper.batchInsert(subList));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveCsv(List<CsvVariable> csvVariables, ApiFileResourceUpdateRequest resourceUpdateRequest) {
|
private void handleCsvUpdate(ScenarioConfig scenarioConfig, ApiScenario scenario, String userId) {
|
||||||
//进行比较一下 哪些是已存在的 那些是新上传的
|
if (scenarioConfig == null || scenarioConfig.getVariable() == null || scenarioConfig.getVariable().getCsvVariables() == null) {
|
||||||
//查询已经存在的fileId 这里直接过滤所有的数据 拿到新上传的本地文件id 和已经存在的文件id 关联的文件id 关于新的 需要删除的 已经存在的
|
return;
|
||||||
ApiScenarioCsvExample apiScenarioCsvExample = new ApiScenarioCsvExample();
|
}
|
||||||
apiScenarioCsvExample.createCriteria().andScenarioIdEqualTo(resourceUpdateRequest.getResourceId());
|
List<CsvVariable> csvVariables = scenarioConfig.getVariable().getCsvVariables();
|
||||||
List<ApiScenarioCsv> dbFileIds = apiScenarioCsvMapper.selectByExample(apiScenarioCsvExample);
|
List<ApiScenarioCsv> dbCsv = getApiScenarioCsv(scenario.getId());
|
||||||
//取出所有的fileId Association为false的数据
|
|
||||||
List<String> dbLocalFileIds = dbFileIds.stream().filter(c -> BooleanUtils.isFalse(c.getAssociation())).map(ApiScenarioCsv::getFileId).toList();
|
|
||||||
//取出所有的fileId Association为true的数据
|
|
||||||
List<String> dbRefFileIds = dbFileIds.stream().filter(c -> BooleanUtils.isTrue(c.getAssociation())).map(ApiScenarioCsv::getFileId).toList();
|
|
||||||
|
|
||||||
//获取传的所有Association为false的数据
|
// 更新 csv 相关数据表
|
||||||
List<String> localFileIds = csvVariables.stream().filter(c -> BooleanUtils.isFalse(c.getAssociation())).map(CsvVariable::getFileId).toList();
|
handleCsvDataUpdate(csvVariables, scenario, dbCsv);
|
||||||
//获取传的所有Association为true的数据
|
|
||||||
List<String> refFileIds = csvVariables.stream().filter(c -> BooleanUtils.isTrue(c.getAssociation())).map(CsvVariable::getFileId).toList();
|
|
||||||
|
|
||||||
//取交集 交集数据是已存在的 不需要重新上传 和处理关联关系 但是需要更新apiScenarioCsv表的数据
|
// 处理文件的上传和删除
|
||||||
List<String> intersectionLocal = ListUtils.intersection(dbLocalFileIds, localFileIds);
|
handleCsvFileUpdate(csvVariables, dbCsv, scenario, userId);
|
||||||
//取差集 dbFileIds和 intersection的差集是需要删除的数据 本地数据需要删除的数据
|
|
||||||
List<String> deleteLocals = ListUtils.subtract(dbLocalFileIds, intersectionLocal);
|
|
||||||
resourceUpdateRequest.setDeleteFileIds(deleteLocals);
|
|
||||||
List<String> addLocal = ListUtils.subtract(localFileIds, intersectionLocal);
|
|
||||||
resourceUpdateRequest.setUploadFileIds(addLocal);
|
|
||||||
//获取 关联文件的交集
|
|
||||||
List<String> intersectionRef = ListUtils.intersection(dbRefFileIds, refFileIds);
|
|
||||||
//获取删除的
|
|
||||||
List<String> deleteRefs = ListUtils.subtract(dbRefFileIds, intersectionRef);
|
|
||||||
List<String> addRef = ListUtils.subtract(refFileIds, intersectionRef);
|
|
||||||
resourceUpdateRequest.setLinkFileIds(addRef);
|
|
||||||
resourceUpdateRequest.setUnLinkFileIds(deleteRefs);
|
|
||||||
//删除不存在的数据
|
|
||||||
deleteCsvResource(resourceUpdateRequest);
|
|
||||||
|
|
||||||
addCsvResource(resourceUpdateRequest, csvVariables);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCsvResource(ApiFileResourceUpdateRequest resourceUpdateRequest,
|
private void handleCsvDataUpdate(List<CsvVariable> csvVariables, ApiScenario scenario, List<ApiScenarioCsv> dbCsv) {
|
||||||
List<CsvVariable> csvVariables) {
|
List<String> dbCsvIds = dbCsv.stream()
|
||||||
List<ApiScenarioCsv> addData = new ArrayList<>();
|
.map(ApiScenarioCsv::getId)
|
||||||
List<ApiScenarioCsv> updateData = new ArrayList<>();
|
.toList();
|
||||||
List<String> addFileIds = resourceUpdateRequest.getUploadFileIds();
|
|
||||||
List<String> linkFileIds = resourceUpdateRequest.getLinkFileIds();
|
List<String> csvIds = csvVariables.stream()
|
||||||
Map<String, String> refFilesMap = new HashMap<>();
|
.map(CsvVariable::getId)
|
||||||
if (CollectionUtils.isNotEmpty(linkFileIds)) {
|
.toList();
|
||||||
//根据fileId查询文件名
|
|
||||||
List<FileMetadata> fileList = fileMetadataService.selectByList(linkFileIds);
|
List<String> deleteCsvIds = ListUtils.subtract(dbCsvIds, csvIds);
|
||||||
if (CollectionUtils.isNotEmpty(fileList)) {
|
|
||||||
//生成map key为文件id 值为文件名称 文件名称为name.类型
|
//删除不存在的数据
|
||||||
refFilesMap = fileList.stream().collect(Collectors.toMap(FileMetadata::getId, f -> f.getName() + "." + f.getType()));
|
deleteCsvResource(deleteCsvIds);
|
||||||
}
|
|
||||||
fileAssociationService.association(resourceUpdateRequest.getResourceId(), FileAssociationSourceUtil.SOURCE_TYPE_API_SCENARIO, linkFileIds,
|
Set<String> dbCsvIdSet = dbCsvIds.stream().collect(Collectors.toSet());
|
||||||
apiFileResourceService.createFileLogRecord(resourceUpdateRequest.getOperator(), resourceUpdateRequest.getProjectId(), OperationLogModule.API_SCENARIO_MANAGEMENT_SCENARIO));
|
|
||||||
}
|
List<ApiScenarioCsv> addCsvList = new ArrayList<>();
|
||||||
Map<String, String> finalRefFilesMap = refFilesMap;
|
csvVariables.stream().forEach(item -> {
|
||||||
// 添加文件与接口的关联关系
|
|
||||||
Map<String, String> addFileMap = new HashMap<>();
|
|
||||||
csvVariables.forEach(item -> {
|
|
||||||
ApiScenarioCsv scenarioCsv = new ApiScenarioCsv();
|
ApiScenarioCsv scenarioCsv = new ApiScenarioCsv();
|
||||||
BeanUtils.copyBean(scenarioCsv, item);
|
BeanUtils.copyBean(scenarioCsv, item);
|
||||||
scenarioCsv.setScenarioId(resourceUpdateRequest.getResourceId());
|
scenarioCsv.setScenarioId(scenario.getId());
|
||||||
scenarioCsv.setProjectId(resourceUpdateRequest.getProjectId());
|
scenarioCsv.setProjectId(scenario.getProjectId());
|
||||||
// uploadFileIds里包含的数据 全部需要上传到minio上或者需要重新建立关联关系
|
if (!dbCsvIdSet.contains(item.getId())) {
|
||||||
if (BooleanUtils.isFalse(item.getAssociation())
|
addCsvList.add(scenarioCsv);
|
||||||
&& CollectionUtils.isNotEmpty(addFileIds)
|
|
||||||
&& addFileIds.contains(item.getFileId())) {
|
|
||||||
scenarioCsv.setFileName(apiFileResourceService.getTempFileNameByFileId(item.getFileId()));
|
|
||||||
addFileMap.put(item.getFileId(), scenarioCsv.getId());
|
|
||||||
} else if (BooleanUtils.isTrue(item.getAssociation())
|
|
||||||
&& finalRefFilesMap.containsKey(item.getFileId())
|
|
||||||
&& CollectionUtils.isNotEmpty(linkFileIds)
|
|
||||||
&& linkFileIds.contains(item.getFileId())) {
|
|
||||||
scenarioCsv.setFileName(finalRefFilesMap.get(item.getFileId()));
|
|
||||||
}
|
|
||||||
if (StringUtils.isBlank(item.getId())) {
|
|
||||||
scenarioCsv.setId(IDGenerator.nextStr());
|
|
||||||
addData.add(scenarioCsv);
|
|
||||||
} else {
|
} else {
|
||||||
updateData.add(scenarioCsv);
|
apiScenarioCsvMapper.updateByPrimaryKey(scenarioCsv);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
|
||||||
ApiScenarioCsvMapper mapper = sqlSession.getMapper(ApiScenarioCsvMapper.class);
|
if (CollectionUtils.isNotEmpty(addCsvList)) {
|
||||||
if (CollectionUtils.isNotEmpty(updateData)) {
|
apiScenarioCsvMapper.batchInsert(addCsvList);
|
||||||
//更新apiScenarioCsv表
|
|
||||||
updateData.forEach(mapper::updateByPrimaryKeySelective);
|
|
||||||
}
|
|
||||||
if (CollectionUtils.isNotEmpty(addData)) {
|
|
||||||
//插入apiScenarioCsv表
|
|
||||||
addData.forEach(mapper::insertSelective);
|
|
||||||
}
|
|
||||||
sqlSession.flushStatements();
|
|
||||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
|
||||||
if (MapUtils.isNotEmpty(addFileMap)) {
|
|
||||||
// 上传文件到对象存储
|
|
||||||
apiFileResourceService.uploadFileResource(resourceUpdateRequest.getFolder(), addFileMap);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteCsvResource(ApiFileResourceUpdateRequest resourceUpdateRequest) {
|
private void handleCsvFileUpdate(List<CsvVariable> csvVariables, List<ApiScenarioCsv> dbCsv, ApiScenario scenario, String userId) {
|
||||||
// 处理本地上传文件
|
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(scenario.getId(), scenario.getProjectId(), userId);
|
||||||
List<String> deleteFileIds = resourceUpdateRequest.getDeleteFileIds();
|
// 设置本地文件相关参数
|
||||||
ApiScenarioCsvExample example = new ApiScenarioCsvExample();
|
setCsvLocalFileParam(csvVariables, dbCsv, resourceUpdateRequest);
|
||||||
ApiScenarioCsvStepExample stepExample = new ApiScenarioCsvStepExample();
|
// 设置关联文件相关参数
|
||||||
if (CollectionUtils.isNotEmpty(deleteFileIds)) {
|
setCsvLinkFileParam(csvVariables, dbCsv, resourceUpdateRequest);
|
||||||
// 删除关联关系
|
apiFileResourceService.addFileResource(resourceUpdateRequest);
|
||||||
deleteFileIds.forEach(fileId -> {
|
}
|
||||||
FileRequest request = new FileRequest();
|
|
||||||
// 删除文件所在目录
|
|
||||||
request.setFolder(resourceUpdateRequest.getFolder() + "/" + fileId);
|
|
||||||
try {
|
|
||||||
FileCenter.getDefaultRepository().deleteFolder(request);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogUtils.error(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
example.createCriteria()
|
private void setCsvLinkFileParam(List<CsvVariable> csvVariables, List<ApiScenarioCsv> dbCsv, ApiFileResourceUpdateRequest resourceUpdateRequest) {
|
||||||
.andScenarioIdEqualTo(resourceUpdateRequest.getResourceId())
|
// 获取数据库中关联的文件id
|
||||||
.andFileIdIn(deleteFileIds);
|
List<String> dbRefFileIds = dbCsv.stream()
|
||||||
apiScenarioCsvMapper.deleteByExample(example);
|
.filter(c -> BooleanUtils.isTrue(c.getAssociation()))
|
||||||
stepExample.createCriteria().andFileIdIn(deleteFileIds);
|
.map(ApiScenarioCsv::getFileId)
|
||||||
apiScenarioCsvStepMapper.deleteByExample(stepExample);
|
.toList();
|
||||||
|
|
||||||
}
|
// 获取请求中关联的文件id
|
||||||
List<String> unLinkFileIds = resourceUpdateRequest.getUnLinkFileIds();
|
List<String> refFileIds = csvVariables.stream()
|
||||||
// 处理关联文件
|
.filter(c -> BooleanUtils.isTrue(c.getAssociation())).map(CsvVariable::getFileId).toList();
|
||||||
if (CollectionUtils.isNotEmpty(unLinkFileIds)) {
|
|
||||||
fileAssociationService.deleteBySourceIdAndFileIds(resourceUpdateRequest.getResourceId(), unLinkFileIds,
|
List<String> unlinkFileIds = ListUtils.subtract(dbRefFileIds, refFileIds);
|
||||||
apiFileResourceService.createFileLogRecord(resourceUpdateRequest.getOperator(), resourceUpdateRequest.getProjectId(), resourceUpdateRequest.getLogModule()));
|
resourceUpdateRequest.setUnLinkFileIds(unlinkFileIds);
|
||||||
example.clear();
|
List<String> linkFileIds = ListUtils.subtract(refFileIds, dbRefFileIds);
|
||||||
example.createCriteria()
|
resourceUpdateRequest.setLinkFileIds(linkFileIds);
|
||||||
.andScenarioIdEqualTo(resourceUpdateRequest.getResourceId())
|
}
|
||||||
.andFileIdIn(unLinkFileIds);
|
|
||||||
|
private void setCsvLocalFileParam(List<CsvVariable> csvVariables, List<ApiScenarioCsv> dbCsv, ApiFileResourceUpdateRequest resourceUpdateRequest) {
|
||||||
|
// 获取数据库中的本地文件
|
||||||
|
List<String> dbLocalFileIds = dbCsv.stream()
|
||||||
|
.filter(c -> BooleanUtils.isFalse(c.getAssociation()))
|
||||||
|
.map(ApiScenarioCsv::getFileId)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
// 获取请求中的本地文件
|
||||||
|
List<String> localFileIds = csvVariables.stream()
|
||||||
|
.filter(c -> BooleanUtils.isFalse(c.getAssociation()))
|
||||||
|
.map(CsvVariable::getFileId).toList();
|
||||||
|
|
||||||
|
// 待删除文件
|
||||||
|
List<String> deleteLocals = ListUtils.subtract(dbLocalFileIds, localFileIds);
|
||||||
|
resourceUpdateRequest.setDeleteFileIds(deleteLocals);
|
||||||
|
// 新上传文件
|
||||||
|
List<String> addLocal = ListUtils.subtract(localFileIds, dbLocalFileIds);
|
||||||
|
resourceUpdateRequest.setUploadFileIds(addLocal);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ApiScenarioCsv> getApiScenarioCsv(String scenarioId) {
|
||||||
|
ApiScenarioCsvExample apiScenarioCsvExample = new ApiScenarioCsvExample();
|
||||||
|
apiScenarioCsvExample.createCriteria().andScenarioIdEqualTo(scenarioId);
|
||||||
|
return apiScenarioCsvMapper.selectByExample(apiScenarioCsvExample);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteCsvResource(List<String> deleteCsvIds) {
|
||||||
|
if (CollectionUtils.isNotEmpty(deleteCsvIds)) {
|
||||||
|
ApiScenarioCsvExample example = new ApiScenarioCsvExample();
|
||||||
|
example.createCriteria().andIdIn(deleteCsvIds);
|
||||||
apiScenarioCsvMapper.deleteByExample(example);
|
apiScenarioCsvMapper.deleteByExample(example);
|
||||||
stepExample.clear();
|
|
||||||
stepExample.createCriteria().andFileIdIn(deleteFileIds);
|
ApiScenarioCsvStepExample stepExample = new ApiScenarioCsvStepExample();
|
||||||
|
stepExample.createCriteria().andIdIn(deleteCsvIds);
|
||||||
apiScenarioCsvStepMapper.deleteByExample(stepExample);
|
apiScenarioCsvStepMapper.deleteByExample(stepExample);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -719,32 +686,14 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
updateApiScenarioStep(request, originScenario, updater);
|
updateApiScenarioStep(request, originScenario, updater);
|
||||||
|
|
||||||
// 处理步骤文件
|
// 处理步骤文件
|
||||||
handleStepFiles(request, updater, originScenario);
|
handleStepFilesUpdate(request, updater, originScenario);
|
||||||
|
|
||||||
// 处理场景文件
|
// 处理 csv 文件
|
||||||
handleScenarioFiles(request, updater, originScenario);
|
handleCsvUpdate(request.getScenarioConfig(), scenario, updater);
|
||||||
|
|
||||||
return scenario;
|
return scenario;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleScenarioFiles(ApiScenarioUpdateRequest request, String updater, ApiScenario scenario) {
|
|
||||||
// 处理场景文件
|
|
||||||
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(scenario.getId(), scenario.getProjectId(), updater);
|
|
||||||
ResourceAddFileParam fileParam = request.getFileParam();
|
|
||||||
if (fileParam != null) {
|
|
||||||
resourceUpdateRequest = BeanUtils.copyBean(resourceUpdateRequest, fileParam);
|
|
||||||
apiFileResourceService.updateFileResource(resourceUpdateRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
//处理csv变量
|
|
||||||
if (request.getScenarioConfig() != null
|
|
||||||
&& request.getScenarioConfig().getVariable() != null) {
|
|
||||||
saveCsv(request.getScenarioConfig().getVariable().getCsvVariables(), resourceUpdateRequest);
|
|
||||||
} else {
|
|
||||||
saveCsv(new ArrayList<>(), resourceUpdateRequest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新场景步骤
|
* 更新场景步骤
|
||||||
*/
|
*/
|
||||||
|
@ -764,8 +713,9 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
// 获取待更新的步骤
|
// 获取待更新的步骤
|
||||||
List<ApiScenarioStep> apiScenarioSteps = getApiScenarioSteps(null, steps, scenarioCsvSteps);
|
List<ApiScenarioStep> apiScenarioSteps = getApiScenarioSteps(null, steps, scenarioCsvSteps);
|
||||||
apiScenarioSteps.forEach(step -> step.setScenarioId(scenario.getId()));
|
apiScenarioSteps.forEach(step -> step.setScenarioId(scenario.getId()));
|
||||||
|
scenarioCsvSteps.forEach(step -> step.setScenarioId(scenario.getId()));
|
||||||
|
|
||||||
saveStepCsv(apiScenarioSteps, scenarioCsvSteps);
|
saveStepCsv(scenario.getId(), apiScenarioSteps, scenarioCsvSteps);
|
||||||
// 获取待更新的步骤详情
|
// 获取待更新的步骤详情
|
||||||
addSpecialStepDetails(steps, request.getStepDetails());
|
addSpecialStepDetails(steps, request.getStepDetails());
|
||||||
List<ApiScenarioStepBlob> updateStepBlobs = getUpdateStepBlobs(apiScenarioSteps, request.getStepDetails());
|
List<ApiScenarioStepBlob> updateStepBlobs = getUpdateStepBlobs(apiScenarioSteps, request.getStepDetails());
|
||||||
|
@ -941,9 +891,9 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CollectionUtils.isNotEmpty(step.getCsvFileIds())) {
|
if (CollectionUtils.isNotEmpty(step.getCsvIds())) {
|
||||||
//如果是csv文件 需要保存到apiScenarioCsvStep表中
|
//如果是csv文件 需要保存到apiScenarioCsvStep表中
|
||||||
step.getCsvFileIds().forEach(fileId -> {
|
step.getCsvIds().forEach(fileId -> {
|
||||||
ApiScenarioCsvStep csvStep = new ApiScenarioCsvStep();
|
ApiScenarioCsvStep csvStep = new ApiScenarioCsvStep();
|
||||||
csvStep.setId(IDGenerator.nextStr());
|
csvStep.setId(IDGenerator.nextStr());
|
||||||
csvStep.setStepId(apiScenarioStep.getId());
|
csvStep.setStepId(apiScenarioStep.getId());
|
||||||
|
@ -1183,16 +1133,11 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
private void deleteCsvByScenarioId(String id) {
|
private void deleteCsvByScenarioId(String id) {
|
||||||
ApiScenarioCsvExample example = new ApiScenarioCsvExample();
|
ApiScenarioCsvExample example = new ApiScenarioCsvExample();
|
||||||
example.createCriteria().andScenarioIdEqualTo(id);
|
example.createCriteria().andScenarioIdEqualTo(id);
|
||||||
List<ApiScenarioCsv> apiScenarioCsv = apiScenarioCsvMapper.selectByExample(example);
|
|
||||||
if (CollectionUtils.isNotEmpty(apiScenarioCsv)) {
|
|
||||||
List<String> fileIds = apiScenarioCsv.stream().map(ApiScenarioCsv::getFileId).toList();
|
|
||||||
//删除关联关系
|
|
||||||
ApiScenarioCsvStepExample stepExample = new ApiScenarioCsvStepExample();
|
|
||||||
stepExample.createCriteria().andFileIdIn(fileIds);
|
|
||||||
apiScenarioCsvStepMapper.deleteByExample(stepExample);
|
|
||||||
}
|
|
||||||
apiScenarioCsvMapper.deleteByExample(example);
|
apiScenarioCsvMapper.deleteByExample(example);
|
||||||
|
|
||||||
|
ApiScenarioCsvStepExample stepExample = new ApiScenarioCsvStepExample();
|
||||||
|
stepExample.createCriteria().andScenarioIdEqualTo(id);
|
||||||
|
apiScenarioCsvStepMapper.deleteByExample(stepExample);
|
||||||
}
|
}
|
||||||
|
|
||||||
//级联删除
|
//级联删除
|
||||||
|
@ -1810,6 +1755,7 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
msTestElement.setName(step.getName());
|
msTestElement.setName(step.getName());
|
||||||
// 步骤ID,设置为唯一ID
|
// 步骤ID,设置为唯一ID
|
||||||
msTestElement.setStepId(step.getUniqueId());
|
msTestElement.setStepId(step.getUniqueId());
|
||||||
|
msTestElement.setCsvIds(step.getCsvIds());
|
||||||
|
|
||||||
// 记录引用的资源ID和项目ID,下载执行文件时需要使用
|
// 记录引用的资源ID和项目ID,下载执行文件时需要使用
|
||||||
parseParam.getRefProjectIds().add(step.getProjectId());
|
parseParam.getRefProjectIds().add(step.getProjectId());
|
||||||
|
@ -2152,15 +2098,14 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
ApiScenarioDetail apiScenarioDetail = BeanUtils.copyBean(new ApiScenarioDetail(), apiScenario);
|
ApiScenarioDetail apiScenarioDetail = BeanUtils.copyBean(new ApiScenarioDetail(), apiScenario);
|
||||||
apiScenarioDetail.setSteps(List.of());
|
apiScenarioDetail.setSteps(List.of());
|
||||||
ApiScenarioBlob apiScenarioBlob = apiScenarioBlobMapper.selectByPrimaryKey(scenarioId);
|
ApiScenarioBlob apiScenarioBlob = apiScenarioBlobMapper.selectByPrimaryKey(scenarioId);
|
||||||
|
|
||||||
if (apiScenarioBlob != null) {
|
if (apiScenarioBlob != null) {
|
||||||
apiScenarioDetail.setScenarioConfig(JSON.parseObject(new String(apiScenarioBlob.getConfig()), ScenarioConfig.class));
|
apiScenarioDetail.setScenarioConfig(JSON.parseObject(new String(apiScenarioBlob.getConfig()), ScenarioConfig.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
//存放csv变量
|
//存放csv变量
|
||||||
List<CsvVariable> csvVariables = extApiScenarioStepMapper.getCsvVariableByScenarioId(scenarioId);
|
List<CsvVariable> csvVariables = extApiScenarioStepMapper.getCsvVariableByScenarioId(scenarioId);
|
||||||
if (CollectionUtils.isNotEmpty(csvVariables) && apiScenarioDetail.getScenarioConfig() != null
|
apiScenarioDetail.getScenarioConfig().getVariable().setCsvVariables(csvVariables);
|
||||||
&& apiScenarioDetail.getScenarioConfig().getVariable() != null) {
|
|
||||||
apiScenarioDetail.getScenarioConfig().getVariable().setCsvVariables(csvVariables);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取所有步骤
|
// 获取所有步骤
|
||||||
List<ApiScenarioStepDTO> allSteps = getAllStepsByScenarioIds(List.of(scenarioId))
|
List<ApiScenarioStepDTO> allSteps = getAllStepsByScenarioIds(List.of(scenarioId))
|
||||||
|
@ -2169,16 +2114,13 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
//获取所有步骤的csv的关联关系
|
//获取所有步骤的csv的关联关系
|
||||||
List<String> stepIds = allSteps.stream().map(ApiScenarioStepDTO::getId).toList();
|
List<ApiScenarioCsvStep> csvSteps = extApiScenarioStepMapper.getCsvStepByScenarioId(scenarioId);
|
||||||
if (CollectionUtils.isNotEmpty(stepIds)) {
|
// 构造 map,key 为步骤ID,value 为csv文件ID列表
|
||||||
List<ApiScenarioCsvStep> csvSteps = extApiScenarioStepMapper.getCsvStepByStepIds(stepIds);
|
Map<String, List<String>> stepsCsvMap = csvSteps.stream()
|
||||||
// 构造 map,key 为步骤ID,value 为csv文件ID列表
|
.collect(Collectors.groupingBy(ApiScenarioCsvStep::getStepId, Collectors.mapping(ApiScenarioCsvStep::getFileId, Collectors.toList())));
|
||||||
Map<String, List<String>> stepsCsvMap = csvSteps.stream()
|
//将stepsCsvMap根据步骤id放入到allSteps中
|
||||||
.collect(Collectors.groupingBy(ApiScenarioCsvStep::getStepId, Collectors.mapping(ApiScenarioCsvStep::getFileId, Collectors.toList())));
|
if (CollectionUtils.isNotEmpty(allSteps)) {
|
||||||
//将stepsCsvMap根据步骤id放入到allSteps中
|
allSteps.forEach(step -> step.setCsvIds(stepsCsvMap.get(step.getId())));
|
||||||
if (CollectionUtils.isNotEmpty(allSteps)) {
|
|
||||||
allSteps.forEach(step -> step.setCsvFileIds(stepsCsvMap.get(step.getId())));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构造 map,key 为场景ID,value 为步骤列表
|
// 构造 map,key 为场景ID,value 为步骤列表
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
package io.metersphere.api.utils;
|
package io.metersphere.api.utils;
|
||||||
|
|
||||||
import io.metersphere.api.parser.jmeter.*;
|
import io.metersphere.api.parser.jmeter.*;
|
||||||
|
import io.metersphere.api.parser.jmeter.child.MsCsvChildPreConverter;
|
||||||
|
import io.metersphere.api.parser.jmeter.controller.MsConstantTimerControllerConverter;
|
||||||
|
import io.metersphere.api.parser.jmeter.controller.MsIfControllerConverter;
|
||||||
|
import io.metersphere.api.parser.jmeter.controller.MsLoopControllerConverter;
|
||||||
|
import io.metersphere.api.parser.jmeter.controller.MsOnceOnlyControllerConverter;
|
||||||
import io.metersphere.plugin.api.spi.AbstractJmeterElementConverter;
|
import io.metersphere.plugin.api.spi.AbstractJmeterElementConverter;
|
||||||
import io.metersphere.plugin.api.spi.MsTestElement;
|
import io.metersphere.plugin.api.spi.MsTestElement;
|
||||||
import io.metersphere.plugin.sdk.util.PluginLogUtils;
|
import io.metersphere.plugin.sdk.util.PluginLogUtils;
|
||||||
|
@ -24,7 +29,11 @@ public class JmeterElementConverterRegister {
|
||||||
private static final Map<Class<? extends MsTestElement>, AbstractJmeterElementConverter<? extends MsTestElement>> parserMap = new HashMap<>();
|
private static final Map<Class<? extends MsTestElement>, AbstractJmeterElementConverter<? extends MsTestElement>> parserMap = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// 注册默认的转换器 todo 注册插件的转换器
|
// 设置获取转换器的方法
|
||||||
|
AbstractJmeterElementConverter.setGetConverterFunc(JmeterElementConverterRegister::getConverter);
|
||||||
|
// 注册子步骤前置解析器
|
||||||
|
AbstractJmeterElementConverter.registerChildPreConverters(new MsCsvChildPreConverter());
|
||||||
|
// 注册默认的转换器
|
||||||
register(MsHTTPElementConverter.class);
|
register(MsHTTPElementConverter.class);
|
||||||
register(MsCommonElementConverter.class);
|
register(MsCommonElementConverter.class);
|
||||||
register(MsScriptElementConverter.class);
|
register(MsScriptElementConverter.class);
|
||||||
|
@ -43,8 +52,6 @@ public class JmeterElementConverterRegister {
|
||||||
public static void register(Class<? extends AbstractJmeterElementConverter<? extends MsTestElement>> elementConverterClass) {
|
public static void register(Class<? extends AbstractJmeterElementConverter<? extends MsTestElement>> elementConverterClass) {
|
||||||
try {
|
try {
|
||||||
AbstractJmeterElementConverter<? extends MsTestElement> elementConverter = elementConverterClass.getDeclaredConstructor().newInstance();
|
AbstractJmeterElementConverter<? extends MsTestElement> elementConverter = elementConverterClass.getDeclaredConstructor().newInstance();
|
||||||
// 设置获取转换器的方法
|
|
||||||
elementConverter.setGetConverterFunc(JmeterElementConverterRegister::getConverter);
|
|
||||||
// 注册到解析器集合中
|
// 注册到解析器集合中
|
||||||
parserMap.put(elementConverter.testElementClass, elementConverter);
|
parserMap.put(elementConverter.testElementClass, elementConverter);
|
||||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
|
||||||
|
|
|
@ -5,7 +5,6 @@ import io.metersphere.api.domain.*;
|
||||||
import io.metersphere.api.dto.ApiFile;
|
import io.metersphere.api.dto.ApiFile;
|
||||||
import io.metersphere.api.dto.ApiRunModeRequest;
|
import io.metersphere.api.dto.ApiRunModeRequest;
|
||||||
import io.metersphere.api.dto.ReferenceRequest;
|
import io.metersphere.api.dto.ReferenceRequest;
|
||||||
import io.metersphere.api.dto.ResourceAddFileParam;
|
|
||||||
import io.metersphere.api.dto.assertion.MsAssertionConfig;
|
import io.metersphere.api.dto.assertion.MsAssertionConfig;
|
||||||
import io.metersphere.api.dto.debug.ModuleCreateRequest;
|
import io.metersphere.api.dto.debug.ModuleCreateRequest;
|
||||||
import io.metersphere.api.dto.definition.*;
|
import io.metersphere.api.dto.definition.*;
|
||||||
|
@ -106,6 +105,9 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
private static final String UPDATE_STATUS = "update-status";
|
private static final String UPDATE_STATUS = "update-status";
|
||||||
private static final String UPDATE_PRIORITY = "update-priority";
|
private static final String UPDATE_PRIORITY = "update-priority";
|
||||||
private static final String BATCH_RUN = "batch-operation/run";
|
private static final String BATCH_RUN = "batch-operation/run";
|
||||||
|
private static final String TRANSFER_OPTIONS = "transfer/options/{0}";
|
||||||
|
private static final String TRANSFER = "transfer";
|
||||||
|
private static final String STEP_TRANSFER = "step/transfer";
|
||||||
|
|
||||||
private static final Map<String, String> BATCH_OPERATION_SCENARIO_MODULE_MAP = new HashMap<>();
|
private static final Map<String, String> BATCH_OPERATION_SCENARIO_MODULE_MAP = new HashMap<>();
|
||||||
private static final List<String> BATCH_OPERATION_SCENARIO_ID = new ArrayList<>();
|
private static final List<String> BATCH_OPERATION_SCENARIO_ID = new ArrayList<>();
|
||||||
|
@ -355,9 +357,6 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
request.setSteps(steps);
|
request.setSteps(steps);
|
||||||
request.setStepDetails(steptDetailMap);
|
request.setStepDetails(steptDetailMap);
|
||||||
request.setScenarioConfig(getScenarioConfig());
|
request.setScenarioConfig(getScenarioConfig());
|
||||||
String fileId = doUploadTempFile(getMockMultipartFile());
|
|
||||||
request.setFileParam(new ResourceAddFileParam());
|
|
||||||
request.getFileParam().setUploadFileIds(List.of(fileId));
|
|
||||||
MvcResult mvcResult = this.requestPostWithOkAndReturn(DEFAULT_ADD, request);
|
MvcResult mvcResult = this.requestPostWithOkAndReturn(DEFAULT_ADD, request);
|
||||||
ApiScenario resultData = getResultData(mvcResult, ApiScenario.class);
|
ApiScenario resultData = getResultData(mvcResult, ApiScenario.class);
|
||||||
this.addApiScenario = apiScenarioMapper.selectByPrimaryKey(resultData.getId());
|
this.addApiScenario = apiScenarioMapper.selectByPrimaryKey(resultData.getId());
|
||||||
|
@ -365,7 +364,6 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
assertUpdateSteps(steps, steptDetailMap);
|
assertUpdateSteps(steps, steptDetailMap);
|
||||||
|
|
||||||
request.setName("anOther name");
|
request.setName("anOther name");
|
||||||
request.getFileParam().setUploadFileIds(List.of());
|
|
||||||
request.setGrouped(true);
|
request.setGrouped(true);
|
||||||
request.setEnvironmentId(envGroupId);
|
request.setEnvironmentId(envGroupId);
|
||||||
ApiScenarioStepRequest stepRequest = new ApiScenarioStepRequest();
|
ApiScenarioStepRequest stepRequest = new ApiScenarioStepRequest();
|
||||||
|
@ -387,6 +385,7 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
stepRequest2.setProjectId(DEFAULT_PROJECT_ID);
|
stepRequest2.setProjectId(DEFAULT_PROJECT_ID);
|
||||||
steps = List.of(stepRequest, stepRequest2);
|
steps = List.of(stepRequest, stepRequest2);
|
||||||
request.setSteps(steps);
|
request.setSteps(steps);
|
||||||
|
request.getScenarioConfig().getVariable().getCsvVariables().forEach(csvVariable -> csvVariable.setId(UUID.randomUUID().toString()));
|
||||||
mvcResult = this.requestPostWithOkAndReturn(DEFAULT_ADD, request);
|
mvcResult = this.requestPostWithOkAndReturn(DEFAULT_ADD, request);
|
||||||
this.anOtherAddApiScenario = apiScenarioMapper.selectByPrimaryKey(getResultData(mvcResult, ApiScenario.class).getId());
|
this.anOtherAddApiScenario = apiScenarioMapper.selectByPrimaryKey(getResultData(mvcResult, ApiScenario.class).getId());
|
||||||
assertUpdateApiScenario(request, request.getScenarioConfig(), anOtherAddApiScenario.getId());
|
assertUpdateApiScenario(request, request.getScenarioConfig(), anOtherAddApiScenario.getId());
|
||||||
|
@ -444,7 +443,7 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScenarioConfig getScenarioConfig() throws Exception {
|
private ScenarioConfig getScenarioConfig() {
|
||||||
ScenarioConfig scenarioConfig = new ScenarioConfig();
|
ScenarioConfig scenarioConfig = new ScenarioConfig();
|
||||||
MsAssertionConfig msAssertionConfig = new MsAssertionConfig();
|
MsAssertionConfig msAssertionConfig = new MsAssertionConfig();
|
||||||
MsScriptAssertion scriptAssertion = new MsScriptAssertion();
|
MsScriptAssertion scriptAssertion = new MsScriptAssertion();
|
||||||
|
@ -478,16 +477,20 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
fileMetadataId = fileMetadataService.upload(fileUploadRequest, "admin", file);
|
fileMetadataId = fileMetadataService.upload(fileUploadRequest, "admin", file);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<CsvVariable> getCsvVariables() throws Exception {
|
public List<CsvVariable> getCsvVariables() {
|
||||||
List<CsvVariable> csvVariables = new ArrayList<>();
|
List<CsvVariable> csvVariables = new ArrayList<>();
|
||||||
CsvVariable csvVariable = new CsvVariable();
|
CsvVariable csvVariable = new CsvVariable();
|
||||||
|
csvVariable.setId(UUID.randomUUID().toString());
|
||||||
csvVariable.setFileId(localFileId);
|
csvVariable.setFileId(localFileId);
|
||||||
csvVariable.setName("csv变量");
|
csvVariable.setName("csv变量");
|
||||||
|
csvVariable.setFileName("test.jbc");
|
||||||
csvVariable.setScope(CsvVariable.CsvVariableScope.SCENARIO.name());
|
csvVariable.setScope(CsvVariable.CsvVariableScope.SCENARIO.name());
|
||||||
csvVariables.add(csvVariable);
|
csvVariables.add(csvVariable);
|
||||||
csvVariable = new CsvVariable();
|
csvVariable = new CsvVariable();
|
||||||
|
csvVariable.setId(UUID.randomUUID().toString());
|
||||||
csvVariable.setFileId(fileMetadataId);
|
csvVariable.setFileId(fileMetadataId);
|
||||||
csvVariable.setName("csv-关联的");
|
csvVariable.setName("csv-关联的");
|
||||||
|
csvVariable.setFileName("test.jbc");
|
||||||
csvVariable.setScope(CsvVariable.CsvVariableScope.SCENARIO.name());
|
csvVariable.setScope(CsvVariable.CsvVariableScope.SCENARIO.name());
|
||||||
csvVariable.setAssociation(true);
|
csvVariable.setAssociation(true);
|
||||||
csvVariables.add(csvVariable);
|
csvVariables.add(csvVariable);
|
||||||
|
@ -506,7 +509,7 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
stepRequest.setStepType(ApiScenarioStepType.API_CASE.name());
|
stepRequest.setStepType(ApiScenarioStepType.API_CASE.name());
|
||||||
stepRequest.setProjectId(DEFAULT_PROJECT_ID);
|
stepRequest.setProjectId(DEFAULT_PROJECT_ID);
|
||||||
stepRequest.setConfig(new HashMap<>());
|
stepRequest.setConfig(new HashMap<>());
|
||||||
stepRequest.setCsvFileIds(List.of(fileMetadataId));
|
stepRequest.setCsvIds(List.of(fileMetadataId));
|
||||||
|
|
||||||
ApiScenarioStepRequest stepRequest2 = new ApiScenarioStepRequest();
|
ApiScenarioStepRequest stepRequest2 = new ApiScenarioStepRequest();
|
||||||
stepRequest2.setId(IDGenerator.nextStr());
|
stepRequest2.setId(IDGenerator.nextStr());
|
||||||
|
@ -518,7 +521,7 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
stepRequest2.setStepType(ApiScenarioStepType.API_CASE.name());
|
stepRequest2.setStepType(ApiScenarioStepType.API_CASE.name());
|
||||||
stepRequest2.setRefType(ApiScenarioStepRefType.COPY.name());
|
stepRequest2.setRefType(ApiScenarioStepRefType.COPY.name());
|
||||||
stepRequest2.setProjectId(DEFAULT_PROJECT_ID);
|
stepRequest2.setProjectId(DEFAULT_PROJECT_ID);
|
||||||
stepRequest2.setCsvFileIds(List.of(fileMetadataId));
|
stepRequest2.setCsvIds(List.of(fileMetadataId));
|
||||||
|
|
||||||
ApiScenarioStepRequest stepRequest3 = new ApiScenarioStepRequest();
|
ApiScenarioStepRequest stepRequest3 = new ApiScenarioStepRequest();
|
||||||
stepRequest3.setId(IDGenerator.nextStr());
|
stepRequest3.setId(IDGenerator.nextStr());
|
||||||
|
@ -809,7 +812,7 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
@Test
|
@Test
|
||||||
@Order(7)
|
@Order(7)
|
||||||
public void testTransfer() throws Exception {
|
public void testTransfer() throws Exception {
|
||||||
this.requestGetWithOk("transfer/options/" + "/" + DEFAULT_PROJECT_ID);
|
this.requestGetWithOk(TRANSFER_OPTIONS, DEFAULT_PROJECT_ID);
|
||||||
ApiTransferRequest apiTransferRequest = new ApiTransferRequest();
|
ApiTransferRequest apiTransferRequest = new ApiTransferRequest();
|
||||||
apiTransferRequest.setSourceId(addApiScenario.getId());
|
apiTransferRequest.setSourceId(addApiScenario.getId());
|
||||||
apiTransferRequest.setProjectId(DEFAULT_PROJECT_ID);
|
apiTransferRequest.setProjectId(DEFAULT_PROJECT_ID);
|
||||||
|
@ -819,10 +822,10 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
apiTransferRequest.setOriginalName("test-scenario-file.txt");
|
apiTransferRequest.setOriginalName("test-scenario-file.txt");
|
||||||
String uploadFileId = doUploadTempFile(getMockMultipartFile());
|
String uploadFileId = doUploadTempFile(getMockMultipartFile());
|
||||||
apiTransferRequest.setFileId(uploadFileId);
|
apiTransferRequest.setFileId(uploadFileId);
|
||||||
this.requestPost("transfer", apiTransferRequest).andExpect(status().isOk());
|
this.requestPost(TRANSFER, apiTransferRequest).andExpect(status().isOk());
|
||||||
//文件不存在
|
//文件不存在
|
||||||
apiTransferRequest.setFileId("111");
|
apiTransferRequest.setFileId("111");
|
||||||
this.requestPost("transfer", apiTransferRequest).andExpect(status().is5xxServerError());
|
this.requestPost(TRANSFER, apiTransferRequest).andExpect(status().is5xxServerError());
|
||||||
//文件已经上传
|
//文件已经上传
|
||||||
ApiFileResourceExample apiFileResourceExample = new ApiFileResourceExample();
|
ApiFileResourceExample apiFileResourceExample = new ApiFileResourceExample();
|
||||||
apiFileResourceExample.createCriteria().andResourceIdEqualTo(addApiScenario.getId());
|
apiFileResourceExample.createCriteria().andResourceIdEqualTo(addApiScenario.getId());
|
||||||
|
@ -831,8 +834,26 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
apiTransferRequest.setFileId(apiFileResources.get(0).getFileId());
|
apiTransferRequest.setFileId(apiFileResources.get(0).getFileId());
|
||||||
apiTransferRequest.setFileName("test-scenario-file-1");
|
apiTransferRequest.setFileName("test-scenario-file-1");
|
||||||
apiTransferRequest.setOriginalName("test-scenario-file-1.txt");
|
apiTransferRequest.setOriginalName("test-scenario-file-1.txt");
|
||||||
this.requestPost("transfer", apiTransferRequest).andExpect(status().isOk());
|
this.requestPost(TRANSFER, apiTransferRequest).andExpect(status().isOk());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(7)
|
||||||
|
public void testStepTransfer() throws Exception {
|
||||||
|
this.requestGetWithOk(TRANSFER_OPTIONS, DEFAULT_PROJECT_ID);
|
||||||
|
ApiTransferRequest apiTransferRequest = new ApiTransferRequest();
|
||||||
|
apiTransferRequest.setSourceId(addApiScenarioSteps.get(0).getId());
|
||||||
|
apiTransferRequest.setProjectId(DEFAULT_PROJECT_ID);
|
||||||
|
apiTransferRequest.setModuleId("root");
|
||||||
|
apiTransferRequest.setLocal(true);
|
||||||
|
apiTransferRequest.setFileName("test-scenario-step-file");
|
||||||
|
apiTransferRequest.setOriginalName("test-scenario-step-file.txt");
|
||||||
|
String uploadFileId = doUploadTempFile(getMockMultipartFile());
|
||||||
|
apiTransferRequest.setFileId(uploadFileId);
|
||||||
|
this.requestPost(STEP_TRANSFER, apiTransferRequest).andExpect(status().isOk());
|
||||||
|
//文件不存在
|
||||||
|
apiTransferRequest.setFileId("111");
|
||||||
|
this.requestPost(STEP_TRANSFER, apiTransferRequest).andExpect(status().is5xxServerError());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -316,7 +316,7 @@ public class FileAssociationService {
|
||||||
* @return
|
* @return
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public String transferAndAssociation(@Validated FileAssociationDTO fileAssociationDTO) throws Exception {
|
public String transferAndAssociation(@Validated FileAssociationDTO fileAssociationDTO) {
|
||||||
FileAssociationSource source = extFileAssociationMapper.selectNameBySourceTableAndId(FileAssociationSourceUtil.getQuerySql(fileAssociationDTO.getSourceType()), fileAssociationDTO.getSourceId());
|
FileAssociationSource source = extFileAssociationMapper.selectNameBySourceTableAndId(FileAssociationSourceUtil.getQuerySql(fileAssociationDTO.getSourceType()), fileAssociationDTO.getSourceId());
|
||||||
this.validateSourceName(source);
|
this.validateSourceName(source);
|
||||||
String fileId = fileMetadataService.transferFile(
|
String fileId = fileMetadataService.transferFile(
|
||||||
|
|
|
@ -22,10 +22,7 @@ import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.file.FileRepository;
|
import io.metersphere.sdk.file.FileRepository;
|
||||||
import io.metersphere.sdk.file.FileRequest;
|
import io.metersphere.sdk.file.FileRequest;
|
||||||
import io.metersphere.sdk.file.MinioRepository;
|
import io.metersphere.sdk.file.MinioRepository;
|
||||||
import io.metersphere.sdk.util.CommonBeanFactory;
|
import io.metersphere.sdk.util.*;
|
||||||
import io.metersphere.sdk.util.GitRepositoryUtil;
|
|
||||||
import io.metersphere.sdk.util.TempFileUtils;
|
|
||||||
import io.metersphere.sdk.util.Translator;
|
|
||||||
import io.metersphere.system.mapper.BaseUserMapper;
|
import io.metersphere.system.mapper.BaseUserMapper;
|
||||||
import io.metersphere.system.uid.IDGenerator;
|
import io.metersphere.system.uid.IDGenerator;
|
||||||
import io.metersphere.system.utils.PageUtils;
|
import io.metersphere.system.utils.PageUtils;
|
||||||
|
@ -214,7 +211,7 @@ public class FileMetadataService {
|
||||||
* @return
|
* @return
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public String transferFile(String fileName, String originFileName, String projectId, String moduleId, String operator, byte[] fileBytes) throws Exception {
|
public String transferFile(String fileName, String originFileName, String projectId, String moduleId, String operator, byte[] fileBytes) {
|
||||||
if (StringUtils.isBlank(originFileName)) {
|
if (StringUtils.isBlank(originFileName)) {
|
||||||
throw new MSException(Translator.get("file.name.cannot.be.empty"));
|
throw new MSException(Translator.get("file.name.cannot.be.empty"));
|
||||||
}
|
}
|
||||||
|
@ -228,7 +225,13 @@ public class FileMetadataService {
|
||||||
uploadFileRequest.setStorage(StorageType.MINIO.name());
|
uploadFileRequest.setStorage(StorageType.MINIO.name());
|
||||||
|
|
||||||
FileRepository minio = CommonBeanFactory.getBean(MinioRepository.class);
|
FileRepository minio = CommonBeanFactory.getBean(MinioRepository.class);
|
||||||
String filePath = minio.saveFile(fileBytes, uploadFileRequest);
|
String filePath;
|
||||||
|
try {
|
||||||
|
filePath = minio.saveFile(fileBytes, uploadFileRequest);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.error(e);
|
||||||
|
throw new MSException(Translator.get("file.transfer.failed"), e);
|
||||||
|
}
|
||||||
fileMetadata.setPath(filePath);
|
fileMetadata.setPath(filePath);
|
||||||
fileMetadata.setFileVersion(fileMetadata.getId());
|
fileMetadata.setFileVersion(fileMetadata.getId());
|
||||||
fileMetadataMapper.insert(fileMetadata);
|
fileMetadataMapper.insert(fileMetadata);
|
||||||
|
|
Loading…
Reference in New Issue