feat(接口测试): 增加场景相关接口

This commit is contained in:
wxg0103 2024-01-16 10:01:31 +08:00 committed by wxg0103
parent ba3d33c24e
commit 1e4c6911b9
41 changed files with 1629 additions and 325 deletions

View File

@ -1,13 +1,16 @@
package io.metersphere.api.domain;
import io.metersphere.validation.groups.*;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import lombok.Data;
@Data
public class ApiScenario implements Serializable {
@ -35,9 +38,14 @@ public class ApiScenario implements Serializable {
@NotNull(message = "{api_scenario.step_total.not_blank}", groups = {Created.class})
private Integer stepTotal;
@Schema(description = "请求执行率", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_scenario.request_execution_rate.not_blank}", groups = {Created.class})
@Size(min = 1, max = 255, message = "{api_scenario.request_execution_rate.length_range}", groups = {Created.class, Updated.class})
private String requestExecutionRate;
@Schema(description = "通过率", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "{api_scenario.pass_rate.not_blank}", groups = {Created.class})
private Long passRate;
@NotNull(message = "{api_scenario.request_pass_rate.not_blank}", groups = {Created.class})
private Long requestPassRate;
@Schema(description = "最后一次执行的结果状态")
private String lastReportStatus;
@ -116,7 +124,8 @@ public class ApiScenario implements Serializable {
priority("priority", "priority", "VARCHAR", false),
status("status", "status", "VARCHAR", true),
stepTotal("step_total", "stepTotal", "INTEGER", false),
passRate("pass_rate", "passRate", "BIGINT", false),
requestExecutionRate("request_execution_rate", "requestExecutionRate", "VARCHAR", false),
requestPassRate("request_pass_rate", "requestPassRate", "BIGINT", false),
lastReportStatus("last_report_status", "lastReportStatus", "VARCHAR", false),
lastReportId("last_report_id", "lastReportId", "VARCHAR", false),
num("num", "num", "BIGINT", false),
@ -180,7 +189,7 @@ public class ApiScenario implements Serializable {
return this.getEscapedColumnName() + " ASC";
}
public static Column[] excludes(Column ... excludes) {
public static Column[] excludes(Column... excludes) {
ArrayList<Column> columns = new ArrayList<>(Arrays.asList(Column.values()));
if (excludes != null && excludes.length > 0) {
columns.removeAll(new ArrayList<>(Arrays.asList(excludes)));

View File

@ -10,21 +10,11 @@ import lombok.Data;
@Data
public class ApiScenarioEnvironment implements Serializable {
@Schema(description = "场景环境pk", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_scenario_environment.id.not_blank}", groups = {Updated.class})
@Size(min = 1, max = 50, message = "{api_scenario_environment.id.length_range}", groups = {Created.class, Updated.class})
private String id;
@Schema(description = "场景fk", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_scenario_environment.api_scenario_id.not_blank}", groups = {Created.class})
@Size(min = 1, max = 50, message = "{api_scenario_environment.api_scenario_id.length_range}", groups = {Created.class, Updated.class})
private String apiScenarioId;
@Schema(description = "项目fk", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_scenario_environment.project_id.not_blank}", groups = {Created.class})
@Size(min = 1, max = 50, message = "{api_scenario_environment.project_id.length_range}", groups = {Created.class, Updated.class})
private String projectId;
@Schema(description = "环境fk")
private String environmentId;
@ -34,9 +24,7 @@ public class ApiScenarioEnvironment implements Serializable {
private static final long serialVersionUID = 1L;
public enum Column {
id("id", "id", "VARCHAR", false),
apiScenarioId("api_scenario_id", "apiScenarioId", "VARCHAR", false),
projectId("project_id", "projectId", "VARCHAR", false),
environmentId("environment_id", "environmentId", "VARCHAR", false),
environmentGroupId("environment_group_id", "environmentGroupId", "VARCHAR", false);

View File

@ -104,76 +104,6 @@ public class ApiScenarioEnvironmentExample {
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andIdIsNull() {
addCriterion("id is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(String value) {
addCriterion("id =", value, "id");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(String value) {
addCriterion("id <>", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThan(String value) {
addCriterion("id >", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(String value) {
addCriterion("id >=", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThan(String value) {
addCriterion("id <", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(String value) {
addCriterion("id <=", value, "id");
return (Criteria) this;
}
public Criteria andIdLike(String value) {
addCriterion("id like", value, "id");
return (Criteria) this;
}
public Criteria andIdNotLike(String value) {
addCriterion("id not like", value, "id");
return (Criteria) this;
}
public Criteria andIdIn(List<String> values) {
addCriterion("id in", values, "id");
return (Criteria) this;
}
public Criteria andIdNotIn(List<String> values) {
addCriterion("id not in", values, "id");
return (Criteria) this;
}
public Criteria andIdBetween(String value1, String value2) {
addCriterion("id between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andIdNotBetween(String value1, String value2) {
addCriterion("id not between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andApiScenarioIdIsNull() {
addCriterion("api_scenario_id is null");
return (Criteria) this;
@ -244,76 +174,6 @@ public class ApiScenarioEnvironmentExample {
return (Criteria) this;
}
public Criteria andProjectIdIsNull() {
addCriterion("project_id is null");
return (Criteria) this;
}
public Criteria andProjectIdIsNotNull() {
addCriterion("project_id is not null");
return (Criteria) this;
}
public Criteria andProjectIdEqualTo(String value) {
addCriterion("project_id =", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotEqualTo(String value) {
addCriterion("project_id <>", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdGreaterThan(String value) {
addCriterion("project_id >", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdGreaterThanOrEqualTo(String value) {
addCriterion("project_id >=", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdLessThan(String value) {
addCriterion("project_id <", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdLessThanOrEqualTo(String value) {
addCriterion("project_id <=", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdLike(String value) {
addCriterion("project_id like", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotLike(String value) {
addCriterion("project_id not like", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdIn(List<String> values) {
addCriterion("project_id in", values, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotIn(List<String> values) {
addCriterion("project_id not in", values, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdBetween(String value1, String value2) {
addCriterion("project_id between", value1, value2, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotBetween(String value1, String value2) {
addCriterion("project_id not between", value1, value2, "projectId");
return (Criteria) this;
}
public Criteria andEnvironmentIdIsNull() {
addCriterion("environment_id is null");
return (Criteria) this;

View File

@ -478,63 +478,133 @@ public class ApiScenarioExample {
return (Criteria) this;
}
public Criteria andPassRateIsNull() {
addCriterion("pass_rate is null");
public Criteria andRequestExecutionRateIsNull() {
addCriterion("request_execution_rate is null");
return (Criteria) this;
}
public Criteria andPassRateIsNotNull() {
addCriterion("pass_rate is not null");
public Criteria andRequestExecutionRateIsNotNull() {
addCriterion("request_execution_rate is not null");
return (Criteria) this;
}
public Criteria andPassRateEqualTo(Long value) {
addCriterion("pass_rate =", value, "passRate");
public Criteria andRequestExecutionRateEqualTo(String value) {
addCriterion("request_execution_rate =", value, "requestExecutionRate");
return (Criteria) this;
}
public Criteria andPassRateNotEqualTo(Long value) {
addCriterion("pass_rate <>", value, "passRate");
public Criteria andRequestExecutionRateNotEqualTo(String value) {
addCriterion("request_execution_rate <>", value, "requestExecutionRate");
return (Criteria) this;
}
public Criteria andPassRateGreaterThan(Long value) {
addCriterion("pass_rate >", value, "passRate");
public Criteria andRequestExecutionRateGreaterThan(String value) {
addCriterion("request_execution_rate >", value, "requestExecutionRate");
return (Criteria) this;
}
public Criteria andPassRateGreaterThanOrEqualTo(Long value) {
addCriterion("pass_rate >=", value, "passRate");
public Criteria andRequestExecutionRateGreaterThanOrEqualTo(String value) {
addCriterion("request_execution_rate >=", value, "requestExecutionRate");
return (Criteria) this;
}
public Criteria andPassRateLessThan(Long value) {
addCriterion("pass_rate <", value, "passRate");
public Criteria andRequestExecutionRateLessThan(String value) {
addCriterion("request_execution_rate <", value, "requestExecutionRate");
return (Criteria) this;
}
public Criteria andPassRateLessThanOrEqualTo(Long value) {
addCriterion("pass_rate <=", value, "passRate");
public Criteria andRequestExecutionRateLessThanOrEqualTo(String value) {
addCriterion("request_execution_rate <=", value, "requestExecutionRate");
return (Criteria) this;
}
public Criteria andPassRateIn(List<Long> values) {
addCriterion("pass_rate in", values, "passRate");
public Criteria andRequestExecutionRateLike(String value) {
addCriterion("request_execution_rate like", value, "requestExecutionRate");
return (Criteria) this;
}
public Criteria andPassRateNotIn(List<Long> values) {
addCriterion("pass_rate not in", values, "passRate");
public Criteria andRequestExecutionRateNotLike(String value) {
addCriterion("request_execution_rate not like", value, "requestExecutionRate");
return (Criteria) this;
}
public Criteria andPassRateBetween(Long value1, Long value2) {
addCriterion("pass_rate between", value1, value2, "passRate");
public Criteria andRequestExecutionRateIn(List<String> values) {
addCriterion("request_execution_rate in", values, "requestExecutionRate");
return (Criteria) this;
}
public Criteria andPassRateNotBetween(Long value1, Long value2) {
addCriterion("pass_rate not between", value1, value2, "passRate");
public Criteria andRequestExecutionRateNotIn(List<String> values) {
addCriterion("request_execution_rate not in", values, "requestExecutionRate");
return (Criteria) this;
}
public Criteria andRequestExecutionRateBetween(String value1, String value2) {
addCriterion("request_execution_rate between", value1, value2, "requestExecutionRate");
return (Criteria) this;
}
public Criteria andRequestExecutionRateNotBetween(String value1, String value2) {
addCriterion("request_execution_rate not between", value1, value2, "requestExecutionRate");
return (Criteria) this;
}
public Criteria andRequestPassRateIsNull() {
addCriterion("request_pass_rate is null");
return (Criteria) this;
}
public Criteria andRequestPassRateIsNotNull() {
addCriterion("request_pass_rate is not null");
return (Criteria) this;
}
public Criteria andRequestPassRateEqualTo(Long value) {
addCriterion("request_pass_rate =", value, "requestPassRate");
return (Criteria) this;
}
public Criteria andRequestPassRateNotEqualTo(Long value) {
addCriterion("request_pass_rate <>", value, "requestPassRate");
return (Criteria) this;
}
public Criteria andRequestPassRateGreaterThan(Long value) {
addCriterion("request_pass_rate >", value, "requestPassRate");
return (Criteria) this;
}
public Criteria andRequestPassRateGreaterThanOrEqualTo(Long value) {
addCriterion("request_pass_rate >=", value, "requestPassRate");
return (Criteria) this;
}
public Criteria andRequestPassRateLessThan(Long value) {
addCriterion("request_pass_rate <", value, "requestPassRate");
return (Criteria) this;
}
public Criteria andRequestPassRateLessThanOrEqualTo(Long value) {
addCriterion("request_pass_rate <=", value, "requestPassRate");
return (Criteria) this;
}
public Criteria andRequestPassRateIn(List<Long> values) {
addCriterion("request_pass_rate in", values, "requestPassRate");
return (Criteria) this;
}
public Criteria andRequestPassRateNotIn(List<Long> values) {
addCriterion("request_pass_rate not in", values, "requestPassRate");
return (Criteria) this;
}
public Criteria andRequestPassRateBetween(Long value1, Long value2) {
addCriterion("request_pass_rate between", value1, value2, "requestPassRate");
return (Criteria) this;
}
public Criteria andRequestPassRateNotBetween(Long value1, Long value2) {
addCriterion("request_pass_rate not between", value1, value2, "requestPassRate");
return (Criteria) this;
}

View File

@ -1,12 +1,16 @@
package io.metersphere.api.domain;
import io.metersphere.validation.groups.*;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import lombok.Data;
@Data
public class ApiScenarioStep implements Serializable {
@ -114,7 +118,7 @@ public class ApiScenarioStep implements Serializable {
return this.getEscapedColumnName() + " ASC";
}
public static Column[] excludes(Column ... excludes) {
public static Column[] excludes(Column... excludes) {
ArrayList<Column> columns = new ArrayList<>(Arrays.asList(Column.values()));
if (excludes != null && excludes.length > 0) {
columns.removeAll(new ArrayList<>(Arrays.asList(excludes)));

View File

@ -10,7 +10,7 @@ public interface ApiScenarioEnvironmentMapper {
int deleteByExample(ApiScenarioEnvironmentExample example);
int deleteByPrimaryKey(String id);
int deleteByPrimaryKey(String apiScenarioId);
int insert(ApiScenarioEnvironment record);
@ -18,7 +18,7 @@ public interface ApiScenarioEnvironmentMapper {
List<ApiScenarioEnvironment> selectByExample(ApiScenarioEnvironmentExample example);
ApiScenarioEnvironment selectByPrimaryKey(String id);
ApiScenarioEnvironment selectByPrimaryKey(String apiScenarioId);
int updateByExampleSelective(@Param("record") ApiScenarioEnvironment record, @Param("example") ApiScenarioEnvironmentExample example);

View File

@ -2,9 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.api.mapper.ApiScenarioEnvironmentMapper">
<resultMap id="BaseResultMap" type="io.metersphere.api.domain.ApiScenarioEnvironment">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="api_scenario_id" jdbcType="VARCHAR" property="apiScenarioId" />
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
<id column="api_scenario_id" jdbcType="VARCHAR" property="apiScenarioId" />
<result column="environment_id" jdbcType="VARCHAR" property="environmentId" />
<result column="environment_group_id" jdbcType="VARCHAR" property="environmentGroupId" />
</resultMap>
@ -67,7 +65,7 @@
</where>
</sql>
<sql id="Base_Column_List">
id, api_scenario_id, project_id, environment_id, environment_group_id
api_scenario_id, environment_id, environment_group_id
</sql>
<select id="selectByExample" parameterType="io.metersphere.api.domain.ApiScenarioEnvironmentExample" resultMap="BaseResultMap">
select
@ -87,11 +85,11 @@
select
<include refid="Base_Column_List" />
from api_scenario_environment
where id = #{id,jdbcType=VARCHAR}
where api_scenario_id = #{apiScenarioId,jdbcType=VARCHAR}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
delete from api_scenario_environment
where id = #{id,jdbcType=VARCHAR}
where api_scenario_id = #{apiScenarioId,jdbcType=VARCHAR}
</delete>
<delete id="deleteByExample" parameterType="io.metersphere.api.domain.ApiScenarioEnvironmentExample">
delete from api_scenario_environment
@ -100,23 +98,17 @@
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.api.domain.ApiScenarioEnvironment">
insert into api_scenario_environment (id, api_scenario_id, project_id,
environment_id, environment_group_id)
values (#{id,jdbcType=VARCHAR}, #{apiScenarioId,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR},
#{environmentId,jdbcType=VARCHAR}, #{environmentGroupId,jdbcType=VARCHAR})
insert into api_scenario_environment (api_scenario_id, environment_id, environment_group_id
)
values (#{apiScenarioId,jdbcType=VARCHAR}, #{environmentId,jdbcType=VARCHAR}, #{environmentGroupId,jdbcType=VARCHAR}
)
</insert>
<insert id="insertSelective" parameterType="io.metersphere.api.domain.ApiScenarioEnvironment">
insert into api_scenario_environment
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="apiScenarioId != null">
api_scenario_id,
</if>
<if test="projectId != null">
project_id,
</if>
<if test="environmentId != null">
environment_id,
</if>
@ -125,15 +117,9 @@
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=VARCHAR},
</if>
<if test="apiScenarioId != null">
#{apiScenarioId,jdbcType=VARCHAR},
</if>
<if test="projectId != null">
#{projectId,jdbcType=VARCHAR},
</if>
<if test="environmentId != null">
#{environmentId,jdbcType=VARCHAR},
</if>
@ -151,15 +137,9 @@
<update id="updateByExampleSelective" parameterType="map">
update api_scenario_environment
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=VARCHAR},
</if>
<if test="record.apiScenarioId != null">
api_scenario_id = #{record.apiScenarioId,jdbcType=VARCHAR},
</if>
<if test="record.projectId != null">
project_id = #{record.projectId,jdbcType=VARCHAR},
</if>
<if test="record.environmentId != null">
environment_id = #{record.environmentId,jdbcType=VARCHAR},
</if>
@ -173,9 +153,7 @@
</update>
<update id="updateByExample" parameterType="map">
update api_scenario_environment
set id = #{record.id,jdbcType=VARCHAR},
api_scenario_id = #{record.apiScenarioId,jdbcType=VARCHAR},
project_id = #{record.projectId,jdbcType=VARCHAR},
set api_scenario_id = #{record.apiScenarioId,jdbcType=VARCHAR},
environment_id = #{record.environmentId,jdbcType=VARCHAR},
environment_group_id = #{record.environmentGroupId,jdbcType=VARCHAR}
<if test="_parameter != null">
@ -185,12 +163,6 @@
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.api.domain.ApiScenarioEnvironment">
update api_scenario_environment
<set>
<if test="apiScenarioId != null">
api_scenario_id = #{apiScenarioId,jdbcType=VARCHAR},
</if>
<if test="projectId != null">
project_id = #{projectId,jdbcType=VARCHAR},
</if>
<if test="environmentId != null">
environment_id = #{environmentId,jdbcType=VARCHAR},
</if>
@ -198,24 +170,21 @@
environment_group_id = #{environmentGroupId,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
where api_scenario_id = #{apiScenarioId,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.api.domain.ApiScenarioEnvironment">
update api_scenario_environment
set api_scenario_id = #{apiScenarioId,jdbcType=VARCHAR},
project_id = #{projectId,jdbcType=VARCHAR},
environment_id = #{environmentId,jdbcType=VARCHAR},
set environment_id = #{environmentId,jdbcType=VARCHAR},
environment_group_id = #{environmentGroupId,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
where api_scenario_id = #{apiScenarioId,jdbcType=VARCHAR}
</update>
<insert id="batchInsert" parameterType="map">
insert into api_scenario_environment
(id, api_scenario_id, project_id, environment_id, environment_group_id)
(api_scenario_id, environment_id, environment_group_id)
values
<foreach collection="list" item="item" separator=",">
(#{item.id,jdbcType=VARCHAR}, #{item.apiScenarioId,jdbcType=VARCHAR}, #{item.projectId,jdbcType=VARCHAR},
#{item.environmentId,jdbcType=VARCHAR}, #{item.environmentGroupId,jdbcType=VARCHAR}
)
(#{item.apiScenarioId,jdbcType=VARCHAR}, #{item.environmentId,jdbcType=VARCHAR},
#{item.environmentGroupId,jdbcType=VARCHAR})
</foreach>
</insert>
<insert id="batchInsertSelective" parameterType="map">
@ -228,15 +197,9 @@
<foreach collection="list" item="item" separator=",">
(
<foreach collection="selective" item="column" separator=",">
<if test="'id'.toString() == column.value">
#{item.id,jdbcType=VARCHAR}
</if>
<if test="'api_scenario_id'.toString() == column.value">
#{item.apiScenarioId,jdbcType=VARCHAR}
</if>
<if test="'project_id'.toString() == column.value">
#{item.projectId,jdbcType=VARCHAR}
</if>
<if test="'environment_id'.toString() == column.value">
#{item.environmentId,jdbcType=VARCHAR}
</if>

View File

@ -7,7 +7,8 @@
<result column="priority" jdbcType="VARCHAR" property="priority" />
<result column="status" jdbcType="VARCHAR" property="status" />
<result column="step_total" jdbcType="INTEGER" property="stepTotal" />
<result column="pass_rate" jdbcType="BIGINT" property="passRate" />
<result column="request_execution_rate" jdbcType="VARCHAR" property="requestExecutionRate" />
<result column="request_pass_rate" jdbcType="BIGINT" property="requestPassRate" />
<result column="last_report_status" jdbcType="VARCHAR" property="lastReportStatus" />
<result column="last_report_id" jdbcType="VARCHAR" property="lastReportId" />
<result column="num" jdbcType="BIGINT" property="num" />
@ -125,9 +126,10 @@
</where>
</sql>
<sql id="Base_Column_List">
id, `name`, priority, `status`, step_total, pass_rate, last_report_status, last_report_id,
num, deleted, pos, version_id, ref_id, latest, project_id, module_id, description,
tags, grouped, create_user, create_time, delete_time, delete_user, update_user, update_time
id, `name`, priority, `status`, step_total, request_execution_rate, request_pass_rate,
last_report_status, last_report_id, num, deleted, pos, version_id, ref_id, latest,
project_id, module_id, description, tags, grouped, create_user, create_time, delete_time,
delete_user, update_user, update_time
</sql>
<select id="selectByExample" parameterType="io.metersphere.api.domain.ApiScenarioExample" resultMap="BaseResultMap">
select
@ -161,18 +163,18 @@
</delete>
<insert id="insert" parameterType="io.metersphere.api.domain.ApiScenario">
insert into api_scenario (id, `name`, priority,
`status`, step_total, pass_rate,
last_report_status, last_report_id, num,
deleted, pos, version_id,
`status`, step_total, request_execution_rate,
request_pass_rate, last_report_status, last_report_id,
num, deleted, pos, version_id,
ref_id, latest, project_id,
module_id, description, tags,
grouped, create_user, create_time,
delete_time, delete_user, update_user,
update_time)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{priority,jdbcType=VARCHAR},
#{status,jdbcType=VARCHAR}, #{stepTotal,jdbcType=INTEGER}, #{passRate,jdbcType=BIGINT},
#{lastReportStatus,jdbcType=VARCHAR}, #{lastReportId,jdbcType=VARCHAR}, #{num,jdbcType=BIGINT},
#{deleted,jdbcType=BIT}, #{pos,jdbcType=BIGINT}, #{versionId,jdbcType=VARCHAR},
#{status,jdbcType=VARCHAR}, #{stepTotal,jdbcType=INTEGER}, #{requestExecutionRate,jdbcType=VARCHAR},
#{requestPassRate,jdbcType=BIGINT}, #{lastReportStatus,jdbcType=VARCHAR}, #{lastReportId,jdbcType=VARCHAR},
#{num,jdbcType=BIGINT}, #{deleted,jdbcType=BIT}, #{pos,jdbcType=BIGINT}, #{versionId,jdbcType=VARCHAR},
#{refId,jdbcType=VARCHAR}, #{latest,jdbcType=BIT}, #{projectId,jdbcType=VARCHAR},
#{moduleId,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{tags,jdbcType=VARCHAR,typeHandler=io.metersphere.handler.ListTypeHandler},
#{grouped,jdbcType=BIT}, #{createUser,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
@ -197,8 +199,11 @@
<if test="stepTotal != null">
step_total,
</if>
<if test="passRate != null">
pass_rate,
<if test="requestExecutionRate != null">
request_execution_rate,
</if>
<if test="requestPassRate != null">
request_pass_rate,
</if>
<if test="lastReportStatus != null">
last_report_status,
@ -274,8 +279,11 @@
<if test="stepTotal != null">
#{stepTotal,jdbcType=INTEGER},
</if>
<if test="passRate != null">
#{passRate,jdbcType=BIGINT},
<if test="requestExecutionRate != null">
#{requestExecutionRate,jdbcType=VARCHAR},
</if>
<if test="requestPassRate != null">
#{requestPassRate,jdbcType=BIGINT},
</if>
<if test="lastReportStatus != null">
#{lastReportStatus,jdbcType=VARCHAR},
@ -360,8 +368,11 @@
<if test="record.stepTotal != null">
step_total = #{record.stepTotal,jdbcType=INTEGER},
</if>
<if test="record.passRate != null">
pass_rate = #{record.passRate,jdbcType=BIGINT},
<if test="record.requestExecutionRate != null">
request_execution_rate = #{record.requestExecutionRate,jdbcType=VARCHAR},
</if>
<if test="record.requestPassRate != null">
request_pass_rate = #{record.requestPassRate,jdbcType=BIGINT},
</if>
<if test="record.lastReportStatus != null">
last_report_status = #{record.lastReportStatus,jdbcType=VARCHAR},
@ -432,7 +443,8 @@
priority = #{record.priority,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=VARCHAR},
step_total = #{record.stepTotal,jdbcType=INTEGER},
pass_rate = #{record.passRate,jdbcType=BIGINT},
request_execution_rate = #{record.requestExecutionRate,jdbcType=VARCHAR},
request_pass_rate = #{record.requestPassRate,jdbcType=BIGINT},
last_report_status = #{record.lastReportStatus,jdbcType=VARCHAR},
last_report_id = #{record.lastReportId,jdbcType=VARCHAR},
num = #{record.num,jdbcType=BIGINT},
@ -471,8 +483,11 @@
<if test="stepTotal != null">
step_total = #{stepTotal,jdbcType=INTEGER},
</if>
<if test="passRate != null">
pass_rate = #{passRate,jdbcType=BIGINT},
<if test="requestExecutionRate != null">
request_execution_rate = #{requestExecutionRate,jdbcType=VARCHAR},
</if>
<if test="requestPassRate != null">
request_pass_rate = #{requestPassRate,jdbcType=BIGINT},
</if>
<if test="lastReportStatus != null">
last_report_status = #{lastReportStatus,jdbcType=VARCHAR},
@ -540,7 +555,8 @@
priority = #{priority,jdbcType=VARCHAR},
`status` = #{status,jdbcType=VARCHAR},
step_total = #{stepTotal,jdbcType=INTEGER},
pass_rate = #{passRate,jdbcType=BIGINT},
request_execution_rate = #{requestExecutionRate,jdbcType=VARCHAR},
request_pass_rate = #{requestPassRate,jdbcType=BIGINT},
last_report_status = #{lastReportStatus,jdbcType=VARCHAR},
last_report_id = #{lastReportId,jdbcType=VARCHAR},
num = #{num,jdbcType=BIGINT},
@ -564,19 +580,19 @@
</update>
<insert id="batchInsert" parameterType="map">
insert into api_scenario
(id, `name`, priority, `status`, step_total, pass_rate, last_report_status, last_report_id,
num, deleted, pos, version_id, ref_id, latest, project_id, module_id, description,
tags, grouped, create_user, create_time, delete_time, delete_user, update_user,
update_time)
(id, `name`, priority, `status`, step_total, request_execution_rate, request_pass_rate,
last_report_status, last_report_id, num, deleted, pos, version_id, ref_id, latest,
project_id, module_id, description, tags, grouped, create_user, create_time, delete_time,
delete_user, update_user, update_time)
values
<foreach collection="list" item="item" separator=",">
(#{item.id,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR}, #{item.priority,jdbcType=VARCHAR},
#{item.status,jdbcType=VARCHAR}, #{item.stepTotal,jdbcType=INTEGER}, #{item.passRate,jdbcType=BIGINT},
#{item.lastReportStatus,jdbcType=VARCHAR}, #{item.lastReportId,jdbcType=VARCHAR},
#{item.num,jdbcType=BIGINT}, #{item.deleted,jdbcType=BIT}, #{item.pos,jdbcType=BIGINT},
#{item.versionId,jdbcType=VARCHAR}, #{item.refId,jdbcType=VARCHAR}, #{item.latest,jdbcType=BIT},
#{item.projectId,jdbcType=VARCHAR}, #{item.moduleId,jdbcType=VARCHAR}, #{item.description,jdbcType=VARCHAR},
#{item.tags,jdbcType=VARCHAR,typeHandler=io.metersphere.handler.ListTypeHandler},
#{item.status,jdbcType=VARCHAR}, #{item.stepTotal,jdbcType=INTEGER}, #{item.requestExecutionRate,jdbcType=VARCHAR},
#{item.requestPassRate,jdbcType=BIGINT}, #{item.lastReportStatus,jdbcType=VARCHAR},
#{item.lastReportId,jdbcType=VARCHAR}, #{item.num,jdbcType=BIGINT}, #{item.deleted,jdbcType=BIT},
#{item.pos,jdbcType=BIGINT}, #{item.versionId,jdbcType=VARCHAR}, #{item.refId,jdbcType=VARCHAR},
#{item.latest,jdbcType=BIT}, #{item.projectId,jdbcType=VARCHAR}, #{item.moduleId,jdbcType=VARCHAR},
#{item.description,jdbcType=VARCHAR}, #{item.tags,jdbcType=VARCHAR,typeHandler=io.metersphere.handler.ListTypeHandler},
#{item.grouped,jdbcType=BIT}, #{item.createUser,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT},
#{item.deleteTime,jdbcType=BIGINT}, #{item.deleteUser,jdbcType=VARCHAR}, #{item.updateUser,jdbcType=VARCHAR},
#{item.updateTime,jdbcType=BIGINT})
@ -607,8 +623,11 @@
<if test="'step_total'.toString() == column.value">
#{item.stepTotal,jdbcType=INTEGER}
</if>
<if test="'pass_rate'.toString() == column.value">
#{item.passRate,jdbcType=BIGINT}
<if test="'request_execution_rate'.toString() == column.value">
#{item.requestExecutionRate,jdbcType=VARCHAR}
</if>
<if test="'request_pass_rate'.toString() == column.value">
#{item.requestPassRate,jdbcType=BIGINT}
</if>
<if test="'last_report_status'.toString() == column.value">
#{item.lastReportStatus,jdbcType=VARCHAR}

View File

@ -209,7 +209,8 @@ CREATE TABLE IF NOT EXISTS api_scenario(
`priority` VARCHAR(10) NOT NULL COMMENT '场景级别/P0/P1等' ,
`status` VARCHAR(20) NOT NULL COMMENT '场景状态/未规划/已完成 等' ,
`step_total` INT NOT NULL DEFAULT 0 COMMENT '场景步骤总数' ,
`pass_rate` BIGINT NOT NULL DEFAULT 0 COMMENT '通过率' ,
`request_execution_rate` VARCHAR(255) NOT NULL DEFAULT '0.00' COMMENT '请求执行率' ,
`request_pass_rate` BIGINT NOT NULL DEFAULT '0.00' COMMENT '通过率' ,
`last_report_status` VARCHAR(50) COMMENT '最后一次执行的结果状态' ,
`last_report_id` VARCHAR(50) COMMENT '最后一次执行的报告fk' ,
`num` BIGINT NOT NULL COMMENT '编号' ,
@ -549,19 +550,15 @@ CREATE TABLE IF NOT EXISTS api_test_case_blob(
COLLATE = utf8mb4_general_ci COMMENT = '接口用例详情';
CREATE TABLE IF NOT EXISTS api_scenario_environment(
`id` VARCHAR(50) NOT NULL COMMENT '场景环境pk' ,
`api_scenario_id` VARCHAR(50) NOT NULL COMMENT '场景fk' ,
`project_id` VARCHAR(50) NOT NULL COMMENT '项目fk' ,
`environment_id` VARCHAR(50) COMMENT '环境fk' ,
`environment_group_id` VARCHAR(50) COMMENT '环境组fk' ,
PRIMARY KEY (id)
`api_scenario_id` VARCHAR(50) NOT NULL COMMENT '场景fk' ,
`environment_id` VARCHAR(50) COMMENT '环境fk' ,
`environment_group_id` VARCHAR(50) COMMENT '环境组fk' ,
PRIMARY KEY (api_scenario_id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '场景环境';
CREATE INDEX idx_api_scenario_id ON api_scenario_environment(api_scenario_id);
CREATE INDEX idx_project_id ON api_scenario_environment(project_id);
CREATE INDEX idx_environment_id ON api_scenario_environment(environment_id);

View File

@ -28,8 +28,10 @@ api_scenario.create_user.length_range=创建人长度必须在1-50之间
api_scenario.create_user.not_blank=创建人不能为空
api_scenario.update_user.length_range=更新人长度必须在1-50之间
api_scenario.update_user.not_blank=更新人不能为空
api_scenario.level.length_range=场景级别/P0/P1等长度必须在1-10之间
api_scenario.level.not_blank=场景级别/P0/P1等不能为空
api_scenario.priority.length_range=场景级别/P0/P1等长度必须在1-10之间
api_scenario.priority.not_blank=场景级别/P0/P1等不能为空
api_scenario.step_total.not_blank=步骤总数不能为空
api_scenario.pass_rate.not_blank=通过率不能为空
api_scenario.status.length_range=场景状态/未规划/已完成 等长度必须在1-20之间
api_scenario.status.not_blank=场景状态/未规划/已完成 等不能为空
api_scenario.principal.length_range=责任人/用户ID长度必须在1-50之间
@ -40,6 +42,12 @@ api_scenario.environment_group.length_range=是否为环境组长度必须在1-1
api_scenario.environment_group.not_blank=是否为环境组不能为空
api_scenario.project_id.length_range=项目ID长度必须在1-50之间
api_scenario.project_id.not_blank=项目ID不能为空
#module: ApiScenarioStep
api_scenario_step.id.not_blank=ID不能为空
api_scenario_step.id.length_range=步骤ID长度必须在1-50之间
api_scenario_step.scenario_id.not_blank=场景ID不能为空
api_scenario_step.scenario_id.length_range=场景ID长度必须在1-50之间
api_scenario_step.sort.not_blank=步骤排序不能为空
#moduleApiTestCaseFollow
api_test_case_follow.case_id.length_range=用例ID长度必须在1-50之间
api_test_case_follow.case_id.not_blank=用例ID不能为空
@ -171,6 +179,7 @@ api_test_case.sync_enable.not_blank=是否开启同步不能为空
api_test_case.project_id.length_range=项目ID长度必须在1-50之间
api_test_case.project_id.not_blank=项目ID不能为空
api_test_case.api_definition_id.length_range=接口ID长度必须在1-50之间
api_test_case.tag.length_range=标签长度必须在1-50之间
api_test_case.api_definition_id.not_blank=接口ID不能为空
api_test_case.principal.length_range=责任人长度必须在1-50之间
api_test_case.principal.not_blank=责任人不能为空

View File

@ -28,10 +28,12 @@ api_scenario.create_user.length_range=Creator length must be between 1-50
api_scenario.create_user.not_blank=Creator cannot be empty
api_scenario.update_user.length_range=Updater length must be between 1-50
api_scenario.update_user.not_blank=Updater cannot be empty
api_scenario.level.length_range=The scene level/P0/P1 etc. length must be between 1-10
api_scenario.level.not_blank=Scene level/P0/P1, etc. cannot be empty
api_scenario.priority.length_range=The scene level/P0/P1 etc. length must be between 1-10
api_scenario.priority.not_blank=Scene level/P0/P1, etc. cannot be empty
api_scenario.status.length_range=Scene status/unplanned/completed equal length must be between 1-20
api_scenario.status.not_blank=Scene status/unplanned/completed etc. cannot be empty
api_scenario.step_total.not_blank=Total number of steps cannot be empty
api_scenario.pass_rate.not_blank=Pass rate cannot be empty
api_scenario.principal.length_range=Responsible person/user fk length must be between 1-50
api_scenario.principal.not_blank=Responsible person/user fk cannot be empty
api_scenario.deleted.length_range=Delete status length must be between 1-1
@ -40,6 +42,12 @@ api_scenario.environment_group.length_range=Whether it is an environment group l
api_scenario.environment_group.not_blank=Whether it is an environment group cannot be empty
api_scenario.project_id.length_range=Item fk length must be between 1-50
api_scenario.project_id.not_blank=Item fk cannot be empty
#module: ApiScenarioStep
api_scenario_step.id.not_blank=ID cannot be empty
api_scenario_step.id.length_range=Step ID length must be between 1-50
api_scenario_step.scenario_id.not_blank=Scene ID cannot be empty
api_scenario_step.scenario_id.length_range=Scene ID length must be between 1-50
api_scenario_step.sort.not_blank=SORT cannot be empty
#moduleApiTestCaseFollow
api_test_case_follow.case_id.length_range=Use case fk length must be between 1-50
api_test_case_follow.case_id.not_blank=Use case fk cannot be empty
@ -169,6 +177,7 @@ api_test_case.priority.not_blank=Use case class cannot be empty
api_test_case.sync_enable.length_range=Whether to enable synchronization length must be between 1-1
api_test_case.sync_enable.not_blank=Whether to enable synchronization can not be empty
api_test_case.project_id.length_range=Item fk length must be between 1-50
api_test_case.tag.length_range=Use case tag length must be between 1-50
api_test_case.project_id.not_blank=Item fk cannot be empty
api_test_case.api_definition_id.length_range=Interface fk length must be between 1-50
api_test_case.api_definition_id.not_blank=Interface fk cannot be empty

View File

@ -28,10 +28,12 @@ api_scenario.create_user.length_range=创建人长度必须在1-50之间
api_scenario.create_user.not_blank=创建人不能为空
api_scenario.update_user.length_range=更新人长度必须在1-50之间
api_scenario.update_user.not_blank=更新人不能为空
api_scenario.level.length_range=场景级别/P0/P1等长度必须在1-10之间
api_scenario.level.not_blank=场景级别/P0/P1等不能为空
api_scenario.priority.length_range=场景级别/P0/P1等长度必须在1-10之间
api_scenario.priority.not_blank=场景级别/P0/P1等不能为空
api_scenario.status.length_range=场景状态/未规划/已完成 等长度必须在1-20之间
api_scenario.status.not_blank=场景状态/未规划/已完成 等不能为空
api_scenario.step_total.not_blank=步骤总数不能为空
api_scenario.pass_rate.not_blank=通过率不能为空
api_scenario.principal.length_range=责任人/用户ID长度必须在1-50之间
api_scenario.principal.not_blank=责任人/用户ID不能为空
api_scenario.deleted.length_range=删除状态长度必须在1-1之间
@ -40,6 +42,12 @@ api_scenario.environment_group.length_range=是否为环境组长度必须在1-1
api_scenario.environment_group.not_blank=是否为环境组不能为空
api_scenario.project_id.length_range=项目ID长度必须在1-50之间
api_scenario.project_id.not_blank=项目ID不能为空
#module: ApiScenarioStep
api_scenario_step.id.not_blank=ID不能为空
api_scenario_step.id.length_range=步骤ID长度必须在1-50之间
api_scenario_step.scenario_id.not_blank=场景ID不能为空
api_scenario_step.scenario_id.length_range=场景ID长度必须在1-50之间
api_scenario_step.sort.not_blank=步骤排序不能为空
#moduleApiTestCaseFollow
api_test_case_follow.case_id.length_range=用例ID长度必须在1-50之间
api_test_case_follow.case_id.not_blank=用例ID不能为空
@ -165,6 +173,7 @@ api_test_case.update_user.not_blank=更新人不能为空
api_test_case.deleted.length_range=删除标识长度必须在1-1之间
api_test_case.deleted.not_blank=删除标识不能为空
api_test_case.priority.length_range=用例等级长度必须在1-50之间
api_test_case.tag.length_range=标签长度必须在1-50之间
api_test_case.priority.not_blank=用例等级不能为空
api_test_case.sync_enable.length_range=是否开启同步长度必须在1-1之间
api_test_case.sync_enable.not_blank=是否开启同步不能为空

View File

@ -28,10 +28,12 @@ api_scenario.create_user.length_range=創建人長度必須在1-50之間
api_scenario.create_user.not_blank=創建人不能為空
api_scenario.update_user.length_range=更新人長度必須在1-50之間
api_scenario.update_user.not_blank=更新人不能為空
api_scenario.level.length_range=場景級別/P0/P1等長度必須在1-10之間
api_scenario.level.not_blank=場景級別/P0/P1等不能為空
api_scenario.priority.length_range=場景級別/P0/P1等長度必須在1-10之間
api_scenario.priority.not_blank=場景級別/P0/P1等不能為空
api_scenario.status.length_range=場景狀態/未規劃/已完成 等長度必須在1-20之間
api_scenario.status.not_blank=場景狀態/未規劃/已完成 等不能為空
api_scenario.step_total.not_blank=步驟總數不能為空
api_scenario.pass_rate.not_blank=通過率不能為空
api_scenario.principal.length_range=責任人/用戶ID長度必須在1-50之間
api_scenario.principal.not_blank=責任人/用戶ID不能為空
api_scenario.deleted.length_range=刪除狀態長度必須在1-1之間
@ -40,6 +42,12 @@ api_scenario.environment_group.length_range=是否為環境組長度必須在1-1
api_scenario.environment_group.not_blank=是否為環境組不能為空
api_scenario.project_id.length_range=項目ID長度必須在1-50之間
api_scenario.project_id.not_blank=項目ID不能為空
#module: ApiScenarioStep
api_scenario_step.id.not_blank=步骤ID不能為空
api_scenario_step.id.length_range=步骤ID長度必須在1-50之間
api_scenario_step.scenario_id.not_blank=場景ID不能為空
api_scenario_step.scenario_id.length_range=場景ID長度必須在1-50之間
api_scenario_step.sort.not_blank=步驟排序不能為空
#moduleApiTestCaseFollow
api_test_case_follow.case_id.length_range=用例ID長度必須在1-50之間
api_test_case_follow.case_id.not_blank=用例ID不能為空
@ -171,6 +179,7 @@ api_test_case.sync_enable.not_blank=是否開啟同步不能為空
api_test_case.project_id.length_range=項目ID長度必須在1-50之間
api_test_case.project_id.not_blank=項目ID不能為空
api_test_case.api_definition_id.length_range=接口ID長度必須在1-50之間
api_test_case.tag.length_range=標籤長度必須在1-50之間
api_test_case.api_definition_id.not_blank=接口ID不能為空
api_test_case.principal.length_range=責任人長度必須在1-50之間
api_test_case.principal.not_blank=責任人不能為空

View File

@ -492,9 +492,12 @@ api_test_case_not_exist=接口用例不存在
please_recover_the_interface_data_first=请先恢复接口数据
batch_edit_type_error=批量编辑类型错误
environment_id_is_null=环境ID不能为空
environment_group_id_is_null=环境组ID不能为空
environment_group_is_not_exist=环境组不存在
environment_is_not_exist=环境不存在
status_is_null=状态不能为空
priority_is_null=用例等级不能为空
api_scenario_is_not_exist=场景不存在
apikey_has_expired=ApiKey 已过期
user_key.id.not_blank=ApiKey ID不能为空
expire_time_not_null=过期时间不能为空

View File

@ -503,7 +503,10 @@ please_recover_the_interface_data_first=Please recover the interface data first
batch_edit_type_error=Batch edit type error
environment_id_is_null=Environment ID is null
environment_is_not_exist=Environment is not exist
environment_group_id_is_null=Environment group ID is null
environment_group_is_not_exist=Environment group is not exist
status_is_null=Status is null
api_scenario_is_not_exist=API scenario is not exist
priority_is_null=Priority is null
apikey_has_expired=ApiKey has expired
user_key.id.not_blank=User key id can not blank

View File

@ -498,8 +498,11 @@ api_test_case_not_exist=接口用例不存在
please_recover_the_interface_data_first=请先恢复接口数据
batch_edit_type_error=批量编辑类型错误
environment_id_is_null=环境ID不能为空
environment_group_id_is_null=环境组ID不能为空
environment_group_is_not_exist=环境组不存在
environment_is_not_exist=环境不存在
status_is_null=状态不能为空
api_scenario_is_not_exist=场景不存在
priority_is_null=用例等级不能为空
apikey_has_expired=ApiKey 已过期
user_key.id.not_blank=ApiKey ID不能为空

View File

@ -498,9 +498,12 @@ api_test_case_not_exist=接口用例不存在
please_recover_the_interface_data_first=請先恢復接口數據
batch_edit_type_error=批量編輯類型錯誤
environment_id_is_null=環境ID不能為空
environment_group_id_is_null=環境組ID不能為空
environment_group_is_not_exist=環境組不存在
environment_is_not_exist=環境不存在
status_is_null=狀態不能為空
priority_is_null=優先級不能為空
api_scenario_is_not_exist=場景不存在
apikey_has_expired=ApiKey 已過期
user_key.id.not_blank=ApiKey ID不能为空
expire_time_not_null=過期時間不能為空

View File

@ -0,0 +1,68 @@
package io.metersphere.api.controller.scenario;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.api.dto.scenario.ApiScenarioBatchEditRequest;
import io.metersphere.api.dto.scenario.ApiScenarioDTO;
import io.metersphere.api.dto.scenario.ApiScenarioPageRequest;
import io.metersphere.api.service.scenario.ApiScenarioService;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.system.security.CheckOwner;
import io.metersphere.system.utils.PageUtils;
import io.metersphere.system.utils.Pager;
import io.metersphere.system.utils.SessionUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping(value = "/api/scenario")
@Tag(name = "接口测试-接口场景管理")
public class ApiScenarioController {
@Resource
private ApiScenarioService apiScenarioService;
@PostMapping("/page")
@Operation(summary = "接口测试-接口场景管理-场景列表(deleted 状态为 1 时为回收站数据)")
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_READ)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public Pager<List<ApiScenarioDTO>> getPage(@Validated @RequestBody ApiScenarioPageRequest request) {
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "create_time desc");
return PageUtils.setPageInfo(page, apiScenarioService.getScenarioPage(request));
}
@PostMapping("/trash/page")
@Operation(summary = "接口测试-接口场景管理-场景列表(deleted 状态为 1 时为回收站数据)")
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_READ)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public Pager<List<ApiScenarioDTO>> getTrashPage(@Validated @RequestBody ApiScenarioPageRequest request) {
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "create_time desc");
request.setDeleted(true);
return PageUtils.setPageInfo(page, apiScenarioService.getScenarioPage(request));
}
@PostMapping("/batch/edit")
@Operation(summary = "接口测试-接口场景管理-批量编辑")
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_UPDATE)
@CheckOwner(resourceId = "#request.getSelectIds()", resourceType = "api_scenario")
public void batchUpdate(@Validated @RequestBody ApiScenarioBatchEditRequest request) {
apiScenarioService.batchEdit(request, SessionUtils.getUserId());
}
@GetMapping("follow/{id}")
@Operation(summary = "接口测试-接口场景管理-关注/ 取消关注")
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_UPDATE)
@CheckOwner(resourceId = "#id", resourceType = "api_scenario")
public void follow(@PathVariable String id) {
apiScenarioService.follow(id, SessionUtils.getUserId());
}
}

View File

@ -3,7 +3,7 @@ package io.metersphere.api.controller.scenario;
import io.metersphere.api.dto.debug.ModuleCreateRequest;
import io.metersphere.api.dto.debug.ModuleUpdateRequest;
import io.metersphere.api.dto.definition.ApiModuleRequest;
import io.metersphere.api.dto.definition.ApiScenarioModuleRequest;
import io.metersphere.api.dto.scenario.ApiScenarioModuleRequest;
import io.metersphere.api.service.scenario.ApiScenarioModuleService;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.system.dto.sdk.BaseTreeNode;

View File

@ -2,6 +2,7 @@ package io.metersphere.api.dto.definition;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -19,6 +20,7 @@ public class ApiCaseBatchEditRequest extends ApiTestCaseBatchRequest implements
@Schema(description = "标签")
private LinkedHashSet<
@NotBlank
@Size(min = 1, max = 50, message = "{api_test_case.tag.length_range}")
String> tags;
@Schema(description = "批量编辑的类型 用例等级: Priority,状态 :Status,标签: Tags,用例环境: Environment")
@NotBlank

View File

@ -43,6 +43,7 @@ public class ApiTestCaseAddRequest implements Serializable {
@Schema(description = "标签")
private LinkedHashSet<
@NotBlank
@Size(min = 1, max = 50, message = "{api_test_case.tag.length_range}")
String> tags;
@Schema(description = "环境fk")

View File

@ -37,6 +37,7 @@ public class ApiTestCaseUpdateRequest implements Serializable {
@Schema(description = "标签")
private List<
@NotBlank
@Size(min = 1, max = 50, message = "{api_test_case.tag.length_range}")
String> tags;
@Schema(description = "环境fk")

View File

@ -0,0 +1,49 @@
package io.metersphere.api.dto.scenario;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = false)
public class ApiScenarioBatchEditRequest extends ApiScenarioBatchRequest implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "标签")
private LinkedHashSet<
@NotBlank
@Size(min = 1, max = 50, message = "{api_test_case.tag.length_range}")
String> tags;
@Schema(description = "批量编辑的类型 用例等级: Priority,状态 :Status,标签: Tags,用例环境: Environment")
@NotBlank
private String type;
@Schema(description = "默认覆盖原标签")
private boolean appendTag = false;
@Schema(description = "环境id")
private String envId;
@Schema(description = "使用环境组")
private boolean grouped = false;
@Schema(description = "环境组id")
private String groupId;
@Schema(description = "用例状态")
private String status;
@Schema(description = "用例等级")
private String priority;
public List<String> getTags() {
if (tags == null) {
return new ArrayList<>(0);
} else {
return new ArrayList<>(tags);
}
}
}

View File

@ -0,0 +1,36 @@
package io.metersphere.api.dto.scenario;
import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = false)
public class ApiScenarioBatchRequest extends TableBatchProcessDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "场景pk")
private String apiScenarioId;
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_definition.project_id.not_blank}")
@Size(min = 1, max = 50, message = "{api_definition.project_id.length_range}")
private String projectId;
@Schema(description = "模块ID")
private List<@NotBlank String> moduleIds;
@Schema(description = "版本fk")
private String versionId;
@Schema(description = "版本来源")
private String refId;
}

View File

@ -1,22 +1,27 @@
package io.metersphere.api.dto.scenario;
import io.metersphere.api.domain.ApiScenario;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class ApiScenarioDTO extends ApiScenario {
@Schema(description = "场景pk", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_scenario_blob.id.not_blank}", groups = {Updated.class})
@Size(min = 1, max = 50, message = "{api_scenario_blob.id.length_range}", groups = {Created.class, Updated.class})
private String id;
@Schema(description = "项目名称")
private String projectName;
@Schema(description = "创建人名称")
private String createUserName;
@Schema(description = "更新人名称")
private String updateUserName;
@Schema(description = "删除人名称")
private String deleteUserName;
@Schema(description = "版本名称")
private String versionName;
@Schema(description = "所属模块")
private String modulePath;
@Schema(description = "环境名称")
private String environmentName;
@Schema(description = "场景步骤内容")
private byte[] content;
}

View File

@ -1,4 +1,4 @@
package io.metersphere.api.dto.definition;
package io.metersphere.api.dto.scenario;
import io.metersphere.system.dto.sdk.BaseCondition;
import io.swagger.v3.oas.annotations.media.Schema;

View File

@ -0,0 +1,38 @@
package io.metersphere.api.dto.scenario;
import io.metersphere.system.dto.sdk.BasePageRequest;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = false)
public class ApiScenarioPageRequest extends BasePageRequest {
@Schema(description = "场景pk")
@Size(min = 1, max = 50, message = "{api_scenario_step.scenario_id.length_range}")
private String scenarioId;
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_definition.project_id.not_blank}")
@Size(min = 1, max = 50, message = "{api_definition.project_id.length_range}")
private String projectId;
@Schema(description = "版本fk")
@Size(min = 1, max = 50, message = "{api_definition.version_id.length_range}")
private String versionId;
@Schema(description = "版本引用fk")
@Size(min = 1, max = 50, message = "{api_definition.ref_id.length_range}")
private String refId;
@Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)")
private List<@NotBlank String> moduleIds;
@Schema(description = "删除状态(状态为 1 时为回收站数据)")
private Boolean deleted = false;
}

View File

@ -387,7 +387,7 @@
AND m.name like CONCAT('%', #{request.keyword},'%')
</if>
<if test="request.moduleIds != null and request.moduleIds.size() != 0">
AND m.module_id IN
AND m.id IN
<foreach collection="request.moduleIds" item="item" open="(" separator="," close=")">
#{item}
</foreach>
@ -405,7 +405,7 @@
AND m.name like CONCAT('%', #{request.moduleKeyword},'%')
</if>
<if test="request.moduleIds != null and request.moduleIds.size() != 0">
AND m.module_id IN
AND m.id IN
<foreach collection="request.moduleIds" item="item" open="(" separator="," close=")">
#{item}
</foreach>

View File

@ -0,0 +1,20 @@
package io.metersphere.api.mapper;
import io.metersphere.api.domain.ApiScenario;
import io.metersphere.api.dto.scenario.ApiScenarioBatchEditRequest;
import io.metersphere.api.dto.scenario.ApiScenarioDTO;
import io.metersphere.api.dto.scenario.ApiScenarioPageRequest;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface ExtApiScenarioMapper {
List<ApiScenarioDTO> list(@Param("request") ApiScenarioPageRequest request);
List<String> getIds(@Param("request") ApiScenarioBatchEditRequest request, @Param("deleted") boolean deleted);
List<ApiScenario> getInfoByIds(@Param("ids") List<String> ids, @Param("deleted") boolean deleted);
List<ApiScenario> getTagsByIds(@Param("ids") List<String> ids, @Param("deleted") boolean deleted);
}

View File

@ -0,0 +1,266 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.api.mapper.ExtApiScenarioMapper">
<resultMap id="ApiScenarioDTO" type="io.metersphere.api.dto.scenario.ApiScenarioDTO">
<result column="tags" jdbcType="VARCHAR" property="tags" typeHandler="io.metersphere.handler.ListTypeHandler" />
</resultMap>
<resultMap id="BaseResultMap" type="io.metersphere.api.domain.ApiScenario">
<result column="tags" jdbcType="VARCHAR" property="tags" typeHandler="io.metersphere.handler.ListTypeHandler" />
</resultMap>
<select id="list" resultMap="ApiScenarioDTO">
select
api_scenario.id, api_scenario.`name`,api_scenario.priority,
api_scenario.step_total,api_scenario.request_pass_rate,api_scenario.last_report_status,
api_scenario.request_execution_rate,
api_scenario.last_report_id,api_scenario.grouped,
api_scenario.`status`, api_scenario.num, api_scenario.tags, api_scenario.pos,
api_scenario.project_id, api_scenario.module_id, api_scenario.latest, api_scenario.version_id,
api_scenario.ref_id, api_scenario.create_time, api_scenario.create_user,
api_scenario.update_time, api_scenario.update_user, api_scenario.delete_user, api_scenario.delete_time,
api_scenario.deleted, project_version.name as version_name
from api_scenario
LEFT JOIN project_version ON project_version.id = api_scenario.version_id
where api_scenario.deleted = #{request.deleted}
<include refid="queryWhereCondition"/>
</select>
<select id="getIds" resultType="java.lang.String">
select
api_scenario.id
from api_scenario
where api_scenario.deleted = #{deleted}
<include refid="queryWhereConditionByBaseQueryRequest"/>
</select>
<select id="getInfoByIds" resultType="io.metersphere.api.domain.ApiScenario">
SELECT id,
name
FROM api_scenario
WHERE deleted = #{deleted} and id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<select id="getTagsByIds" resultMap="BaseResultMap">
SELECT id,
tags
FROM api_scenario
WHERE deleted = #{deleted} and id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<sql id="queryWhereConditionByBaseQueryRequest">
<if test="request.condition.combine != null">
<include refid="combine">
<property name="condition" value="request.condition.combine"/>
</include>
</if>
<if test="request.condition.keyword != null">
and (
api_scenario.num like concat('%', #{request.keyword},'%')
or api_scenario.name like concat('%', #{request.keyword},'%')
or api_scenario.tags like JSON_CONTAINS(tags, concat('["',#{request.keyword},'"]'))
)
</if>
<include refid="filters">
<property name="filter" value="request.condition.filter"/>
</include>
</sql>
<sql id="queryWhereCondition">
<if test="request.keyword != null and request.keyword != ''">
and (
api_scenario.num like concat('%', #{request.keyword},'%')
or api_scenario.name like concat('%', #{request.keyword},'%')
or api_scenario.tags like JSON_CONTAINS(tags, concat('["',#{request.keyword},'"]'))
)
</if>
<if test="request.projectId != null and request.projectId != ''">
and api_scenario.project_id = #{request.projectId}
</if>
<if test="request.scenarioId != null and request.scenarioId != ''">
and api_scenario.id = #{request.scenarioId}
</if>
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
and api_scenario.module_id in
<foreach collection="request.moduleIds" item="nodeId" separator="," open="(" close=")">
#{nodeId}
</foreach>
</if>
<include refid="filters">
<property name="filter" value="request.filter"/>
</include>
<if test="request.combine != null and request.combine != ''">
<include refid="combine">
<property name="condition" value="request.combine"/>
<property name="name" value="request.name"/>
<property name="ObjectTags" value="request.combine.tags"/>
</include>
</if>
<include refid="queryVersionCondition">
<property name="versionTable" value="api_scenario"/>
</include>
</sql>
<sql id="filters">
<if test="${filter} != null and ${filter}.size() > 0">
<foreach collection="${filter}.entrySet()" index="key" item="values">
<if test="values != null and values.size() > 0">
<choose>
<when test="key=='status'">
and api_scenario.status in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
</when>
<when test="key=='create_user'">
and api_scenario.create_user in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
</when>
<when test="key=='version_id'">
and api_scenario.version_id in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
</when>
<when test="key=='priority'">
and api_scenario.priority in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
</when>
<when test="key.startsWith('custom_single')">
and api_scenario.id in (
select api_id from api_definition_custom_field where concat('custom_single_', field_id) =
#{key}
and trim(both '"' from `value`) in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
)
</when>
<when test="key.startsWith('custom_multiple')">
and api_scenario.id in (
select api_id from api_definition_custom_field where concat('custom_multiple_', field_id) =
#{key}
and
<include refid="io.metersphere.system.mapper.BaseMapper.filterMultipleWrapper"/>
)
</when>
</choose>
</if>
</foreach>
</if>
</sql>
<sql id="combine">
<if test='${condition}.name != null and (${name} == null or ${name} == "")'>
and api_scenario.name
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.name"/>
</include>
</if>
<if test='${condition}.id != null'>
and api_scenario.num
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.id"/>
</include>
</if>
<if test="${condition}.updateTime != null">
and api_scenario.update_time
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.updateTime"/>
</include>
</if>
<if test="${condition}.createTime != null">
and api_scenario.create_time
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.createTime"/>
</include>
</if>
<if test="${condition}.status != null">
and api_scenario.status
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.status"/>
</include>
</if>
<if test='${condition}.tags != null and ${ObjectTags}.operator == "not like"'>
and (api_scenario.tags is null or api_scenario.tags
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.tags"/>
</include>
)
</if>
<if test='${condition}.tags != null and ${ObjectTags}.operator == "like"'>
and api_scenario.tags
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.tags"/>
</include>
</if>
<if test="${condition}.customs != null and ${condition}.customs.size() > 0">
<foreach collection="${condition}.customs" item="custom" separator="" open="" close="">
<if test="custom.value != ''">
<if test='custom.operator == "not like" or custom.operator == "not in"'>
and api_scenario.id not in (
</if>
<if test='custom.operator != "not like" and custom.operator != "not in"'>
and api_scenario.id in (
</if>
select api_id from api_definition_custom_field where field_id = #{custom.id}
<choose>
<when test="custom.type == 'richText' or custom.type == 'textarea' or custom.operator == 'current user'">
and `value`
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="custom"/>
</include>
</when>
<when test="custom.type == 'multipleMember' or custom.type == 'checkbox' or custom.type == 'multipleSelect'">
and ${custom.value}
</when>
<when test="custom.type == 'date' or custom.type == 'datetime'">
and left(replace(unix_timestamp(trim(both '"' from `value`)), '.', ''), 13)
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="custom"/>
</include>
</when>
<otherwise>
and trim(both '"' from `value`)
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="custom"/>
</include>
</otherwise>
</choose>
)
</if>
</foreach>
</if>
</sql>
<sql id="queryVersionCondition">
<if test="request.versionId != null and request.versionId != ''">
and ${versionTable}.version_id = #{request.versionId}
</if>
<if test="request.refId != null and request.refId != ''">
and ${versionTable}.ref_id = #{request.refId}
</if>
<if test="request.versionId == null and request.refId == null and request.scenarioId == null">
AND ${versionTable}.latest = 1
</if>
</sql>
<sql id="queryDocVersionCondition">
<if test="request.versionId != null and request.versionId != ''">
and ${versionTable}.version_id = #{request.versionId}
</if>
<if test="request.versionId == null and request.apiId == null">
AND ${versionTable}.latest = 1
</if>
</sql>
</mapper>

View File

@ -1,6 +1,6 @@
package io.metersphere.api.mapper;
import io.metersphere.api.dto.definition.ApiScenarioModuleRequest;
import io.metersphere.api.dto.scenario.ApiScenarioModuleRequest;
import io.metersphere.project.dto.ModuleCountDTO;
import io.metersphere.project.dto.NodeSortQueryParam;
import io.metersphere.system.dto.sdk.BaseModule;

View File

@ -7,8 +7,8 @@ import io.metersphere.api.dto.definition.ApiTestCaseDTO;
import io.metersphere.api.dto.definition.ApiTestCasePageRequest;
import io.metersphere.api.dto.definition.CasePassDTO;
import io.metersphere.dto.TestCaseProviderDTO;
import io.metersphere.request.TestCasePageProviderRequest;
import io.metersphere.request.AssociateOtherCaseRequest;
import io.metersphere.request.TestCasePageProviderRequest;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@ -50,4 +50,6 @@ public interface ExtApiTestCaseMapper {
List<ApiTestCase> getTestCaseByProvider(@Param("request") AssociateOtherCaseRequest request, @Param("deleted") boolean deleted);
List<ApiTestCase> getTagsByIds(@Param("ids") List<String> ids, @Param("deleted") boolean deleted);
}

View File

@ -9,6 +9,10 @@
<resultMap id="TestCaseProviderDTO" type="io.metersphere.dto.TestCaseProviderDTO">
<result column="tags" jdbcType="VARCHAR" property="tags" typeHandler="io.metersphere.handler.ListTypeHandler" />
</resultMap>
<resultMap id="BaseResultMap" type="io.metersphere.api.domain.ApiTestCase">
<result column="tags" jdbcType="VARCHAR" property="tags" typeHandler="io.metersphere.handler.ListTypeHandler" />
</resultMap>
<update id="batchMoveGc">
UPDATE api_test_case
SET deleted = 1,
@ -191,6 +195,18 @@
WHERE t1.deleted =#{deleted}
<include refid="queryWhereConditionByBatch"/>
</select>
<select id="getTagsByIds" resultMap="BaseResultMap">
SELECT
t1.id,
t1.tags
FROM
api_test_case t1
WHERE t1.deleted =#{deleted}
and t1.id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<sql id="queryWhereConditionByBatch">
<if test="request.protocol != null and request.protocol!=''">

View File

@ -1,5 +1,6 @@
package io.metersphere.api.service.definition;
import io.metersphere.api.constants.ApiDefinitionStatus;
import io.metersphere.api.constants.ApiImportPlatform;
import io.metersphere.api.domain.ApiDefinition;
import io.metersphere.api.domain.ApiDefinitionBlob;
@ -327,7 +328,7 @@ public class ApiDefinitionImportUtilService {
apiDefinition.setUpdateTime(System.currentTimeMillis());
apiDefinition.setNum(NumGenerator.nextNum(request.getProjectId(), ApplicationNumScope.API_DEFINITION));
apiDefinition.setLatest(true);
apiDefinition.setStatus("Underway");
apiDefinition.setStatus(ApiDefinitionStatus.UNDERWAY.name());
apiDefinition.setRefId(apiDefinition.getId());
apiDefinition.setVersionId(request.getVersionId());
apiMapper.insertSelective(apiDefinition);

View File

@ -41,6 +41,7 @@ import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
@Service
@ -413,8 +414,7 @@ public class ApiTestCaseService {
switch (request.getType()) {
case PRIORITY -> batchUpdatePriority(example, updateCase, request.getPriority());
case STATUS -> batchUpdateStatus(example, updateCase, request.getStatus());
case TAGS ->
batchUpdateTags(example, updateCase, request.getTags(), request.isAppendTag(), sqlSession, mapper);
case TAGS -> batchUpdateTags(example, updateCase, request, ids, sqlSession, mapper);
case ENVIRONMENT -> batchUpdateEnvironment(example, updateCase, request.getEnvId());
default -> throw new MSException(Translator.get("batch_edit_type_error"));
}
@ -435,23 +435,27 @@ public class ApiTestCaseService {
}
private void batchUpdateTags(ApiTestCaseExample example, ApiTestCase updateCase,
List<String> tags, boolean appendTag,
ApiCaseBatchEditRequest request, List<String> ids,
SqlSession sqlSession, ApiTestCaseMapper mapper) {
if (CollectionUtils.isEmpty(tags)) {
if (CollectionUtils.isEmpty(request.getTags())) {
throw new MSException(Translator.get("tags_is_null"));
}
if (appendTag) {
List<ApiTestCase> caseList = apiTestCaseMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(caseList)) {
caseList.forEach(apiTestCase -> {
if (CollectionUtils.isNotEmpty(apiTestCase.getTags())) {
List<String> orgTags = apiTestCase.getTags();
orgTags.addAll(tags);
apiTestCase.setTags(orgTags);
if (request.isAppendTag()) {
Map<String, ApiTestCase> caseMap = extApiTestCaseMapper.getTagsByIds(ids, false)
.stream()
.collect(Collectors.toMap(ApiTestCase::getId, Function.identity()));
if (MapUtils.isNotEmpty(caseMap)) {
caseMap.forEach((k, v) -> {
if (CollectionUtils.isNotEmpty(v.getTags())) {
List<String> orgTags = v.getTags();
orgTags.addAll(request.getTags());
v.setTags(orgTags.stream().distinct().toList());
} else {
apiTestCase.setTags(tags);
v.setTags(request.getTags());
}
mapper.updateByPrimaryKey(apiTestCase);
v.setUpdateTime(updateCase.getUpdateTime());
v.setUpdateUser(updateCase.getUpdateUser());
mapper.updateByPrimaryKeySelective(v);
});
sqlSession.flushStatements();
if (sqlSessionFactory != null) {
@ -459,7 +463,7 @@ public class ApiTestCaseService {
}
}
} else {
updateCase.setTags(tags);
updateCase.setTags(request.getTags());
apiTestCaseMapper.updateByExampleSelective(updateCase, example);
}
}

View File

@ -0,0 +1,100 @@
package io.metersphere.api.service.scenario;
import io.metersphere.api.domain.ApiScenario;
import io.metersphere.api.domain.ApiScenarioExample;
import io.metersphere.api.mapper.ApiScenarioMapper;
import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.dto.builder.LogDTOBuilder;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.dto.LogDTO;
import io.metersphere.system.log.service.OperationLogService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class ApiScenarioLogService {
@Resource
private ProjectMapper projectMapper;
@Resource
private OperationLogService operationLogService;
@Resource
private ApiScenarioMapper apiScenarioMapper;
public void batchEditLog(List<ApiScenario> scenarioList, String operator, String projectId) {
saveBatchLog(projectId, scenarioList, "/api/scenario/batch/edit", operator, OperationLogType.UPDATE.name(), false);
}
private void saveBatchLog(String projectId, List<ApiScenario> scenarioList, String path, String operator, String operationType, boolean isHistory) {
Project project = projectMapper.selectByPrimaryKey(projectId);
//取出apiTestCases所有的id为新的list
List<String> scenarioIds = scenarioList.stream().map(ApiScenario::getId).distinct().toList();
ApiScenarioExample example = new ApiScenarioExample();
example.createCriteria().andIdIn(scenarioIds);
List<ApiScenario> apiScenarioList = apiScenarioMapper.selectByExample(example);
List<LogDTO> logs = new ArrayList<>();
apiScenarioList.forEach(item -> {
LogDTO dto = LogDTOBuilder.builder()
.projectId(project.getId())
.organizationId(project.getOrganizationId())
.type(operationType)
.module(OperationLogModule.API_SCENARIO)
.method(HttpMethodConstants.POST.name())
.path(path)
.sourceId(item.getId())
.content(item.getName())
.createUser(operator)
.originalValue(JSON.toJSONBytes(item))
.build().getLogDTO();
dto.setHistory(isHistory);
logs.add(dto);
}
);
operationLogService.batchAdd(logs);
}
public void followLog(String id, String operator) {
ApiScenario scenario = apiScenarioMapper.selectByPrimaryKey(id);
Project project = projectMapper.selectByPrimaryKey(scenario.getProjectId());
LogDTO dto = new LogDTO(
scenario.getProjectId(),
project.getOrganizationId(),
id,
operator,
OperationLogType.UPDATE.name(),
OperationLogModule.API_SCENARIO,
Translator.get("follow") + scenario.getName());
dto.setPath("/api/scenario/follow/" + id);
dto.setMethod(HttpMethodConstants.GET.name());
dto.setOriginalValue(JSON.toJSONBytes(scenario));
operationLogService.add(dto);
}
public void unfollowLog(String id, String operator) {
ApiScenario apiTestCase = apiScenarioMapper.selectByPrimaryKey(id);
Project project = projectMapper.selectByPrimaryKey(apiTestCase.getProjectId());
LogDTO dto = new LogDTO(
apiTestCase.getProjectId(),
project.getOrganizationId(),
id,
operator,
OperationLogType.UPDATE.name(),
OperationLogModule.API_SCENARIO,
Translator.get("unfollow") + apiTestCase.getName());
dto.setPath("/api/scenario/follow/" + id);
dto.setMethod(HttpMethodConstants.GET.name());
dto.setOriginalValue(JSON.toJSONBytes(apiTestCase));
operationLogService.add(dto);
}
}

View File

@ -8,7 +8,7 @@ import io.metersphere.api.domain.ApiScenarioModuleExample;
import io.metersphere.api.dto.debug.ModuleCreateRequest;
import io.metersphere.api.dto.debug.ModuleUpdateRequest;
import io.metersphere.api.dto.definition.ApiModuleRequest;
import io.metersphere.api.dto.definition.ApiScenarioModuleRequest;
import io.metersphere.api.dto.scenario.ApiScenarioModuleRequest;
import io.metersphere.api.mapper.ApiScenarioMapper;
import io.metersphere.api.mapper.ApiScenarioModuleMapper;
import io.metersphere.api.mapper.ExtApiScenarioModuleMapper;

View File

@ -0,0 +1,281 @@
package io.metersphere.api.service.scenario;
import com.alibaba.excel.util.BooleanUtils;
import io.metersphere.api.domain.*;
import io.metersphere.api.dto.scenario.ApiScenarioBatchEditRequest;
import io.metersphere.api.dto.scenario.ApiScenarioDTO;
import io.metersphere.api.dto.scenario.ApiScenarioPageRequest;
import io.metersphere.api.mapper.*;
import io.metersphere.sdk.domain.Environment;
import io.metersphere.sdk.domain.EnvironmentExample;
import io.metersphere.sdk.domain.EnvironmentGroup;
import io.metersphere.sdk.domain.EnvironmentGroupExample;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.mapper.EnvironmentGroupMapper;
import io.metersphere.sdk.mapper.EnvironmentMapper;
import io.metersphere.sdk.util.SubListUtils;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.service.UserLoginService;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service
@Transactional(rollbackFor = Exception.class)
public class ApiScenarioService {
public static final Long ORDER_STEP = 5000L;
@Resource
private ApiScenarioMapper apiScenarioMapper;
@Resource
private ExtApiScenarioMapper extApiScenarioMapper;
@Resource
private UserLoginService userLoginService;
@Resource
private ApiScenarioEnvironmentMapper apiScenarioEnvironmentMapper;
@Resource
private ApiScenarioModuleMapper apiScenarioModuleMapper;
@Resource
private EnvironmentMapper environmentMapper;
@Resource
private EnvironmentGroupMapper environmentGroupMapper;
@Resource
private ApiScenarioLogService apiScenarioLogService;
@Resource
private ApiScenarioFollowerMapper apiScenarioFollowerMapper;
@Resource
private SqlSessionFactory sqlSessionFactory;
public static final String PRIORITY = "Priority";
public static final String STATUS = "Status";
public static final String TAGS = "Tags";
public static final String ENVIRONMENT = "Environment";
public List<ApiScenarioDTO> getScenarioPage(ApiScenarioPageRequest request) {
//CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request, userId);
//TODO 场景的自定义字段 等设计 不一定会有
List<ApiScenarioDTO> list = extApiScenarioMapper.list(request);
if (!CollectionUtils.isEmpty(list)) {
processApiScenario(list);
}
return list;
}
private void processApiScenario(List<ApiScenarioDTO> scenarioLists) {
Set<String> userIds = extractUserIds(scenarioLists);
Map<String, String> userMap = userLoginService.getUserNameMap(new ArrayList<>(userIds));
//取出所有的apiId
List<String> scenarioIds = scenarioLists.stream().map(ApiScenarioDTO::getId).distinct().toList();
ApiScenarioEnvironmentExample scenarioEnvironmentExample = new ApiScenarioEnvironmentExample();
scenarioEnvironmentExample.createCriteria().andApiScenarioIdIn(scenarioIds);
List<ApiScenarioEnvironment> apiScenarioEnvironments = apiScenarioEnvironmentMapper.selectByExample(scenarioEnvironmentExample);
//生成map key为id value为ApiScenarioEnvironment
Map<String, ApiScenarioEnvironment> environmentMap = apiScenarioEnvironments.stream().collect(Collectors.toMap(ApiScenarioEnvironment::getApiScenarioId, item -> item));
List<String> envIds = apiScenarioEnvironments.stream().map(ApiScenarioEnvironment::getEnvironmentId).toList();
EnvironmentExample environmentExample = new EnvironmentExample();
environmentExample.createCriteria().andIdIn(envIds);
List<Environment> environments = environmentMapper.selectByExample(environmentExample);
Map<String, String> envMap = environments.stream().collect(Collectors.toMap(Environment::getId, Environment::getName));
List<String> envGroupIds = apiScenarioEnvironments.stream().map(ApiScenarioEnvironment::getEnvironmentGroupId).toList();
EnvironmentGroupExample groupExample = new EnvironmentGroupExample();
groupExample.createCriteria().andIdIn(envGroupIds);
List<EnvironmentGroup> environmentGroups = environmentGroupMapper.selectByExample(groupExample);
Map<String, String> groupMap = environmentGroups.stream().collect(Collectors.toMap(EnvironmentGroup::getId, EnvironmentGroup::getName));
//取模块id为新的set
List<String> moduleIds = scenarioLists.stream().map(ApiScenarioDTO::getModuleId).distinct().toList();
ApiScenarioModuleExample moduleExample = new ApiScenarioModuleExample();
moduleExample.createCriteria().andIdIn(moduleIds);
List<ApiScenarioModule> modules = apiScenarioModuleMapper.selectByExample(moduleExample);
//生成map key为id value为name
Map<String, String> moduleMap = modules.stream().collect(Collectors.toMap(ApiScenarioModule::getId, ApiScenarioModule::getName));
scenarioLists.forEach(item -> {
item.setCreateUserName(userMap.get(item.getCreateUser()));
item.setDeleteUserName(userMap.get(item.getDeleteUser()));
item.setUpdateUserName(userMap.get(item.getUpdateUser()));
item.setModulePath(StringUtils.isNotBlank(moduleMap.get(item.getModuleId())) ? moduleMap.get(item.getModuleId()) : Translator.get("api_unplanned_scenario"));
if (!item.getGrouped() && environmentMap.containsKey(item.getId()) &&
StringUtils.isNotBlank(environmentMap.get(item.getId()).getEnvironmentId()) &&
envMap.containsKey(environmentMap.get(item.getId()).getEnvironmentId())) {
item.setEnvironmentName(environmentMap.get(item.getId()).getEnvironmentId());
} else if (item.getGrouped() && environmentMap.containsKey(item.getId()) &&
StringUtils.isNotBlank(environmentMap.get(item.getId()).getEnvironmentGroupId()) &&
groupMap.containsKey(environmentMap.get(item.getId()).getEnvironmentGroupId())) {
item.setEnvironmentName(groupMap.get(item.getId()));
}
});
}
private Set<String> extractUserIds(List<ApiScenarioDTO> list) {
return list.stream()
.flatMap(apiDefinition -> Stream.of(apiDefinition.getUpdateUser(), apiDefinition.getDeleteUser(), apiDefinition.getCreateUser()))
.collect(Collectors.toSet());
}
public void batchEdit(ApiScenarioBatchEditRequest request, String userId) {
List<String> ids = doSelectIds(request, false);
if (CollectionUtils.isEmpty(ids)) {
return;
}
SubListUtils.dealForSubList(ids, 500, subList -> batchEditByType(request, subList, userId, request.getProjectId()));
}
private void batchEditByType(ApiScenarioBatchEditRequest request, List<String> ids, String userId, String projectId) {
ApiScenarioExample example = new ApiScenarioExample();
example.createCriteria().andIdIn(ids);
ApiScenario updateScenario = new ApiScenario();
updateScenario.setUpdateUser(userId);
updateScenario.setUpdateTime(System.currentTimeMillis());
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiScenarioMapper mapper = sqlSession.getMapper(ApiScenarioMapper.class);
switch (request.getType()) {
case PRIORITY -> batchUpdatePriority(example, updateScenario, request.getPriority());
case STATUS -> batchUpdateStatus(example, updateScenario, request.getStatus());
case TAGS -> batchUpdateTags(example, updateScenario, request, ids, sqlSession, mapper);
case ENVIRONMENT -> batchUpdateEnvironment(example, updateScenario, request, ids);
default -> throw new MSException(Translator.get("batch_edit_type_error"));
}
List<ApiScenario> scenarioInfoByIds = extApiScenarioMapper.getInfoByIds(ids, false);
apiScenarioLogService.batchEditLog(scenarioInfoByIds, userId, projectId);
}
private void batchUpdateEnvironment(ApiScenarioExample example, ApiScenario updateScenario,
ApiScenarioBatchEditRequest request,
List<String> ids) {
if (BooleanUtils.isFalse(request.isGrouped())) {
if (StringUtils.isBlank(request.getEnvId())) {
throw new MSException(Translator.get("environment_id_is_null"));
}
Environment environment = environmentMapper.selectByPrimaryKey(request.getEnvId());
if (environment == null) {
throw new MSException(Translator.get("environment_is_not_exist"));
}
updateScenario.setGrouped(false);
ApiScenarioEnvironment apiScenarioEnvironment = new ApiScenarioEnvironment();
apiScenarioEnvironment.setEnvironmentId(request.getEnvId());
ApiScenarioEnvironmentExample environmentExample = new ApiScenarioEnvironmentExample();
environmentExample.createCriteria().andApiScenarioIdIn(ids);
apiScenarioEnvironmentMapper.updateByExampleSelective(apiScenarioEnvironment, environmentExample);
} else {
if (StringUtils.isBlank(request.getGroupId())) {
throw new MSException(Translator.get("environment_group_id_is_null"));
}
EnvironmentGroup environmentGroup = environmentGroupMapper.selectByPrimaryKey(request.getGroupId());
if (environmentGroup == null) {
throw new MSException(Translator.get("environment_group_is_not_exist"));
}
updateScenario.setGrouped(true);
ApiScenarioEnvironment apiScenarioEnvironment = new ApiScenarioEnvironment();
apiScenarioEnvironment.setEnvironmentGroupId(request.getGroupId());
ApiScenarioEnvironmentExample environmentExample = new ApiScenarioEnvironmentExample();
environmentExample.createCriteria().andApiScenarioIdIn(ids);
apiScenarioEnvironmentMapper.updateByExampleSelective(apiScenarioEnvironment, environmentExample);
}
apiScenarioMapper.updateByExampleSelective(updateScenario, example);
}
private void batchUpdateTags(ApiScenarioExample example, ApiScenario updateScenario,
ApiScenarioBatchEditRequest request, List<String> ids,
SqlSession sqlSession, ApiScenarioMapper mapper) {
if (CollectionUtils.isEmpty(request.getTags())) {
throw new MSException(Translator.get("tags_is_null"));
}
if (request.isAppendTag()) {
Map<String, ApiScenario> scenarioMap = extApiScenarioMapper.getTagsByIds(ids, false)
.stream()
.collect(Collectors.toMap(ApiScenario::getId, Function.identity()));
if (MapUtils.isNotEmpty(scenarioMap)) {
scenarioMap.forEach((k, v) -> {
if (CollectionUtils.isNotEmpty(v.getTags())) {
List<String> orgTags = v.getTags();
orgTags.addAll(request.getTags());
v.setTags(orgTags.stream().distinct().toList());
} else {
v.setTags(request.getTags());
}
v.setUpdateTime(updateScenario.getUpdateTime());
v.setUpdateUser(updateScenario.getUpdateUser());
mapper.updateByPrimaryKeySelective(v);
});
sqlSession.flushStatements();
if (sqlSessionFactory != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
}
} else {
updateScenario.setTags(request.getTags());
apiScenarioMapper.updateByExampleSelective(updateScenario, example);
}
}
private void batchUpdateStatus(ApiScenarioExample example, ApiScenario updateScenario, String status) {
if (StringUtils.isBlank(status)) {
throw new MSException(Translator.get("status_is_null"));
}
updateScenario.setStatus(status);
apiScenarioMapper.updateByExampleSelective(updateScenario, example);
}
private void batchUpdatePriority(ApiScenarioExample example, ApiScenario updateScenario, String priority) {
if (StringUtils.isBlank(priority)) {
throw new MSException(Translator.get("priority_is_null"));
}
updateScenario.setPriority(priority);
apiScenarioMapper.updateByExampleSelective(updateScenario, example);
}
public List<String> doSelectIds(ApiScenarioBatchEditRequest request, boolean deleted) {
if (request.isSelectAll()) {
List<String> ids = extApiScenarioMapper.getIds(request, deleted);
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
ids.removeAll(request.getExcludeIds());
}
return ids;
} else {
return request.getSelectIds();
}
}
public void follow(String id, String userId) {
checkApiScenario(id);
ApiScenarioFollowerExample example = new ApiScenarioFollowerExample();
example.createCriteria().andApiScenarioIdEqualTo(id).andUserIdEqualTo(userId);
if (apiScenarioFollowerMapper.countByExample(example) > 0) {
apiScenarioFollowerMapper.deleteByPrimaryKey(id, userId);
apiScenarioLogService.unfollowLog(id, userId);
} else {
ApiScenarioFollower apiScenarioFollower = new ApiScenarioFollower();
apiScenarioFollower.setApiScenarioId(id);
apiScenarioFollower.setUserId(userId);
apiScenarioFollowerMapper.insertSelective(apiScenarioFollower);
apiScenarioLogService.followLog(id, userId);
}
}
private ApiScenario checkApiScenario(String id) {
ApiScenario apiScenario = apiScenarioMapper.selectByPrimaryKey(id);
if (apiScenario == null) {
throw new MSException(Translator.get("api_scenario_is_not_exist"));
}
return apiScenario;
}
}

View File

@ -0,0 +1,455 @@
package io.metersphere.api.controller;
import io.metersphere.api.domain.*;
import io.metersphere.api.dto.scenario.ApiScenarioBatchEditRequest;
import io.metersphere.api.dto.scenario.ApiScenarioDTO;
import io.metersphere.api.dto.scenario.ApiScenarioPageRequest;
import io.metersphere.api.mapper.*;
import io.metersphere.sdk.constants.ApplicationNumScope;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.domain.Environment;
import io.metersphere.sdk.domain.EnvironmentExample;
import io.metersphere.sdk.domain.EnvironmentGroup;
import io.metersphere.sdk.mapper.EnvironmentGroupMapper;
import io.metersphere.sdk.mapper.EnvironmentMapper;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.uid.NumGenerator;
import io.metersphere.system.utils.Pager;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class ApiScenarioControllerTests extends BaseTest {
private static final String BASE_PATH = "/api/scenario/";
private static final String PAGE = BASE_PATH + "page";
private static final String TRASH_PAGE = BASE_PATH + "trash/page";
private static final String BATCH_EDIT = BASE_PATH + "batch/edit";
private static final String FOLLOW = BASE_PATH + "follow/";
private static final ResultMatcher ERROR_REQUEST_MATCHER = status().is5xxServerError();
@Resource
private ApiScenarioMapper apiScenarioMapper;
@Resource
private ApiScenarioModuleMapper apiScenarioModuleMapper;
@Resource
private ExtApiScenarioMapper extApiScenarioMapper;
@Resource
private ApiScenarioEnvironmentMapper apiScenarioEnvironmentMapper;
@Resource
private EnvironmentMapper environmentMapper;
@Resource
private ApiScenarioFollowerMapper apiScenarioFollowerMapper;
@Resource
private EnvironmentGroupMapper environmentGroupMapper;
public static <T> T parseObjectFromMvcResult(MvcResult mvcResult, Class<T> parseClass) {
try {
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
//返回请求正常
Assertions.assertNotNull(resultHolder);
return JSON.parseObject(JSON.toJSONString(resultHolder.getData()), parseClass);
} catch (Exception ignore) {
}
return null;
}
private MvcResult responsePost(String url, Object param) throws Exception {
return mockMvc.perform(MockMvcRequestBuilders.post(url)
.header(SessionConstants.HEADER_TOKEN, sessionId)
.header(SessionConstants.CSRF_TOKEN, csrfToken)
.content(JSON.toJSONString(param))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn();
}
public void initApiScenario() {
ApiScenarioModule apiScenarioModule = new ApiScenarioModule();
apiScenarioModule.setId("scenario-moduleId");
apiScenarioModule.setProjectId(DEFAULT_PROJECT_ID);
apiScenarioModule.setName("场景模块");
apiScenarioModule.setCreateTime(System.currentTimeMillis());
apiScenarioModule.setUpdateTime(System.currentTimeMillis());
apiScenarioModule.setCreateUser("admin");
apiScenarioModule.setUpdateUser("admin");
apiScenarioModule.setPos(0L);
apiScenarioModuleMapper.insertSelective(apiScenarioModule);
// 创建环境组
EnvironmentGroup environmentGroup = new EnvironmentGroup();
environmentGroup.setId("scenario-environment-group-id");
environmentGroup.setProjectId(DEFAULT_PROJECT_ID);
environmentGroup.setName("环境组");
environmentGroup.setCreateTime(System.currentTimeMillis());
environmentGroup.setUpdateTime(System.currentTimeMillis());
environmentGroup.setCreateUser("admin");
environmentGroup.setUpdateUser("admin");
environmentGroup.setPos(0L);
environmentGroupMapper.insertSelective(environmentGroup);
EnvironmentExample environmentExample = new EnvironmentExample();
environmentExample.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID).andMockEqualTo(true);
List<Environment> environments = environmentMapper.selectByExample(environmentExample);
for (int i = 0; i < 10; i++) {
ApiScenario apiScenario = new ApiScenario();
apiScenario.setId("api-scenario-id" + i);
apiScenario.setProjectId(DEFAULT_PROJECT_ID);
apiScenario.setName(StringUtils.join("接口场景", apiScenario.getId()));
apiScenario.setModuleId("scenario-moduleId");
apiScenario.setStatus("未规划");
apiScenario.setNum(NumGenerator.nextNum(DEFAULT_PROJECT_ID, ApplicationNumScope.API_SCENARIO));
apiScenario.setPos(0L);
apiScenario.setPriority("P0");
apiScenario.setLatest(true);
apiScenario.setVersionId("1.0");
apiScenario.setRefId(apiScenario.getId());
apiScenario.setCreateTime(System.currentTimeMillis());
apiScenario.setUpdateTime(System.currentTimeMillis());
apiScenario.setCreateUser("admin");
apiScenario.setUpdateUser("admin");
ApiScenarioEnvironment apiScenarioEnvironment = new ApiScenarioEnvironment();
apiScenarioEnvironment.setApiScenarioId(apiScenario.getId());
if (i % 2 == 0) {
apiScenario.setTags(new ArrayList<>(List.of("tag1", "tag2")));
apiScenario.setGrouped(true);
apiScenarioEnvironment.setEnvironmentGroupId("scenario-environment-group-id");
} else {
apiScenario.setGrouped(false);
apiScenarioEnvironment.setEnvironmentId(environments.get(0).getId());
}
apiScenarioMapper.insertSelective(apiScenario);
apiScenarioEnvironmentMapper.insertSelective(apiScenarioEnvironment);
}
}
public void initApiScenarioTrash() {
ApiScenarioModule apiScenarioModule = new ApiScenarioModule();
apiScenarioModule.setId("scenario-moduleId-trash");
apiScenarioModule.setProjectId(DEFAULT_PROJECT_ID);
apiScenarioModule.setName("场景模块-trash");
apiScenarioModule.setCreateTime(System.currentTimeMillis());
apiScenarioModule.setUpdateTime(System.currentTimeMillis());
apiScenarioModule.setCreateUser("admin");
apiScenarioModule.setUpdateUser("admin");
apiScenarioModule.setPos(0L);
apiScenarioModuleMapper.insertSelective(apiScenarioModule);
for (int i = 0; i < 10; i++) {
ApiScenario apiScenario = new ApiScenario();
apiScenario.setId("trash-api-scenario-id" + i);
apiScenario.setProjectId(DEFAULT_PROJECT_ID);
apiScenario.setName(StringUtils.join("接口场景-回收站", apiScenario.getId()));
apiScenario.setModuleId("scenario-moduleId-trash");
apiScenario.setStatus("未规划");
apiScenario.setNum(NumGenerator.nextNum(DEFAULT_PROJECT_ID, ApplicationNumScope.API_SCENARIO));
apiScenario.setPos(0L);
apiScenario.setLatest(true);
apiScenario.setPriority("P0");
apiScenario.setVersionId("1.0");
apiScenario.setRefId(apiScenario.getId());
apiScenario.setCreateTime(System.currentTimeMillis());
apiScenario.setUpdateTime(System.currentTimeMillis());
apiScenario.setCreateUser("admin");
apiScenario.setUpdateUser("admin");
apiScenarioMapper.insertSelective(apiScenario);
ApiScenarioEnvironment apiScenarioEnvironment = new ApiScenarioEnvironment();
apiScenarioEnvironment.setApiScenarioId(apiScenario.getId());
apiScenarioEnvironmentMapper.insertSelective(apiScenarioEnvironment);
}
}
@Test
@Order(11)
public void page() throws Exception {
// @@请求成功
initApiScenario();
ApiScenarioPageRequest pageRequest = new ApiScenarioPageRequest();
pageRequest.setProjectId(DEFAULT_PROJECT_ID);
pageRequest.setPageSize(10);
pageRequest.setCurrent(1);
MvcResult mvcResult = responsePost(PAGE, pageRequest);
Pager<?> returnPager = parseObjectFromMvcResult(mvcResult, Pager.class);
//返回值不为空
Assertions.assertNotNull(returnPager);
//返回值的页码和当前页码相同
Assertions.assertEquals(returnPager.getCurrent(), pageRequest.getCurrent());
//返回的数据量不超过规定要返回的数据量相同
Assertions.assertTrue(((List<ApiScenarioDTO>) returnPager.getList()).size() <= pageRequest.getPageSize());
//查询api-scenario-id1的数据
pageRequest.setScenarioId("api-scenario-id1");
mvcResult = responsePost(PAGE, pageRequest);
returnPager = parseObjectFromMvcResult(mvcResult, Pager.class);
//返回值不为空
Assertions.assertNotNull(returnPager);
//返回值的页码和当前页码相同
Assertions.assertEquals(returnPager.getCurrent(), pageRequest.getCurrent());
List<ApiScenarioDTO> scenarioDTOS = JSON.parseArray(JSON.toJSONString(returnPager.getList()), ApiScenarioDTO.class);
scenarioDTOS.forEach(caseDTO -> Assertions.assertEquals(caseDTO.getId(), "api-scenario-id1"));
//查询模块为moduleId1的数据
pageRequest.setScenarioId(null);
pageRequest.setModuleIds(List.of("scenario-moduleId"));
mvcResult = responsePost(PAGE, pageRequest);
returnPager = parseObjectFromMvcResult(mvcResult, Pager.class);
//返回值不为空
Assertions.assertNotNull(returnPager);
//返回值的页码和当前页码相同
Assertions.assertEquals(returnPager.getCurrent(), pageRequest.getCurrent());
scenarioDTOS = JSON.parseArray(JSON.toJSONString(returnPager.getList()), ApiScenarioDTO.class);
scenarioDTOS.forEach(scenario -> Assertions.assertEquals(scenario.getModuleId(), "scenario-moduleId"));
pageRequest.setModuleIds(null);
pageRequest.setSort(new HashMap<>() {{
put("createTime", "asc");
}});
responsePost(PAGE, pageRequest);
pageRequest = new ApiScenarioPageRequest();
pageRequest.setProjectId(DEFAULT_PROJECT_ID);
pageRequest.setPageSize(10);
pageRequest.setCurrent(1);
pageRequest.setModuleIds(List.of("scenario-moduleId"));
pageRequest.setFilter(new HashMap<>() {{
put("priority", List.of("P0"));
}});
mvcResult = responsePost(PAGE, pageRequest);
returnPager = parseObjectFromMvcResult(mvcResult, Pager.class);
//返回值不为空
Assertions.assertNotNull(returnPager);
//返回值的页码和当前页码相同
Assertions.assertEquals(returnPager.getCurrent(), pageRequest.getCurrent());
scenarioDTOS = JSON.parseArray(JSON.toJSONString(returnPager.getList()), ApiScenarioDTO.class);
scenarioDTOS.forEach(scenario -> Assertions.assertEquals(scenario.getPriority(), "P0"));
//校验权限
requestPostPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_READ, PAGE, pageRequest);
}
@Test
@Order(12)
public void follow() throws Exception {
// @@请求成功
this.requestGetWithOk(FOLLOW + "api-scenario-id1");
ApiScenarioFollowerExample example = new ApiScenarioFollowerExample();
example.createCriteria().andApiScenarioIdEqualTo("api-scenario-id1").andUserIdEqualTo("admin");
List<ApiScenarioFollower> followers = apiScenarioFollowerMapper.selectByExample(example);
Assertions.assertTrue(CollectionUtils.isNotEmpty(followers));
// @@校验日志
checkLog("api-scenario-id1", OperationLogType.UPDATE);
this.requestGet(FOLLOW + "111").andExpect(ERROR_REQUEST_MATCHER);
// @@校验权限
requestGetPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_UPDATE, FOLLOW + "api-scenario-id1");
// @@请求成功
this.requestGetWithOk(FOLLOW + "api-scenario-id1");
example = new ApiScenarioFollowerExample();
example.createCriteria().andApiScenarioIdEqualTo("api-scenario-id1").andUserIdEqualTo("admin");
followers = apiScenarioFollowerMapper.selectByExample(example);
Assertions.assertTrue(CollectionUtils.isEmpty(followers));
// @@校验日志
checkLog("api-scenario-id1", OperationLogType.UPDATE);
this.requestGet(FOLLOW + "111").andExpect(ERROR_REQUEST_MATCHER);
}
@Test
@Order(13)
public void batchEdit() throws Exception {
// 追加标签
ApiScenarioBatchEditRequest request = new ApiScenarioBatchEditRequest();
request.setProjectId(DEFAULT_PROJECT_ID);
request.setType("Tags");
request.setAppendTag(true);
request.setSelectAll(true);
request.setTags(new LinkedHashSet<>(List.of("tag1", "tag3", "tag4")));
responsePost(BATCH_EDIT, request);
ApiScenarioExample example = new ApiScenarioExample();
List<String> ids = extApiScenarioMapper.getIds(request, false);
example.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID).andDeletedEqualTo(false).andIdIn(ids);
apiScenarioMapper.selectByExample(example).forEach(apiTestCase -> {
Assertions.assertTrue(apiTestCase.getTags().contains("tag1"));
Assertions.assertTrue(apiTestCase.getTags().contains("tag3"));
Assertions.assertTrue(apiTestCase.getTags().contains("tag4"));
});
//覆盖标签
request.setTags(new LinkedHashSet<>(List.of("tag1")));
request.setAppendTag(false);
responsePost(BATCH_EDIT, request);
apiScenarioMapper.selectByExample(example).forEach(scenario -> {
Assertions.assertEquals(scenario.getTags(), List.of("tag1"));
});
//标签为空 报错
request.setTags(new LinkedHashSet<>());
this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER);
//ids为空的时候
request.setTags(new LinkedHashSet<>(List.of("tag1")));
request.setSelectAll(true);
List<ApiScenario> apiScenarioList = apiScenarioMapper.selectByExample(example);
//提取所有的id
List<String> apiIdList = apiScenarioList.stream().map(ApiScenario::getId).toList();
request.setSelectIds(apiIdList);
request.setExcludeIds(apiIdList);
responsePost(BATCH_EDIT, request);
//优先级
request.setTags(new LinkedHashSet<>());
request.setSelectAll(true);
request.setType("Priority");
request.setModuleIds(List.of("scenario-moduleId"));
request.setPriority("P3");
request.setExcludeIds(new ArrayList<>());
responsePost(BATCH_EDIT, request);
//判断数据的优先级是不是P3
example.clear();
example.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID).andDeletedEqualTo(false);
List<ApiScenario> apiScenarios = apiScenarioMapper.selectByExample(example);
apiScenarios.forEach(apiTestCase -> Assertions.assertEquals(apiTestCase.getPriority(), "P3"));
//优先级数据为空
request.setPriority(null);
this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER);
//ids为空的时候
request.setPriority("P3");
request.setSelectAll(false);
request.setSelectIds(List.of("api-scenario-id1"));
request.setExcludeIds(List.of("api-scenario-id1"));
responsePost(BATCH_EDIT, request);
//状态
request.setPriority(null);
request.setType("Status");
request.setStatus("Completed");
request.setSelectAll(true);
request.setExcludeIds(new ArrayList<>());
responsePost(BATCH_EDIT, request);
//判断数据的状态是不是Completed
apiScenarios = apiScenarioMapper.selectByExample(example);
apiScenarios.forEach(apiTestCase -> Assertions.assertEquals(apiTestCase.getStatus(), "Completed"));
//状态数据为空
request.setStatus(null);
this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER);
//环境
request.setStatus(null);
request.setType("Environment");
EnvironmentExample environmentExample = new EnvironmentExample();
environmentExample.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID).andMockEqualTo(true);
List<Environment> environments = environmentMapper.selectByExample(environmentExample);
request.setEnvId(environments.get(0).getId());
responsePost(BATCH_EDIT, request);
//取所有的ids
List<String> scenarioIds = apiScenarios.stream().map(ApiScenario::getId).toList();
//判断数据的环境是不是environments.get(0).getId()
ApiScenarioEnvironmentExample apiScenarioEnvironmentExample = new ApiScenarioEnvironmentExample();
apiScenarioEnvironmentExample.createCriteria().andApiScenarioIdIn(scenarioIds);
List<ApiScenarioEnvironment> apiScenarioEnvironments = apiScenarioEnvironmentMapper.selectByExample(apiScenarioEnvironmentExample);
apiScenarioEnvironments.forEach(apiTestCase -> Assertions.assertEquals(apiTestCase.getEnvironmentId(), environments.get(0).getId()));
//环境数据为空
request.setEnvId(null);
this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER);
//环境不存在
request.setEnvId("111");
this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER);
//环境组
request.setGrouped(true);
request.setGroupId("scenario-environment-group-id");
responsePost(BATCH_EDIT, request);
apiScenarioEnvironments = apiScenarioEnvironmentMapper.selectByExample(apiScenarioEnvironmentExample);
apiScenarioEnvironments.forEach(apiTestCase -> Assertions.assertEquals(apiTestCase.getEnvironmentGroupId(), "scenario-environment-group-id"));
apiScenarios = apiScenarioMapper.selectByExample(example);
apiScenarios.forEach(apiTestCase -> Assertions.assertEquals(apiTestCase.getGrouped(), true));
//环境组数据为空
request.setGroupId(null);
this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER);
//环境组不存在
request.setGroupId("111");
this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER);
//类型错误
request.setType("111");
this.requestPost(BATCH_EDIT, request, ERROR_REQUEST_MATCHER);
//校验权限
requestPostPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_UPDATE, BATCH_EDIT, request);
}
@Test
@Order(15)
public void trashPage() throws Exception {
// @@请求成功
initApiScenarioTrash();
ApiScenarioPageRequest pageRequest = new ApiScenarioPageRequest();
pageRequest.setProjectId(DEFAULT_PROJECT_ID);
pageRequest.setPageSize(10);
pageRequest.setCurrent(1);
MvcResult mvcResult = responsePost(TRASH_PAGE, pageRequest);
Pager<?> returnPager = parseObjectFromMvcResult(mvcResult, Pager.class);
//返回值不为空
Assertions.assertNotNull(returnPager);
//返回值的页码和当前页码相同
Assertions.assertEquals(returnPager.getCurrent(), pageRequest.getCurrent());
//返回的数据量不超过规定要返回的数据量相同
Assertions.assertTrue(((List<ApiScenarioDTO>) returnPager.getList()).size() <= pageRequest.getPageSize());
//查询api-scenario-id1的数据
pageRequest.setScenarioId("trash-api-scenario-id1");
mvcResult = responsePost(TRASH_PAGE, pageRequest);
returnPager = parseObjectFromMvcResult(mvcResult, Pager.class);
//返回值不为空
Assertions.assertNotNull(returnPager);
//返回值的页码和当前页码相同
Assertions.assertEquals(returnPager.getCurrent(), pageRequest.getCurrent());
List<ApiScenarioDTO> scenarioDTOS = JSON.parseArray(JSON.toJSONString(returnPager.getList()), ApiScenarioDTO.class);
scenarioDTOS.forEach(caseDTO -> Assertions.assertEquals(caseDTO.getId(), "trash-api-scenario-id1"));
//查询模块为moduleId1的数据
pageRequest.setScenarioId(null);
pageRequest.setModuleIds(List.of("scenario-moduleId-trash"));
mvcResult = responsePost(TRASH_PAGE, pageRequest);
returnPager = parseObjectFromMvcResult(mvcResult, Pager.class);
//返回值不为空
Assertions.assertNotNull(returnPager);
//返回值的页码和当前页码相同
Assertions.assertEquals(returnPager.getCurrent(), pageRequest.getCurrent());
scenarioDTOS = JSON.parseArray(JSON.toJSONString(returnPager.getList()), ApiScenarioDTO.class);
scenarioDTOS.forEach(scenario -> Assertions.assertEquals(scenario.getModuleId(), "scenario-moduleId-trash"));
pageRequest.setModuleIds(null);
pageRequest.setSort(new HashMap<>() {{
put("createTime", "asc");
}});
responsePost(TRASH_PAGE, pageRequest);
//校验权限
requestPostPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_READ, TRASH_PAGE, pageRequest);
}
}

View File

@ -6,7 +6,7 @@ import io.metersphere.api.domain.ApiScenarioModule;
import io.metersphere.api.domain.ApiScenarioModuleExample;
import io.metersphere.api.dto.debug.ModuleCreateRequest;
import io.metersphere.api.dto.debug.ModuleUpdateRequest;
import io.metersphere.api.dto.definition.ApiScenarioModuleRequest;
import io.metersphere.api.dto.scenario.ApiScenarioModuleRequest;
import io.metersphere.api.mapper.ApiScenarioMapper;
import io.metersphere.api.mapper.ApiScenarioModuleMapper;
import io.metersphere.api.service.scenario.ApiScenarioModuleService;

View File

@ -21,6 +21,7 @@ public class OperationLogModule {
public static final String API_DEFINITION = "API_DEFINITION";
public static final String API_DEFINITION_MOCK = "API_DEFINITION_MOCK";
public static final String API_DEFINITION_CASE = "API_DEFINITION_CASE";
public static final String API_SCENARIO = "API_SCENARIO";
public static final String AUTH_TITLE = "AUTH_TITLE";
public static final String PROJECT_ENVIRONMENT_SETTING = "PROJECT_ENVIRONMENT_SETTING";
public static final String PROJECT_PROJECT_MANAGER = "PROJECT_PROJECT_MANAGER";