feat(接口测试): 新增接口调试接口
This commit is contained in:
parent
280af80e18
commit
57bc8ddae9
|
@ -36,7 +36,9 @@ public class ApiDebug implements Serializable {
|
|||
@Size(min = 1, max = 50, message = "{api_debug.project_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "模块fk")
|
||||
@Schema(description = "模块fk", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{api_debug.module_id.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{api_debug.module_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String moduleId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
package io.metersphere.api.domain;
|
||||
|
||||
import io.metersphere.validation.groups.*;
|
||||
import io.metersphere.validation.groups.Created;
|
||||
import io.metersphere.validation.groups.Updated;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ApiDebugModule implements Serializable {
|
||||
|
@ -21,8 +25,8 @@ public class ApiDebugModule implements Serializable {
|
|||
private String name;
|
||||
|
||||
@Schema(description = "协议", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{api_debug_module.protocol.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 64, message = "{api_debug_module.protocol.length_range}", groups = {Created.class, Updated.class})
|
||||
@NotBlank(message = "{api_debug.protocol.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 20, message = "{api_debug.protocol.length_range}", groups = {Created.class, Updated.class})
|
||||
private String protocol;
|
||||
|
||||
@Schema(description = "父级fk", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
|
@ -35,10 +39,6 @@ public class ApiDebugModule implements Serializable {
|
|||
@Size(min = 1, max = 50, message = "{api_debug_module.project_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "树节点级别", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "{api_debug_module.level.not_blank}", groups = {Created.class})
|
||||
private Integer level;
|
||||
|
||||
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "{api_debug_module.pos.not_blank}", groups = {Created.class})
|
||||
private Integer pos;
|
||||
|
@ -63,7 +63,6 @@ public class ApiDebugModule implements Serializable {
|
|||
protocol("protocol", "protocol", "VARCHAR", false),
|
||||
parentId("parent_id", "parentId", "VARCHAR", false),
|
||||
projectId("project_id", "projectId", "VARCHAR", false),
|
||||
level("level", "level", "INTEGER", true),
|
||||
pos("pos", "pos", "INTEGER", false),
|
||||
createTime("create_time", "createTime", "BIGINT", false),
|
||||
updateTime("update_time", "updateTime", "BIGINT", false),
|
||||
|
|
|
@ -454,66 +454,6 @@ public class ApiDebugModuleExample {
|
|||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelIsNull() {
|
||||
addCriterion("`level` is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelIsNotNull() {
|
||||
addCriterion("`level` is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelEqualTo(Integer value) {
|
||||
addCriterion("`level` =", value, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelNotEqualTo(Integer value) {
|
||||
addCriterion("`level` <>", value, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelGreaterThan(Integer value) {
|
||||
addCriterion("`level` >", value, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelGreaterThanOrEqualTo(Integer value) {
|
||||
addCriterion("`level` >=", value, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelLessThan(Integer value) {
|
||||
addCriterion("`level` <", value, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelLessThanOrEqualTo(Integer value) {
|
||||
addCriterion("`level` <=", value, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelIn(List<Integer> values) {
|
||||
addCriterion("`level` in", values, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelNotIn(List<Integer> values) {
|
||||
addCriterion("`level` not in", values, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelBetween(Integer value1, Integer value2) {
|
||||
addCriterion("`level` between", value1, value2, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelNotBetween(Integer value1, Integer value2) {
|
||||
addCriterion("`level` not between", value1, value2, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosIsNull() {
|
||||
addCriterion("pos is null");
|
||||
return (Criteria) this;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<result column="protocol" jdbcType="VARCHAR" property="protocol" />
|
||||
<result column="parent_id" jdbcType="VARCHAR" property="parentId" />
|
||||
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
|
||||
<result column="level" jdbcType="INTEGER" property="level" />
|
||||
<result column="pos" jdbcType="INTEGER" property="pos" />
|
||||
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
|
||||
|
@ -73,8 +72,8 @@
|
|||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, `name`, protocol, parent_id, project_id, `level`, pos, create_time, update_time,
|
||||
update_user, create_user
|
||||
id, `name`, protocol, parent_id, project_id, pos, create_time, update_time, update_user,
|
||||
create_user
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.api.domain.ApiDebugModuleExample" resultMap="BaseResultMap">
|
||||
select
|
||||
|
@ -108,13 +107,13 @@
|
|||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.api.domain.ApiDebugModule">
|
||||
insert into api_debug_module (id, `name`, protocol,
|
||||
parent_id, project_id, `level`,
|
||||
pos, create_time, update_time,
|
||||
update_user, create_user)
|
||||
parent_id, project_id, pos,
|
||||
create_time, update_time, update_user,
|
||||
create_user)
|
||||
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{protocol,jdbcType=VARCHAR},
|
||||
#{parentId,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{level,jdbcType=INTEGER},
|
||||
#{pos,jdbcType=INTEGER}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
||||
#{updateUser,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR})
|
||||
#{parentId,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{pos,jdbcType=INTEGER},
|
||||
#{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{updateUser,jdbcType=VARCHAR},
|
||||
#{createUser,jdbcType=VARCHAR})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.api.domain.ApiDebugModule">
|
||||
insert into api_debug_module
|
||||
|
@ -134,9 +133,6 @@
|
|||
<if test="projectId != null">
|
||||
project_id,
|
||||
</if>
|
||||
<if test="level != null">
|
||||
`level`,
|
||||
</if>
|
||||
<if test="pos != null">
|
||||
pos,
|
||||
</if>
|
||||
|
@ -169,9 +165,6 @@
|
|||
<if test="projectId != null">
|
||||
#{projectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="level != null">
|
||||
#{level,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="pos != null">
|
||||
#{pos,jdbcType=INTEGER},
|
||||
</if>
|
||||
|
@ -213,9 +206,6 @@
|
|||
<if test="record.projectId != null">
|
||||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.level != null">
|
||||
`level` = #{record.level,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="record.pos != null">
|
||||
pos = #{record.pos,jdbcType=INTEGER},
|
||||
</if>
|
||||
|
@ -243,7 +233,6 @@
|
|||
protocol = #{record.protocol,jdbcType=VARCHAR},
|
||||
parent_id = #{record.parentId,jdbcType=VARCHAR},
|
||||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||
`level` = #{record.level,jdbcType=INTEGER},
|
||||
pos = #{record.pos,jdbcType=INTEGER},
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
update_time = #{record.updateTime,jdbcType=BIGINT},
|
||||
|
@ -268,9 +257,6 @@
|
|||
<if test="projectId != null">
|
||||
project_id = #{projectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="level != null">
|
||||
`level` = #{level,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="pos != null">
|
||||
pos = #{pos,jdbcType=INTEGER},
|
||||
</if>
|
||||
|
@ -295,7 +281,6 @@
|
|||
protocol = #{protocol,jdbcType=VARCHAR},
|
||||
parent_id = #{parentId,jdbcType=VARCHAR},
|
||||
project_id = #{projectId,jdbcType=VARCHAR},
|
||||
`level` = #{level,jdbcType=INTEGER},
|
||||
pos = #{pos,jdbcType=INTEGER},
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
update_time = #{updateTime,jdbcType=BIGINT},
|
||||
|
@ -305,14 +290,14 @@
|
|||
</update>
|
||||
<insert id="batchInsert" parameterType="map">
|
||||
insert into api_debug_module
|
||||
(id, `name`, protocol, parent_id, project_id, `level`, pos, create_time, update_time,
|
||||
update_user, create_user)
|
||||
(id, `name`, protocol, parent_id, project_id, pos, create_time, update_time, update_user,
|
||||
create_user)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.id,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR}, #{item.protocol,jdbcType=VARCHAR},
|
||||
#{item.parentId,jdbcType=VARCHAR}, #{item.projectId,jdbcType=VARCHAR}, #{item.level,jdbcType=INTEGER},
|
||||
#{item.pos,jdbcType=INTEGER}, #{item.createTime,jdbcType=BIGINT}, #{item.updateTime,jdbcType=BIGINT},
|
||||
#{item.updateUser,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR})
|
||||
#{item.parentId,jdbcType=VARCHAR}, #{item.projectId,jdbcType=VARCHAR}, #{item.pos,jdbcType=INTEGER},
|
||||
#{item.createTime,jdbcType=BIGINT}, #{item.updateTime,jdbcType=BIGINT}, #{item.updateUser,jdbcType=VARCHAR},
|
||||
#{item.createUser,jdbcType=VARCHAR})
|
||||
</foreach>
|
||||
</insert>
|
||||
<insert id="batchInsertSelective" parameterType="map">
|
||||
|
@ -340,9 +325,6 @@
|
|||
<if test="'project_id'.toString() == column.value">
|
||||
#{item.projectId,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'level'.toString() == column.value">
|
||||
#{item.level,jdbcType=INTEGER}
|
||||
</if>
|
||||
<if test="'pos'.toString() == column.value">
|
||||
#{item.pos,jdbcType=INTEGER}
|
||||
</if>
|
||||
|
|
|
@ -9,7 +9,7 @@ CREATE TABLE api_debug(
|
|||
`method` VARCHAR(20) COMMENT 'http协议类型post/get/其它协议则是协议名(mqtt)' ,
|
||||
`path` VARCHAR(500) COMMENT 'http协议路径/其它协议则为空' ,
|
||||
`project_id` VARCHAR(50) NOT NULL COMMENT '项目fk' ,
|
||||
`module_id` VARCHAR(50) DEFAULT 'NONE' COMMENT '模块fk' ,
|
||||
`module_id` VARCHAR(50) NOT NULL DEFAULT 'root' COMMENT '模块fk' ,
|
||||
`create_time` BIGINT NOT NULL COMMENT '创建时间' ,
|
||||
`create_user` VARCHAR(50) NOT NULL COMMENT '创建人' ,
|
||||
`update_time` BIGINT NOT NULL COMMENT '修改时间' ,
|
||||
|
@ -41,10 +41,9 @@ DROP TABLE IF EXISTS api_debug_module;
|
|||
CREATE TABLE api_debug_module(
|
||||
`id` VARCHAR(50) NOT NULL COMMENT '接口模块pk' ,
|
||||
`name` VARCHAR(255) NOT NULL COMMENT '模块名称' ,
|
||||
`protocol` VARCHAR(64) NOT NULL COMMENT '协议' ,
|
||||
`protocol` VARCHAR(20) NOT NULL COMMENT '协议' ,
|
||||
`parent_id` VARCHAR(50) NOT NULL DEFAULT 'NONE' COMMENT '父级fk' ,
|
||||
`project_id` VARCHAR(50) NOT NULL COMMENT '项目fk' ,
|
||||
`level` INT NOT NULL DEFAULT 1 COMMENT '树节点级别' ,
|
||||
`pos` INT NOT NULL COMMENT '排序' ,
|
||||
`create_time` BIGINT NOT NULL COMMENT '创建时间' ,
|
||||
`update_time` BIGINT NOT NULL COMMENT '修改时间' ,
|
||||
|
@ -58,6 +57,7 @@ CREATE TABLE api_debug_module(
|
|||
CREATE INDEX idx_project_id ON api_debug_module(project_id);
|
||||
CREATE INDEX idx_protocol ON api_debug_module(protocol);
|
||||
CREATE INDEX idx_pos ON api_debug_module(pos);
|
||||
CREATE INDEX idx_create_user ON api_debug_module(create_user);
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS api_definition;
|
||||
|
|
|
@ -13,4 +13,6 @@ public class ModuleConstants {
|
|||
public static final String NODE_TYPE_GITEE = "Gitee";
|
||||
//GitLab节点类型
|
||||
public static final String NODE_TYPE_GITLAB = "GitLab";
|
||||
|
||||
public static final String NODE_PROTOCOL_HTTP = "HTTP";
|
||||
}
|
||||
|
|
|
@ -220,4 +220,13 @@ public class PermissionConstants {
|
|||
|
||||
|
||||
/*------ end: FUNCTIONAL_CASE ------*/
|
||||
|
||||
/*------ start: API_DEBUG ------*/
|
||||
public static final String PROJECT_API_DEBUG_READ = "PROJECT_API_DEBUG:READ";
|
||||
public static final String PROJECT_API_DEBUG_READ_ADD = "PROJECT_API_DEBUG:READ+ADD";
|
||||
public static final String PROJECT_API_DEBUG_READ_UPDATE = "PROJECT_API_DEBUG:READ+UPDATE";
|
||||
public static final String PROJECT_API_DEBUG_READ_DELETE = "PROJECT_API_DEBUG:READ+DELETE";
|
||||
public static final String PROJECT_API_DEBUG_READ_IMPORT = "PROJECT_API_DEBUG:READ+IMPORT";
|
||||
public static final String PROJECT_API_DEBUG_READ_EXECUTE = "PROJECT_API_DEBUG:READ+EXECUTE";
|
||||
/*------ end: API_DEBUG ------*/
|
||||
}
|
||||
|
|
|
@ -250,4 +250,27 @@ api_scenario_report_detail.report_id.not_blank=报告ID不能为空
|
|||
api_scenario_report_detail.resource_id.length_range=场景中各个步骤请求唯一标识长度必须在1-50之间
|
||||
api_scenario_report_detail.resource_id.not_blank=场景中各个步骤请求唯一标识不能为空
|
||||
#module:ApiDefinitionBlob
|
||||
api_definition_blob.api_definition_id.not_blank=接口ID/ 一对一关系不能为空
|
||||
api_definition_blob.api_definition_id.not_blank=接口ID/ 一对一关系不能为空
|
||||
#module: ApiDebug
|
||||
api_debug.id.not_blank=ID不能为空
|
||||
api_debug.id.length_range=接口ID长度必须在1-50之间
|
||||
api_debug.name.not_blank=接口名称不能为空
|
||||
api_debug.name.length_range=接口名称长度必须在1-255之间
|
||||
api_debug.protocol.not_blank=协议不能为空
|
||||
api_debug.protocol.length_range=协议长度必须在1-20之间
|
||||
api_debug.project_id.not_blank=项目ID不能为空
|
||||
api_debug.project_id.length_range=项目ID长度必须在1-50之间
|
||||
api_debug.module_id.not_blank=模块ID不能为空
|
||||
api_debug.module_id.length_range=模块ID长度必须在1-50之间
|
||||
#module: ApiDebugModule
|
||||
api_debug_module.id.not_blank=ID不能为空
|
||||
api_debug_module.id.length_range=模块ID长度必须在1-50之间
|
||||
api_debug_module.name.not_blank=模块名称不能为空
|
||||
api_debug_module.name.length_range=模块名称长度必须在1-255之间
|
||||
api_debug_module.parent_id.not_blank=父级ID不能为空
|
||||
api_debug_module.parent_id.length_range=父级ID长度必须在1-50之间
|
||||
api_debug_module.project_id.not_blank=项目ID不能为空
|
||||
api_debug_module.project_id.length_range=项目ID长度必须在1-50之间
|
||||
api_debug_module.pos.not_blank=模块位置不能为空
|
||||
api_debug_module.name.not_contain_slash=模块名称不能包含斜杠
|
||||
|
||||
|
|
|
@ -250,4 +250,27 @@ api_scenario_report_detail.report_id.not_blank=report fk cannot be empty
|
|||
api_scenario_report_detail.resource_id.length_range=Each step in the scenario requests a unique identifier length must be between 1-50
|
||||
api_scenario_report_detail.resource_id.not_blank=The unique identifier requested by each step in the scenario cannot be empty
|
||||
#module:ApiDefinitionBlob
|
||||
api_definition_blob.api_definition_id.not_blank=The interface fk/one-to-one relationship cannot be empty
|
||||
api_definition_blob.api_definition_id.not_blank=The interface fk/one-to-one relationship cannot be empty
|
||||
|
||||
api_debug.id.not_blank=ID cannot be blank
|
||||
api_debug.id.length_range=The interface ID length must be between 1-50
|
||||
api_debug.name.not_blank=Interface name cannot be blank
|
||||
api_debug.name.length_range=The interface name length must be between 1-255
|
||||
api_debug.protocol.not_blank=Protocol cannot be blank
|
||||
api_debug.protocol.length_range=Protocol length must be between 1-20
|
||||
api_debug.project_id.not_blank=Project ID cannot be blank
|
||||
api_debug.project_id.length_range=Project ID length must be between 1-50
|
||||
api_debug.module_id.not_blank=Module ID cannot be blank
|
||||
api_debug.module_id.length_range=Module ID length must be between 1-50
|
||||
#module: ApiDebugModule
|
||||
api_debug_module.id.not_blank=ID cannot be blank
|
||||
api_debug_module.id.length_range=Module ID length must be between 1-50
|
||||
api_debug_module.name.not_blank=Module name cannot be blank
|
||||
api_debug_module.name.length_range=Module name length must be between 1-255
|
||||
api_debug_module.parent_id.not_blank=Parent ID cannot be blank
|
||||
api_debug_module.parent_id.length_range=Parent ID length must be between 1-50
|
||||
api_debug_module.project_id.not_blank=Project ID cannot be blank
|
||||
api_debug_module.project_id.length_range=Project ID length must be between 1-50
|
||||
api_debug_module.pos.not_blank=Module position cannot be blank
|
||||
api_debug_module.name.not_contain_slash=Module name cannot contain slashes
|
||||
api_debug_module.unplanned_request=Unplanned request
|
|
@ -250,4 +250,28 @@ api_scenario_report_detail.report_id.not_blank=报告ID不能为空
|
|||
api_scenario_report_detail.resource_id.length_range=场景中各个步骤请求唯一标识长度必须在1-50之间
|
||||
api_scenario_report_detail.resource_id.not_blank=场景中各个步骤请求唯一标识不能为空
|
||||
#module:ApiDefinitionBlob
|
||||
api_definition_blob.api_definition_id.not_blank=接口ID/ 一对一关系不能为空
|
||||
api_definition_blob.api_definition_id.not_blank=接口ID/ 一对一关系不能为空
|
||||
|
||||
#module: ApiDebug
|
||||
api_debug.id.not_blank=ID不能为空
|
||||
api_debug.id.length_range=接口ID长度必须在1-50之间
|
||||
api_debug.name.not_blank=接口名称不能为空
|
||||
api_debug.name.length_range=接口名称长度必须在1-255之间
|
||||
api_debug.protocol.not_blank=协议不能为空
|
||||
api_debug.protocol.length_range=协议长度必须在1-20之间
|
||||
api_debug.project_id.not_blank=项目ID不能为空
|
||||
api_debug.project_id.length_range=项目ID长度必须在1-50之间
|
||||
api_debug.module_id.not_blank=模块ID不能为空
|
||||
api_debug.module_id.length_range=模块ID长度必须在1-50之间
|
||||
#module: ApiDebugModule
|
||||
api_debug_module.id.not_blank=ID不能为空
|
||||
api_debug_module.id.length_range=模块ID长度必须在1-50之间
|
||||
api_debug_module.name.not_blank=模块名称不能为空
|
||||
api_debug_module.name.length_range=模块名称长度必须在1-255之间
|
||||
api_debug_module.parent_id.not_blank=父级ID不能为空
|
||||
api_debug_module.parent_id.length_range=父级ID长度必须在1-50之间
|
||||
api_debug_module.project_id.not_blank=项目ID不能为空
|
||||
api_debug_module.project_id.length_range=项目ID长度必须在1-50之间
|
||||
api_debug_module.pos.not_blank=模块位置不能为空
|
||||
api_debug_module.name.not_contain_slash=名称中不能包含正反斜杠
|
||||
api_debug_module.unplanned_request=未规划请求
|
|
@ -250,4 +250,28 @@ api_scenario_report_detail.report_id.not_blank=報告ID不能為空
|
|||
api_scenario_report_detail.resource_id.length_range=場景中各個步驟請求唯一標識長度必須在1-50之間
|
||||
api_scenario_report_detail.resource_id.not_blank=場景中各個步驟請求唯一標識不能為空
|
||||
#module:ApiDefinitionBlob
|
||||
api_definition_blob.api_definition_id.not_blank=接口ID/ 一對一關繫不能為空
|
||||
api_definition_blob.api_definition_id.not_blank=接口ID/ 一對一關繫不能為空
|
||||
|
||||
#module: ApiDebug
|
||||
api_debug.id.not_blank=ID不能為空
|
||||
api_debug.id.length_range=接口ID長度必須在1-50之間
|
||||
api_debug.name.not_blank=接口名稱不能為空
|
||||
api_debug.name.length_range=接口名稱長度必須在1-255之間
|
||||
api_debug.protocol.not_blank=協定不能為空
|
||||
api_debug.protocol.length_range=協定長度必須在1-20之間
|
||||
api_debug.project_id.not_blank=項目ID不能為空
|
||||
api_debug.project_id.length_range=項目ID長度必須在1-50之間
|
||||
api_debug.module_id.not_blank=模塊ID不能為空
|
||||
api_debug.module_id.length_range=模塊ID長度必須在1-50之間
|
||||
#module: ApiDebugModule
|
||||
api_debug_module.id.not_blank=ID不能為空
|
||||
api_debug_module.id.length_range=模塊ID長度必須在1-50之間
|
||||
api_debug_module.name.not_blank=模塊名稱不能為空
|
||||
api_debug_module.name.length_range=模塊名稱長度必須在1-255之間
|
||||
api_debug_module.parent_id.not_blank=父級ID不能為空
|
||||
api_debug_module.parent_id.length_range=父級ID長度必須在1-50之間
|
||||
api_debug_module.project_id.not_blank=項目ID不能為空
|
||||
api_debug_module.project_id.length_range=項目ID長度必須在1-50之間
|
||||
api_debug_module.pos.not_blank=模塊位置不能為空
|
||||
api_debug_module.name.not_contain_slash=模塊名稱不能包含斜線
|
||||
api_debug_module.unplanned_request=未規劃請求
|
|
@ -0,0 +1,71 @@
|
|||
package io.metersphere.api.controller;
|
||||
|
||||
import io.metersphere.api.request.ApiDebugRequest;
|
||||
import io.metersphere.api.request.DebugModuleCreateRequest;
|
||||
import io.metersphere.api.request.DebugModuleUpdateRequest;
|
||||
import io.metersphere.api.service.ApiDebugModuleService;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||
import io.metersphere.system.dto.sdk.request.NodeMoveRequest;
|
||||
import io.metersphere.system.utils.SessionUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "接口测试-接口调试-模块")
|
||||
@RestController
|
||||
@RequestMapping("/api/debug/module")
|
||||
public class ApiDebugModuleController {
|
||||
|
||||
@Resource
|
||||
private ApiDebugModuleService apiDebugModuleService;
|
||||
|
||||
@GetMapping("/tree/{protocol}")
|
||||
@Operation(summary = "接口测试-接口调试-模块-查找模块")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEBUG_READ)
|
||||
public List<BaseTreeNode> getTree(@PathVariable String protocol) {
|
||||
return apiDebugModuleService.getTree(protocol, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
@Operation(summary = "接口测试-接口调试-模块-添加模块")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEBUG_READ_ADD)
|
||||
public String add(@RequestBody @Validated DebugModuleCreateRequest request) {
|
||||
return apiDebugModuleService.add(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "接口测试-接口调试-模块-修改模块")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEBUG_READ_UPDATE)
|
||||
public boolean list(@RequestBody @Validated DebugModuleUpdateRequest request) {
|
||||
apiDebugModuleService.update(request, SessionUtils.getUserId(), SessionUtils.getCurrentProjectId());
|
||||
return true;
|
||||
}
|
||||
|
||||
@GetMapping("/delete/{deleteId}")
|
||||
@Operation(summary = "接口测试-接口调试-模块-删除模块")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEBUG_READ_DELETE)
|
||||
public void deleteNode(@PathVariable String deleteId) {
|
||||
apiDebugModuleService.deleteModule(deleteId, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping("/move")
|
||||
@Operation(summary = "接口测试-接口调试-模块-移动模块")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEBUG_READ_UPDATE)
|
||||
public void moveNode(@Validated @RequestBody NodeMoveRequest request) {
|
||||
apiDebugModuleService.moveNode(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping("/count")
|
||||
@Operation(summary = "接口测试-接口调试-模块-统计模块数量")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEBUG_READ)
|
||||
public Map<String, Long> moduleCount(@Validated @RequestBody ApiDebugRequest request) {
|
||||
return apiDebugModuleService.moduleCount(request, SessionUtils.getUserId());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package io.metersphere.api.mapper;
|
||||
|
||||
import io.metersphere.api.domain.ApiDebugModule;
|
||||
import io.metersphere.api.request.ApiDebugRequest;
|
||||
import io.metersphere.api.request.ApiTreeNode;
|
||||
import io.metersphere.project.dto.ModuleCountDTO;
|
||||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtApiDebugModuleMapper {
|
||||
List<BaseTreeNode> selectBaseByProtocolAndUser(String protocol, String userId);
|
||||
|
||||
List<BaseTreeNode> selectIdAndParentIdByProtocolAndUserId(String protocol, String userId);
|
||||
|
||||
List<String> selectChildrenIdsByParentIds(@Param("ids") List<String> deleteIds);
|
||||
|
||||
List<String> selectChildrenIdsSortByPos(String parentId);
|
||||
|
||||
void deleteByIds(@Param("ids") List<String> deleteId);
|
||||
|
||||
Integer getMaxPosByParentId(String parentId);
|
||||
|
||||
List<String> selectIdsByProjectId(String projectId);
|
||||
|
||||
ApiDebugModule getLastModuleByParentId(String id);
|
||||
|
||||
ApiDebugModule getNextModuleInParentId(@Param("parentId") String parentId, @Param("pos") int pos);
|
||||
|
||||
ApiDebugModule getPreviousModuleInParentId(@Param("parentId") String parentId, @Param("pos") int pos);
|
||||
|
||||
List<ApiTreeNode> selectApiDebugByProtocolAndUser(String protocol, String userId);
|
||||
|
||||
List<ModuleCountDTO> countModuleIdByKeywordAndProtocol(@Param("request") ApiDebugRequest request, @Param("userId") String userId);
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.metersphere.api.mapper.ExtApiDebugModuleMapper">
|
||||
<select id="selectBaseByProtocolAndUser" resultType="io.metersphere.system.dto.sdk.BaseTreeNode">
|
||||
SELECT id,
|
||||
NAME,
|
||||
parent_id AS parentId,
|
||||
'module' AS type
|
||||
FROM api_debug_module
|
||||
WHERE protocol = #{protocol}
|
||||
AND create_user = #{userId}
|
||||
ORDER BY pos
|
||||
</select>
|
||||
<select id="selectIdAndParentIdByProtocolAndUserId" resultType="io.metersphere.system.dto.sdk.BaseTreeNode">
|
||||
SELECT id,
|
||||
parent_id AS parentId
|
||||
FROM api_debug_module
|
||||
WHERE protocol = #{protocol}
|
||||
|
||||
AND create_user = #{userId}
|
||||
</select>
|
||||
<select id="selectIdsByProjectId" resultType="java.lang.String">
|
||||
SELECT id
|
||||
FROM api_debug_module
|
||||
WHERE project_id = #{0}
|
||||
</select>
|
||||
<select id="selectChildrenIdsByParentIds" resultType="java.lang.String">
|
||||
SELECT id
|
||||
FROM api_debug_module
|
||||
WHERE parent_id IN
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
<delete id="deleteByIds">
|
||||
DELETE
|
||||
FROM api_debug_module
|
||||
WHERE id IN
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
<select id="getMaxPosByParentId" resultType="java.lang.Integer">
|
||||
SELECT max(pos)
|
||||
FROM api_debug_module
|
||||
WHERE parent_id = #{0}
|
||||
</select>
|
||||
<select id="selectChildrenIdsSortByPos" resultType="java.lang.String">
|
||||
SELECT id
|
||||
FROM api_debug_module
|
||||
WHERE parent_id = #{0}
|
||||
|
||||
ORDER BY pos ASC
|
||||
</select>
|
||||
<select id="getLastModuleByParentId" resultType="io.metersphere.api.domain.ApiDebugModule">
|
||||
SELECT *
|
||||
FROM api_debug_module
|
||||
WHERE parent_id = #{0}
|
||||
|
||||
ORDER BY pos DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
<select id="getNextModuleInParentId" resultType="io.metersphere.api.domain.ApiDebugModule">
|
||||
SELECT *
|
||||
from api_debug_module
|
||||
WHERE parent_id = #{parentId}
|
||||
AND pos > #{pos}
|
||||
order by pos asc
|
||||
limit 1
|
||||
</select>
|
||||
<select id="getPreviousModuleInParentId" resultType="io.metersphere.api.domain.ApiDebugModule">
|
||||
SELECT *
|
||||
from api_debug_module
|
||||
WHERE parent_id = #{parentId}
|
||||
AND pos < #{pos}
|
||||
order by pos
|
||||
desc
|
||||
limit 1
|
||||
</select>
|
||||
<select id="selectApiDebugByProtocolAndUser" resultType="io.metersphere.api.request.ApiTreeNode">
|
||||
SELECT id,
|
||||
NAME,
|
||||
module_id AS parentId,
|
||||
'api' AS type,
|
||||
method
|
||||
FROM api_debug
|
||||
WHERE protocol = #{protocol}
|
||||
|
||||
AND create_user = #{userId}
|
||||
|
||||
ORDER BY update_time DESC
|
||||
</select>
|
||||
<select id="countModuleIdByKeywordAndProtocol" resultType="io.metersphere.project.dto.ModuleCountDTO">
|
||||
SELECT f.module_id AS moduleId, count(f.id) AS dataCount
|
||||
FROM api_debug f
|
||||
<include refid="debug_page_request"/>
|
||||
GROUP BY f.module_id
|
||||
</select>
|
||||
|
||||
<sql id="debug_page_request">
|
||||
<where>
|
||||
f.create_user = #{userId}
|
||||
<if test="request.keyword != null and request.keyword != ''">
|
||||
AND f.name like CONCAT('%', #{request.keyword},'%')
|
||||
</if>
|
||||
<if test="request.moduleIds != null and request.moduleIds.size() != 0">
|
||||
AND f.module_id IN
|
||||
<foreach collection="request.moduleIds" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="request.protocol != null and request.protocol != ''">
|
||||
AND f.protocol = #{request.protocol}
|
||||
</if>
|
||||
|
||||
</where>
|
||||
</sql>
|
||||
</mapper>
|
|
@ -0,0 +1,23 @@
|
|||
package io.metersphere.api.request;
|
||||
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ApiDebugRequest {
|
||||
@Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)")
|
||||
private List<String> moduleIds;
|
||||
|
||||
@Schema(description = "协议", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{api_debug_module.protocol.not_blank}")
|
||||
@Size(min = 1, max = 20, message = "{api_debug.protocol.length_range}")
|
||||
private String protocol = ModuleConstants.NODE_PROTOCOL_HTTP;
|
||||
|
||||
@Schema(description = "关键字")
|
||||
private String keyword;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package io.metersphere.api.request;
|
||||
|
||||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ApiTreeNode extends BaseTreeNode {
|
||||
@Schema(description = "方法")
|
||||
private String method;
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package io.metersphere.api.request;
|
||||
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
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.NotEmpty;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DebugModuleCreateRequest {
|
||||
|
||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{project.id.not_blank}")
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "模块名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "{file_module.name.not_blank}")
|
||||
@Pattern(regexp = "^[^\\\\/]*$", message = "{api_debug_module.name.not_contain_slash}")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "父模块ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "{parent.node.not_blank}")
|
||||
private String parentId = ModuleConstants.ROOT_NODE_PARENT_ID;
|
||||
|
||||
@Schema(description = "协议", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{api_debug_module.protocol.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 20, message = "{api_debug.protocol.length_range}", groups = {Created.class, Updated.class})
|
||||
private String protocol = ModuleConstants.NODE_PROTOCOL_HTTP;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package io.metersphere.api.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DebugModuleUpdateRequest {
|
||||
@Schema(description = "模块ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{file_module.id.not_blank}")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "模块名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "{file_module.name.not_blank}")
|
||||
@Pattern(regexp = "^[^\\\\/]*$", message = "{api_debug_module.name.not_contain_slash}")
|
||||
private String name;
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
package io.metersphere.api.service;
|
||||
|
||||
import io.metersphere.api.domain.ApiDebugModule;
|
||||
import io.metersphere.project.domain.Project;
|
||||
import io.metersphere.project.dto.NodeSortDTO;
|
||||
import io.metersphere.project.mapper.ProjectMapper;
|
||||
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.dto.builder.LogDTOBuilder;
|
||||
import io.metersphere.system.dto.sdk.BaseModule;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.log.dto.LogDTO;
|
||||
import io.metersphere.system.log.service.OperationLogService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class ApiDebugModuleLogService {
|
||||
private static final String API_DEBUG_MODULE = "/api/debug/module";
|
||||
private static final String ADD = API_DEBUG_MODULE + "/add";
|
||||
private static final String UPDATE = API_DEBUG_MODULE + "/update";
|
||||
private static final String DELETE = API_DEBUG_MODULE + "/delete";
|
||||
private static final String MOVE = API_DEBUG_MODULE + "/move";
|
||||
private static final String MOVE_TO = "file.log.move_to";
|
||||
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private OperationLogService operationLogService;
|
||||
|
||||
public void saveAddLog(ApiDebugModule module, String operator) {
|
||||
Project project = projectMapper.selectByPrimaryKey(module.getProjectId());
|
||||
LogDTO dto = LogDTOBuilder.builder()
|
||||
.projectId(module.getProjectId())
|
||||
.organizationId(project.getOrganizationId())
|
||||
.type(OperationLogType.ADD.name())
|
||||
.module(OperationLogModule.API_DEBUG)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path(ADD)
|
||||
.sourceId(module.getId())
|
||||
.content(module.getName())
|
||||
.originalValue(JSON.toJSONBytes(module))
|
||||
.createUser(operator)
|
||||
.build().getLogDTO();
|
||||
operationLogService.add(dto);
|
||||
}
|
||||
|
||||
public void saveUpdateLog(ApiDebugModule module, String projectId, String operator) {
|
||||
Project project = projectMapper.selectByPrimaryKey(projectId);
|
||||
LogDTO dto = LogDTOBuilder.builder()
|
||||
.projectId(projectId)
|
||||
.organizationId(project.getOrganizationId())
|
||||
.type(OperationLogType.UPDATE.name())
|
||||
.module(OperationLogModule.API_DEBUG)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path(UPDATE)
|
||||
.sourceId(module.getId())
|
||||
.content(module.getName())
|
||||
.originalValue(JSON.toJSONBytes(module))
|
||||
.createUser(operator)
|
||||
.build().getLogDTO();
|
||||
|
||||
operationLogService.add(dto);
|
||||
}
|
||||
|
||||
public void saveDeleteLog(ApiDebugModule deleteModule, String operator) {
|
||||
Project project = projectMapper.selectByPrimaryKey(deleteModule.getProjectId());
|
||||
LogDTO dto = LogDTOBuilder.builder()
|
||||
.projectId(deleteModule.getProjectId())
|
||||
.organizationId(project.getOrganizationId())
|
||||
.type(OperationLogType.DELETE.name())
|
||||
.module(OperationLogModule.API_DEBUG)
|
||||
.method(HttpMethodConstants.GET.name())
|
||||
.path(DELETE + "/%s")
|
||||
.sourceId(deleteModule.getId())
|
||||
.content(deleteModule.getName() + " " + Translator.get("file.log.delete_module"))
|
||||
.originalValue(JSON.toJSONBytes(deleteModule))
|
||||
.createUser(operator)
|
||||
.build().getLogDTO();
|
||||
operationLogService.add(dto);
|
||||
}
|
||||
|
||||
public void saveMoveLog(@Validated NodeSortDTO request, String operator) {
|
||||
BaseModule moveNode = request.getNode();
|
||||
BaseModule previousNode = request.getPreviousNode();
|
||||
BaseModule nextNode = request.getNextNode();
|
||||
BaseModule parentModule = request.getParent();
|
||||
|
||||
Project project = projectMapper.selectByPrimaryKey(moveNode.getProjectId());
|
||||
String logContent;
|
||||
if (nextNode == null && previousNode == null) {
|
||||
logContent = moveNode.getName() + " " + Translator.get(MOVE_TO) + parentModule.getName();
|
||||
} else if (nextNode == null) {
|
||||
logContent = moveNode.getName() + " " + Translator.get(MOVE_TO) + parentModule.getName() + " " + previousNode.getName() + Translator.get("file.log.next");
|
||||
} else if (previousNode == null) {
|
||||
logContent = moveNode.getName() + " " + Translator.get(MOVE_TO) + parentModule.getName() + " " + nextNode.getName() + Translator.get("file.log.previous");
|
||||
} else {
|
||||
logContent = moveNode.getName() + " " + Translator.get(MOVE_TO) + parentModule.getName() + " " +
|
||||
previousNode.getName() + Translator.get("file.log.next") + " " + nextNode.getName() + Translator.get("file.log.previous");
|
||||
}
|
||||
LogDTO dto = LogDTOBuilder.builder()
|
||||
.projectId(moveNode.getProjectId())
|
||||
.organizationId(project.getOrganizationId())
|
||||
.type(OperationLogType.UPDATE.name())
|
||||
.module(OperationLogModule.API_DEBUG)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path(MOVE)
|
||||
.sourceId(moveNode.getId())
|
||||
.content(logContent)
|
||||
.originalValue(JSON.toJSONBytes(moveNode))
|
||||
.createUser(operator)
|
||||
.build().getLogDTO();
|
||||
operationLogService.add(dto);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,333 @@
|
|||
package io.metersphere.api.service;
|
||||
|
||||
import io.metersphere.api.domain.*;
|
||||
import io.metersphere.api.mapper.ApiDebugBlobMapper;
|
||||
import io.metersphere.api.mapper.ApiDebugMapper;
|
||||
import io.metersphere.api.mapper.ApiDebugModuleMapper;
|
||||
import io.metersphere.api.mapper.ExtApiDebugModuleMapper;
|
||||
import io.metersphere.api.request.ApiDebugRequest;
|
||||
import io.metersphere.api.request.ApiTreeNode;
|
||||
import io.metersphere.api.request.DebugModuleCreateRequest;
|
||||
import io.metersphere.api.request.DebugModuleUpdateRequest;
|
||||
import io.metersphere.project.dto.ModuleCountDTO;
|
||||
import io.metersphere.project.dto.NodeSortDTO;
|
||||
import io.metersphere.project.service.ModuleTreeService;
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.dto.sdk.BaseModule;
|
||||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||
import io.metersphere.system.dto.sdk.request.NodeMoveRequest;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.session.ExecutorType;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class ApiDebugModuleService extends ModuleTreeService {
|
||||
private static final String UNPLANNED = "api_debug_module.unplanned_request";
|
||||
private static final String METHOD = "method";
|
||||
private static final String DEBUG_MODULE_COUNT_ALL = "all";
|
||||
@Resource
|
||||
private ApiDebugModuleLogService apiDebugModuleLogService;
|
||||
@Resource
|
||||
private ApiDebugModuleMapper apiDebugModuleMapper;
|
||||
@Resource
|
||||
private ExtApiDebugModuleMapper extApiDebugModuleMapper;
|
||||
@Resource
|
||||
private ApiDebugMapper apiDebugMapper;
|
||||
@Resource
|
||||
private ApiDebugBlobMapper apiDebugBlobMapper;
|
||||
@Resource
|
||||
private SqlSessionFactory sqlSessionFactory;
|
||||
|
||||
public List<BaseTreeNode> getTree(String protocol, String userId) {
|
||||
List<BaseTreeNode> fileModuleList = extApiDebugModuleMapper.selectBaseByProtocolAndUser(protocol, userId);
|
||||
List<BaseTreeNode> baseTreeNodes = super.buildTreeAndCountResource(fileModuleList, true, Translator.get(UNPLANNED));
|
||||
List<ApiTreeNode> apiTreeNodeList = extApiDebugModuleMapper.selectApiDebugByProtocolAndUser(protocol, userId);
|
||||
//将apiTreeNodeList转换成BaseTreeNode method放入map中
|
||||
if (CollectionUtils.isEmpty(apiTreeNodeList)) {
|
||||
return baseTreeNodes;
|
||||
}
|
||||
List<BaseTreeNode> nodeList = apiTreeNodeList.stream().map(apiTreeNode -> {
|
||||
BaseTreeNode baseTreeNode = new BaseTreeNode();
|
||||
baseTreeNode.setId(apiTreeNode.getId());
|
||||
baseTreeNode.setName(apiTreeNode.getName());
|
||||
baseTreeNode.setParentId(apiTreeNode.getParentId());
|
||||
baseTreeNode.setType(apiTreeNode.getType());
|
||||
baseTreeNode.putAttachInfo(METHOD, apiTreeNode.getMethod());
|
||||
return baseTreeNode;
|
||||
}).toList();
|
||||
//apiTreeNodeList使用stream实现将parentId分组生成map
|
||||
Map<String, List<BaseTreeNode>> apiTreeNodeMap = nodeList.stream().collect(Collectors.groupingBy(BaseTreeNode::getParentId));
|
||||
//遍历baseTreeNodes,将apiTreeNodeMap中的id相等的数据添加到baseTreeNodes中
|
||||
return generateTree(baseTreeNodes, apiTreeNodeMap);
|
||||
|
||||
}
|
||||
|
||||
//生成树结构
|
||||
public List<BaseTreeNode> generateTree(List<BaseTreeNode> baseTreeNodes, Map<String, List<BaseTreeNode>> apiTreeNodeMap) {
|
||||
baseTreeNodes.forEach(baseTreeNode -> {
|
||||
if (apiTreeNodeMap.containsKey(baseTreeNode.getId())) {
|
||||
baseTreeNode.getChildren().addAll(apiTreeNodeMap.get(baseTreeNode.getId()));
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(baseTreeNode.getChildren())) {
|
||||
generateTree(baseTreeNode.getChildren(), apiTreeNodeMap);
|
||||
}
|
||||
});
|
||||
return baseTreeNodes;
|
||||
}
|
||||
|
||||
public List<BaseTreeNode> getTreeOnlyIdsAndResourceCount(String protocol, String userId, List<ModuleCountDTO> moduleCountDTOList) {
|
||||
//节点内容只有Id和parentId
|
||||
List<BaseTreeNode> fileModuleList = extApiDebugModuleMapper.selectIdAndParentIdByProtocolAndUserId(protocol, userId);
|
||||
return super.buildTreeAndCountResource(fileModuleList, moduleCountDTOList, true, Translator.get(UNPLANNED));
|
||||
}
|
||||
|
||||
public String add(DebugModuleCreateRequest request, String operator) {
|
||||
ApiDebugModule apiDebugModule = new ApiDebugModule();
|
||||
apiDebugModule.setId(IDGenerator.nextStr());
|
||||
apiDebugModule.setName(request.getName());
|
||||
apiDebugModule.setParentId(request.getParentId());
|
||||
apiDebugModule.setProjectId(request.getProjectId());
|
||||
apiDebugModule.setProtocol(request.getProtocol());
|
||||
apiDebugModule.setCreateUser(operator);
|
||||
this.checkDataValidity(apiDebugModule);
|
||||
apiDebugModule.setCreateTime(System.currentTimeMillis());
|
||||
apiDebugModule.setUpdateTime(apiDebugModule.getCreateTime());
|
||||
apiDebugModule.setPos(this.countPos(request.getParentId()));
|
||||
apiDebugModule.setUpdateUser(operator);
|
||||
apiDebugModuleMapper.insert(apiDebugModule);
|
||||
//记录日志
|
||||
apiDebugModuleLogService.saveAddLog(apiDebugModule, operator);
|
||||
return apiDebugModule.getId();
|
||||
}
|
||||
|
||||
private Integer countPos(String parentId) {
|
||||
Integer maxPos = extApiDebugModuleMapper.getMaxPosByParentId(parentId);
|
||||
if (maxPos == null) {
|
||||
return LIMIT_POS;
|
||||
} else {
|
||||
return maxPos + LIMIT_POS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查数据的合法性
|
||||
*/
|
||||
private void checkDataValidity(ApiDebugModule apiDebugModule) {
|
||||
ApiDebugModuleExample example = new ApiDebugModuleExample();
|
||||
if (!StringUtils.equals(apiDebugModule.getParentId(), ModuleConstants.ROOT_NODE_PARENT_ID)) {
|
||||
//检查父ID是否存在 调试模块的逻辑是 同一个用户下的同级模块不能重名 每个协议是不同的模块
|
||||
example.createCriteria().andIdEqualTo(apiDebugModule.getParentId())
|
||||
.andCreateUserEqualTo(apiDebugModule.getCreateUser())
|
||||
.andProtocolEqualTo(apiDebugModule.getProtocol());
|
||||
if (apiDebugModuleMapper.countByExample(example) == 0) {
|
||||
throw new MSException(Translator.get("parent.node.not_blank"));
|
||||
}
|
||||
example.clear();
|
||||
}
|
||||
example.createCriteria().andParentIdEqualTo(apiDebugModule.getParentId())
|
||||
.andNameEqualTo(apiDebugModule.getName())
|
||||
.andIdNotEqualTo(apiDebugModule.getId())
|
||||
.andCreateUserEqualTo(apiDebugModule.getCreateUser())
|
||||
.andProtocolEqualTo(apiDebugModule.getProtocol());
|
||||
if (apiDebugModuleMapper.countByExample(example) > 0) {
|
||||
throw new MSException(Translator.get("node.name.repeat"));
|
||||
}
|
||||
example.clear();
|
||||
}
|
||||
|
||||
public void update(DebugModuleUpdateRequest request, String userId, String projectId) {
|
||||
ApiDebugModule module = apiDebugModuleMapper.selectByPrimaryKey(request.getId());
|
||||
if (module == null) {
|
||||
throw new MSException("file_module.not.exist");
|
||||
}
|
||||
ApiDebugModule updateModule = new ApiDebugModule();
|
||||
updateModule.setId(request.getId());
|
||||
updateModule.setName(request.getName());
|
||||
updateModule.setParentId(module.getParentId());
|
||||
updateModule.setProtocol(module.getProtocol());
|
||||
updateModule.setCreateUser(module.getCreateUser());
|
||||
this.checkDataValidity(updateModule);
|
||||
updateModule.setUpdateTime(System.currentTimeMillis());
|
||||
updateModule.setUpdateUser(userId);
|
||||
updateModule.setProjectId(projectId);
|
||||
apiDebugModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||
//记录日志
|
||||
apiDebugModuleLogService.saveUpdateLog(updateModule, projectId, userId);
|
||||
}
|
||||
|
||||
|
||||
public void deleteModule(String deleteId, String currentUser) {
|
||||
ApiDebugModule deleteModule = apiDebugModuleMapper.selectByPrimaryKey(deleteId);
|
||||
if (deleteModule != null) {
|
||||
this.deleteModule(Collections.singletonList(deleteId));
|
||||
//记录日志
|
||||
apiDebugModuleLogService.saveDeleteLog(deleteModule, currentUser);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteModule(List<String> deleteIds) {
|
||||
if (CollectionUtils.isEmpty(deleteIds)) {
|
||||
return;
|
||||
}
|
||||
extApiDebugModuleMapper.deleteByIds(deleteIds);
|
||||
//删除模块下的所有接口
|
||||
ApiDebugExample example = new ApiDebugExample();
|
||||
example.createCriteria().andModuleIdIn(deleteIds);
|
||||
List<ApiDebug> apiDebugs = apiDebugMapper.selectByExample(example);
|
||||
if (CollectionUtils.isNotEmpty(apiDebugs)) {
|
||||
List<String> apiDebugIds = apiDebugs.stream().map(ApiDebug::getId).collect(Collectors.toList());
|
||||
apiDebugMapper.deleteByExample(example);
|
||||
ApiDebugBlobExample blobExample = new ApiDebugBlobExample();
|
||||
blobExample.createCriteria().andIdIn(apiDebugIds);
|
||||
apiDebugBlobMapper.deleteByExample(blobExample);
|
||||
}
|
||||
|
||||
List<String> childrenIds = extApiDebugModuleMapper.selectChildrenIdsByParentIds(deleteIds);
|
||||
if (CollectionUtils.isNotEmpty(childrenIds)) {
|
||||
deleteModule(childrenIds);
|
||||
}
|
||||
}
|
||||
|
||||
public void moveNode(NodeMoveRequest request, String currentUser) {
|
||||
BaseModule module;
|
||||
BaseModule parentModule;
|
||||
BaseModule previousNode = null;
|
||||
BaseModule nextNode = null;
|
||||
|
||||
ApiDebugModule dragNode = apiDebugModuleMapper.selectByPrimaryKey(request.getDragNodeId());
|
||||
if (dragNode == null) {
|
||||
throw new MSException("file_module.not.exist:" + request.getDragNodeId());
|
||||
} else {
|
||||
module = new BaseModule(dragNode.getId(), dragNode.getName(), dragNode.getPos(), dragNode.getProjectId(), dragNode.getParentId());
|
||||
}
|
||||
|
||||
if (StringUtils.equals(request.getDragNodeId(), request.getDropNodeId())) {
|
||||
//两种节点不能一样
|
||||
throw new MSException(Translator.get("invalid_parameter"));
|
||||
}
|
||||
|
||||
ApiDebugModule dropNode = apiDebugModuleMapper.selectByPrimaryKey(request.getDropNodeId());
|
||||
if (dropNode == null) {
|
||||
throw new MSException("file_module.not.exist:" + request.getDropNodeId());
|
||||
}
|
||||
|
||||
if (request.getDropPosition() == 0) {
|
||||
//dropPosition=0: 放到dropNode节点内,最后一个节点之后
|
||||
parentModule = new BaseModule(dropNode.getId(), dropNode.getName(), dropNode.getPos(), dropNode.getProjectId(), dropNode.getParentId());
|
||||
ApiDebugModule previousModule = extApiDebugModuleMapper.getLastModuleByParentId(parentModule.getId());
|
||||
if (previousModule != null) {
|
||||
previousNode = new BaseModule(previousModule.getId(), previousModule.getName(), previousModule.getPos(), previousModule.getProjectId(), previousModule.getParentId());
|
||||
}
|
||||
} else {
|
||||
if (StringUtils.equals(dropNode.getParentId(), ModuleConstants.ROOT_NODE_PARENT_ID)) {
|
||||
parentModule = new BaseModule(ModuleConstants.ROOT_NODE_PARENT_ID, ModuleConstants.ROOT_NODE_PARENT_ID, 0, module.getProjectId(), ModuleConstants.ROOT_NODE_PARENT_ID);
|
||||
} else {
|
||||
ApiDebugModule parent = apiDebugModuleMapper.selectByPrimaryKey(dropNode.getParentId());
|
||||
parentModule = new BaseModule(parent.getId(), parent.getName(), parent.getPos(), parent.getProjectId(), parent.getParentId());
|
||||
}
|
||||
|
||||
if (request.getDropPosition() == 1) {
|
||||
//dropPosition=1: 放到dropNode节点后,原dropNode后面的节点之前
|
||||
previousNode = new BaseModule(dropNode.getId(), dropNode.getName(), dropNode.getPos(), dropNode.getProjectId(), dropNode.getParentId());
|
||||
ApiDebugModule nextModule = extApiDebugModuleMapper.getNextModuleInParentId(previousNode.getParentId(), previousNode.getPos());
|
||||
if (nextModule != null) {
|
||||
nextNode = new BaseModule(nextModule.getId(), nextModule.getName(), nextModule.getPos(), nextModule.getProjectId(), nextModule.getParentId());
|
||||
}
|
||||
} else if (request.getDropPosition() == -1) {
|
||||
//dropPosition=-1: 放到dropNode节点前,原dropNode前面的节点之后
|
||||
nextNode = new BaseModule(dropNode.getId(), dropNode.getName(), dropNode.getPos(), dropNode.getProjectId(), dropNode.getParentId());
|
||||
ApiDebugModule previousModule = extApiDebugModuleMapper.getPreviousModuleInParentId(nextNode.getParentId(), nextNode.getPos());
|
||||
if (previousModule != null) {
|
||||
previousNode = new BaseModule(previousModule.getId(), previousModule.getName(), previousModule.getPos(), previousModule.getProjectId(), previousModule.getParentId());
|
||||
}
|
||||
} else {
|
||||
throw new MSException(Translator.get("invalid_parameter"));
|
||||
}
|
||||
}
|
||||
|
||||
ApiDebugModuleExample example = new ApiDebugModuleExample();
|
||||
example.createCriteria().andParentIdEqualTo(parentModule.getId()).andIdEqualTo(module.getId());
|
||||
//节点换到了别的节点下,要先更新parent节点.
|
||||
if (apiDebugModuleMapper.countByExample(example) == 0) {
|
||||
ApiDebugModule fileModule = new ApiDebugModule();
|
||||
fileModule.setId(module.getId());
|
||||
fileModule.setParentId(parentModule.getId());
|
||||
apiDebugModuleMapper.updateByPrimaryKeySelective(fileModule);
|
||||
}
|
||||
|
||||
NodeSortDTO nodeMoveDTO = new NodeSortDTO(module, parentModule, previousNode, nextNode);
|
||||
super.sort(nodeMoveDTO);
|
||||
|
||||
//记录日志
|
||||
apiDebugModuleLogService.saveMoveLog(nodeMoveDTO, currentUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找当前项目下模块每个节点对应的资源统计
|
||||
*/
|
||||
public Map<String, Long> getModuleCountMap(String protocol, String userId, List<ModuleCountDTO> moduleCountDTOList) {
|
||||
Map<String, Long> returnMap = new HashMap<>();
|
||||
//构建模块树,并计算每个节点下的所有数量(包含子节点)
|
||||
List<BaseTreeNode> treeNodeList = this.getTreeOnlyIdsAndResourceCount(protocol, userId, moduleCountDTOList);
|
||||
//通过广度遍历的方式构建返回值
|
||||
List<BaseTreeNode> whileList = new ArrayList<>(treeNodeList);
|
||||
while (CollectionUtils.isNotEmpty(whileList)) {
|
||||
List<BaseTreeNode> childList = new ArrayList<>();
|
||||
for (BaseTreeNode treeNode : whileList) {
|
||||
returnMap.put(treeNode.getId(), treeNode.getCount());
|
||||
childList.addAll(treeNode.getChildren());
|
||||
}
|
||||
whileList = childList;
|
||||
}
|
||||
return returnMap;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updatePos(String id, int pos) {
|
||||
ApiDebugModule updateModule = new ApiDebugModule();
|
||||
updateModule.setPos(pos);
|
||||
updateModule.setId(id);
|
||||
apiDebugModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshPos(String parentId) {
|
||||
List<String> childrenIdSortByPos = extApiDebugModuleMapper.selectChildrenIdsSortByPos(parentId);
|
||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
ApiDebugModuleMapper batchUpdateMapper = sqlSession.getMapper(ApiDebugModuleMapper.class);
|
||||
for (int i = 0; i < childrenIdSortByPos.size(); i++) {
|
||||
String nodeId = childrenIdSortByPos.get(i);
|
||||
ApiDebugModule updateModule = new ApiDebugModule();
|
||||
updateModule.setId(nodeId);
|
||||
updateModule.setPos((i + 1) * LIMIT_POS);
|
||||
batchUpdateMapper.updateByPrimaryKeySelective(updateModule);
|
||||
}
|
||||
sqlSession.flushStatements();
|
||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
}
|
||||
|
||||
public Map<String, Long> moduleCount(ApiDebugRequest request, String operator) {
|
||||
//查出每个模块节点下的资源数量。 不需要按照模块进行筛选
|
||||
request.setModuleIds(null);
|
||||
List<ModuleCountDTO> moduleCountDTOList = extApiDebugModuleMapper.countModuleIdByKeywordAndProtocol(request, operator);
|
||||
long allCount = getAllCount(moduleCountDTOList);
|
||||
Map<String, Long> moduleCountMap = getModuleCountMap(request.getProtocol(), operator, moduleCountDTOList);
|
||||
moduleCountMap.put(DEBUG_MODULE_COUNT_ALL, allCount);
|
||||
return moduleCountMap;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,822 @@
|
|||
package io.metersphere.api.controller;
|
||||
|
||||
import io.metersphere.api.domain.*;
|
||||
import io.metersphere.api.mapper.ApiDebugBlobMapper;
|
||||
import io.metersphere.api.mapper.ApiDebugMapper;
|
||||
import io.metersphere.api.mapper.ApiDebugModuleMapper;
|
||||
import io.metersphere.api.request.ApiDebugRequest;
|
||||
import io.metersphere.api.request.DebugModuleCreateRequest;
|
||||
import io.metersphere.api.request.DebugModuleUpdateRequest;
|
||||
import io.metersphere.api.service.ApiDebugModuleService;
|
||||
import io.metersphere.project.domain.Project;
|
||||
import io.metersphere.project.mapper.ProjectMapper;
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.sdk.constants.SessionConstants;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.base.BaseTest;
|
||||
import io.metersphere.system.controller.handler.ResultHolder;
|
||||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||
import io.metersphere.system.dto.sdk.request.NodeMoveRequest;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.ResultMatcher;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
@AutoConfigureMockMvc
|
||||
public class ApiDebugModuleControllerTests extends BaseTest {
|
||||
|
||||
private static final String URL_MODULE_ADD = "/api/debug/module/add";
|
||||
private static final String URL_MODULE_UPDATE = "/api/debug/module/update";
|
||||
private static final String URL_MODULE_DELETE = "/api/debug/module/delete/%s";
|
||||
private static final String URL_MODULE_TREE = "/api/debug/module/tree/%s";
|
||||
private static final String URL_MODULE_MOVE = "/api/debug/module/move";
|
||||
private static final String URL_FILE_MODULE_COUNT = "/api/debug/module/count";
|
||||
private static final ResultMatcher BAD_REQUEST_MATCHER = status().isBadRequest();
|
||||
private static final ResultMatcher ERROR_REQUEST_MATCHER = status().is5xxServerError();
|
||||
private static Project project;
|
||||
private static List<BaseTreeNode> preliminaryTreeNodes = new ArrayList<>();
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private ApiDebugModuleMapper apiDebugModuleMapper;
|
||||
@Resource
|
||||
private ApiDebugMapper apiDebugMapper;
|
||||
@Resource
|
||||
private ApiDebugBlobMapper apiDebugBlobMapper;
|
||||
@Resource
|
||||
private ApiDebugModuleService apiDebugModuleService;
|
||||
|
||||
public static BaseTreeNode getNodeByName(List<BaseTreeNode> preliminaryTreeNodes, String nodeName) {
|
||||
for (BaseTreeNode firstLevelNode : preliminaryTreeNodes) {
|
||||
if (StringUtils.equals(firstLevelNode.getName(), nodeName) && StringUtils.equals(firstLevelNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
|
||||
return firstLevelNode;
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(firstLevelNode.getChildren())) {
|
||||
for (BaseTreeNode secondLevelNode : firstLevelNode.getChildren()) {
|
||||
if (StringUtils.equals(secondLevelNode.getName(), nodeName) && StringUtils.equals(secondLevelNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
|
||||
return secondLevelNode;
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(secondLevelNode.getChildren())) {
|
||||
for (BaseTreeNode thirdLevelNode : secondLevelNode.getChildren()) {
|
||||
if (StringUtils.equals(thirdLevelNode.getName(), nodeName) && StringUtils.equals(thirdLevelNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
|
||||
return thirdLevelNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void initTestData() {
|
||||
if (project == null) {
|
||||
Project initProject = new Project();
|
||||
initProject.setId(IDGenerator.nextStr());
|
||||
initProject.setNum(null);
|
||||
initProject.setOrganizationId("100001");
|
||||
initProject.setName("接口调试的项目");
|
||||
initProject.setDescription("接口调试的项目");
|
||||
initProject.setCreateUser("admin");
|
||||
initProject.setUpdateUser("admin");
|
||||
initProject.setCreateTime(System.currentTimeMillis());
|
||||
initProject.setUpdateTime(System.currentTimeMillis());
|
||||
initProject.setEnable(true);
|
||||
initProject.setModuleSetting("[\"apiTest\",\"uiTest\"]");
|
||||
projectMapper.insertSelective(initProject);
|
||||
project = projectMapper.selectByPrimaryKey(initProject.getId());
|
||||
}
|
||||
}
|
||||
|
||||
public void initApiDebugData(String moduleId) {
|
||||
ApiDebug apiDebug = new ApiDebug();
|
||||
apiDebug.setId(IDGenerator.nextStr());
|
||||
apiDebug.setProjectId(project.getId());
|
||||
apiDebug.setName(StringUtils.join("接口调试", apiDebug.getId()));
|
||||
apiDebug.setModuleId(moduleId);
|
||||
apiDebug.setProtocol("HTTP");
|
||||
apiDebug.setMethod("GET");
|
||||
apiDebug.setPath(StringUtils.join("api/debug/", apiDebug.getId()));
|
||||
apiDebug.setCreateTime(System.currentTimeMillis());
|
||||
apiDebug.setUpdateTime(System.currentTimeMillis());
|
||||
apiDebug.setCreateUser("admin");
|
||||
apiDebug.setUpdateUser("admin");
|
||||
apiDebugMapper.insertSelective(apiDebug);
|
||||
ApiDebugBlob apiDebugBlob = new ApiDebugBlob();
|
||||
apiDebugBlob.setId(apiDebug.getId());
|
||||
apiDebugBlob.setRequest(new byte[0]);
|
||||
apiDebugBlob.setResponse(new byte[0]);
|
||||
apiDebugBlobMapper.insertSelective(apiDebugBlob);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
public void addModuleTestSuccess() throws Exception {
|
||||
//根目录下创建节点(a1)
|
||||
DebugModuleCreateRequest request = new DebugModuleCreateRequest();
|
||||
request.setProjectId(project.getId());
|
||||
request.setName("a1");
|
||||
MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
|
||||
String returnId = mvcResult.getResponse().getContentAsString();
|
||||
Assertions.assertNotNull(returnId);
|
||||
List<BaseTreeNode> treeNodes = this.getDebugModuleTreeNode();
|
||||
BaseTreeNode a1Node = null;
|
||||
for (BaseTreeNode baseTreeNode : treeNodes) {
|
||||
if (StringUtils.equals(baseTreeNode.getName(), request.getName())) {
|
||||
a1Node = baseTreeNode;
|
||||
}
|
||||
Assertions.assertNotNull(baseTreeNode.getParentId());
|
||||
}
|
||||
Assertions.assertNotNull(a1Node);
|
||||
initApiDebugData(a1Node.getId());
|
||||
checkLog(a1Node.getId(), OperationLogType.ADD, URL_MODULE_ADD);
|
||||
|
||||
//根目录下创建节点a2和a3,在a1下创建子节点a1-b1
|
||||
request = new DebugModuleCreateRequest();
|
||||
request.setProjectId(project.getId());
|
||||
request.setName("a2");
|
||||
this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
|
||||
|
||||
|
||||
request.setName("a3");
|
||||
this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
|
||||
|
||||
request = new DebugModuleCreateRequest();
|
||||
request.setProjectId(project.getId());
|
||||
request.setName("a1-b1");
|
||||
request.setParentId(a1Node.getId());
|
||||
this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
|
||||
|
||||
treeNodes = this.getDebugModuleTreeNode();
|
||||
BaseTreeNode a1b1Node = null;
|
||||
BaseTreeNode a2Node = null;
|
||||
for (BaseTreeNode baseTreeNode : treeNodes) {
|
||||
Assertions.assertNotNull(baseTreeNode.getParentId());
|
||||
if (StringUtils.equals(baseTreeNode.getName(), "a1") && CollectionUtils.isNotEmpty(baseTreeNode.getChildren())) {
|
||||
for (BaseTreeNode childNode : baseTreeNode.getChildren()) {
|
||||
if (StringUtils.equals(childNode.getName(), "a1-b1") && StringUtils.equals(childNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
|
||||
a1b1Node = childNode;
|
||||
}
|
||||
Assertions.assertNotNull(childNode.getParentId());
|
||||
}
|
||||
} else if (StringUtils.equals(baseTreeNode.getName(), "a2") && StringUtils.equals(baseTreeNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
|
||||
a2Node = baseTreeNode;
|
||||
}
|
||||
}
|
||||
Assertions.assertNotNull(a2Node);
|
||||
Assertions.assertNotNull(a1b1Node);
|
||||
initApiDebugData(a2Node.getId());
|
||||
initApiDebugData(a1b1Node.getId());
|
||||
checkLog(a2Node.getId(), OperationLogType.ADD, URL_MODULE_ADD);
|
||||
checkLog(a1b1Node.getId(), OperationLogType.ADD, URL_MODULE_ADD);
|
||||
|
||||
//a1节点下可以继续添加a1节点
|
||||
request = new DebugModuleCreateRequest();
|
||||
request.setProjectId(project.getId());
|
||||
request.setName("a1");
|
||||
request.setParentId(a1Node.getId());
|
||||
this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
|
||||
|
||||
//继续创建a1下继续创建a1-a1-b1,
|
||||
treeNodes = this.getDebugModuleTreeNode();
|
||||
BaseTreeNode a1ChildNode = null;
|
||||
for (BaseTreeNode baseTreeNode : treeNodes) {
|
||||
Assertions.assertNotNull(baseTreeNode.getParentId());
|
||||
if (StringUtils.equals(baseTreeNode.getName(), "a1") && CollectionUtils.isNotEmpty(baseTreeNode.getChildren())) {
|
||||
for (BaseTreeNode childNode : baseTreeNode.getChildren()) {
|
||||
Assertions.assertNotNull(childNode.getParentId());
|
||||
if (StringUtils.equals(childNode.getName(), "a1") && StringUtils.equals(childNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
|
||||
a1ChildNode = childNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Assertions.assertNotNull(a1ChildNode);
|
||||
initApiDebugData(a1ChildNode.getId());
|
||||
checkLog(a1ChildNode.getId(), OperationLogType.ADD, URL_MODULE_ADD);
|
||||
|
||||
//a1的子节点a1下继续创建节点a1-a1-c1
|
||||
request = new DebugModuleCreateRequest();
|
||||
request.setProjectId(project.getId());
|
||||
request.setName("a1-a1-c1");
|
||||
request.setParentId(a1ChildNode.getId());
|
||||
this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
|
||||
treeNodes = this.getDebugModuleTreeNode();
|
||||
BaseTreeNode a1a1c1Node = null;
|
||||
for (BaseTreeNode baseTreeNode : treeNodes) {
|
||||
Assertions.assertNotNull(baseTreeNode.getParentId());
|
||||
if (StringUtils.equals(baseTreeNode.getName(), "a1") && CollectionUtils.isNotEmpty(baseTreeNode.getChildren())) {
|
||||
for (BaseTreeNode secondNode : baseTreeNode.getChildren()) {
|
||||
Assertions.assertNotNull(secondNode.getParentId());
|
||||
if (StringUtils.equals(secondNode.getName(), "a1") && CollectionUtils.isNotEmpty(secondNode.getChildren())) {
|
||||
for (BaseTreeNode thirdNode : secondNode.getChildren()) {
|
||||
Assertions.assertNotNull(thirdNode.getParentId());
|
||||
if (StringUtils.equals(thirdNode.getName(), "a1-a1-c1") && StringUtils.equals(thirdNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
|
||||
a1a1c1Node = thirdNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Assertions.assertNotNull(a1a1c1Node);
|
||||
initApiDebugData(a1a1c1Node.getId());
|
||||
checkLog(a1a1c1Node.getId(), OperationLogType.ADD, URL_MODULE_ADD);
|
||||
|
||||
//子节点a1-b1下继续创建节点a1-b1-c1
|
||||
request = new DebugModuleCreateRequest();
|
||||
request.setProjectId(project.getId());
|
||||
request.setName("a1-b1-c1");
|
||||
request.setParentId(a1b1Node.getId());
|
||||
this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
|
||||
treeNodes = this.getDebugModuleTreeNode();
|
||||
BaseTreeNode a1b1c1Node = null;
|
||||
for (BaseTreeNode baseTreeNode : treeNodes) {
|
||||
if (StringUtils.equals(baseTreeNode.getName(), "a1") && CollectionUtils.isNotEmpty(baseTreeNode.getChildren())) {
|
||||
for (BaseTreeNode secondNode : baseTreeNode.getChildren()) {
|
||||
if (StringUtils.equals(secondNode.getName(), "a1-b1") && CollectionUtils.isNotEmpty(secondNode.getChildren())) {
|
||||
for (BaseTreeNode thirdNode : secondNode.getChildren()) {
|
||||
if (StringUtils.equals(thirdNode.getName(), "a1-b1-c1") && StringUtils.equals(thirdNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
|
||||
a1b1c1Node = thirdNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Assertions.assertNotNull(a1b1c1Node);
|
||||
initApiDebugData(a1b1c1Node.getId());
|
||||
preliminaryTreeNodes = treeNodes;
|
||||
|
||||
checkLog(a1b1c1Node.getId(), OperationLogType.ADD, URL_MODULE_ADD);
|
||||
//校验权限
|
||||
request = new DebugModuleCreateRequest();
|
||||
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||
request.setName("defaultProject");
|
||||
requestPostPermissionTest(PermissionConstants.PROJECT_API_DEBUG_READ_ADD, URL_MODULE_ADD, request);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(3)
|
||||
public void addModuleTestError() throws Exception {
|
||||
this.preliminaryData();
|
||||
|
||||
BaseTreeNode a1Node = getNodeByName(preliminaryTreeNodes, "a1");
|
||||
assert a1Node != null;
|
||||
|
||||
//参数校验
|
||||
DebugModuleCreateRequest request = new DebugModuleCreateRequest();
|
||||
request.setProjectId(project.getId());
|
||||
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
|
||||
request = new DebugModuleCreateRequest();
|
||||
request.setName("none");
|
||||
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
|
||||
request = new DebugModuleCreateRequest();
|
||||
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
|
||||
request = new DebugModuleCreateRequest();
|
||||
request.setParentId(null);
|
||||
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
|
||||
//名称存在特殊字符
|
||||
request.setName("a1/a2");
|
||||
request.setParentId(a1Node.getId());
|
||||
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
|
||||
|
||||
//父节点ID不存在的
|
||||
request = new DebugModuleCreateRequest();
|
||||
request.setProjectId(project.getId());
|
||||
request.setName("ParentIsUUID");
|
||||
request.setParentId(IDGenerator.nextStr());
|
||||
this.requestPost(URL_MODULE_ADD, request).andExpect(ERROR_REQUEST_MATCHER);
|
||||
|
||||
//添加重复的a1节点
|
||||
request = new DebugModuleCreateRequest();
|
||||
request.setProjectId(project.getId());
|
||||
request.setName("a1");
|
||||
this.requestPost(URL_MODULE_ADD, request).andExpect(ERROR_REQUEST_MATCHER);
|
||||
|
||||
//a1节点下添加重复的a1-b1节点
|
||||
request = new DebugModuleCreateRequest();
|
||||
request.setProjectId(project.getId());
|
||||
request.setName("a1-b1");
|
||||
request.setParentId(a1Node.getId());
|
||||
this.requestPost(URL_MODULE_ADD, request).andExpect(ERROR_REQUEST_MATCHER);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(4)
|
||||
public void updateModuleTestSuccess() throws Exception {
|
||||
if (CollectionUtils.isEmpty(preliminaryTreeNodes)) {
|
||||
this.addModuleTestSuccess();
|
||||
}
|
||||
//更改名称
|
||||
BaseTreeNode a1Node = null;
|
||||
for (BaseTreeNode node : preliminaryTreeNodes) {
|
||||
if (StringUtils.equals(node.getName(), "a1")) {
|
||||
for (BaseTreeNode a1ChildrenNode : node.getChildren()) {
|
||||
if (StringUtils.equals(a1ChildrenNode.getName(), "a1")) {
|
||||
a1Node = a1ChildrenNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert a1Node != null;
|
||||
DebugModuleUpdateRequest updateRequest = new DebugModuleUpdateRequest();
|
||||
updateRequest.setId(a1Node.getId());
|
||||
updateRequest.setName("a1-a1");
|
||||
//无法拿到当前用户的projectID 所以需要传入
|
||||
mockMvc.perform(MockMvcRequestBuilders.post(URL_MODULE_UPDATE)
|
||||
.header(SessionConstants.HEADER_TOKEN, sessionId)
|
||||
.header(SessionConstants.CSRF_TOKEN, csrfToken)
|
||||
.header(SessionConstants.CURRENT_PROJECT, project.getId())
|
||||
.content(JSON.toJSONString(updateRequest))
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn();
|
||||
|
||||
preliminaryTreeNodes = this.getDebugModuleTreeNode();
|
||||
checkLog(a1Node.getId(), OperationLogType.UPDATE, URL_MODULE_UPDATE);
|
||||
|
||||
//校验权限
|
||||
ApiDebugModuleExample example = new ApiDebugModuleExample();
|
||||
example.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID).andNameEqualTo("defaultProject");
|
||||
List<ApiDebugModule> apiDebugModules = apiDebugModuleMapper.selectByExample(example);
|
||||
assert CollectionUtils.isNotEmpty(apiDebugModules);
|
||||
updateRequest = new DebugModuleUpdateRequest();
|
||||
updateRequest.setId(apiDebugModules.get(0).getId());
|
||||
updateRequest.setName("default-update-Project");
|
||||
requestPostPermissionTest(PermissionConstants.PROJECT_API_DEBUG_READ_UPDATE, URL_MODULE_UPDATE, updateRequest);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(5)
|
||||
public void updateModuleTestError() throws Exception {
|
||||
BaseTreeNode a1Node = getNodeByName(preliminaryTreeNodes, "a1-a1");
|
||||
assert a1Node != null;
|
||||
//反例-参数校验
|
||||
DebugModuleUpdateRequest updateRequest = new DebugModuleUpdateRequest();
|
||||
this.requestPost(URL_MODULE_UPDATE, updateRequest).andExpect(BAD_REQUEST_MATCHER);
|
||||
//参数名称带有特殊字符
|
||||
updateRequest = new DebugModuleUpdateRequest();
|
||||
updateRequest.setId(a1Node.getId());
|
||||
updateRequest.setName("a1/a2");
|
||||
this.requestPost(URL_MODULE_UPDATE, updateRequest).andExpect(BAD_REQUEST_MATCHER);
|
||||
|
||||
//id不存在
|
||||
updateRequest = new DebugModuleUpdateRequest();
|
||||
updateRequest.setId(IDGenerator.nextStr());
|
||||
updateRequest.setName(IDGenerator.nextStr());
|
||||
this.requestPost(URL_MODULE_UPDATE, updateRequest).andExpect(ERROR_REQUEST_MATCHER);
|
||||
|
||||
//名称重复 a1-a1改为a1-b1
|
||||
updateRequest = new DebugModuleUpdateRequest();
|
||||
updateRequest.setId(a1Node.getId());
|
||||
updateRequest.setName("a1-b1");
|
||||
this.requestPost(URL_MODULE_UPDATE, updateRequest).andExpect(ERROR_REQUEST_MATCHER);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(6)
|
||||
public void moveTest() throws Exception {
|
||||
this.preliminaryData();
|
||||
/*
|
||||
*默认节点
|
||||
|
|
||||
·a1 +
|
||||
| |
|
||||
| ·a1-b1 +
|
||||
| | |
|
||||
| | ·a1-b1-c1
|
||||
| |
|
||||
| *a1-a1 +(创建的时候是a1,通过修改改为a1-a1)
|
||||
| |
|
||||
| ·a1-a1-c1
|
||||
|
|
||||
·a2
|
||||
|
|
||||
·a3
|
||||
*/
|
||||
BaseTreeNode a1Node = getNodeByName(preliminaryTreeNodes, "a1");
|
||||
BaseTreeNode a2Node = getNodeByName(preliminaryTreeNodes, "a2");
|
||||
BaseTreeNode a3Node = getNodeByName(preliminaryTreeNodes, "a3");
|
||||
BaseTreeNode a1a1Node = getNodeByName(preliminaryTreeNodes, "a1-a1");
|
||||
BaseTreeNode a1b1Node = getNodeByName(preliminaryTreeNodes, "a1-b1");
|
||||
|
||||
//父节点内移动-移动到首位 a1挪到a3后面
|
||||
NodeMoveRequest request = new NodeMoveRequest();
|
||||
{
|
||||
assert a1Node != null;
|
||||
request.setDragNodeId(a1Node.getId());
|
||||
assert a3Node != null;
|
||||
request.setDropNodeId(a3Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a3Node.getId(), a1Node.getId(), null, false);
|
||||
}
|
||||
//父节点内移动-移动到末位 在上面的基础上,a1挪到a2上面
|
||||
{
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a1Node.getId());
|
||||
assert a2Node != null;
|
||||
request.setDropNodeId(a2Node.getId());
|
||||
request.setDropPosition(-1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a1Node.getId(), a2Node.getId(), null, false);
|
||||
}
|
||||
|
||||
//父节点内移动-移动到中位 a1移动到a2-a3中间
|
||||
{
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a1Node.getId());
|
||||
request.setDropNodeId(a2Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a2Node.getId(), a1Node.getId(), a3Node.getId(), false);
|
||||
//移动回去
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a1Node.getId());
|
||||
request.setDropNodeId(a2Node.getId());
|
||||
request.setDropPosition(-1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a1Node.getId(), a2Node.getId(), null, false);
|
||||
}
|
||||
|
||||
//跨节点移动-移动到首位 a3移动到a1-b1前面,然后移动回来;
|
||||
{
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a1b1Node.getId());
|
||||
request.setDropPosition(-1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a3Node.getId(), a1b1Node.getId(), null, false);
|
||||
//移动回去
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a2Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
|
||||
}
|
||||
|
||||
//跨节点移动-移动到末尾 a3移动到a1-a1后面,然后移动回来;
|
||||
{
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
assert a1a1Node != null;
|
||||
request.setDropNodeId(a1a1Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a1a1Node.getId(), a3Node.getId(), null, false);
|
||||
//移动回去
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a2Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
|
||||
}
|
||||
|
||||
//跨节点移动-移动到中位 a3移动到a1-b1和a1-a1中间,然后移动回来;
|
||||
{
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a1b1Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a1b1Node.getId(), a3Node.getId(), a1a1Node.getId(), false);
|
||||
//移动回去
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a2Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
|
||||
}
|
||||
|
||||
//父节点内移动-a3移动到首位pos小于2,是否触发计算函数 (先手动更改a1的pos为2,然后移动a3到a1前面)
|
||||
{
|
||||
//更改pos
|
||||
ApiDebugModule updateModule = new ApiDebugModule();
|
||||
updateModule.setId(a1Node.getId());
|
||||
updateModule.setPos(2);
|
||||
apiDebugModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||
|
||||
//开始移动
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a1Node.getId());
|
||||
request.setDropPosition(-1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a3Node.getId(), a1Node.getId(), null, true);
|
||||
|
||||
//移动回去
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a2Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
|
||||
}
|
||||
|
||||
//父节点内移动-移动到中位,前后节点pos差不大于2,是否触发计算函数(在上面的 a3-a1-a2的基础上, 先手动更改a1pos为3*64,a2的pos为3*64+2,然后移动a3到a1和a2中间)
|
||||
{
|
||||
//更改pos
|
||||
ApiDebugModule updateModule = new ApiDebugModule();
|
||||
updateModule.setId(a1Node.getId());
|
||||
updateModule.setPos(3 * 64);
|
||||
apiDebugModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||
updateModule.setId(a2Node.getId());
|
||||
updateModule.setPos(3 * 64 + 2);
|
||||
apiDebugModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||
|
||||
//开始移动
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a1Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a1Node.getId(), a3Node.getId(), a2Node.getId(), true);
|
||||
|
||||
//移动回去
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a2Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
|
||||
}
|
||||
//跨节点移动-移动到首位pos小于2,是否触发计算函数(先手动更改a1-b1的pos为2,然后移动a3到a1-b1前面,最后再移动回来)
|
||||
{
|
||||
//更改pos
|
||||
ApiDebugModule updateModule = new ApiDebugModule();
|
||||
updateModule.setId(a1b1Node.getId());
|
||||
updateModule.setPos(2);
|
||||
apiDebugModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||
|
||||
//开始移动
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a1b1Node.getId());
|
||||
request.setDropPosition(-1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a3Node.getId(), a1b1Node.getId(), null, true);
|
||||
|
||||
//移动回去
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a2Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
|
||||
}
|
||||
//跨节点移动-移动到中位,前后节点pos差不大于2,是否触发计算函数先手动更改a1-a1的pos为a1-b1+2,然后移动a3到a1-a1前面,最后再移动回来)
|
||||
{
|
||||
//更改pos
|
||||
ApiDebugModule updateModule = new ApiDebugModule();
|
||||
updateModule.setId(a1b1Node.getId());
|
||||
updateModule.setPos(3 * 64);
|
||||
apiDebugModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||
updateModule.setId(a1a1Node.getId());
|
||||
updateModule.setPos(3 * 64 + 2);
|
||||
apiDebugModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||
|
||||
//开始移动
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a1a1Node.getId());
|
||||
request.setDropPosition(-1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a1b1Node.getId(), a3Node.getId(), a1a1Node.getId(), true);
|
||||
|
||||
//移动回去
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a2Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
|
||||
}
|
||||
//移动到没有子节点的节点下 a3移动到a2下
|
||||
{
|
||||
//开始移动
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a2Node.getId());
|
||||
request.setDropPosition(0);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
ApiDebugModule a3Module = apiDebugModuleMapper.selectByPrimaryKey(a3Node.getId());
|
||||
Assertions.assertEquals(a3Module.getParentId(), a2Node.getId());
|
||||
|
||||
//移动回去
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a3Node.getId());
|
||||
request.setDropNodeId(a2Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPostWithOk(URL_MODULE_MOVE, request);
|
||||
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
|
||||
}
|
||||
|
||||
checkLog(a1Node.getId(), OperationLogType.UPDATE, URL_MODULE_MOVE);
|
||||
checkLog(a3Node.getId(), OperationLogType.UPDATE, URL_MODULE_MOVE);
|
||||
requestPostPermissionTest(PermissionConstants.PROJECT_API_DEBUG_READ_UPDATE, URL_MODULE_MOVE, request);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(7)
|
||||
public void moveTestError() throws Exception {
|
||||
this.preliminaryData();
|
||||
BaseTreeNode a1Node = getNodeByName(preliminaryTreeNodes, "a1");
|
||||
BaseTreeNode a2Node = getNodeByName(preliminaryTreeNodes, "a2");
|
||||
//drag节点为空
|
||||
NodeMoveRequest request = new NodeMoveRequest();
|
||||
request.setDragNodeId(null);
|
||||
assert a1Node != null;
|
||||
request.setDropNodeId(a1Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPost(URL_MODULE_MOVE, request).andExpect(BAD_REQUEST_MATCHER);
|
||||
//drag节点不存在
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(IDGenerator.nextStr());
|
||||
request.setDropNodeId(a1Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPost(URL_MODULE_MOVE, request).andExpect(ERROR_REQUEST_MATCHER);
|
||||
|
||||
//drop节点为空
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a1Node.getId());
|
||||
request.setDropNodeId(null);
|
||||
request.setDropPosition(1);
|
||||
this.requestPost(URL_MODULE_MOVE, request).andExpect(BAD_REQUEST_MATCHER);
|
||||
|
||||
//drop节点不存在
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a1Node.getId());
|
||||
request.setDropNodeId(IDGenerator.nextStr());
|
||||
request.setDropPosition(1);
|
||||
this.requestPost(URL_MODULE_MOVE, request).andExpect(ERROR_REQUEST_MATCHER);
|
||||
|
||||
//position为0的时候节点不存在
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a1Node.getId());
|
||||
request.setDropNodeId(IDGenerator.nextStr());
|
||||
request.setDropPosition(0);
|
||||
this.requestPost(URL_MODULE_MOVE, request).andExpect(ERROR_REQUEST_MATCHER);
|
||||
|
||||
//dragNode和dropNode一样
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a1Node.getId());
|
||||
request.setDropNodeId(a1Node.getId());
|
||||
request.setDropPosition(1);
|
||||
this.requestPost(URL_MODULE_MOVE, request).andExpect(ERROR_REQUEST_MATCHER);
|
||||
|
||||
//position不是-1 0 1
|
||||
request = new NodeMoveRequest();
|
||||
request.setDragNodeId(a1Node.getId());
|
||||
assert a2Node != null;
|
||||
request.setDropNodeId(a2Node.getId());
|
||||
request.setDropPosition(4);
|
||||
this.requestPost(URL_MODULE_MOVE, request).andExpect(ERROR_REQUEST_MATCHER);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(8)
|
||||
public void TestModuleCountSuccess() throws Exception {
|
||||
this.preliminaryData();
|
||||
ApiDebugRequest request = new ApiDebugRequest() {{
|
||||
this.setProtocol("HTTP");
|
||||
}};
|
||||
MvcResult moduleCountMvcResult = this.requestPostWithOkAndReturn(URL_FILE_MODULE_COUNT, request);
|
||||
Map<String, Integer> moduleCountResult = JSON.parseObject(JSON.toJSONString(
|
||||
JSON.parseObject(moduleCountMvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData()),
|
||||
Map.class);
|
||||
Assertions.assertTrue(moduleCountResult.containsKey("all"));
|
||||
requestPostPermissionTest(PermissionConstants.PROJECT_API_DEBUG_READ, URL_FILE_MODULE_COUNT, request);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(8)
|
||||
public void TestModuleCountError() throws Exception {
|
||||
ApiDebugRequest request = new ApiDebugRequest();
|
||||
request.setProtocol(null);
|
||||
this.requestPost(URL_FILE_MODULE_COUNT, request).andExpect(BAD_REQUEST_MATCHER);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(10)
|
||||
public void deleteModuleTestSuccess() throws Exception {
|
||||
this.preliminaryData();
|
||||
|
||||
// 删除没有文件的节点a1-b1-c1 检查是否级联删除根节点
|
||||
BaseTreeNode a1b1Node = getNodeByName(this.getDebugModuleTreeNode(), "a1-b1");
|
||||
assert a1b1Node != null;
|
||||
this.requestGetWithOk(String.format(URL_MODULE_DELETE, a1b1Node.getId()));
|
||||
this.checkModuleIsEmpty(a1b1Node.getId());
|
||||
checkLog(a1b1Node.getId(), OperationLogType.DELETE, URL_MODULE_DELETE);
|
||||
|
||||
// 删除有文件的节点 a1-a1 检查是否级联删除根节点
|
||||
BaseTreeNode a1a1Node = getNodeByName(this.getDebugModuleTreeNode(), "a1-a1");
|
||||
assert a1a1Node != null;
|
||||
this.requestGetWithOk(String.format(URL_MODULE_DELETE, a1a1Node.getId()));
|
||||
this.checkModuleIsEmpty(a1a1Node.getId());
|
||||
checkLog(a1a1Node.getId(), OperationLogType.DELETE, URL_MODULE_DELETE);
|
||||
|
||||
//删除不存在的节点
|
||||
this.requestGetWithOk(String.format(URL_MODULE_DELETE, IDGenerator.nextNum()));
|
||||
// 测试删除根节点
|
||||
this.requestGetWithOk(String.format(URL_MODULE_DELETE, ModuleConstants.DEFAULT_NODE_ID));
|
||||
|
||||
//service层判断:测试删除空集合
|
||||
apiDebugModuleService.deleteModule(new ArrayList<>());
|
||||
//校验权限
|
||||
requestGetPermissionTest(PermissionConstants.PROJECT_API_DEBUG_READ_DELETE, String.format(URL_MODULE_DELETE, IDGenerator.nextNum()));
|
||||
|
||||
}
|
||||
|
||||
private List<BaseTreeNode> getDebugModuleTreeNode() throws Exception {
|
||||
MvcResult result = this.requestGetWithOkAndReturn(String.format(URL_MODULE_TREE, ModuleConstants.NODE_PROTOCOL_HTTP));
|
||||
String returnData = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
return JSON.parseArray(JSON.toJSONString(resultHolder.getData()), BaseTreeNode.class);
|
||||
}
|
||||
|
||||
private void preliminaryData() throws Exception {
|
||||
if (CollectionUtils.isEmpty(preliminaryTreeNodes)) {
|
||||
/*
|
||||
这里需要获取修改过的树的结构。期望的最终结构是这样的(*为测试用例中挂载文件的节点, · 为空节点):
|
||||
|
||||
*默认节点
|
||||
|
|
||||
·a1 +
|
||||
| |
|
||||
| ·a1-b1 +
|
||||
| | |
|
||||
| | ·a1-b1-c1
|
||||
| |
|
||||
| *a1-a1 +(创建的时候是a1,通过修改改为a1-a1)
|
||||
| | |
|
||||
| | ·a1-a1-c1
|
||||
|
|
||||
·a2
|
||||
|
|
||||
·a3
|
||||
*/
|
||||
this.updateModuleTestSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkModuleIsEmpty(String id) {
|
||||
ApiDebugModuleExample example = new ApiDebugModuleExample();
|
||||
example.createCriteria().andParentIdEqualTo(id);
|
||||
Assertions.assertEquals(0, apiDebugModuleMapper.countByExample(example));
|
||||
|
||||
ApiDebugExample apiDebugExample = new ApiDebugExample();
|
||||
example = new ApiDebugModuleExample();
|
||||
example.createCriteria().andIdEqualTo(id);
|
||||
Assertions.assertEquals(0, apiDebugModuleMapper.countByExample(example));
|
||||
apiDebugExample.createCriteria().andModuleIdEqualTo(id);
|
||||
Assertions.assertEquals(0, apiDebugMapper.countByExample(apiDebugExample));
|
||||
}
|
||||
|
||||
private void checkModulePos(String firstNode, String secondNode, String thirdNode, boolean isRecalculate) {
|
||||
ApiDebugModule firstModule = apiDebugModuleMapper.selectByPrimaryKey(firstNode);
|
||||
ApiDebugModule secondModule = apiDebugModuleMapper.selectByPrimaryKey(secondNode);
|
||||
ApiDebugModule thirdModule = null;
|
||||
Assertions.assertTrue(firstModule.getPos() < secondModule.getPos());
|
||||
if (StringUtils.isNotBlank(thirdNode)) {
|
||||
thirdModule = apiDebugModuleMapper.selectByPrimaryKey(thirdNode);
|
||||
Assertions.assertTrue(secondModule.getPos() < thirdModule.getPos());
|
||||
}
|
||||
if (isRecalculate) {
|
||||
int limitPos = 64;
|
||||
Assertions.assertEquals(0, firstModule.getPos() % limitPos);
|
||||
Assertions.assertEquals(0, secondModule.getPos() % limitPos);
|
||||
if (thirdModule != null) {
|
||||
Assertions.assertEquals(0, thirdModule.getPos() % limitPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -26,6 +26,9 @@ spring.datasource.hikari.max-lifetime=1800000
|
|||
spring.datasource.hikari.connection-timeout=30000
|
||||
spring.datasource.hikari.connection-test-query=SELECT 1
|
||||
|
||||
# 单元测试初始化权限 sql
|
||||
spring.sql.init.mode=always
|
||||
spring.sql.init.schema-locations=classpath*:dml/init_permission_test.sql
|
||||
#
|
||||
# spring.kafka
|
||||
spring.kafka.bootstrap-servers=${embedded.kafka.brokerList}
|
||||
|
@ -82,6 +85,6 @@ minio.endpoint=http://${embedded.minio.host}:${embedded.minio.port}
|
|||
minio.access-key=${embedded.minio.accessKey}
|
||||
minio.secret-key=${embedded.minio.secretKey}
|
||||
|
||||
logging.level.org.springframework.jdbc.core=info
|
||||
logging.level.io.metersphere.sdk.mapper=info
|
||||
logging.level.io.metersphere.project.mapper=info
|
||||
logging.level.org.springframework.jdbc.core=debug
|
||||
logging.level.io.metersphere.sdk.mapper=debug
|
||||
logging.level.io.metersphere.project.mapper=debug
|
|
@ -0,0 +1,14 @@
|
|||
-- 初始化用于权限测试的组织用户
|
||||
INSERT INTO user(id, name, email, password, create_time, update_time, language, last_organization_id, phone, source,
|
||||
last_project_id, create_user, update_user, deleted)
|
||||
VALUES ('PROJECT', 'PROJECT', 'PROJECT@fit2cloud.com', MD5('metersphere'),
|
||||
UNIX_TIMESTAMP() * 1000,
|
||||
UNIX_TIMESTAMP() * 1000, NULL, NUll, '', 'LOCAL', NULL, 'admin', 'admin', false);
|
||||
|
||||
-- 初始化一个用于权限测试的用户组,这里默认使用 PROJECT 作为ID,如果是组织和项目级别类似,便于根据权限的前缀找到对应测试的用户组
|
||||
INSERT INTO user_role (id, name, description, internal, type, create_time, update_time, create_user, scope_id)
|
||||
VALUES ('PROJECT', '项目级别权限校验', '', 1, 'PROJECT', 1620674220005, 1620674220000, 'admin', 'global');
|
||||
|
||||
-- 初始化用户和组的关系
|
||||
INSERT INTO user_role_relation (id, user_id, role_id, source_id, organization_id, create_time, create_user)
|
||||
SELECT 'PROJECT', 'PROJECT', 'PROJECT', id, organization_id, 1684747668375, 'admin' FROM project WHERE num = 100001;
|
|
@ -5,7 +5,9 @@ import lombok.Data;
|
|||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
|
@ -26,6 +28,9 @@ public class BaseTreeNode {
|
|||
@Schema(description = "子节点")
|
||||
private List<BaseTreeNode> children = new ArrayList<>();
|
||||
|
||||
@Schema(description = "附加信息")
|
||||
private Map<String, String> attachInfo = new HashMap<>();
|
||||
|
||||
@Schema(description = "节点资源数量(多数情况下不会随着节点信息返回,视接口而定)")
|
||||
private long count = 0;
|
||||
|
||||
|
@ -45,4 +50,8 @@ public class BaseTreeNode {
|
|||
public void addChild(BaseTreeNode node) {
|
||||
children.add(node);
|
||||
}
|
||||
|
||||
public void putAttachInfo(String key, String value) {
|
||||
attachInfo.put(key, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,4 +97,7 @@ public class OperationLogModule {
|
|||
|
||||
//用例
|
||||
public static final String FUNCTIONAL_CASE = "FUNCTIONAL_CASE";
|
||||
|
||||
//接口调试
|
||||
public static final String API_DEBUG = "API_DEBUG";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue