feat(测试计划): 测试计划组后台相关功能开发
This commit is contained in:
parent
d30cf886f2
commit
0e57b01a8b
|
@ -4,13 +4,13 @@ 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.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;
|
||||
|
||||
@Data
|
||||
public class TestPlan implements Serializable {
|
||||
|
@ -53,7 +53,7 @@ public class TestPlan implements Serializable {
|
|||
private String type;
|
||||
|
||||
@Schema(description = "标签")
|
||||
private List<String> tags;
|
||||
private java.util.List<String> tags;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Long createTime;
|
||||
|
@ -79,9 +79,13 @@ public class TestPlan implements Serializable {
|
|||
@Schema(description = "实际结束时间")
|
||||
private Long actualEndTime;
|
||||
|
||||
@Schema(description = "描述;描述")
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "自定义排序", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "{test_plan.pos.not_blank}", groups = {Created.class})
|
||||
private Long pos;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public enum Column {
|
||||
|
@ -102,7 +106,8 @@ public class TestPlan implements Serializable {
|
|||
plannedEndTime("planned_end_time", "plannedEndTime", "BIGINT", false),
|
||||
actualStartTime("actual_start_time", "actualStartTime", "BIGINT", false),
|
||||
actualEndTime("actual_end_time", "actualEndTime", "BIGINT", false),
|
||||
description("description", "description", "VARCHAR", false);
|
||||
description("description", "description", "VARCHAR", false),
|
||||
pos("pos", "pos", "BIGINT", false);
|
||||
|
||||
private static final String BEGINNING_DELIMITER = "`";
|
||||
|
||||
|
|
|
@ -1327,6 +1327,66 @@ public class TestPlanExample {
|
|||
addCriterion("description not between", value1, value2, "description");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosIsNull() {
|
||||
addCriterion("pos is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosIsNotNull() {
|
||||
addCriterion("pos is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosEqualTo(Long value) {
|
||||
addCriterion("pos =", value, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosNotEqualTo(Long value) {
|
||||
addCriterion("pos <>", value, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosGreaterThan(Long value) {
|
||||
addCriterion("pos >", value, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosGreaterThanOrEqualTo(Long value) {
|
||||
addCriterion("pos >=", value, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosLessThan(Long value) {
|
||||
addCriterion("pos <", value, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosLessThanOrEqualTo(Long value) {
|
||||
addCriterion("pos <=", value, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosIn(List<Long> values) {
|
||||
addCriterion("pos in", values, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosNotIn(List<Long> values) {
|
||||
addCriterion("pos not in", values, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosBetween(Long value1, Long value2) {
|
||||
addCriterion("pos between", value1, value2, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosNotBetween(Long value1, Long value2) {
|
||||
addCriterion("pos not between", value1, value2, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criteria extends GeneratedCriteria {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
<result column="actual_start_time" jdbcType="BIGINT" property="actualStartTime" />
|
||||
<result column="actual_end_time" jdbcType="BIGINT" property="actualEndTime" />
|
||||
<result column="description" jdbcType="VARCHAR" property="description" />
|
||||
<result column="pos" jdbcType="BIGINT" property="pos" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
|
@ -120,7 +121,7 @@
|
|||
<sql id="Base_Column_List">
|
||||
id, num, project_id, group_id, module_id, `name`, `status`, `type`, tags, create_time,
|
||||
create_user, update_time, update_user, planned_start_time, planned_end_time, actual_start_time,
|
||||
actual_end_time, description
|
||||
actual_end_time, description, pos
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.plan.domain.TestPlanExample" resultMap="BaseResultMap">
|
||||
select
|
||||
|
@ -158,15 +159,15 @@
|
|||
`status`, `type`, tags,
|
||||
create_time, create_user, update_time,
|
||||
update_user, planned_start_time, planned_end_time,
|
||||
actual_start_time, actual_end_time, description
|
||||
)
|
||||
actual_start_time, actual_end_time, description,
|
||||
pos)
|
||||
values (#{id,jdbcType=VARCHAR}, #{num,jdbcType=BIGINT}, #{projectId,jdbcType=VARCHAR},
|
||||
#{groupId,jdbcType=VARCHAR}, #{moduleId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
|
||||
#{status,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{tags,jdbcType=VARCHAR,typeHandler=io.metersphere.handler.ListTypeHandler},
|
||||
#{createTime,jdbcType=BIGINT}, #{createUser,jdbcType=VARCHAR}, #{updateTime,jdbcType=BIGINT},
|
||||
#{updateUser,jdbcType=VARCHAR}, #{plannedStartTime,jdbcType=BIGINT}, #{plannedEndTime,jdbcType=BIGINT},
|
||||
#{actualStartTime,jdbcType=BIGINT}, #{actualEndTime,jdbcType=BIGINT}, #{description,jdbcType=VARCHAR}
|
||||
)
|
||||
#{actualStartTime,jdbcType=BIGINT}, #{actualEndTime,jdbcType=BIGINT}, #{description,jdbcType=VARCHAR},
|
||||
#{pos,jdbcType=BIGINT})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.plan.domain.TestPlan">
|
||||
insert into test_plan
|
||||
|
@ -225,6 +226,9 @@
|
|||
<if test="description != null">
|
||||
description,
|
||||
</if>
|
||||
<if test="pos != null">
|
||||
pos,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
|
@ -281,6 +285,9 @@
|
|||
<if test="description != null">
|
||||
#{description,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="pos != null">
|
||||
#{pos,jdbcType=BIGINT},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.plan.domain.TestPlanExample" resultType="java.lang.Long">
|
||||
|
@ -346,6 +353,9 @@
|
|||
<if test="record.description != null">
|
||||
description = #{record.description,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.pos != null">
|
||||
pos = #{record.pos,jdbcType=BIGINT},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
|
@ -370,7 +380,8 @@
|
|||
planned_end_time = #{record.plannedEndTime,jdbcType=BIGINT},
|
||||
actual_start_time = #{record.actualStartTime,jdbcType=BIGINT},
|
||||
actual_end_time = #{record.actualEndTime,jdbcType=BIGINT},
|
||||
description = #{record.description,jdbcType=VARCHAR}
|
||||
description = #{record.description,jdbcType=VARCHAR},
|
||||
pos = #{record.pos,jdbcType=BIGINT}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -429,6 +440,9 @@
|
|||
<if test="description != null">
|
||||
description = #{description,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="pos != null">
|
||||
pos = #{pos,jdbcType=BIGINT},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
|
@ -450,14 +464,15 @@
|
|||
planned_end_time = #{plannedEndTime,jdbcType=BIGINT},
|
||||
actual_start_time = #{actualStartTime,jdbcType=BIGINT},
|
||||
actual_end_time = #{actualEndTime,jdbcType=BIGINT},
|
||||
description = #{description,jdbcType=VARCHAR}
|
||||
description = #{description,jdbcType=VARCHAR},
|
||||
pos = #{pos,jdbcType=BIGINT}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<insert id="batchInsert" parameterType="map">
|
||||
insert into test_plan
|
||||
(id, num, project_id, group_id, module_id, `name`, `status`, `type`, tags, create_time,
|
||||
create_user, update_time, update_user, planned_start_time, planned_end_time, actual_start_time,
|
||||
actual_end_time, description)
|
||||
actual_end_time, description, pos)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.id,jdbcType=VARCHAR}, #{item.num,jdbcType=BIGINT}, #{item.projectId,jdbcType=VARCHAR},
|
||||
|
@ -466,7 +481,8 @@
|
|||
#{item.createTime,jdbcType=BIGINT}, #{item.createUser,jdbcType=VARCHAR}, #{item.updateTime,jdbcType=BIGINT},
|
||||
#{item.updateUser,jdbcType=VARCHAR}, #{item.plannedStartTime,jdbcType=BIGINT},
|
||||
#{item.plannedEndTime,jdbcType=BIGINT}, #{item.actualStartTime,jdbcType=BIGINT},
|
||||
#{item.actualEndTime,jdbcType=BIGINT}, #{item.description,jdbcType=VARCHAR})
|
||||
#{item.actualEndTime,jdbcType=BIGINT}, #{item.description,jdbcType=VARCHAR}, #{item.pos,jdbcType=BIGINT}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
<insert id="batchInsertSelective" parameterType="map">
|
||||
|
@ -533,6 +549,9 @@
|
|||
<if test="'description'.toString() == column.value">
|
||||
#{item.description,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'pos'.toString() == column.value">
|
||||
#{item.pos,jdbcType=BIGINT}
|
||||
</if>
|
||||
</foreach>
|
||||
)
|
||||
</foreach>
|
||||
|
|
|
@ -11,6 +11,10 @@ CREATE TABLE IF NOT EXISTS platform_source(
|
|||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT = '平台对接保存参数';
|
||||
|
||||
-- 测试计划增加排序字段
|
||||
alter table test_plan
|
||||
ADD COLUMN `pos` BIGINT NOT NULL DEFAULT 0 COMMENT '自定义排序';
|
||||
|
||||
-- 修改计划配置表
|
||||
ALTER TABLE test_plan_config DROP `test_planning`;
|
||||
|
||||
|
|
|
@ -86,11 +86,25 @@ test_plan_principal.user_id.not_blank=用户id不能为空
|
|||
test_plan_report_content.id.not_blank=测试计划报告内容id不能为空
|
||||
test_plan_report_content.test_plan_report_id.length_range=测试计划报告id长度过长
|
||||
test_plan_report_content.test_plan_report_id.not_blank=测试计划报告id不能为空
|
||||
log.delete.test_plan=删除测试计划
|
||||
log.delete.test_plan_group=删除测试计划组
|
||||
log.test_plan.add=关联了资源
|
||||
log.test_plan.remove=移除了资源
|
||||
log.test_plan.move=移动了资源
|
||||
log.test_plan.move.test_plan=移动了测试计划
|
||||
log.test_plan.update=修改了资源
|
||||
log.test_plan.functional_case=功能用例
|
||||
log.test_plan.api_case=接口用例
|
||||
log.test_plan.api_scenario=接口场景
|
||||
test_plan.type.not_blank=测试计划类型不能为空
|
||||
test_plan.group.not_plan=当前测试计划组没有可归档计划
|
||||
test_plan.group.error=不是合法的测试计划组
|
||||
test_plan_group.batch.log={0}测试计划组
|
||||
test_plan.batch.log={0}测试计划
|
||||
test_plan_report_not_exist=测试计划报告不存在
|
||||
test_plan_report_id.not_blank=测试计划报告id不能为空
|
||||
test_plan_report_name.not_blank=测试计划报告名称不能为空
|
||||
run_functional_case=执行功能用例
|
||||
test_plan_not_exist=测试计划不存在
|
||||
test_plan.report_id.not_blank=测试计划报告ID不能为空
|
||||
test_plan.report.share_id.not_blank=测试计划报告分享ID不能为空
|
||||
|
|
|
@ -91,12 +91,14 @@ log.delete.test_plan_group=Test plan group deleted
|
|||
log.test_plan.add=Association resources
|
||||
log.test_plan.remove=Remove resource
|
||||
log.test_plan.move=Move resources
|
||||
log.test_plan.move.test_plan=Move test plan
|
||||
log.test_plan.update=Update resources
|
||||
log.test_plan.functional_case=Functional case
|
||||
log.test_plan.api_case=Api case
|
||||
log.test_plan.api_scenario=Api scenario
|
||||
test_plan.type.not_blank=Test plan type cannot be empty
|
||||
test_plan.group.not_plan=There are no archived plans in the current testing plan group
|
||||
test_plan.group.error=Test plan group error
|
||||
test_plan_group.batch.log={0} test plan group
|
||||
test_plan.batch.log={0} plan
|
||||
test_plan_report_not_exist=The test plan report does not exist
|
||||
|
|
|
@ -91,12 +91,14 @@ log.delete.test_plan_group=删除测试计划组
|
|||
log.test_plan.add=关联了资源
|
||||
log.test_plan.remove=移除了资源
|
||||
log.test_plan.move=移动了资源
|
||||
log.test_plan.move.test_plan=移动了测试计划
|
||||
log.test_plan.update=修改了资源
|
||||
log.test_plan.functional_case=功能用例
|
||||
log.test_plan.api_case=接口用例
|
||||
log.test_plan.api_scenario=接口场景
|
||||
test_plan.type.not_blank=测试计划类型不能为空
|
||||
test_plan.group.not_plan=当前测试计划组没有可归档计划
|
||||
test_plan.group.error=不是合法的测试计划组
|
||||
test_plan_group.batch.log={0}测试计划组
|
||||
test_plan.batch.log={0}测试计划
|
||||
test_plan_report_not_exist=测试计划报告不存在
|
||||
|
|
|
@ -91,12 +91,14 @@ log.delete.test_plan_group=刪除測試計劃組
|
|||
log.test_plan.add=關聯了資源
|
||||
log.test_plan.remove=移除了資源
|
||||
log.test_plan.move=移動了資源
|
||||
log.test_plan.move.test_plan=移動了測試計劃
|
||||
log.test_plan.update=修改了資源
|
||||
log.test_plan.functional_case=功能用例
|
||||
log.test_plan.api_case=接口用例
|
||||
log.test_plan.api_scenario=接口場景
|
||||
test_plan.type.not_blank=測試計劃類型不能為空
|
||||
test_plan.group.not_plan=當前測試計劃組沒有可歸檔計劃
|
||||
test_plan.group.error=不是合法的測試計劃組
|
||||
test_plan_group.batch.log={0}測試計劃組
|
||||
test_plan.batch.log={0}測試計劃
|
||||
test_plan_report_not_exist=測試計劃報告不存在
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package io.metersphere.api.service.debug;
|
||||
|
||||
import io.metersphere.sdk.constants.ApiFileResourceType;
|
||||
import io.metersphere.api.constants.ApiResourceType;
|
||||
import io.metersphere.api.domain.ApiDebug;
|
||||
import io.metersphere.api.domain.ApiDebugBlob;
|
||||
|
@ -24,6 +23,7 @@ import io.metersphere.project.domain.FileMetadata;
|
|||
import io.metersphere.project.dto.MoveNodeSortDTO;
|
||||
import io.metersphere.project.service.MoveNodeService;
|
||||
import io.metersphere.project.service.ProjectService;
|
||||
import io.metersphere.sdk.constants.ApiFileResourceType;
|
||||
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
||||
import io.metersphere.sdk.dto.api.task.TaskRequestDTO;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
|
@ -265,7 +265,7 @@ public class ApiDebugService extends MoveNodeService {
|
|||
}
|
||||
|
||||
public void moveNode(PosRequest posRequest) {
|
||||
NodeMoveRequest request = super.getNodeMoveRequest(posRequest);
|
||||
NodeMoveRequest request = super.getNodeMoveRequest(posRequest, true);
|
||||
MoveNodeSortDTO sortDTO = super.getNodeSortDTO(
|
||||
posRequest.getProjectId(),
|
||||
request,
|
||||
|
|
|
@ -25,7 +25,10 @@ import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
|
|||
import io.metersphere.project.service.EnvironmentService;
|
||||
import io.metersphere.project.service.MoveNodeService;
|
||||
import io.metersphere.project.service.ProjectService;
|
||||
import io.metersphere.sdk.constants.*;
|
||||
import io.metersphere.sdk.constants.ApiFileResourceType;
|
||||
import io.metersphere.sdk.constants.ApplicationNumScope;
|
||||
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.metersphere.sdk.domain.OperationLogBlob;
|
||||
import io.metersphere.sdk.dto.api.task.TaskRequestDTO;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
|
@ -1062,7 +1065,7 @@ public class ApiDefinitionService extends MoveNodeService {
|
|||
}
|
||||
|
||||
public void moveNode(PosRequest posRequest) {
|
||||
NodeMoveRequest request = super.getNodeMoveRequest(posRequest);
|
||||
NodeMoveRequest request = super.getNodeMoveRequest(posRequest, true);
|
||||
MoveNodeSortDTO sortDTO = super.getNodeSortDTO(
|
||||
posRequest.getProjectId(),
|
||||
request,
|
||||
|
|
|
@ -826,7 +826,7 @@ public class ApiTestCaseService extends MoveNodeService {
|
|||
}
|
||||
|
||||
public void moveNode(PosRequest posRequest) {
|
||||
NodeMoveRequest request = super.getNodeMoveRequest(posRequest);
|
||||
NodeMoveRequest request = super.getNodeMoveRequest(posRequest,true);
|
||||
MoveNodeSortDTO sortDTO = super.getNodeSortDTO(
|
||||
posRequest.getProjectId(),
|
||||
request,
|
||||
|
|
|
@ -2997,7 +2997,7 @@ public class ApiScenarioService extends MoveNodeService {
|
|||
}
|
||||
|
||||
public void moveNode(PosRequest posRequest) {
|
||||
NodeMoveRequest request = super.getNodeMoveRequest(posRequest);
|
||||
NodeMoveRequest request = super.getNodeMoveRequest(posRequest, true);
|
||||
MoveNodeSortDTO sortDTO = super.getNodeSortDTO(
|
||||
posRequest.getProjectId(),
|
||||
request,
|
||||
|
|
|
@ -7,8 +7,8 @@ import lombok.Data;
|
|||
@Data
|
||||
@AllArgsConstructor
|
||||
public class MoveNodeSortDTO {
|
||||
@Schema(description = "项目ID")
|
||||
private String projectId;
|
||||
@Schema(description = "排序范围ID")
|
||||
private String sortRangeId;
|
||||
|
||||
@Schema(description = "要排序的节点")
|
||||
private DropNode sortNode;
|
||||
|
@ -18,6 +18,4 @@ public class MoveNodeSortDTO {
|
|||
|
||||
@Schema(description = "后一个节点")
|
||||
private DropNode nextNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -273,7 +273,7 @@ public class EnvironmentGroupService extends MoveNodeService{
|
|||
}
|
||||
|
||||
public void moveNode(PosRequest posRequest) {
|
||||
NodeMoveRequest request = super.getNodeMoveRequest(posRequest);
|
||||
NodeMoveRequest request = super.getNodeMoveRequest(posRequest, true);
|
||||
MoveNodeSortDTO sortDTO = super.getNodeSortDTO(
|
||||
posRequest.getProjectId(),
|
||||
request,
|
||||
|
|
|
@ -564,7 +564,7 @@ public class EnvironmentService extends MoveNodeService {
|
|||
}
|
||||
|
||||
public void moveNode(PosRequest posRequest) {
|
||||
NodeMoveRequest request = super.getNodeMoveRequest(posRequest);
|
||||
NodeMoveRequest request = super.getNodeMoveRequest(posRequest,true);
|
||||
MoveNodeSortDTO sortDTO = super.getNodeSortDTO(
|
||||
posRequest.getProjectId(),
|
||||
request,
|
||||
|
|
|
@ -27,9 +27,6 @@ public abstract class ModuleTreeService {
|
|||
|
||||
protected static final long LIMIT_POS = NodeSortUtils.DEFAULT_NODE_INTERVAL_POS;
|
||||
|
||||
//默认节点所在分支最大数量不超过200, 后续会根据需求排期进行调整
|
||||
protected static final int MAX_BRANCHES_NODE_SIZE = 200;
|
||||
|
||||
public BaseTreeNode getDefaultModule(String name) {
|
||||
//默认模块下不允许创建子模块。 它本身也就是叶子节点。
|
||||
return new BaseTreeNode(ModuleConstants.DEFAULT_NODE_ID, name, ModuleConstants.NODE_TYPE_DEFAULT, ModuleConstants.ROOT_NODE_PARENT_ID);
|
||||
|
|
|
@ -7,7 +7,6 @@ import io.metersphere.project.dto.NodeSortQueryParam;
|
|||
import io.metersphere.project.utils.NodeSortUtils;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.dto.sdk.enums.MoveTypeEnum;
|
||||
import io.metersphere.system.dto.sdk.request.NodeMoveRequest;
|
||||
import io.metersphere.system.dto.sdk.request.PosRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -28,23 +27,29 @@ public abstract class MoveNodeService {
|
|||
private static final String MOVE_POS_OPERATOR_MORE = "moreThan";
|
||||
private static final String DRAG_NODE_NOT_EXIST = "drag_node.not.exist";
|
||||
|
||||
public NodeMoveRequest getNodeMoveRequest(PosRequest posRequest) {
|
||||
/**
|
||||
* 构建节点移动的请求参数
|
||||
*
|
||||
* @param posRequest 拖拽的前端请求参数
|
||||
* @param isDesc 是否是降序排列
|
||||
*/
|
||||
public NodeMoveRequest getNodeMoveRequest(PosRequest posRequest, boolean isDesc) {
|
||||
NodeMoveRequest request = new NodeMoveRequest();
|
||||
request.setDragNodeId(posRequest.getMoveId());
|
||||
request.setDropNodeId(posRequest.getTargetId());
|
||||
request.setDropPosition(StringUtils.equals(MoveTypeEnum.AFTER.name(), posRequest.getMoveMode()) ? -1 : 1);
|
||||
request.setAndConvertDropPosition(posRequest.getMoveMode(), isDesc);
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建节点排序的参数
|
||||
*
|
||||
* @param sortRangeId 排序范围ID
|
||||
* @param request 拖拽的前端请求参数
|
||||
* @param selectIdNodeFunc 通过id查询节点的函数
|
||||
* @param selectPosNodeFunc 通过parentId和pos运算符查询节点的函数
|
||||
* @return
|
||||
*/
|
||||
public MoveNodeSortDTO getNodeSortDTO(String projectId , NodeMoveRequest request, Function<String, DropNode> selectIdNodeFunc, Function<NodeSortQueryParam, DropNode> selectPosNodeFunc) {
|
||||
public MoveNodeSortDTO getNodeSortDTO(String sortRangeId, NodeMoveRequest request, Function<String, DropNode> selectIdNodeFunc, Function<NodeSortQueryParam, DropNode> selectPosNodeFunc) {
|
||||
if (StringUtils.equals(request.getDragNodeId(), request.getDropNodeId())) {
|
||||
//两种节点不能一样
|
||||
throw new MSException(Translator.get("invalid_parameter") + ": drag node and drop node");
|
||||
|
@ -69,7 +74,7 @@ public abstract class MoveNodeService {
|
|||
NodeSortQueryParam sortParam = new NodeSortQueryParam();
|
||||
sortParam.setPos(previousNode.getPos());
|
||||
sortParam.setOperator(MOVE_POS_OPERATOR_MORE);
|
||||
sortParam.setParentId(projectId);
|
||||
sortParam.setParentId(sortRangeId);
|
||||
nextNode = selectPosNodeFunc.apply(sortParam);
|
||||
} else if (request.getDropPosition() == -1) {
|
||||
//dropPosition=-1: 放到dropNode节点前,原dropNode前面的节点之后
|
||||
|
@ -77,29 +82,26 @@ public abstract class MoveNodeService {
|
|||
NodeSortQueryParam sortParam = new NodeSortQueryParam();
|
||||
sortParam.setPos(nextNode.getPos());
|
||||
sortParam.setOperator(MOVE_POS_OPERATOR_LESS);
|
||||
sortParam.setParentId(projectId);
|
||||
sortParam.setParentId(sortRangeId);
|
||||
previousNode = selectPosNodeFunc.apply(sortParam);
|
||||
} else {
|
||||
throw new MSException(Translator.get("invalid_parameter") + ": dropPosition");
|
||||
}
|
||||
|
||||
return new MoveNodeSortDTO(projectId, dragNode, previousNode, nextNode);
|
||||
return new MoveNodeSortDTO(sortRangeId, dragNode, previousNode, nextNode);
|
||||
}
|
||||
|
||||
//排序
|
||||
public void sort(MoveNodeSortDTO sortDTO) {
|
||||
|
||||
// 获取相邻节点
|
||||
DropNode previousNode = sortDTO.getPreviousNode();
|
||||
DropNode nextNode = sortDTO.getNextNode();
|
||||
|
||||
ModuleSortCountResultDTO countResultDTO = NodeSortUtils.countModuleSort(
|
||||
previousNode == null ? -1 : previousNode.getPos(),
|
||||
nextNode == null ? -1 : nextNode.getPos());
|
||||
|
||||
updatePos(sortDTO.getSortNode().getId(), countResultDTO.getPos());
|
||||
if (countResultDTO.isRefreshPos()) {
|
||||
refreshPos(sortDTO.getProjectId());
|
||||
refreshPos(sortDTO.getSortRangeId());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import io.metersphere.project.dto.ModuleSortCountResultDTO;
|
|||
public class NodeSortUtils {
|
||||
|
||||
//默认节点间隔
|
||||
public static final long DEFAULT_NODE_INTERVAL_POS = 64;
|
||||
public static final long DEFAULT_NODE_INTERVAL_POS = 4096;
|
||||
|
||||
/**
|
||||
* 计算模块排序
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package io.metersphere.system.dto.sdk.request;
|
||||
|
||||
import io.metersphere.system.dto.sdk.enums.MoveTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@Data
|
||||
public class NodeMoveRequest {
|
||||
|
@ -16,5 +18,13 @@ public class NodeMoveRequest {
|
|||
|
||||
@Schema(description = "放入的位置(取值:-1,,1。 -1:dropNodeId节点之前。 1:dropNodeId节点后)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private int dropPosition;
|
||||
|
||||
public void setAndConvertDropPosition(String position, boolean isSortDesc) {
|
||||
if (StringUtils.equals(MoveTypeEnum.BEFORE.name(), position)) {
|
||||
this.dropPosition = isSortDesc ? 1 : -1;
|
||||
} else {
|
||||
this.dropPosition = isSortDesc ? -1 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,10 @@ package io.metersphere.system.dto.sdk.request;
|
|||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
@ -13,6 +15,8 @@ import java.io.Serializable;
|
|||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PosRequest implements Serializable {
|
||||
|
||||
@Serial
|
||||
|
@ -22,6 +26,10 @@ public class PosRequest implements Serializable {
|
|||
@NotBlank(message = "{case_review.project_id.not_blank}")
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "移动用例id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{functional_case_relationship_edge.source_id.not_blank}")
|
||||
private String moveId;
|
||||
|
||||
@Schema(description = "目标用例id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{functional_case_relationship_edge.target_id.not_blank}")
|
||||
private String targetId;
|
||||
|
@ -29,8 +37,4 @@ public class PosRequest implements Serializable {
|
|||
@Schema(description = "移动类型", requiredMode = Schema.RequiredMode.REQUIRED, allowableValues = {"BEFORE", "AFTER", "APPEND"})
|
||||
@NotBlank(message = "{case_review.moveMode.not_blank}")
|
||||
private String moveMode;
|
||||
|
||||
@Schema(description = "移动用例id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{functional_case_relationship_edge.source_id.not_blank}")
|
||||
private String moveId;
|
||||
}
|
||||
|
|
|
@ -4,11 +4,14 @@ import io.metersphere.plan.constants.TestPlanResourceConfig;
|
|||
import io.metersphere.plan.domain.TestPlan;
|
||||
import io.metersphere.plan.dto.request.*;
|
||||
import io.metersphere.plan.dto.response.TestPlanDetailResponse;
|
||||
import io.metersphere.plan.dto.response.TestPlanResourceSortResponse;
|
||||
import io.metersphere.plan.dto.response.TestPlanResponse;
|
||||
import io.metersphere.plan.dto.response.TestPlanStatisticsResponse;
|
||||
import io.metersphere.plan.service.*;
|
||||
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.system.dto.LogInsertModule;
|
||||
import io.metersphere.system.dto.sdk.request.PosRequest;
|
||||
import io.metersphere.system.log.annotation.Log;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.notice.annotation.SendNotice;
|
||||
|
@ -193,4 +196,13 @@ public class TestPlanController {
|
|||
testPlanService.filterArchivedIds(request);
|
||||
testPlanService.batchEdit(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping(value = "/sort")
|
||||
@Operation(summary = "测试计划移动(测试计划拖进、拖出到测试计划组、测试计划在测试计划组内的排序")
|
||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE)
|
||||
@CheckOwner(resourceId = "#request.getMoveId()", resourceType = "test_plan")
|
||||
public TestPlanResourceSortResponse sortTestPlan(@Validated @RequestBody PosRequest request) {
|
||||
testPlanManagementService.checkModuleIsOpen(request.getMoveId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN));
|
||||
return testPlanService.sortInGroup(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/move", HttpMethodConstants.POST.name()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
package io.metersphere.plan.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class AssociationNode {
|
||||
private String id;
|
||||
private long pos;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package io.metersphere.plan.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class AssociationNodeSortDTO {
|
||||
@Schema(description = "测试计划ID")
|
||||
private String testPlanId;
|
||||
|
||||
@Schema(description = "要排序的节点")
|
||||
private AssociationNode sortNode;
|
||||
|
||||
@Schema(description = "前一个节点")
|
||||
private AssociationNode previousNode;
|
||||
|
||||
@Schema(description = "后一个节点")
|
||||
private AssociationNode nextNode;
|
||||
|
||||
}
|
||||
|
|
@ -1,9 +1,13 @@
|
|||
package io.metersphere.plan.dto.response;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TestPlanResourceSortResponse {
|
||||
@Schema(description = "本次排序的数量")
|
||||
private long sortNodeNum;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package io.metersphere.plan.mapper;
|
||||
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionDTO;
|
||||
import io.metersphere.plan.dto.AssociationNode;
|
||||
import io.metersphere.plan.dto.ResourceSelectParam;
|
||||
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
|
||||
import io.metersphere.plan.dto.request.TestPlanApiRequest;
|
||||
import io.metersphere.project.dto.DropNode;
|
||||
import io.metersphere.project.dto.NodeSortQueryParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
|
@ -20,9 +20,9 @@ public interface ExtTestPlanApiCaseMapper {
|
|||
|
||||
List<String> getIdByParam(ResourceSelectParam resourceSelectParam);
|
||||
|
||||
AssociationNode selectDragInfoById(String id);
|
||||
DropNode selectDragInfoById(String id);
|
||||
|
||||
AssociationNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam);
|
||||
DropNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam);
|
||||
|
||||
List<TestPlanCaseRunResultCount> selectCaseExecResultCount(String testPlanId);
|
||||
|
||||
|
|
|
@ -51,14 +51,14 @@
|
|||
</if>
|
||||
</select>
|
||||
|
||||
<select id="selectDragInfoById" resultType="io.metersphere.plan.dto.AssociationNode">
|
||||
<select id="selectDragInfoById" resultType="io.metersphere.project.dto.DropNode">
|
||||
SELECT id, pos
|
||||
FROM test_plan_api_case
|
||||
WHERE id = #{0}
|
||||
</select>
|
||||
<select id="selectNodeByPosOperator"
|
||||
parameterType="io.metersphere.project.dto.NodeSortQueryParam"
|
||||
resultType="io.metersphere.plan.dto.AssociationNode">
|
||||
resultType="io.metersphere.project.dto.DropNode">
|
||||
SELECT id, pos
|
||||
FROM test_plan_api_case
|
||||
WHERE test_plan_id = #{parentId}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.metersphere.plan.mapper;
|
||||
|
||||
import io.metersphere.plan.dto.AssociationNode;
|
||||
import io.metersphere.plan.dto.ResourceSelectParam;
|
||||
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
|
||||
import io.metersphere.project.dto.DropNode;
|
||||
import io.metersphere.project.dto.NodeSortQueryParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
|
@ -18,9 +18,9 @@ public interface ExtTestPlanApiScenarioMapper {
|
|||
|
||||
List<String> getIdByParam(ResourceSelectParam resourceSelectParam);
|
||||
|
||||
AssociationNode selectDragInfoById(String id);
|
||||
DropNode selectDragInfoById(String id);
|
||||
|
||||
AssociationNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam);
|
||||
DropNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam);
|
||||
|
||||
List<TestPlanCaseRunResultCount> selectCaseExecResultCount(String testPlanId);
|
||||
}
|
||||
|
|
|
@ -44,14 +44,14 @@
|
|||
ORDER BY #{orderString}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectDragInfoById" resultType="io.metersphere.plan.dto.AssociationNode">
|
||||
<select id="selectDragInfoById" resultType="io.metersphere.project.dto.DropNode">
|
||||
SELECT id, pos
|
||||
FROM test_plan_api_scenario
|
||||
WHERE id = #{0}
|
||||
</select>
|
||||
<select id="selectNodeByPosOperator"
|
||||
parameterType="io.metersphere.project.dto.NodeSortQueryParam"
|
||||
resultType="io.metersphere.plan.dto.AssociationNode">
|
||||
resultType="io.metersphere.project.dto.DropNode">
|
||||
SELECT id, pos
|
||||
FROM test_plan_api_scenario
|
||||
WHERE test_plan_id = #{parentId}
|
||||
|
|
|
@ -4,12 +4,12 @@ import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO;
|
|||
import io.metersphere.functional.dto.FunctionalCaseModuleDTO;
|
||||
import io.metersphere.functional.dto.ProjectOptionDTO;
|
||||
import io.metersphere.plan.domain.TestPlanFunctionalCase;
|
||||
import io.metersphere.plan.dto.AssociationNode;
|
||||
import io.metersphere.plan.dto.ResourceSelectParam;
|
||||
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
|
||||
import io.metersphere.plan.dto.request.BasePlanCaseBatchRequest;
|
||||
import io.metersphere.plan.dto.request.TestPlanCaseRequest;
|
||||
import io.metersphere.plan.dto.response.TestPlanCasePageResponse;
|
||||
import io.metersphere.project.dto.DropNode;
|
||||
import io.metersphere.project.dto.NodeSortQueryParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
|
@ -27,9 +27,9 @@ public interface ExtTestPlanFunctionalCaseMapper {
|
|||
|
||||
List<String> getIdByParam(ResourceSelectParam resourceSelectParam);
|
||||
|
||||
AssociationNode selectDragInfoById(String id);
|
||||
DropNode selectDragInfoById(String id);
|
||||
|
||||
AssociationNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam);
|
||||
DropNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam);
|
||||
|
||||
List<TestPlanCasePageResponse> getCasePage(@Param("request") TestPlanCaseRequest request, @Param("deleted") boolean deleted, @Param("sort") String sort);
|
||||
|
||||
|
|
|
@ -65,14 +65,14 @@
|
|||
<include refid="queryWhereConditionByBatchQueryRequest"/>
|
||||
</select>
|
||||
|
||||
<select id="selectDragInfoById" resultType="io.metersphere.plan.dto.AssociationNode">
|
||||
<select id="selectDragInfoById" resultType="io.metersphere.project.dto.DropNode">
|
||||
SELECT id, pos
|
||||
FROM test_plan_functional_case
|
||||
WHERE id = #{0}
|
||||
</select>
|
||||
<select id="selectNodeByPosOperator"
|
||||
parameterType="io.metersphere.project.dto.NodeSortQueryParam"
|
||||
resultType="io.metersphere.plan.dto.AssociationNode">
|
||||
resultType="io.metersphere.project.dto.DropNode">
|
||||
SELECT id, pos
|
||||
FROM test_plan_functional_case
|
||||
WHERE test_plan_id = #{parentId}
|
||||
|
|
|
@ -5,7 +5,9 @@ import io.metersphere.plan.dto.TestPlanQueryConditions;
|
|||
import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest;
|
||||
import io.metersphere.plan.dto.request.TestPlanTableRequest;
|
||||
import io.metersphere.plan.dto.response.TestPlanResponse;
|
||||
import io.metersphere.project.dto.DropNode;
|
||||
import io.metersphere.project.dto.ModuleCountDTO;
|
||||
import io.metersphere.project.dto.NodeSortQueryParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -40,4 +42,10 @@ public interface ExtTestPlanMapper {
|
|||
List<String> selectIdByProjectId(String projectId);
|
||||
|
||||
List<String> selectNotArchivedIds(@Param("ids") List<String> selectIds);
|
||||
|
||||
DropNode selectDragInfoById(String s);
|
||||
|
||||
DropNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam);
|
||||
|
||||
long selectMaxPosByGroupId(String groupId);
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
t.module_id as moduleId,
|
||||
t.type,
|
||||
t.description,
|
||||
t.pos,
|
||||
t.tags
|
||||
FROM test_plan t
|
||||
INNER JOIN user createUser ON t.create_user = createUser.id
|
||||
|
@ -63,6 +64,7 @@
|
|||
</foreach>
|
||||
</if>
|
||||
<include refid="queryWhereCondition"/>
|
||||
ORDER BY t.pos ASC
|
||||
</select>
|
||||
|
||||
<sql id="queryWhereCondition">
|
||||
|
@ -90,7 +92,7 @@
|
|||
</when>
|
||||
<when test="request.type == 'GROUP'">
|
||||
and t.group_id = 'NONE'
|
||||
and t.type = 'GTOUP'
|
||||
and t.type = 'GROUP'
|
||||
</when>
|
||||
</choose>
|
||||
</if>
|
||||
|
@ -408,7 +410,35 @@
|
|||
</foreach>
|
||||
AND status != 'ARCHIVED'
|
||||
</select>
|
||||
<select id="selectDragInfoById" resultType="io.metersphere.project.dto.DropNode">
|
||||
SELECT id, pos
|
||||
FROM test_plan
|
||||
WHERE id = #{0}
|
||||
</select>
|
||||
|
||||
<select id="selectNodeByPosOperator"
|
||||
parameterType="io.metersphere.project.dto.NodeSortQueryParam"
|
||||
resultType="io.metersphere.project.dto.DropNode">
|
||||
SELECT id, pos
|
||||
FROM test_plan
|
||||
WHERE group_id = #{parentId}
|
||||
<if test="operator == 'moreThan'">
|
||||
AND pos > #{pos}
|
||||
</if>
|
||||
<if test="operator == 'lessThan'">
|
||||
AND pos < #{pos}
|
||||
</if>
|
||||
ORDER BY pos
|
||||
<if test="operator == 'lessThan' or operator == 'latest'">
|
||||
DESC
|
||||
</if>
|
||||
LIMIT 1
|
||||
</select>
|
||||
<select id="selectMaxPosByGroupId" resultType="java.lang.Long">
|
||||
SELECT IF(MAX(pos) IS NULL, 0, MAX(pos)) AS pos
|
||||
FROM test_plan
|
||||
WHERE group_id = #{0}
|
||||
</select>
|
||||
|
||||
<update id="batchUpdate">
|
||||
update test_plan
|
||||
|
|
|
@ -18,7 +18,6 @@ import io.metersphere.functional.service.FunctionalCaseAttachmentService;
|
|||
import io.metersphere.functional.service.FunctionalCaseModuleService;
|
||||
import io.metersphere.functional.service.FunctionalCaseService;
|
||||
import io.metersphere.plan.domain.*;
|
||||
import io.metersphere.plan.dto.AssociationNodeSortDTO;
|
||||
import io.metersphere.plan.dto.ResourceLogInsertModule;
|
||||
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
|
||||
import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
|
||||
|
@ -28,6 +27,7 @@ import io.metersphere.plan.mapper.*;
|
|||
import io.metersphere.plugin.platform.dto.SelectOption;
|
||||
import io.metersphere.project.domain.Project;
|
||||
import io.metersphere.project.dto.ModuleCountDTO;
|
||||
import io.metersphere.project.dto.MoveNodeSortDTO;
|
||||
import io.metersphere.provider.BaseAssociateBugProvider;
|
||||
import io.metersphere.request.AssociateBugPageRequest;
|
||||
import io.metersphere.request.BugPageProviderRequest;
|
||||
|
@ -171,9 +171,9 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
|
|||
throw new MSException(Translator.get("test_plan.drag.node.error"));
|
||||
}
|
||||
TestPlanResourceSortResponse response = new TestPlanResourceSortResponse();
|
||||
AssociationNodeSortDTO sortDTO = super.getNodeSortDTO(
|
||||
super.getNodeMoveRequest(request),
|
||||
MoveNodeSortDTO sortDTO = super.getNodeSortDTO(
|
||||
request.getTestPlanId(),
|
||||
super.getNodeMoveRequest(request, true),
|
||||
extTestPlanFunctionalCaseMapper::selectDragInfoById,
|
||||
extTestPlanFunctionalCaseMapper::selectNodeByPosOperator
|
||||
);
|
||||
|
|
|
@ -1,8 +1,93 @@
|
|||
package io.metersphere.plan.service;
|
||||
|
||||
import io.metersphere.plan.domain.TestPlan;
|
||||
import io.metersphere.plan.domain.TestPlanConfig;
|
||||
import io.metersphere.plan.domain.TestPlanExample;
|
||||
import io.metersphere.plan.mapper.ExtTestPlanMapper;
|
||||
import io.metersphere.plan.mapper.TestPlanMapper;
|
||||
import io.metersphere.project.dto.MoveNodeSortDTO;
|
||||
import io.metersphere.sdk.constants.TestPlanConstants;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.dto.sdk.enums.MoveTypeEnum;
|
||||
import io.metersphere.system.dto.sdk.request.PosRequest;
|
||||
import io.metersphere.system.utils.ServiceUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
public interface TestPlanGroupService {
|
||||
boolean validateGroup(TestPlan testPlan, TestPlanConfig testPlanConfig);
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class TestPlanGroupService extends TestPlanSortService {
|
||||
|
||||
@Resource
|
||||
private TestPlanMapper testPlanMapper;
|
||||
@Resource
|
||||
private ExtTestPlanMapper extTestPlanMapper;
|
||||
|
||||
@Override
|
||||
public long getNextOrder(String groupId) {
|
||||
long maxPos = extTestPlanMapper.selectMaxPosByGroupId(groupId);
|
||||
return maxPos + ServiceUtils.POS_STEP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePos(String id, long pos) {
|
||||
TestPlan testPlan = new TestPlan();
|
||||
testPlan.setId(id);
|
||||
testPlan.setPos(pos);
|
||||
testPlanMapper.updateByPrimaryKeySelective(testPlan);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshPos(String groupId) {
|
||||
TestPlanExample testPlanExample = new TestPlanExample();
|
||||
testPlanExample.createCriteria().andGroupIdEqualTo(groupId);
|
||||
testPlanExample.setOrderByClause("pos asc");
|
||||
List<TestPlan> testPlans = testPlanMapper.selectByExample(testPlanExample);
|
||||
long pos = 1;
|
||||
for (TestPlan testPlanItem : testPlans) {
|
||||
this.updatePos(testPlanItem.getId(), pos * ServiceUtils.POS_STEP);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
public void sort(PosRequest request) {
|
||||
TestPlan dropPlan = testPlanMapper.selectByPrimaryKey(request.getMoveId());
|
||||
TestPlan targetPlan = testPlanMapper.selectByPrimaryKey(request.getTargetId());
|
||||
|
||||
// 校验排序的参数 (暂时不支持测试计划的移入移出)
|
||||
validateMoveRequest(dropPlan, targetPlan, request.getMoveMode());
|
||||
MoveNodeSortDTO sortDTO = super.getNodeSortDTO(
|
||||
targetPlan.getGroupId(),
|
||||
this.getNodeMoveRequest(request, false),
|
||||
extTestPlanMapper::selectDragInfoById,
|
||||
extTestPlanMapper::selectNodeByPosOperator
|
||||
);
|
||||
|
||||
this.sort(sortDTO);
|
||||
}
|
||||
|
||||
private void validateMoveRequest(TestPlan dropPlan, TestPlan targetPlan, String moveType) {
|
||||
//测试计划组不能进行移动操作
|
||||
if (dropPlan == null || StringUtils.equalsIgnoreCase(dropPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
|
||||
throw new MSException(Translator.get("test_plan.drag.node.error"));
|
||||
}
|
||||
if (targetPlan == null || StringUtils.equalsIgnoreCase(targetPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
|
||||
throw new MSException(Translator.get("test_plan.drag.node.error"));
|
||||
}
|
||||
if (StringUtils.equalsIgnoreCase(MoveTypeEnum.APPEND.name(), moveType)) {
|
||||
if (!StringUtils.equalsIgnoreCase(targetPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
|
||||
throw new MSException(Translator.get("test_plan.drag.node.error"));
|
||||
}
|
||||
} else if (StringUtils.equalsAnyIgnoreCase(moveType, MoveTypeEnum.BEFORE.name(), MoveTypeEnum.AFTER.name())) {
|
||||
if (StringUtils.equalsAny(TestPlanConstants.TEST_PLAN_TYPE_GROUP, dropPlan.getType())) {
|
||||
throw new MSException(Translator.get("test_plan.drag.node.error"));
|
||||
}
|
||||
} else {
|
||||
throw new MSException(Translator.get("test_plan.drag.position.error"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import io.metersphere.sdk.constants.HttpMethodConstants;
|
|||
import io.metersphere.sdk.constants.TestPlanConstants;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.dto.LogInsertModule;
|
||||
import io.metersphere.system.dto.builder.LogDTOBuilder;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
|
@ -245,4 +246,22 @@ public class TestPlanLogService {
|
|||
}
|
||||
return dtoList;
|
||||
}
|
||||
|
||||
public void saveMoveLog(TestPlan testPlan, String moveId, LogInsertModule logInsertModule) {
|
||||
|
||||
Project project = projectMapper.selectByPrimaryKey(testPlan.getProjectId());
|
||||
LogDTO dto = LogDTOBuilder.builder()
|
||||
.projectId(testPlan.getProjectId())
|
||||
.organizationId(project.getOrganizationId())
|
||||
.type(OperationLogType.UPDATE.name())
|
||||
.module(logModule)
|
||||
.method(logInsertModule.getRequestMethod())
|
||||
.path(logInsertModule.getRequestUrl())
|
||||
.sourceId(moveId)
|
||||
.content(Translator.get("log.test_plan.move.test_plan") + ":" + testPlan.getName() + StringUtils.SPACE)
|
||||
.createUser(logInsertModule.getOperator())
|
||||
.build().getLogDTO();
|
||||
operationLogService.add(dto);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -55,9 +55,6 @@ public class TestPlanManagementService {
|
|||
|
||||
/**
|
||||
* 测试计划列表查询
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public Pager<List<TestPlanResponse>> page(TestPlanTableRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
|
||||
|
@ -73,8 +70,6 @@ public class TestPlanManagementService {
|
|||
|
||||
/**
|
||||
* 计划组子节点
|
||||
*
|
||||
* @param testPlanResponses
|
||||
*/
|
||||
private void handChildren(List<TestPlanResponse> testPlanResponses, String projectId) {
|
||||
List<String> groupIds = testPlanResponses.stream().filter(item -> StringUtils.equals(item.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)).map(TestPlanResponse::getId).toList();
|
||||
|
|
|
@ -1,57 +1,33 @@
|
|||
package io.metersphere.plan.service;
|
||||
|
||||
import io.metersphere.plan.domain.TestPlan;
|
||||
import io.metersphere.plan.dto.AssociationNode;
|
||||
import io.metersphere.plan.dto.AssociationNodeSortDTO;
|
||||
import io.metersphere.plan.dto.ResourceLogInsertModule;
|
||||
import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
|
||||
import io.metersphere.plan.dto.request.BasePlanCaseBatchRequest;
|
||||
import io.metersphere.plan.dto.response.TestPlanAssociationResponse;
|
||||
import io.metersphere.plan.mapper.TestPlanMapper;
|
||||
import io.metersphere.project.dto.ModuleSortCountResultDTO;
|
||||
import io.metersphere.project.dto.NodeSortQueryParam;
|
||||
import io.metersphere.project.service.MoveNodeService;
|
||||
import io.metersphere.project.utils.NodeSortUtils;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.dto.LogInsertModule;
|
||||
import io.metersphere.system.dto.sdk.request.NodeMoveRequest;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
//测试计划关联表 通用方法
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public abstract class TestPlanResourceService extends MoveNodeService {
|
||||
|
||||
@Resource
|
||||
private TestPlanMapper testPlanMapper;
|
||||
@Resource
|
||||
private TestPlanResourceLogService testPlanResourceLogService;
|
||||
|
||||
protected static final long DEFAULT_NODE_INTERVAL_POS = NodeSortUtils.DEFAULT_NODE_INTERVAL_POS;
|
||||
|
||||
public abstract void updatePos(String id, long pos);
|
||||
|
||||
public abstract void refreshPos(String testPlanId);
|
||||
public abstract class TestPlanResourceService extends TestPlanSortService {
|
||||
|
||||
public abstract void deleteBatchByTestPlanId(List<String> testPlanIdList);
|
||||
|
||||
public abstract Map<String, Long> caseExecResultCount(String testPlanId);
|
||||
|
||||
private static final String MOVE_POS_OPERATOR_LESS = "lessThan";
|
||||
private static final String MOVE_POS_OPERATOR_MORE = "moreThan";
|
||||
private static final String DRAG_NODE_NOT_EXIST = "drag_node.not.exist";
|
||||
|
||||
@Resource
|
||||
private TestPlanMapper testPlanMapper;
|
||||
@Resource
|
||||
private TestPlanResourceLogService testPlanResourceLogService;
|
||||
|
||||
/**
|
||||
* 取消关联资源od
|
||||
|
@ -75,73 +51,4 @@ public abstract class TestPlanResourceService extends MoveNodeService {
|
|||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建节点排序的参数
|
||||
*
|
||||
* @param request 拖拽的前端请求参数
|
||||
* @param selectIdNodeFunc 通过id查询节点的函数
|
||||
* @param selectPosNodeFunc 通过parentId和pos运算符查询节点的函数
|
||||
* @return
|
||||
*/
|
||||
public AssociationNodeSortDTO getNodeSortDTO(NodeMoveRequest request, String testPlanId, Function<String, AssociationNode> selectIdNodeFunc, Function<NodeSortQueryParam, AssociationNode> selectPosNodeFunc) {
|
||||
if (StringUtils.equals(request.getDragNodeId(), request.getDropNodeId())) {
|
||||
//两种节点不能一样
|
||||
throw new MSException(Translator.get("invalid_parameter") + ": drag node and drop node");
|
||||
}
|
||||
|
||||
AssociationNode dragNode = selectIdNodeFunc.apply(request.getDragNodeId());
|
||||
if (dragNode == null) {
|
||||
throw new MSException(Translator.get(DRAG_NODE_NOT_EXIST) + ":" + request.getDragNodeId());
|
||||
}
|
||||
|
||||
AssociationNode dropNode = selectIdNodeFunc.apply(request.getDropNodeId());
|
||||
if (dropNode == null) {
|
||||
throw new MSException(Translator.get(DRAG_NODE_NOT_EXIST) + ":" + request.getDropNodeId());
|
||||
}
|
||||
|
||||
AssociationNode previousNode;
|
||||
AssociationNode nextNode;
|
||||
|
||||
if (request.getDropPosition() == 1) {
|
||||
//dropPosition=1: 放到dropNode节点后,原dropNode后面的节点之前
|
||||
previousNode = dropNode;
|
||||
|
||||
NodeSortQueryParam sortParam = new NodeSortQueryParam();
|
||||
sortParam.setParentId(testPlanId);
|
||||
sortParam.setPos(previousNode.getPos());
|
||||
sortParam.setOperator(MOVE_POS_OPERATOR_MORE);
|
||||
nextNode = selectPosNodeFunc.apply(sortParam);
|
||||
} else if (request.getDropPosition() == -1) {
|
||||
//dropPosition=-1: 放到dropNode节点前,原dropNode前面的节点之后
|
||||
nextNode = dropNode;
|
||||
NodeSortQueryParam sortParam = new NodeSortQueryParam();
|
||||
sortParam.setPos(nextNode.getPos());
|
||||
sortParam.setParentId(testPlanId);
|
||||
sortParam.setOperator(MOVE_POS_OPERATOR_LESS);
|
||||
previousNode = selectPosNodeFunc.apply(sortParam);
|
||||
} else {
|
||||
throw new MSException(Translator.get("invalid_parameter") + ": dropPosition");
|
||||
}
|
||||
|
||||
return new AssociationNodeSortDTO(testPlanId, dragNode, previousNode, nextNode);
|
||||
}
|
||||
|
||||
//排序
|
||||
public void sort(AssociationNodeSortDTO sortDTO) {
|
||||
|
||||
// 获取相邻节点
|
||||
AssociationNode previousNode = sortDTO.getPreviousNode();
|
||||
AssociationNode nextNode = sortDTO.getNextNode();
|
||||
|
||||
ModuleSortCountResultDTO countResultDTO = NodeSortUtils.countModuleSort(
|
||||
previousNode == null ? -1 : previousNode.getPos(),
|
||||
nextNode == null ? -1 : nextNode.getPos());
|
||||
|
||||
updatePos(sortDTO.getSortNode().getId(), countResultDTO.getPos());
|
||||
if (countResultDTO.isRefreshPos()) {
|
||||
refreshPos(sortDTO.getTestPlanId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.metersphere.plan.service;
|
|||
import io.metersphere.plan.domain.*;
|
||||
import io.metersphere.plan.dto.request.*;
|
||||
import io.metersphere.plan.dto.response.TestPlanDetailResponse;
|
||||
import io.metersphere.plan.dto.response.TestPlanResourceSortResponse;
|
||||
import io.metersphere.plan.mapper.*;
|
||||
import io.metersphere.sdk.constants.*;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
|
@ -13,6 +14,8 @@ import io.metersphere.sdk.util.Translator;
|
|||
import io.metersphere.system.domain.ScheduleExample;
|
||||
import io.metersphere.system.domain.TestPlanModuleExample;
|
||||
import io.metersphere.system.domain.User;
|
||||
import io.metersphere.system.dto.LogInsertModule;
|
||||
import io.metersphere.system.dto.sdk.request.PosRequest;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.mapper.ScheduleMapper;
|
||||
import io.metersphere.system.mapper.TestPlanModuleMapper;
|
||||
|
@ -49,6 +52,8 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
@Resource
|
||||
private ExtTestPlanMapper extTestPlanMapper;
|
||||
@Resource
|
||||
private TestPlanGroupService testPlanGroupService;
|
||||
@Resource
|
||||
private TestPlanConfigMapper testPlanConfigMapper;
|
||||
@Resource
|
||||
private TestPlanLogService testPlanLogService;
|
||||
|
@ -82,12 +87,6 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
|
||||
/**
|
||||
* 创建测试计划
|
||||
*
|
||||
* @param testPlanCreateRequest
|
||||
* @param operator
|
||||
* @param requestUrl
|
||||
* @param requestMethod
|
||||
* @return
|
||||
*/
|
||||
public TestPlan add(TestPlanCreateRequest testPlanCreateRequest, String operator, String requestUrl, String requestMethod) {
|
||||
TestPlan testPlan = savePlanDTO(testPlanCreateRequest, operator, null);
|
||||
|
@ -108,8 +107,7 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
checkModule(createOrCopyRequest.getModuleId());
|
||||
TestPlan createTestPlan = new TestPlan();
|
||||
BeanUtils.copyBean(createTestPlan, createOrCopyRequest);
|
||||
// 5.21,查询需求文档、测试用例:测试计划名称允许重复
|
||||
// validateTestPlan(createTestPlan);
|
||||
initTestPlanPos(createTestPlan);
|
||||
|
||||
createTestPlan.setId(IDGenerator.nextStr());
|
||||
long operateTime = System.currentTimeMillis();
|
||||
|
@ -138,6 +136,22 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
return createTestPlan;
|
||||
}
|
||||
|
||||
//校验测试计划
|
||||
private void initTestPlanPos(TestPlan createTestPlan) {
|
||||
if (!StringUtils.equals(createTestPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
|
||||
//如果测试计划组不为NONE,判断是否真实存在并未归档
|
||||
TestPlanExample example = new TestPlanExample();
|
||||
example.createCriteria().andIdEqualTo(createTestPlan.getGroupId()).andStatusNotEqualTo(TEST_PLAN_STATUS_ARCHIVED);
|
||||
if (testPlanMapper.countByExample(example) == 0) {
|
||||
throw new MSException(Translator.get("test_plan.group.error"));
|
||||
} else {
|
||||
createTestPlan.setPos(testPlanGroupService.getNextOrder(createTestPlan.getGroupId()));
|
||||
}
|
||||
} else {
|
||||
createTestPlan.setPos(0L);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除测试计划
|
||||
|
@ -179,6 +193,7 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
private void deleteGroupByList(List<String> testPlanGroupIds) {
|
||||
if (CollectionUtils.isNotEmpty(testPlanGroupIds)) {
|
||||
TestPlanReportService testPlanReportService = CommonBeanFactory.getBean(TestPlanReportService.class);
|
||||
assert testPlanReportService != null;
|
||||
BatchProcessUtils.consumerByString(testPlanGroupIds, (deleteGroupIds) -> {
|
||||
/*
|
||||
* 计划组删除逻辑{第一版需求: 删除组, 组下的子计划Group置为None}:
|
||||
|
@ -189,12 +204,13 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
testPlanExample.createCriteria().andGroupIdIn(deleteGroupIds);
|
||||
List<TestPlan> deleteGroupPlans = testPlanMapper.selectByExample(testPlanExample);
|
||||
List<String> deleteGroupPlanIds = deleteGroupPlans.stream().map(TestPlan::getId).toList();
|
||||
if (CollectionUtils.isNotEmpty(deleteGroupPlanIds)) {
|
||||
// 级联删除子计划关联的资源(计划组不存在关联的资源)
|
||||
List<String> allDeleteIds = ListUtils.union(deleteGroupIds, deleteGroupPlanIds);
|
||||
if (CollectionUtils.isNotEmpty(allDeleteIds)) {
|
||||
// 级联删除子计划关联的资源(计划组不存在关联的资源,但是存在报告)
|
||||
this.cascadeDeleteTestPlanIds(deleteGroupPlanIds, testPlanReportService);
|
||||
}
|
||||
testPlanExample.clear();
|
||||
testPlanExample.createCriteria().andIdIn(ListUtils.union(deleteGroupIds, deleteGroupPlanIds));
|
||||
testPlanExample.createCriteria().andIdIn(allDeleteIds);
|
||||
testPlanMapper.deleteByExample(testPlanExample);
|
||||
});
|
||||
}
|
||||
|
@ -275,12 +291,6 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
|
||||
/**
|
||||
* 更新测试计划
|
||||
*
|
||||
* @param request
|
||||
* @param userId
|
||||
* @param requestUrl
|
||||
* @param requestMethod
|
||||
* @return
|
||||
*/
|
||||
public TestPlan update(TestPlanUpdateRequest request, String userId, String requestUrl, String requestMethod) {
|
||||
this.checkTestPlanNotArchived(request.getId());
|
||||
|
@ -296,8 +306,6 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
if (StringUtils.isNotBlank(request.getName())) {
|
||||
updateTestPlan.setName(request.getName());
|
||||
updateTestPlan.setProjectId(testPlan.getProjectId());
|
||||
// 5.21,查询需求文档、测试用例:测试计划名称允许重复
|
||||
// validateTestPlan(updateTestPlan);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(request.getTags())) {
|
||||
updateTestPlan.setTags(new ArrayList<>(request.getTags()));
|
||||
|
@ -706,4 +714,11 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
testPlan.setStatus(testPlanFinalStatus);
|
||||
testPlanMapper.updateByPrimaryKeySelective(testPlan);
|
||||
}
|
||||
|
||||
public TestPlanResourceSortResponse sortInGroup(PosRequest request, LogInsertModule logInsertModule) {
|
||||
testPlanGroupService.sort(request);
|
||||
testPlanLogService.saveMoveLog(testPlanMapper.selectByPrimaryKey(request.getMoveId()), request.getMoveId(), logInsertModule);
|
||||
return new TestPlanResourceSortResponse(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
package io.metersphere.plan.service;
|
||||
|
||||
import io.metersphere.project.service.MoveNodeService;
|
||||
import io.metersphere.project.utils.NodeSortUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
//测试计划关联表 通用方法
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public abstract class TestPlanSortService extends MoveNodeService {
|
||||
|
||||
protected static final long DEFAULT_NODE_INTERVAL_POS = NodeSortUtils.DEFAULT_NODE_INTERVAL_POS;
|
||||
|
||||
public abstract void updatePos(String id, long pos);
|
||||
|
||||
public abstract void refreshPos(String testPlanId);
|
||||
|
||||
private static final String MOVE_POS_OPERATOR_LESS = "lessThan";
|
||||
private static final String MOVE_POS_OPERATOR_MORE = "moreThan";
|
||||
private static final String DRAG_NODE_NOT_EXIST = "drag_node.not.exist";
|
||||
|
||||
/**
|
||||
* 构建节点排序的参数
|
||||
*
|
||||
* @param request 拖拽的前端请求参数
|
||||
* @param selectIdNodeFunc 通过id查询节点的函数
|
||||
* @param selectPosNodeFunc 通过parentId和pos运算符查询节点的函数
|
||||
* @return
|
||||
*/
|
||||
|
||||
|
||||
// public MoveNodeSortDTO getNodeSortDTO(NodeMoveRequest request, String testPlanId, Function<String, DropNode> selectIdNodeFunc, Function<NodeSortQueryParam, DropNode> selectPosNodeFunc) {
|
||||
//
|
||||
//
|
||||
// if (StringUtils.equals(request.getDragNodeId(), request.getDropNodeId())) {
|
||||
// //两种节点不能一样
|
||||
// throw new MSException(Translator.get("invalid_parameter") + ": drag node and drop node");
|
||||
// }
|
||||
//
|
||||
// DropNode dragNode = selectIdNodeFunc.apply(request.getDragNodeId());
|
||||
// if (dragNode == null) {
|
||||
// throw new MSException(Translator.get(DRAG_NODE_NOT_EXIST) + ":" + request.getDragNodeId());
|
||||
// }
|
||||
//
|
||||
// DropNode dropNode = selectIdNodeFunc.apply(request.getDropNodeId());
|
||||
// if (dropNode == null) {
|
||||
// throw new MSException(Translator.get(DRAG_NODE_NOT_EXIST) + ":" + request.getDropNodeId());
|
||||
// }
|
||||
//
|
||||
// DropNode previousNode;
|
||||
// DropNode nextNode;
|
||||
//
|
||||
// if (request.getDropPosition() == 1) {
|
||||
// //dropPosition=1: 放到dropNode节点后,原dropNode后面的节点之前
|
||||
// previousNode = dropNode;
|
||||
//
|
||||
// NodeSortQueryParam sortParam = new NodeSortQueryParam();
|
||||
// sortParam.setParentId(testPlanId);
|
||||
// sortParam.setPos(previousNode.getPos());
|
||||
// sortParam.setOperator(MOVE_POS_OPERATOR_MORE);
|
||||
// nextNode = selectPosNodeFunc.apply(sortParam);
|
||||
// } else if (request.getDropPosition() == -1) {
|
||||
// //dropPosition=-1: 放到dropNode节点前,原dropNode前面的节点之后
|
||||
// nextNode = dropNode;
|
||||
// NodeSortQueryParam sortParam = new NodeSortQueryParam();
|
||||
// sortParam.setPos(nextNode.getPos());
|
||||
// sortParam.setParentId(testPlanId);
|
||||
// sortParam.setOperator(MOVE_POS_OPERATOR_LESS);
|
||||
// previousNode = selectPosNodeFunc.apply(sortParam);
|
||||
// } else {
|
||||
// throw new MSException(Translator.get("invalid_parameter") + ": dropPosition");
|
||||
// }
|
||||
// return new MoveNodeSortDTO(testPlanId, dragNode, previousNode, nextNode);
|
||||
// }
|
||||
|
||||
}
|
|
@ -16,6 +16,7 @@ import io.metersphere.project.domain.Project;
|
|||
import io.metersphere.project.dto.filemanagement.request.FileModuleCreateRequest;
|
||||
import io.metersphere.project.dto.filemanagement.request.FileModuleUpdateRequest;
|
||||
import io.metersphere.sdk.constants.*;
|
||||
import io.metersphere.sdk.util.BeanUtils;
|
||||
import io.metersphere.sdk.util.CommonBeanFactory;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.base.BaseTest;
|
||||
|
@ -26,6 +27,7 @@ import io.metersphere.system.dto.AddProjectRequest;
|
|||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||
import io.metersphere.system.dto.sdk.enums.MoveTypeEnum;
|
||||
import io.metersphere.system.dto.sdk.request.NodeMoveRequest;
|
||||
import io.metersphere.system.dto.sdk.request.PosRequest;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.mapper.TestPlanModuleMapper;
|
||||
|
@ -106,6 +108,7 @@ public class TestPlanTests extends BaseTest {
|
|||
private static final String URL_POST_TEST_PLAN_STATISTICS = "/test-plan/statistics";
|
||||
private static final String URL_POST_TEST_PLAN_MODULE_COUNT = "/test-plan/module/count";
|
||||
private static final String URL_POST_TEST_PLAN_ADD = "/test-plan/add";
|
||||
private static final String URL_POST_TEST_PLAN_SORT = "/test-plan/sort";
|
||||
private static final String URL_POST_TEST_PLAN_UPDATE = "/test-plan/update";
|
||||
private static final String URL_POST_TEST_PLAN_BATCH_DELETE = "/test-plan/batch-delete";
|
||||
|
||||
|
@ -136,7 +139,7 @@ public class TestPlanTests extends BaseTest {
|
|||
|
||||
@BeforeEach
|
||||
public void initTestData() {
|
||||
//文件管理专用项目
|
||||
//测试计划专用项目
|
||||
if (project == null) {
|
||||
AddProjectRequest initProject = new AddProjectRequest();
|
||||
initProject.setOrganizationId("100001");
|
||||
|
@ -607,7 +610,6 @@ public class TestPlanTests extends BaseTest {
|
|||
request.setType(TestPlanConstants.TEST_PLAN_TYPE_PLAN);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
抽查:
|
||||
testPlan_13没有设置计划开始时间、没有设置重复添加用例和自动更新状态、阈值为100、描述为空;
|
||||
|
@ -681,25 +683,133 @@ public class TestPlanTests extends BaseTest {
|
|||
request.setPassThreshold(100);
|
||||
this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ_ADD, URL_POST_TEST_PLAN_ADD, request);
|
||||
|
||||
|
||||
this.checkTestPlanSortInGroup(groupTestPlanId7);
|
||||
}
|
||||
|
||||
protected void checkTestPlanSortInGroup(String groupTestPlanId7) throws Exception {
|
||||
/*
|
||||
排序校验用例设计:
|
||||
1.第一个移动到最后一个。
|
||||
2.最后一个移动到第一个(还原为原来的顺序)
|
||||
3.第三个移动到第二个
|
||||
4.修改第一个和第二个之间的pos差小于2,将第三个移动到第二个(还原为原来的顺序),并检查pos有没有初始化
|
||||
*/
|
||||
|
||||
TestPlanExample example = new TestPlanExample();
|
||||
example.createCriteria().andGroupIdEqualTo(groupTestPlanId7);
|
||||
example.setOrderByClause("pos asc");
|
||||
List<TestPlan> defaultTestPlanInGroup = testPlanMapper.selectByExample(example);
|
||||
List<TestPlan> lastTestPlanInGroup = defaultTestPlanInGroup;
|
||||
TestPlan movePlan, targetPlan = null;
|
||||
PosRequest posRequest = null;
|
||||
TestPlanResourceSortResponse response = null;
|
||||
|
||||
// 第一个移动到最后一个
|
||||
movePlan = lastTestPlanInGroup.getFirst();
|
||||
targetPlan = lastTestPlanInGroup.getLast();
|
||||
posRequest = new PosRequest(project.getId(), movePlan.getId(), targetPlan.getId(), MoveTypeEnum.AFTER.name());
|
||||
response = JSON.parseObject(
|
||||
JSON.toJSONString(
|
||||
JSON.parseObject(
|
||||
this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_SORT, posRequest)
|
||||
.getResponse().getContentAsString(), ResultHolder.class).getData()),
|
||||
TestPlanResourceSortResponse.class);
|
||||
//位置校验
|
||||
List<TestPlan> newTestPlanInGroup = testPlanMapper.selectByExample(example);
|
||||
Assertions.assertEquals(response.getSortNodeNum(), 1);
|
||||
Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size());
|
||||
for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) {
|
||||
int oldListIndex = newListIndex == newTestPlanInGroup.size() - 1 ? 0 : newListIndex + 1;
|
||||
Assertions.assertEquals(newTestPlanInGroup.get(newListIndex).getId(), lastTestPlanInGroup.get(oldListIndex).getId());
|
||||
}
|
||||
lastTestPlanInGroup = newTestPlanInGroup;
|
||||
|
||||
// 最后一个移动到第一个 (还原为原来的顺序)
|
||||
movePlan = lastTestPlanInGroup.getLast();
|
||||
targetPlan = lastTestPlanInGroup.getFirst();
|
||||
posRequest = new PosRequest(project.getId(), movePlan.getId(), targetPlan.getId(), MoveTypeEnum.BEFORE.name());
|
||||
response = JSON.parseObject(
|
||||
JSON.toJSONString(
|
||||
JSON.parseObject(
|
||||
this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_SORT, posRequest)
|
||||
.getResponse().getContentAsString(), ResultHolder.class).getData()),
|
||||
TestPlanResourceSortResponse.class);
|
||||
//位置校验
|
||||
newTestPlanInGroup = testPlanMapper.selectByExample(example);
|
||||
Assertions.assertEquals(response.getSortNodeNum(), 1);
|
||||
Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size());
|
||||
for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) {
|
||||
Assertions.assertEquals(newTestPlanInGroup.get(newListIndex).getId(), defaultTestPlanInGroup.get(newListIndex).getId());
|
||||
}
|
||||
lastTestPlanInGroup = newTestPlanInGroup;
|
||||
|
||||
// 第三个移动到第二个
|
||||
movePlan = lastTestPlanInGroup.get(2);
|
||||
targetPlan = lastTestPlanInGroup.get(1);
|
||||
posRequest = new PosRequest(project.getId(), movePlan.getId(), targetPlan.getId(), MoveTypeEnum.BEFORE.name());
|
||||
response = JSON.parseObject(
|
||||
JSON.toJSONString(
|
||||
JSON.parseObject(
|
||||
this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_SORT, posRequest)
|
||||
.getResponse().getContentAsString(), ResultHolder.class).getData()),
|
||||
TestPlanResourceSortResponse.class);
|
||||
//位置校验
|
||||
newTestPlanInGroup = testPlanMapper.selectByExample(example);
|
||||
Assertions.assertEquals(response.getSortNodeNum(), 1);
|
||||
Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size());
|
||||
for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) {
|
||||
int oldListIndex = newListIndex;
|
||||
if (oldListIndex == 1) {
|
||||
oldListIndex = 2;
|
||||
} else if (oldListIndex == 2) {
|
||||
oldListIndex = 1;
|
||||
}
|
||||
Assertions.assertEquals(newTestPlanInGroup.get(newListIndex).getId(), lastTestPlanInGroup.get(oldListIndex).getId());
|
||||
}
|
||||
lastTestPlanInGroup = newTestPlanInGroup;
|
||||
|
||||
// 修改第一个和第二个之间的pos差为2(拖拽的最小pos差),将第三个移动到第二个(换回来),然后检查pos有没有变化
|
||||
movePlan = lastTestPlanInGroup.get(2);
|
||||
targetPlan = lastTestPlanInGroup.get(1);
|
||||
targetPlan.setPos(lastTestPlanInGroup.get(0).getPos() + 2);
|
||||
testPlanMapper.updateByPrimaryKey(targetPlan);
|
||||
|
||||
posRequest = new PosRequest(project.getId(), movePlan.getId(), targetPlan.getId(), MoveTypeEnum.BEFORE.name());
|
||||
response = JSON.parseObject(
|
||||
JSON.toJSONString(
|
||||
JSON.parseObject(
|
||||
this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_SORT, posRequest)
|
||||
.getResponse().getContentAsString(), ResultHolder.class).getData()),
|
||||
TestPlanResourceSortResponse.class);
|
||||
//位置校验
|
||||
newTestPlanInGroup = testPlanMapper.selectByExample(example);
|
||||
Assertions.assertEquals(response.getSortNodeNum(), 1);
|
||||
Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size());
|
||||
long lastPos = 0;
|
||||
for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) {
|
||||
Assertions.assertEquals(newTestPlanInGroup.get(newListIndex).getId(), defaultTestPlanInGroup.get(newListIndex).getId());
|
||||
Assertions.assertTrue(newTestPlanInGroup.get(newListIndex).getPos() > (lastPos + 1));
|
||||
lastPos = newTestPlanInGroup.get(newListIndex).getPos();
|
||||
}
|
||||
}
|
||||
@Test
|
||||
@Order(12)
|
||||
public void testPlanPageCountTest() throws Exception {
|
||||
TestPlanTableRequest testPlanTableRequest = new TestPlanTableRequest();
|
||||
testPlanTableRequest.setProjectId(project.getId());
|
||||
testPlanTableRequest.setType("ALL");
|
||||
testPlanTableRequest.setPageSize(10);
|
||||
testPlanTableRequest.setCurrent(1);
|
||||
TestPlanTableRequest dataRequest = new TestPlanTableRequest();
|
||||
dataRequest.setProjectId(project.getId());
|
||||
dataRequest.setType("ALL");
|
||||
dataRequest.setPageSize(10);
|
||||
dataRequest.setCurrent(1);
|
||||
|
||||
//测试项目没有开启测试计划模块时能否使用
|
||||
testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "testPlan");
|
||||
this.requestPost(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest).andExpect(status().is5xxServerError());
|
||||
this.requestPost(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest).andExpect(status().is5xxServerError());
|
||||
this.requestPost(URL_POST_TEST_PLAN_MODULE_COUNT, dataRequest).andExpect(status().is5xxServerError());
|
||||
this.requestPost(URL_POST_TEST_PLAN_MODULE_COUNT, dataRequest).andExpect(status().is5xxServerError());
|
||||
//恢复
|
||||
testPlanTestService.resetProjectModule(project, PROJECT_MODULE);
|
||||
|
||||
MvcResult moduleCountResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest);
|
||||
MvcResult moduleCountResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_MODULE_COUNT, dataRequest);
|
||||
String moduleCountReturnData = moduleCountResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
Map<String, Object> moduleCountMap = JSON.parseObject(JSON.toJSONString(JSON.parseObject(moduleCountReturnData, ResultHolder.class).getData()), Map.class);
|
||||
AtomicBoolean testPlanIsEmpty = new AtomicBoolean(true);
|
||||
|
@ -711,11 +821,19 @@ public class TestPlanTests extends BaseTest {
|
|||
}
|
||||
|
||||
if (testPlanIsEmpty.get()) {
|
||||
//如果没有数据,先创建999条再调用这个方法
|
||||
//如果没有数据,先创建再调用这个方法
|
||||
this.testPlanAddTest();
|
||||
this.testPlanPageCountTest();
|
||||
} else {
|
||||
//this.checkModuleCount(moduleCountMap, a1NodeCount, a2NodeCount, a3NodeCount, a1a1NodeCount, a1b1NodeCount);
|
||||
//只查询组
|
||||
TestPlanTableRequest groupRequest = new TestPlanTableRequest();
|
||||
//查询游离态测试计划
|
||||
TestPlanTableRequest onlyPlanRequest = new TestPlanTableRequest();
|
||||
BeanUtils.copyBean(groupRequest, dataRequest);
|
||||
BeanUtils.copyBean(onlyPlanRequest, dataRequest);
|
||||
groupRequest.setType(TestPlanConstants.TEST_PLAN_TYPE_GROUP);
|
||||
onlyPlanRequest.setType(TestPlanConstants.TEST_PLAN_TYPE_PLAN);
|
||||
|
||||
|
||||
BaseTreeNode a1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1");
|
||||
BaseTreeNode a2Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a2");
|
||||
|
@ -724,96 +842,82 @@ public class TestPlanTests extends BaseTest {
|
|||
BaseTreeNode a1b1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1-b1");
|
||||
assert a1Node != null & a2Node != null & a3Node != null & a1a1Node != null & a1b1Node != null;
|
||||
|
||||
//查询测试计划列表
|
||||
MvcResult pageResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest);
|
||||
String returnData = pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
Pager<Object> result = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
|
||||
//返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(result.getCurrent(), testPlanTableRequest.getCurrent());
|
||||
//返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(result.getList())).size() <= testPlanTableRequest.getPageSize());
|
||||
Assertions.assertEquals(result.getTotal(), 1010);
|
||||
testPlanTestService.checkTestPlanPage(this.requestPostWithOkAndReturn(
|
||||
URL_POST_TEST_PLAN_PAGE, dataRequest).getResponse().getContentAsString(StandardCharsets.UTF_8),
|
||||
dataRequest.getCurrent(),
|
||||
dataRequest.getPageSize(),
|
||||
1010);
|
||||
testPlanTestService.checkTestPlanPage(this.requestPostWithOkAndReturn(
|
||||
URL_POST_TEST_PLAN_PAGE, groupRequest).getResponse().getContentAsString(StandardCharsets.UTF_8),
|
||||
dataRequest.getCurrent(),
|
||||
dataRequest.getPageSize(),
|
||||
2);
|
||||
testPlanTestService.checkTestPlanPage(this.requestPostWithOkAndReturn(
|
||||
URL_POST_TEST_PLAN_PAGE, onlyPlanRequest).getResponse().getContentAsString(StandardCharsets.UTF_8),
|
||||
dataRequest.getCurrent(),
|
||||
dataRequest.getPageSize(),
|
||||
1008);
|
||||
|
||||
//按照名称倒叙
|
||||
testPlanTableRequest.setSort(new HashMap<>() {{
|
||||
dataRequest.setSort(new HashMap<>() {{
|
||||
this.put("name", "desc");
|
||||
}});
|
||||
pageResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest);
|
||||
returnData = pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
result = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
|
||||
//返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(result.getCurrent(), testPlanTableRequest.getCurrent());
|
||||
//返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(result.getList())).size() <= testPlanTableRequest.getPageSize());
|
||||
Assertions.assertEquals(result.getTotal(), 1010);
|
||||
testPlanTestService.checkTestPlanPage(this.requestPostWithOkAndReturn(
|
||||
URL_POST_TEST_PLAN_PAGE, dataRequest).getResponse().getContentAsString(StandardCharsets.UTF_8),
|
||||
dataRequest.getCurrent(),
|
||||
dataRequest.getPageSize(),
|
||||
1010);
|
||||
|
||||
|
||||
//指定模块ID查询 (查询count时,不会因为选择了模块而更改了总量
|
||||
testPlanTableRequest.setModuleIds(Arrays.asList(a1Node.getId(), a1a1Node.getId(), a1b1Node.getId()));
|
||||
moduleCountResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest);
|
||||
dataRequest.setModuleIds(Arrays.asList(a1Node.getId(), a1a1Node.getId(), a1b1Node.getId()));
|
||||
moduleCountResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_MODULE_COUNT, dataRequest);
|
||||
moduleCountReturnData = moduleCountResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
moduleCountMap = JSON.parseObject(JSON.toJSONString(JSON.parseObject(moduleCountReturnData, ResultHolder.class).getData()), Map.class);
|
||||
|
||||
|
||||
pageResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest);
|
||||
returnData = pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
result = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
|
||||
//返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(result.getCurrent(), testPlanTableRequest.getCurrent());
|
||||
//返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(result.getList())).size() <= testPlanTableRequest.getPageSize());
|
||||
|
||||
testPlanTestService.checkTestPlanPage(this.requestPostWithOkAndReturn(
|
||||
URL_POST_TEST_PLAN_PAGE, dataRequest).getResponse().getContentAsString(StandardCharsets.UTF_8),
|
||||
dataRequest.getCurrent(),
|
||||
dataRequest.getPageSize(),
|
||||
910);
|
||||
|
||||
//测试根据名称模糊查询: Plan_2 预期结果: a1Node下有11条(testPlan_2,testPlan_20~testPlan_29), a1b1Node下有100条(testPlan_200~testPlan_299)
|
||||
testPlanTableRequest.setModuleIds(null);
|
||||
testPlanTableRequest.initKeyword("Plan_2");
|
||||
moduleCountResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest);
|
||||
dataRequest.setModuleIds(null);
|
||||
dataRequest.initKeyword("Plan_2");
|
||||
moduleCountResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_MODULE_COUNT, dataRequest);
|
||||
moduleCountReturnData = moduleCountResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
moduleCountMap = JSON.parseObject(JSON.toJSONString(JSON.parseObject(moduleCountReturnData, ResultHolder.class).getData()), Map.class);
|
||||
|
||||
|
||||
pageResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest);
|
||||
returnData = pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
result = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
|
||||
//返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(result.getCurrent(), testPlanTableRequest.getCurrent());
|
||||
//返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(result.getList())).size() <= testPlanTableRequest.getPageSize());
|
||||
|
||||
long allSize = Long.parseLong(String.valueOf(moduleCountMap.get("all")));
|
||||
testPlanTestService.checkTestPlanPage(this.requestPostWithOkAndReturn(
|
||||
URL_POST_TEST_PLAN_PAGE, dataRequest).getResponse().getContentAsString(StandardCharsets.UTF_8),
|
||||
dataRequest.getCurrent(),
|
||||
dataRequest.getPageSize(),
|
||||
allSize);
|
||||
|
||||
//测试根据名称模糊查询(包含测试组的): Plan_7 预期结果: a1Node下有1条(testPlan_7), a2Node下有10条(testPlan_70~testPlan_79),a1b1Node下有100条(testPlan_700~testPlan_799)
|
||||
testPlanTableRequest.initKeyword("Plan_7");
|
||||
testPlanTableRequest.setSort(new HashMap<>() {{
|
||||
dataRequest.initKeyword("Plan_7");
|
||||
dataRequest.setSort(new HashMap<>() {{
|
||||
this.put("num", "asc");
|
||||
}});
|
||||
moduleCountResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest);
|
||||
moduleCountResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_MODULE_COUNT, dataRequest);
|
||||
moduleCountReturnData = moduleCountResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
moduleCountMap = JSON.parseObject(JSON.toJSONString(JSON.parseObject(moduleCountReturnData, ResultHolder.class).getData()), Map.class);
|
||||
|
||||
|
||||
pageResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest);
|
||||
returnData = pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
result = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
|
||||
//返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(result.getCurrent(), testPlanTableRequest.getCurrent());
|
||||
//返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(result.getList())).size() <= testPlanTableRequest.getPageSize());
|
||||
|
||||
allSize = Long.parseLong(String.valueOf(moduleCountMap.get("all")));
|
||||
testPlanTestService.checkTestPlanPage(this.requestPostWithOkAndReturn(
|
||||
URL_POST_TEST_PLAN_PAGE, dataRequest).getResponse().getContentAsString(StandardCharsets.UTF_8),
|
||||
dataRequest.getCurrent(),
|
||||
dataRequest.getPageSize(),
|
||||
allSize);
|
||||
|
||||
//反例:参数校验(项目ID不存在)
|
||||
testPlanTableRequest.setProjectId(null);
|
||||
this.requestPost(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest).andExpect(status().isBadRequest());
|
||||
this.requestPost(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest).andExpect(status().isBadRequest());
|
||||
dataRequest.setProjectId(null);
|
||||
this.requestPost(URL_POST_TEST_PLAN_MODULE_COUNT, dataRequest).andExpect(status().isBadRequest());
|
||||
this.requestPost(URL_POST_TEST_PLAN_PAGE, dataRequest).andExpect(status().isBadRequest());
|
||||
|
||||
//测试权限
|
||||
testPlanTableRequest.setProjectId(DEFAULT_PROJECT_ID);
|
||||
this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ, URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest);
|
||||
this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ, URL_POST_TEST_PLAN_PAGE, testPlanTableRequest);
|
||||
dataRequest.setProjectId(DEFAULT_PROJECT_ID);
|
||||
this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ, URL_POST_TEST_PLAN_MODULE_COUNT, dataRequest);
|
||||
this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ, URL_POST_TEST_PLAN_PAGE, dataRequest);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,9 +16,11 @@ import io.metersphere.project.mapper.ProjectMapper;
|
|||
import io.metersphere.sdk.constants.*;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.sdk.util.SubListUtils;
|
||||
import io.metersphere.system.controller.handler.ResultHolder;
|
||||
import io.metersphere.system.domain.TestPlanModuleExample;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import io.metersphere.system.uid.NumGenerator;
|
||||
import io.metersphere.system.utils.Pager;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -433,4 +435,16 @@ public class TestPlanTestService {
|
|||
|
||||
});
|
||||
}
|
||||
|
||||
public void checkTestPlanPage(String returnData, long current, long pageSize, long allData) {
|
||||
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
Pager<Object> result = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
|
||||
//返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(result.getCurrent(), current);
|
||||
//返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(result.getList())).size() <= pageSize);
|
||||
if (allData > 0) {
|
||||
Assertions.assertEquals(result.getTotal(), allData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
package io.metersphere.plan.service.mock;
|
||||
|
||||
import io.metersphere.plan.domain.TestPlan;
|
||||
import io.metersphere.plan.domain.TestPlanConfig;
|
||||
import io.metersphere.plan.service.TestPlanGroupService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class TestPlanGroupServiceImpl implements TestPlanGroupService {
|
||||
|
||||
@Override
|
||||
public boolean validateGroup(TestPlan testPlan, TestPlanConfig testPlanConfig) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue