feat(用例评审): 新增用例评审添加功能

This commit is contained in:
guoyuqi 2023-11-24 09:40:17 +08:00 committed by Craftsman
parent 8f221ee39b
commit 674927efab
23 changed files with 728 additions and 91 deletions

View File

@ -40,6 +40,10 @@ public class CaseReview implements Serializable {
@Size(min = 1, max = 64, message = "{case_review.review_pass_rule.length_range}", groups = {Created.class, Updated.class}) @Size(min = 1, max = 64, message = "{case_review.review_pass_rule.length_range}", groups = {Created.class, Updated.class})
private String reviewPassRule; private String reviewPassRule;
@Schema(description = "自定义排序间隔5000", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "{case_review.pos.not_blank}", groups = {Created.class})
private Long pos;
@Schema(description = "评审开始时间") @Schema(description = "评审开始时间")
private Long startTime; private Long startTime;
@ -73,6 +77,7 @@ public class CaseReview implements Serializable {
projectId("project_id", "projectId", "VARCHAR", false), projectId("project_id", "projectId", "VARCHAR", false),
status("status", "status", "VARCHAR", true), status("status", "status", "VARCHAR", true),
reviewPassRule("review_pass_rule", "reviewPassRule", "VARCHAR", false), reviewPassRule("review_pass_rule", "reviewPassRule", "VARCHAR", false),
pos("pos", "pos", "BIGINT", false),
startTime("start_time", "startTime", "BIGINT", false), startTime("start_time", "startTime", "BIGINT", false),
endTime("end_time", "endTime", "BIGINT", false), endTime("end_time", "endTime", "BIGINT", false),
tags("tags", "tags", "VARCHAR", false), tags("tags", "tags", "VARCHAR", false),

View File

@ -524,6 +524,66 @@ public class CaseReviewExample {
return (Criteria) this; 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 Criteria andStartTimeIsNull() { public Criteria andStartTimeIsNull() {
addCriterion("start_time is null"); addCriterion("start_time is null");
return (Criteria) this; return (Criteria) this;

View File

@ -1,11 +1,8 @@
package io.metersphere.functional.domain; package io.metersphere.functional.domain;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.*;
import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -18,8 +15,7 @@ public class FunctionalCase implements Serializable {
@Size(min = 1, max = 50, message = "{functional_case.id.length_range}", groups = {Created.class, Updated.class}) @Size(min = 1, max = 50, message = "{functional_case.id.length_range}", groups = {Created.class, Updated.class})
private String id; private String id;
@Schema(description = "业务ID", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "业务ID")
@NotNull(message = "{functional_case.num.not_blank}", groups = {Created.class})
private Long num; private Long num;
@Schema(description = "模块ID", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "模块ID", requiredMode = Schema.RequiredMode.REQUIRED)
@ -56,8 +52,7 @@ public class FunctionalCase implements Serializable {
private String caseEditType; private String caseEditType;
@Schema(description = "自定义排序间隔5000", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "自定义排序间隔5000", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{functional_case.pos.not_blank}", groups = {Created.class}) @NotNull(message = "{functional_case.pos.not_blank}", groups = {Created.class})
@Size(min = 1, max = 19, message = "{functional_case.pos.length_range}", groups = {Created.class, Updated.class})
private Long pos; private Long pos;
@Schema(description = "版本ID", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "版本ID", requiredMode = Schema.RequiredMode.REQUIRED)
@ -76,18 +71,15 @@ public class FunctionalCase implements Serializable {
private String lastExecuteResult; private String lastExecuteResult;
@Schema(description = "是否在回收站0-否1-是", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "是否在回收站0-否1-是", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{functional_case.deleted.not_blank}", groups = {Created.class}) @NotNull(message = "{functional_case.deleted.not_blank}", groups = {Created.class})
@Size(min = 1, max = 1, message = "{functional_case.deleted.length_range}", groups = {Created.class, Updated.class})
private Boolean deleted; private Boolean deleted;
@Schema(description = "是否是公共用例0-否1-是", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "是否是公共用例0-否1-是", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{functional_case.public_case.not_blank}", groups = {Created.class}) @NotNull(message = "{functional_case.public_case.not_blank}", groups = {Created.class})
@Size(min = 1, max = 1, message = "{functional_case.public_case.length_range}", groups = {Created.class, Updated.class})
private Boolean publicCase; private Boolean publicCase;
@Schema(description = "是否为最新版本0-否1-是", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "是否为最新版本0-否1-是", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{functional_case.latest.not_blank}", groups = {Created.class}) @NotNull(message = "{functional_case.latest.not_blank}", groups = {Created.class})
@Size(min = 1, max = 1, message = "{functional_case.latest.length_range}", groups = {Created.class, Updated.class})
private Boolean latest; private Boolean latest;
@Schema(description = "创建人") @Schema(description = "创建人")

View File

@ -8,6 +8,7 @@
<result column="project_id" jdbcType="VARCHAR" property="projectId" /> <result column="project_id" jdbcType="VARCHAR" property="projectId" />
<result column="status" jdbcType="VARCHAR" property="status" /> <result column="status" jdbcType="VARCHAR" property="status" />
<result column="review_pass_rule" jdbcType="VARCHAR" property="reviewPassRule" /> <result column="review_pass_rule" jdbcType="VARCHAR" property="reviewPassRule" />
<result column="pos" jdbcType="BIGINT" property="pos" />
<result column="start_time" jdbcType="BIGINT" property="startTime" /> <result column="start_time" jdbcType="BIGINT" property="startTime" />
<result column="end_time" jdbcType="BIGINT" property="endTime" /> <result column="end_time" jdbcType="BIGINT" property="endTime" />
<result column="tags" jdbcType="VARCHAR" property="tags" /> <result column="tags" jdbcType="VARCHAR" property="tags" />
@ -76,7 +77,7 @@
</where> </where>
</sql> </sql>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
id, `name`, module_id, project_id, `status`, review_pass_rule, start_time, end_time, id, `name`, module_id, project_id, `status`, review_pass_rule, pos, start_time, end_time,
tags, description, create_time, create_user, update_time, update_user tags, description, create_time, create_user, update_time, update_user
</sql> </sql>
<select id="selectByExample" parameterType="io.metersphere.functional.domain.CaseReviewExample" resultMap="BaseResultMap"> <select id="selectByExample" parameterType="io.metersphere.functional.domain.CaseReviewExample" resultMap="BaseResultMap">
@ -112,14 +113,16 @@
<insert id="insert" parameterType="io.metersphere.functional.domain.CaseReview"> <insert id="insert" parameterType="io.metersphere.functional.domain.CaseReview">
insert into case_review (id, `name`, module_id, insert into case_review (id, `name`, module_id,
project_id, `status`, review_pass_rule, project_id, `status`, review_pass_rule,
start_time, end_time, tags, pos, start_time, end_time,
description, create_time, create_user, tags, description, create_time,
update_time, update_user) create_user, update_time, update_user
)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{moduleId,jdbcType=VARCHAR}, values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{moduleId,jdbcType=VARCHAR},
#{projectId,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{reviewPassRule,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{reviewPassRule,jdbcType=VARCHAR},
#{startTime,jdbcType=BIGINT}, #{endTime,jdbcType=BIGINT}, #{tags,jdbcType=VARCHAR}, #{pos,jdbcType=BIGINT}, #{startTime,jdbcType=BIGINT}, #{endTime,jdbcType=BIGINT},
#{description,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{createUser,jdbcType=VARCHAR}, #{tags,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
#{updateTime,jdbcType=BIGINT}, #{updateUser,jdbcType=VARCHAR}) #{createUser,jdbcType=VARCHAR}, #{updateTime,jdbcType=BIGINT}, #{updateUser,jdbcType=VARCHAR}
)
</insert> </insert>
<insert id="insertSelective" parameterType="io.metersphere.functional.domain.CaseReview"> <insert id="insertSelective" parameterType="io.metersphere.functional.domain.CaseReview">
insert into case_review insert into case_review
@ -142,6 +145,9 @@
<if test="reviewPassRule != null"> <if test="reviewPassRule != null">
review_pass_rule, review_pass_rule,
</if> </if>
<if test="pos != null">
pos,
</if>
<if test="startTime != null"> <if test="startTime != null">
start_time, start_time,
</if> </if>
@ -186,6 +192,9 @@
<if test="reviewPassRule != null"> <if test="reviewPassRule != null">
#{reviewPassRule,jdbcType=VARCHAR}, #{reviewPassRule,jdbcType=VARCHAR},
</if> </if>
<if test="pos != null">
#{pos,jdbcType=BIGINT},
</if>
<if test="startTime != null"> <if test="startTime != null">
#{startTime,jdbcType=BIGINT}, #{startTime,jdbcType=BIGINT},
</if> </if>
@ -239,6 +248,9 @@
<if test="record.reviewPassRule != null"> <if test="record.reviewPassRule != null">
review_pass_rule = #{record.reviewPassRule,jdbcType=VARCHAR}, review_pass_rule = #{record.reviewPassRule,jdbcType=VARCHAR},
</if> </if>
<if test="record.pos != null">
pos = #{record.pos,jdbcType=BIGINT},
</if>
<if test="record.startTime != null"> <if test="record.startTime != null">
start_time = #{record.startTime,jdbcType=BIGINT}, start_time = #{record.startTime,jdbcType=BIGINT},
</if> </if>
@ -276,6 +288,7 @@
project_id = #{record.projectId,jdbcType=VARCHAR}, project_id = #{record.projectId,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=VARCHAR}, `status` = #{record.status,jdbcType=VARCHAR},
review_pass_rule = #{record.reviewPassRule,jdbcType=VARCHAR}, review_pass_rule = #{record.reviewPassRule,jdbcType=VARCHAR},
pos = #{record.pos,jdbcType=BIGINT},
start_time = #{record.startTime,jdbcType=BIGINT}, start_time = #{record.startTime,jdbcType=BIGINT},
end_time = #{record.endTime,jdbcType=BIGINT}, end_time = #{record.endTime,jdbcType=BIGINT},
tags = #{record.tags,jdbcType=VARCHAR}, tags = #{record.tags,jdbcType=VARCHAR},
@ -306,6 +319,9 @@
<if test="reviewPassRule != null"> <if test="reviewPassRule != null">
review_pass_rule = #{reviewPassRule,jdbcType=VARCHAR}, review_pass_rule = #{reviewPassRule,jdbcType=VARCHAR},
</if> </if>
<if test="pos != null">
pos = #{pos,jdbcType=BIGINT},
</if>
<if test="startTime != null"> <if test="startTime != null">
start_time = #{startTime,jdbcType=BIGINT}, start_time = #{startTime,jdbcType=BIGINT},
</if> </if>
@ -340,6 +356,7 @@
project_id = #{projectId,jdbcType=VARCHAR}, project_id = #{projectId,jdbcType=VARCHAR},
`status` = #{status,jdbcType=VARCHAR}, `status` = #{status,jdbcType=VARCHAR},
review_pass_rule = #{reviewPassRule,jdbcType=VARCHAR}, review_pass_rule = #{reviewPassRule,jdbcType=VARCHAR},
pos = #{pos,jdbcType=BIGINT},
start_time = #{startTime,jdbcType=BIGINT}, start_time = #{startTime,jdbcType=BIGINT},
end_time = #{endTime,jdbcType=BIGINT}, end_time = #{endTime,jdbcType=BIGINT},
tags = #{tags,jdbcType=VARCHAR}, tags = #{tags,jdbcType=VARCHAR},
@ -352,15 +369,17 @@
</update> </update>
<insert id="batchInsert" parameterType="map"> <insert id="batchInsert" parameterType="map">
insert into case_review insert into case_review
(id, `name`, module_id, project_id, `status`, review_pass_rule, start_time, end_time, (id, `name`, module_id, project_id, `status`, review_pass_rule, pos, start_time,
tags, description, create_time, create_user, update_time, update_user) end_time, tags, description, create_time, create_user, update_time, update_user
)
values values
<foreach collection="list" item="item" separator=","> <foreach collection="list" item="item" separator=",">
(#{item.id,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR}, #{item.moduleId,jdbcType=VARCHAR}, (#{item.id,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR}, #{item.moduleId,jdbcType=VARCHAR},
#{item.projectId,jdbcType=VARCHAR}, #{item.status,jdbcType=VARCHAR}, #{item.reviewPassRule,jdbcType=VARCHAR}, #{item.projectId,jdbcType=VARCHAR}, #{item.status,jdbcType=VARCHAR}, #{item.reviewPassRule,jdbcType=VARCHAR},
#{item.startTime,jdbcType=BIGINT}, #{item.endTime,jdbcType=BIGINT}, #{item.tags,jdbcType=VARCHAR}, #{item.pos,jdbcType=BIGINT}, #{item.startTime,jdbcType=BIGINT}, #{item.endTime,jdbcType=BIGINT},
#{item.description,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT}, #{item.createUser,jdbcType=VARCHAR}, #{item.tags,jdbcType=VARCHAR}, #{item.description,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT},
#{item.updateTime,jdbcType=BIGINT}, #{item.updateUser,jdbcType=VARCHAR}) #{item.createUser,jdbcType=VARCHAR}, #{item.updateTime,jdbcType=BIGINT}, #{item.updateUser,jdbcType=VARCHAR}
)
</foreach> </foreach>
</insert> </insert>
<insert id="batchInsertSelective" parameterType="map"> <insert id="batchInsertSelective" parameterType="map">
@ -391,6 +410,9 @@
<if test="'review_pass_rule'.toString() == column.value"> <if test="'review_pass_rule'.toString() == column.value">
#{item.reviewPassRule,jdbcType=VARCHAR} #{item.reviewPassRule,jdbcType=VARCHAR}
</if> </if>
<if test="'pos'.toString() == column.value">
#{item.pos,jdbcType=BIGINT}
</if>
<if test="'start_time'.toString() == column.value"> <if test="'start_time'.toString() == column.value">
#{item.startTime,jdbcType=BIGINT} #{item.startTime,jdbcType=BIGINT}
</if> </if>

View File

@ -40,6 +40,7 @@ CREATE INDEX idx_delete_time ON functional_case (delete_time);
CREATE INDEX idx_update_time ON functional_case (update_time); CREATE INDEX idx_update_time ON functional_case (update_time);
CREATE INDEX idx_num ON functional_case (num); CREATE INDEX idx_num ON functional_case (num);
CREATE INDEX idx_project_id ON functional_case (project_id); CREATE INDEX idx_project_id ON functional_case (project_id);
CREATE INDEX idx_pos ON functional_case(pos);
CREATE TABLE IF NOT EXISTS functional_case_blob CREATE TABLE IF NOT EXISTS functional_case_blob
@ -252,6 +253,7 @@ CREATE TABLE IF NOT EXISTS case_review
`project_id` VARCHAR(50) NOT NULL COMMENT '项目ID', `project_id` VARCHAR(50) NOT NULL COMMENT '项目ID',
`status` VARCHAR(64) NOT NULL DEFAULT 'PREPARE' COMMENT '评审状态:未开始/进行中/已完成/已结束/已归档', `status` VARCHAR(64) NOT NULL DEFAULT 'PREPARE' COMMENT '评审状态:未开始/进行中/已完成/已结束/已归档',
`review_pass_rule` VARCHAR(64) NOT NULL DEFAULT 'SINGLE' COMMENT '通过标准:单人通过/全部通过', `review_pass_rule` VARCHAR(64) NOT NULL DEFAULT 'SINGLE' COMMENT '通过标准:单人通过/全部通过',
`pos` BIGINT NOT NULL DEFAULT 0 COMMENT '自定义排序间隔5000' ,
`start_time` BIGINT COMMENT '评审开始时间', `start_time` BIGINT COMMENT '评审开始时间',
`end_time` BIGINT COMMENT '评审结束时间', `end_time` BIGINT COMMENT '评审结束时间',
`tags` VARCHAR(1000) COMMENT '标签', `tags` VARCHAR(1000) COMMENT '标签',
@ -275,6 +277,7 @@ CREATE INDEX idx_create_time ON case_review (create_time);
CREATE INDEX idx_update_time ON case_review (update_time); CREATE INDEX idx_update_time ON case_review (update_time);
CREATE INDEX idx_update_user ON case_review (update_user); CREATE INDEX idx_update_user ON case_review (update_user);
CREATE INDEX idx_module_id ON case_review (module_id); CREATE INDEX idx_module_id ON case_review (module_id);
CREATE INDEX idx_pos ON case_review(pos);
CREATE TABLE IF NOT EXISTS case_review_user CREATE TABLE IF NOT EXISTS case_review_user
@ -306,6 +309,8 @@ CREATE TABLE IF NOT EXISTS case_review_functional_case
CREATE INDEX idx_case_id ON case_review_functional_case (case_id); CREATE INDEX idx_case_id ON case_review_functional_case (case_id);
CREATE INDEX idx_review_id ON case_review_functional_case (review_id); CREATE INDEX idx_review_id ON case_review_functional_case (review_id);
CREATE INDEX idx_status ON case_review_functional_case (status); CREATE INDEX idx_status ON case_review_functional_case (status);
CREATE INDEX idx_pos ON case_review_functional_case(pos);
CREATE TABLE IF NOT EXISTS case_review_functional_case_archive( CREATE TABLE IF NOT EXISTS case_review_functional_case_archive(
`review_id` VARCHAR(50) NOT NULL COMMENT '用例评审ID', `review_id` VARCHAR(50) NOT NULL COMMENT '用例评审ID',

View File

@ -137,3 +137,10 @@ case_module.not.exist=用例模块不存在
#case #case
case.demand.not.exist=需求不存在 case.demand.not.exist=需求不存在
case.demand.name.not.exist=需求名称不能为空 case.demand.name.not.exist=需求名称不能为空
case_review.prepared=未开始
case_review.underway=进行中
case_review.completed=已完成
case_review.archived=已归档
case_review.single=单人评审
case_review.multiple=多人评审
case_review.not.exist=用例评审不存在

View File

@ -158,3 +158,10 @@ file.transfer.failed=File transfer FAILED
#case #case
case.demand.not.exist=Demand does not exist case.demand.not.exist=Demand does not exist
case.demand.name.not.exist=Demand name cannot be empty case.demand.name.not.exist=Demand name cannot be empty
case_review.prepared=Prepared
case_review.underway=Underway
case_review.completed=Completed
case_review.archived=Archived
case_review.single=Single person review
case_review.multiple=Multiple reviewers
case_review.not.exist=Case review does not exist

View File

@ -157,3 +157,10 @@ file.transfer.failed=文件转存失败
#case #case
case.demand.not.exist=需求不存在 case.demand.not.exist=需求不存在
case.demand.name.not.exist=需求名称不能为空 case.demand.name.not.exist=需求名称不能为空
case_review.prepared=未开始
case_review.underway=进行中
case_review.completed=已完成
case_review.archived=已归档
case_review.single=单人评审
case_review.multiple=多人评审
case_review.not.exist=用例评审不存在

View File

@ -158,3 +158,11 @@ file.transfer.failed=文件轉存失敗
#case #case
case.demand.not.exist=需求不存在 case.demand.not.exist=需求不存在
case.demand.name.not.exist=需求名稱不能為空 case.demand.name.not.exist=需求名稱不能為空
case_review.prepared=未開始
case_review.underway=進行中
case_review.completed=已完成
case_review.archived=已歸檔
case_review.single=單人評審
case_review.multiple=多人評審
case_review.not.exist=用例評審不存在

View File

@ -1,6 +1,26 @@
package io.metersphere.functional.constants; package io.metersphere.functional.constants;
import io.metersphere.sdk.util.Translator;
public enum CaseReviewPassRule { public enum CaseReviewPassRule {
SINGLE, SINGLE("case_review.single"),
MULTIPLE MULTIPLE("case_review.multiple");
private final String name;
CaseReviewPassRule(String name) {
this.name = name;
}
public String getName() {
return getTranslationName(this.name);
}
/**
* 返回国际化后的规则信息
* 如果没有匹配则返回原文
*/
String getTranslationName(String name) {
return Translator.get(name, name);
}
} }

View File

@ -1,8 +1,30 @@
package io.metersphere.functional.constants; package io.metersphere.functional.constants;
import io.metersphere.sdk.util.Translator;
public enum CaseReviewStatus { public enum CaseReviewStatus {
PREPARED,
UNDERWAY,
COMPLETED, PREPARED("case_review.prepared"),
ARCHIVED; UNDERWAY("case_review.underway"),
COMPLETED("case_review.completed"),
ARCHIVED("case_review.archived");
private final String name;
CaseReviewStatus(String name) {
this.name = name;
}
public String getName() {
return getTranslationName(this.name);
}
/**
* 返回国际化后的状态信息
* 如果没有匹配则返回原文
*/
String getTranslationName(String name) {
return Translator.get(name, name);
}
} }

View File

@ -1,14 +1,24 @@
package io.metersphere.functional.controller; package io.metersphere.functional.controller;
import io.metersphere.functional.dto.CaseReviewDTO; import io.metersphere.functional.request.CaseReviewAddRequest;
import io.metersphere.functional.request.CaseReviewFollowerRequest;
import io.metersphere.functional.service.CaseReviewLogService;
import io.metersphere.functional.service.CaseReviewService; import io.metersphere.functional.service.CaseReviewService;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.system.log.annotation.Log;
import io.metersphere.system.log.constants.OperationLogType;
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 jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@Tag(name = "用例管理-用例评审")
@RestController @RestController
@RequestMapping("/case/review") @RequestMapping("/case/review")
public class CaseReviewController { public class CaseReviewController {
@ -16,9 +26,19 @@ public class CaseReviewController {
@Resource @Resource
private CaseReviewService caseReviewService; private CaseReviewService caseReviewService;
@PostMapping("/add")
@Operation(summary = "用例管理-用例评审-创建用例评审")
@Log(type = OperationLogType.ADD, expression = "#msClass.addCaseReviewLog(#request)", msClass = CaseReviewLogService.class)
@RequiresPermissions(PermissionConstants.CASE_REVIEW_READ_ADD)
public void addCaseReview(@Validated @RequestBody CaseReviewAddRequest request) {
caseReviewService.addCaseReview(request, SessionUtils.getUserId());
}
@GetMapping("/get/{id}") @PostMapping("/edit/follower")
public CaseReviewDTO get(@PathVariable String id) { @Operation(summary = "用例管理-用例评审-关注/取消关注用例")
return caseReviewService.get(id); @RequiresPermissions(PermissionConstants.CASE_REVIEW_READ_UPDATE)
public void editFollower(@Validated @RequestBody CaseReviewFollowerRequest request) {
caseReviewService.editFollower(request.getCaseReviewId(), SessionUtils.getUserId());
} }
} }

View File

@ -13,6 +13,7 @@ import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.utils.PageUtils; import io.metersphere.system.utils.PageUtils;
import io.metersphere.system.utils.Pager; import io.metersphere.system.utils.Pager;
import io.metersphere.system.utils.SessionUtils; import io.metersphere.system.utils.SessionUtils;
import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -50,7 +51,7 @@ public class FunctionalCaseDemandController {
@PostMapping("/update") @PostMapping("/update")
@Operation(summary = "用例管理-功能用例-关联需求-更新需求") @Operation(summary = "用例管理-功能用例-关联需求-更新需求")
@RequiresPermissions(value = {PermissionConstants.FUNCTIONAL_CASE_READ_ADD, PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE, PermissionConstants.FUNCTIONAL_CASE_READ_DELETE}, logical = Logical.OR) @RequiresPermissions(value = {PermissionConstants.FUNCTIONAL_CASE_READ_ADD, PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE, PermissionConstants.FUNCTIONAL_CASE_READ_DELETE}, logical = Logical.OR)
public void updateDemand(@RequestBody @Validated FunctionalCaseDemandRequest request) { public void updateDemand(@RequestBody @Validated({Updated.class}) FunctionalCaseDemandRequest request) {
functionalCaseDemandService.updateDemand(request, SessionUtils.getUserId()); functionalCaseDemandService.updateDemand(request, SessionUtils.getUserId());
} }

View File

@ -0,0 +1,54 @@
package io.metersphere.functional.request;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = false)
public class CaseReviewAddRequest implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "项目id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{case_review.project_id.not_blank}")
private String projectId;
@Schema(description = "评审名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{case_review.name.not_blank}")
private String name;
@Schema(description = "模块id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{case_review.module_id.not_blank}")
private String moduleId;
@Schema(description = "通过标准:单人通过(SINGLE)/多人通过(MULTIPLE)", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{case_review.review_pass_rule.not_blank}")
private String reviewPassRule;
@Schema(description = "评审开始时间")
private Long startTime;
@Schema(description = "评审结束时间")
private Long endTime;
@Schema(description = "标签")
private List<String> tags;
@Schema(description = "描述")
private String description;
@Schema(description = "默认评审人", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "{case_review.reviewers.not_empty}")
private List<String> reviewers;
@Schema(description = "关联的用例id", requiredMode = Schema.RequiredMode.REQUIRED)
private List<String> caseIds;
}

View File

@ -0,0 +1,27 @@
package io.metersphere.functional.request;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* @author guoyuqi
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class CaseReviewFollowerRequest implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "用户id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{user_id.not_blank}")
private String userId;
@Schema(description = "用例评审id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{case_review.id.not_blank}")
private String caseReviewId;
}

View File

@ -2,14 +2,16 @@ package io.metersphere.functional.result;
import io.metersphere.sdk.exception.IResultCode; import io.metersphere.sdk.exception.IResultCode;
public enum FunctionalCaseResultCode implements IResultCode { public enum CaseManagementResultCode implements IResultCode {
FUNCTIONAL_CASE_NOT_FOUND(105001, "case_comment.case_is_null"); FUNCTIONAL_CASE_NOT_FOUND(105001, "case_comment.case_is_null"),
CASE_REVIEW_NOT_FOUND(105001, "case_review.not.exist");
private final int code; private final int code;
private final String message; private final String message;
FunctionalCaseResultCode(int code, String message) { CaseManagementResultCode(int code, String message) {
this.code = code; this.code = code;
this.message = message; this.message = message;
} }

View File

@ -0,0 +1,40 @@
package io.metersphere.functional.service;
import io.metersphere.functional.request.CaseReviewAddRequest;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.dto.LogDTO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* @author guoyuqi
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class CaseReviewLogService {
/**
* 新增用例评审 日志
*
* @param requests 页面参数
* @return LogDTO
*/
public LogDTO addCaseReviewLog(CaseReviewAddRequest requests) {
LogDTO dto = new LogDTO(
requests.getProjectId(),
null,
null,
null,
OperationLogType.ADD.name(),
OperationLogModule.CASE_REVIEW,
requests.getName());
dto.setPath("/case/review/add");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(requests));
return dto;
}
}

View File

@ -1,8 +1,23 @@
package io.metersphere.functional.service; package io.metersphere.functional.service;
import io.metersphere.functional.dto.CaseReviewDTO; import io.metersphere.functional.constants.CaseReviewStatus;
import io.metersphere.functional.domain.*;
import io.metersphere.functional.mapper.*;
import io.metersphere.functional.request.CaseReviewAddRequest;
import io.metersphere.functional.result.CaseManagementResultCode;
import io.metersphere.sdk.constants.FunctionalCaseReviewStatus;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/** /**
* 用例评审表服务实现类 * 用例评审表服务实现类
@ -10,11 +25,149 @@ import org.springframework.stereotype.Service;
* @date : 2023-5-17 * @date : 2023-5-17
*/ */
@Service @Service
@Transactional(rollbackFor = Exception.class)
public class CaseReviewService { public class CaseReviewService {
public static final int ORDER_STEP = 5000;
public CaseReviewDTO get(String id) { @Resource
CaseReviewDTO caseReviewDto = new CaseReviewDTO(); private ExtFunctionalCaseMapper extFunctionalCaseMapper;
return caseReviewDto; @Resource
private CaseReviewMapper caseReviewMapper;
@Resource
private CaseReviewFollowerMapper caseReviewFollowerMapper;
@Resource
SqlSessionFactory sqlSessionFactory;
/**
* 添加用例评审
*
* @param request 页面参数
* @param userId 当前操作人
*/
public void addCaseReview(CaseReviewAddRequest request, String userId) {
String caseReviewId = IDGenerator.nextStr();
addCaseReview(request, userId, caseReviewId);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
CaseReviewUserMapper mapper = sqlSession.getMapper(CaseReviewUserMapper.class);
CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper = sqlSession.getMapper(CaseReviewFunctionalCaseMapper.class);
try {
//保存和评审人的关系
addCaseReviewUser(request, caseReviewId, mapper);
//保存和用例的关系
addCaseReviewFunctionalCase(request, userId, caseReviewId, caseReviewFunctionalCaseMapper);
sqlSession.flushStatements();
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
} }
} }
/**
* 保存用例评审和功能用例的关系
* @param request request
* @param userId 当前操作人
* @param caseReviewId 用例评审id
* @param caseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper
*/
private void addCaseReviewFunctionalCase(CaseReviewAddRequest request, String userId, String caseReviewId, CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper) {
if (CollectionUtils.isNotEmpty(request.getCaseIds())) {
request.getReviewers().forEach(caseId -> {
CaseReviewFunctionalCase caseReviewFunctionalCase = new CaseReviewFunctionalCase();
caseReviewFunctionalCase.setReviewId(caseReviewId);
caseReviewFunctionalCase.setCaseId(caseId);
caseReviewFunctionalCase.setStatus(FunctionalCaseReviewStatus.UN_REVIEWED.toString());
caseReviewFunctionalCase.setCreateUser(userId);
caseReviewFunctionalCase.setCreateTime(System.currentTimeMillis());
caseReviewFunctionalCase.setUpdateTime(System.currentTimeMillis());
caseReviewFunctionalCase.setId(IDGenerator.nextStr());
caseReviewFunctionalCase.setPos(getNextOrder(request.getProjectId()));
caseReviewFunctionalCaseMapper.insert(caseReviewFunctionalCase);
});
}
}
/**
* 保存用例评审和评审人的关系
* @param request request
* @param caseReviewId 用例评审
* @param caseReviewUserMapper caseReviewUserMapper
*/
private static void addCaseReviewUser(CaseReviewAddRequest request, String caseReviewId, CaseReviewUserMapper caseReviewUserMapper) {
request.getReviewers().forEach(user -> {
CaseReviewUser caseReviewUser = new CaseReviewUser();
caseReviewUser.setReviewId(caseReviewId);
caseReviewUser.setUserId(user);
caseReviewUserMapper.insert(caseReviewUser);
});
}
/**
* 新增用例评审
* @param request request
* @param userId 当前操作人
* @param caseReviewId 用例评审id
*/
private void addCaseReview(CaseReviewAddRequest request, String userId, String caseReviewId) {
CaseReview caseReview = new CaseReview();
caseReview.setId(caseReviewId);
caseReview.setProjectId(request.getProjectId());
caseReview.setName(request.getName());
caseReview.setModuleId(request.getModuleId());
caseReview.setStatus(CaseReviewStatus.PREPARED.toString());
caseReview.setReviewPassRule(request.getReviewPassRule());
caseReview.setPos(getNextOrder(request.getProjectId()));
if (CollectionUtils.isNotEmpty(request.getTags())) {
caseReview.setTags(JSON.toJSONString(request.getTags()));
}
caseReview.setStartTime(request.getStartTime());
caseReview.setEndTime(request.getEndTime());
caseReview.setCreateTime(System.currentTimeMillis());
caseReview.setUpdateTime(System.currentTimeMillis());
caseReview.setCreateUser(userId);
caseReview.setUpdateUser(userId);
caseReviewMapper.insert(caseReview);
}
/**
* 关注/取消关注用例
*
* @param caseReviewId 用例评审id
* @param userId 当前操作人
*/
public void editFollower(String caseReviewId, String userId) {
checkCaseReview(caseReviewId);
CaseReviewFollowerExample example = new CaseReviewFollowerExample();
example.createCriteria().andReviewIdEqualTo(caseReviewId).andUserIdEqualTo(userId);
if (caseReviewFollowerMapper.countByExample(example) > 0) {
caseReviewFollowerMapper.deleteByPrimaryKey(caseReviewId, userId);
} else {
CaseReviewFollower caseReviewFollower = new CaseReviewFollower();
caseReviewFollower.setReviewId(caseReviewId);
caseReviewFollower.setUserId(userId);
caseReviewFollowerMapper.insert(caseReviewFollower);
}
}
/**
* 检查用例评审是否存在
*
* @param caseReviewId 用例评审id
* @return CaseReview
*/
private CaseReview checkCaseReview(String caseReviewId) {
CaseReviewExample caseReviewExample = new CaseReviewExample();
caseReviewExample.createCriteria().andIdEqualTo(caseReviewId);
CaseReview caseReview = caseReviewMapper.selectByPrimaryKey(caseReviewId);
if (caseReview == null) {
throw new MSException(CaseManagementResultCode.CASE_REVIEW_NOT_FOUND);
}
return caseReview;
}
public Long getNextOrder(String projectId) {
Long pos = extFunctionalCaseMapper.getPos(projectId);
return (pos == null ? 0 : pos) + ORDER_STEP;
}
}

View File

@ -4,7 +4,7 @@ import io.metersphere.functional.domain.*;
import io.metersphere.functional.dto.*; import io.metersphere.functional.dto.*;
import io.metersphere.functional.mapper.*; import io.metersphere.functional.mapper.*;
import io.metersphere.functional.request.*; import io.metersphere.functional.request.*;
import io.metersphere.functional.result.FunctionalCaseResultCode; import io.metersphere.functional.result.CaseManagementResultCode;
import io.metersphere.project.dto.ModuleCountDTO; import io.metersphere.project.dto.ModuleCountDTO;
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper; import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
import io.metersphere.project.service.ProjectTemplateService; import io.metersphere.project.service.ProjectTemplateService;
@ -73,9 +73,6 @@ public class FunctionalCaseService {
@Resource @Resource
private ExtBaseProjectVersionMapper extBaseProjectVersionMapper; private ExtBaseProjectVersionMapper extBaseProjectVersionMapper;
@Resource
private FunctionalCaseModuleMapper functionalCaseModuleMapper;
@Resource @Resource
private FunctionalCaseModuleService functionalCaseModuleService; private FunctionalCaseModuleService functionalCaseModuleService;
@ -204,7 +201,7 @@ public class FunctionalCaseService {
functionalCaseExample.createCriteria().andIdEqualTo(functionalCaseId).andDeletedEqualTo(false); functionalCaseExample.createCriteria().andIdEqualTo(functionalCaseId).andDeletedEqualTo(false);
FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(functionalCaseId); FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(functionalCaseId);
if (functionalCase == null) { if (functionalCase == null) {
throw new MSException(FunctionalCaseResultCode.FUNCTIONAL_CASE_NOT_FOUND); throw new MSException(CaseManagementResultCode.FUNCTIONAL_CASE_NOT_FOUND);
} }
return functionalCase; return functionalCase;
} }

View File

@ -1,16 +1,26 @@
package io.metersphere.functional.controller; package io.metersphere.functional.controller;
import io.metersphere.sdk.constants.SessionConstants; import io.metersphere.functional.constants.CaseReviewPassRule;
import io.metersphere.functional.domain.*;
import io.metersphere.functional.mapper.CaseReviewFollowerMapper;
import io.metersphere.functional.mapper.CaseReviewFunctionalCaseMapper;
import io.metersphere.functional.mapper.CaseReviewMapper;
import io.metersphere.functional.mapper.CaseReviewUserMapper;
import io.metersphere.functional.request.CaseReviewAddRequest;
import io.metersphere.functional.request.CaseReviewFollowerRequest;
import io.metersphere.system.base.BaseTest; import io.metersphere.system.base.BaseTest;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.junit.jupiter.api.MethodOrderer; import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Order; import org.junit.jupiter.api.*;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.SqlConfig;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -22,12 +32,149 @@ public class CaseReviewControllerTests extends BaseTest {
@Resource @Resource
private MockMvc mockMvc; private MockMvc mockMvc;
private static final String projectId = "project-gyq-case-review-test";
private static final String ADD_CASE_REVIEW = "/case/review/add";
private static final String FOLLOW_CASE_REVIEW = "/case/review/edit/follower";
@Resource
private CaseReviewMapper caseReviewMapper;
@Resource
private CaseReviewFollowerMapper caseReviewFollowerMapper;
@Resource
private CaseReviewUserMapper caseReviewUserMapper;
@Resource
private CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper;
@Test @Test
@Order(1) @Order(1)
public void testGetCaseReview() throws Exception { @Sql(scripts = {"/dml/init_case_review.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED))
mockMvc.perform(MockMvcRequestBuilders.get("/case/review/get/case-review-id") public void addCaseReviewSuccess() throws Exception {
.header(SessionConstants.HEADER_TOKEN, sessionId) CaseReviewAddRequest caseReviewAddRequest = getCaseReviewAddRequest("创建评审1", CaseReviewPassRule.SINGLE.toString(), "CASE_REVIEW_TEST_GYQ_ID", false, true);
.header(SessionConstants.CSRF_TOKEN, csrfToken)) this.requestPostWithOk(ADD_CASE_REVIEW,caseReviewAddRequest);
.andExpect(status().isOk()); CaseReviewExample caseReviewExample = new CaseReviewExample();
caseReviewExample.createCriteria().andNameEqualTo("创建评审1");
List<CaseReview> caseReviews = caseReviewMapper.selectByExample(caseReviewExample);
Assertions.assertEquals(1, caseReviews.size());
String caseReviewId = caseReviews.get(0).getId();
CaseReviewUserExample caseReviewUserExample = new CaseReviewUserExample();
caseReviewUserExample.createCriteria().andReviewIdEqualTo(caseReviewId);
List<CaseReviewUser> caseReviewUsers = caseReviewUserMapper.selectByExample(caseReviewUserExample);
Assertions.assertEquals(1, caseReviewUsers.size());
CaseReviewFunctionalCaseExample caseReviewFunctionalCaseExample = new CaseReviewFunctionalCaseExample();
caseReviewFunctionalCaseExample.createCriteria().andReviewIdEqualTo(caseReviewId);
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = caseReviewFunctionalCaseMapper.selectByExample(caseReviewFunctionalCaseExample);
Assertions.assertEquals(1, caseReviewFunctionalCases.size());
} }
@NotNull
private static CaseReviewAddRequest getCaseReviewAddRequest(String name, String reviewPassRule, String caseId, boolean tag, boolean reviewer) {
CaseReviewAddRequest caseReviewAddRequest = new CaseReviewAddRequest();
caseReviewAddRequest.setProjectId(projectId);
caseReviewAddRequest.setName(name);
caseReviewAddRequest.setModuleId("CASE_REVIEW_REAL_MODULE_ID");
caseReviewAddRequest.setReviewPassRule(reviewPassRule);
List<String> reviewers = new ArrayList<>();
reviewers.add("admin");
if (reviewer) {
caseReviewAddRequest.setReviewers(reviewers);
}
if (StringUtils.isNotBlank(caseId)) {
List<String> caseIds = new ArrayList<>();
caseIds.add(caseId);
caseReviewAddRequest.setCaseIds(caseIds);
}
if (tag) {
List<String> tags = new ArrayList<>();
tags.add("11");
caseReviewAddRequest.setTags(tags);
}
return caseReviewAddRequest;
}
@Test
@Order(2)
public void addCaseReviewWidthOutCaseIdsSuccess() throws Exception {
CaseReviewAddRequest caseReviewAddRequest = getCaseReviewAddRequest("创建评审2", CaseReviewPassRule.SINGLE.toString(), null, false, true);
this.requestPostWithOk(ADD_CASE_REVIEW,caseReviewAddRequest);
CaseReviewExample caseReviewExample = new CaseReviewExample();
caseReviewExample.createCriteria().andNameEqualTo("创建评审2");
List<CaseReview> caseReviews = caseReviewMapper.selectByExample(caseReviewExample);
Assertions.assertEquals(1, caseReviews.size());
String caseReviewId = caseReviews.get(0).getId();
CaseReviewUserExample caseReviewUserExample = new CaseReviewUserExample();
caseReviewUserExample.createCriteria().andReviewIdEqualTo(caseReviewId);
List<CaseReviewUser> caseReviewUsers = caseReviewUserMapper.selectByExample(caseReviewUserExample);
Assertions.assertEquals(1, caseReviewUsers.size());
CaseReviewFunctionalCaseExample caseReviewFunctionalCaseExample = new CaseReviewFunctionalCaseExample();
caseReviewFunctionalCaseExample.createCriteria().andReviewIdEqualTo(caseReviewId);
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = caseReviewFunctionalCaseMapper.selectByExample(caseReviewFunctionalCaseExample);
Assertions.assertEquals(0, caseReviewFunctionalCases.size());
}
@Test
@Order(3)
public void addCaseReviewWidthTagsSuccess() throws Exception {
CaseReviewAddRequest caseReviewAddRequest = getCaseReviewAddRequest("创建评审3", CaseReviewPassRule.SINGLE.toString(), null, true, true);
this.requestPostWithOk(ADD_CASE_REVIEW,caseReviewAddRequest);
CaseReviewExample caseReviewExample = new CaseReviewExample();
caseReviewExample.createCriteria().andNameEqualTo("创建评审3");
List<CaseReview> caseReviews = caseReviewMapper.selectByExample(caseReviewExample);
Assertions.assertEquals(1, caseReviews.size());
String caseReviewId = caseReviews.get(0).getId();
Assertions.assertNotNull(caseReviews.get(0).getTags());
CaseReviewUserExample caseReviewUserExample = new CaseReviewUserExample();
caseReviewUserExample.createCriteria().andReviewIdEqualTo(caseReviewId);
List<CaseReviewUser> caseReviewUsers = caseReviewUserMapper.selectByExample(caseReviewUserExample);
Assertions.assertEquals(1, caseReviewUsers.size());
CaseReviewFunctionalCaseExample caseReviewFunctionalCaseExample = new CaseReviewFunctionalCaseExample();
caseReviewFunctionalCaseExample.createCriteria().andReviewIdEqualTo(caseReviewId);
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = caseReviewFunctionalCaseMapper.selectByExample(caseReviewFunctionalCaseExample);
Assertions.assertEquals(0, caseReviewFunctionalCases.size());
}
@Test
@Order(4)
public void addCaseReviewFalse() throws Exception {
CaseReviewAddRequest caseReviewAddRequestNoReviewer= getCaseReviewAddRequest("创建评审4", CaseReviewPassRule.SINGLE.toString(), null, true, false);
this.requestPost(ADD_CASE_REVIEW, caseReviewAddRequestNoReviewer).andExpect(status().is4xxClientError());
CaseReviewAddRequest caseReviewAddRequestNoName = getCaseReviewAddRequest(null, CaseReviewPassRule.SINGLE.toString(), null, true, true);
this.requestPost(ADD_CASE_REVIEW, caseReviewAddRequestNoName).andExpect(status().is4xxClientError());
}
@Test
@Order(5)
public void followCaseReview() throws Exception {
CaseReviewExample caseReviewExample = new CaseReviewExample();
caseReviewExample.createCriteria().andNameEqualTo("创建评审1");
List<CaseReview> caseReviews = caseReviewMapper.selectByExample(caseReviewExample);
CaseReview caseReview = caseReviews.get(0);
CaseReviewFollowerRequest caseReviewFollowerRequest = new CaseReviewFollowerRequest();
caseReviewFollowerRequest.setCaseReviewId(caseReview.getId());
caseReviewFollowerRequest.setUserId("admin");
this.requestPostWithOk(FOLLOW_CASE_REVIEW,caseReviewFollowerRequest);
CaseReviewFollowerExample example = new CaseReviewFollowerExample();
example.createCriteria().andReviewIdEqualTo(caseReview.getId()).andUserIdEqualTo("admin");
Assertions.assertTrue(caseReviewFollowerMapper.countByExample(example) > 0);
caseReviewFollowerRequest = new CaseReviewFollowerRequest();
caseReviewFollowerRequest.setCaseReviewId(caseReview.getId());
caseReviewFollowerRequest.setUserId("admin");
this.requestPostWithOk(FOLLOW_CASE_REVIEW,caseReviewFollowerRequest);
example = new CaseReviewFollowerExample();
example.createCriteria().andReviewIdEqualTo(caseReview.getId()).andUserIdEqualTo("admin");
Assertions.assertEquals(0, caseReviewFollowerMapper.countByExample(example));
}
@Test
@Order(6)
public void followCaseReviewFalse() throws Exception {
CaseReviewFollowerRequest caseReviewFollowerRequest = new CaseReviewFollowerRequest();
caseReviewFollowerRequest.setCaseReviewId("XXXXX");
caseReviewFollowerRequest.setUserId("admin");
this.requestPost(FOLLOW_CASE_REVIEW, caseReviewFollowerRequest).andExpect(status().is5xxServerError());
}
} }

View File

@ -4,7 +4,7 @@ import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.functional.dto.CaseCustomFieldDTO; import io.metersphere.functional.dto.CaseCustomFieldDTO;
import io.metersphere.functional.dto.FunctionalCasePageDTO; import io.metersphere.functional.dto.FunctionalCasePageDTO;
import io.metersphere.functional.request.*; import io.metersphere.functional.request.*;
import io.metersphere.functional.result.FunctionalCaseResultCode; import io.metersphere.functional.result.CaseManagementResultCode;
import io.metersphere.functional.utils.FileBaseUtils; import io.metersphere.functional.utils.FileBaseUtils;
import io.metersphere.project.domain.Notification; import io.metersphere.project.domain.Notification;
import io.metersphere.project.domain.NotificationExample; import io.metersphere.project.domain.NotificationExample;
@ -122,7 +122,7 @@ public class FunctionalCaseControllerTests extends BaseTest {
@Test @Test
@Order(3) @Order(3)
public void testFunctionalCaseDetail() throws Exception { public void testFunctionalCaseDetail() throws Exception {
assertErrorCode(this.requestGet(FUNCTIONAL_CASE_DETAIL_URL + "ERROR_TEST_FUNCTIONAL_CASE_ID"), FunctionalCaseResultCode.FUNCTIONAL_CASE_NOT_FOUND); assertErrorCode(this.requestGet(FUNCTIONAL_CASE_DETAIL_URL + "ERROR_TEST_FUNCTIONAL_CASE_ID"), CaseManagementResultCode.FUNCTIONAL_CASE_NOT_FOUND);
this.requestGetWithOkAndReturn(FUNCTIONAL_CASE_DETAIL_URL + "TEST_FUNCTIONAL_CASE_ID_1"); this.requestGetWithOkAndReturn(FUNCTIONAL_CASE_DETAIL_URL + "TEST_FUNCTIONAL_CASE_ID_1");
MvcResult mvcResult = this.requestGetWithOkAndReturn(FUNCTIONAL_CASE_DETAIL_URL + "TEST_FUNCTIONAL_CASE_ID"); MvcResult mvcResult = this.requestGetWithOkAndReturn(FUNCTIONAL_CASE_DETAIL_URL + "TEST_FUNCTIONAL_CASE_ID");
// 获取返回值 // 获取返回值

View File

@ -185,6 +185,16 @@ public class FunctionalCaseDemandControllerTests extends BaseTest {
functionalCaseDemandRequest.setDemandList(demandList); functionalCaseDemandRequest.setDemandList(demandList);
this.requestPost(URL_DEMAND_UPDATE, functionalCaseDemandRequest).andExpect(status().is5xxServerError()); this.requestPost(URL_DEMAND_UPDATE, functionalCaseDemandRequest).andExpect(status().is5xxServerError());
functionalCaseDemandRequest = new FunctionalCaseDemandRequest();
functionalCaseDemandRequest.setCaseId("DEMAND_TEST_FUNCTIONAL_CASE_ID");
functionalCaseDemandRequest.setDemandPlatform("LOCAL");
demandList = new ArrayList<>();
demandDTO = new DemandDTO();
demandDTO.setDemandId("111");
demandDTO.setDemandName("手动执行2");
demandList.add(demandDTO);
functionalCaseDemandRequest.setDemandList(demandList);
this.requestPost(URL_DEMAND_UPDATE, functionalCaseDemandRequest).andExpect(status().is4xxClientError());
} }
private String getId(String caseId) { private String getId(String caseId) {

View File

@ -0,0 +1,31 @@
INSERT INTO organization(id, num, name, description, create_time, update_time, create_user, update_user, deleted, delete_user, delete_time) VALUE
('organization-gyq-case-review-test', null, 'organization-gyq-case-review-test', 'organization-gyq-case-review-test', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'admin', 0, null, null);
INSERT INTO project (id, num, organization_id, name, description, create_user, update_user, create_time, update_time) VALUES
('project-gyq-case-review-test', null, 'organization-gyq-case-review-test', '用例评审项目', '系统默认创建的项目', 'admin', 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000);
INSERT INTO template (id, name, remark, internal, update_time, create_time, create_user, scope_type, scope_id, enable_third_part, ref_id, scene)
VALUES ('test_template_case_review_gyq_id', 'functional_case_review_gyq', '', b'0', 1696992836000, 1696992836000, 'admin', 'PROJECT', 'project-gyq-case-review-test', b'0', NULL, 'FUNCTIONAL');
INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time)
VALUES ('CASE_REVIEW_TEST_GYQ_ID', 1, 'CASE_REVIEW_TEST_MODULE_ID', 'project-gyq-case-review-test', '100001', '关联需求测试', 'UN_REVIEWED', NULL, 'STEP', 0, 'v1.0.0', 'CASE_REVIEW_TEST_GYQ_ID', 'UN_EXECUTED', true, b'0', b'0', 'gyq', 'gyq', '', 1698058347559, 1698058347559, NULL);
INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time)
VALUES ('CASE_REVIEW_TEST_GYQ_ID2', 1, 'CASE_REVIEW_TEST_MODULE_ID', 'project-gyq-case-review-test', '100001', '关联需求测试', 'UN_REVIEWED', NULL, 'STEP', 0, 'v1.0.0', 'CASE_REVIEW_TEST_GYQ_ID2', 'UN_EXECUTED', true, b'0', b'0', 'gyq', 'gyq', '', 1698058347559, 1698058347559, NULL);
INSERT INTO functional_case_custom_field(case_id, field_id, value) VALUES ('CASE_REVIEW_TEST_GYQ_ID', 'gyq_custom_id_review1', '22');
INSERT INTO functional_case_custom_field(case_id, field_id, value) VALUES ('CASE_REVIEW_TEST_GYQ_ID', 'gyq_custom_id_review2', '33');
INSERT INTO custom_field(id, name, scene, `type`, remark, internal, scope_type, create_time, update_time, create_user, scope_id)
VALUES('gyq_custom_id_review1', 'functional_priority', 'FUNCTIONAL', 'SELECT', '', 1, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'test_template_case_review_gyq_id');
INSERT INTO custom_field(id, name, scene, `type`, remark, internal, scope_type, create_time, update_time, create_user, scope_id)
VALUES('gyq_custom_id_review2', 'level', 'FUNCTIONAL', 'SELECT', '', 1, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'test_template_case_review_gyq_id');
INSERT INTO functional_case_module(id, project_id, name, parent_id, pos, create_time, update_time, create_user, update_user) VALUES ('CASE_REVIEW_TEST_MODULE_ID', 'project-gyq-case-review-test', '测试用例评审所属模块', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin');
INSERT INTO case_review_module(id, project_id, name, parent_id, pos, create_time, update_time, create_user, update_user) VALUES ('CASE_REVIEW_REAL_MODULE_ID', 'project-gyq-case-review-test', '用例评审所属模块', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin');