feat(功能用例): 增加模块功能
This commit is contained in:
parent
b4bf910a06
commit
6aa377e7d1
|
@ -124,4 +124,6 @@ case_comment.case_is_null=功能用例不存在
|
||||||
case_comment.parent_id_is_null=当前回复的评论id为空
|
case_comment.parent_id_is_null=当前回复的评论id为空
|
||||||
case_comment.parent_case_is_null=当前回复的评论不存在
|
case_comment.parent_case_is_null=当前回复的评论不存在
|
||||||
case_comment.reply_user_is_null=回复的用户为空
|
case_comment.reply_user_is_null=回复的用户为空
|
||||||
case_comment.id_is_null=当前评论id为空
|
case_comment.id_is_null=当前评论id为空
|
||||||
|
#module
|
||||||
|
case_module.not.exist=用例模块不存在
|
||||||
|
|
|
@ -142,3 +142,7 @@ case_comment.parent_id_is_null=The comment id of the current reply is empty
|
||||||
case_comment.parent_case_is_null=The comment currently being replied to does not exist
|
case_comment.parent_case_is_null=The comment currently being replied to does not exist
|
||||||
case_comment.reply_user_is_null=The user who replied is empty
|
case_comment.reply_user_is_null=The user who replied is empty
|
||||||
case_comment.id_is_null=The current comment id is empty
|
case_comment.id_is_null=The current comment id is empty
|
||||||
|
un_follow_functional_case=unfollow functional case
|
||||||
|
follow_functional_case=followed functional case
|
||||||
|
#module
|
||||||
|
case_module.not.exist=Case module does not exist
|
|
@ -142,3 +142,7 @@ case_comment.parent_id_is_null=当前回复的评论id为空
|
||||||
case_comment.parent_case_is_null=当前回复的评论不存在
|
case_comment.parent_case_is_null=当前回复的评论不存在
|
||||||
case_comment.reply_user_is_null=回复的用户为空
|
case_comment.reply_user_is_null=回复的用户为空
|
||||||
case_comment.id_is_null=当前评论id为空
|
case_comment.id_is_null=当前评论id为空
|
||||||
|
un_follow_functional_case=取消关注用例
|
||||||
|
follow_functional_case=关注用例
|
||||||
|
#module
|
||||||
|
case_module.not.exist=用例模块不存在
|
|
@ -142,3 +142,7 @@ case_comment.parent_id_is_null=目前回覆的評論id為空
|
||||||
case_comment.parent_case_is_null=目前回應的評論不存在
|
case_comment.parent_case_is_null=目前回應的評論不存在
|
||||||
case_comment.reply_user_is_null=回覆的用戶為空
|
case_comment.reply_user_is_null=回覆的用戶為空
|
||||||
case_comment.id_is_null=目前評論id為空
|
case_comment.id_is_null=目前評論id為空
|
||||||
|
un_follow_functional_case=取消關注用例
|
||||||
|
follow_functional_case=關注用例
|
||||||
|
#module
|
||||||
|
case_module.not.exist=用例模組不存在
|
|
@ -0,0 +1,61 @@
|
||||||
|
package io.metersphere.functional.controller;
|
||||||
|
|
||||||
|
import io.metersphere.functional.request.FunctionalCaseModuleCreateRequest;
|
||||||
|
import io.metersphere.functional.request.FunctionalCaseModuleUpdateRequest;
|
||||||
|
import io.metersphere.functional.service.FunctionalCaseModuleService;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Tag(name = "用例管理-功能用例-模块")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/functional/case/module")
|
||||||
|
public class FunctionalCaseModuleController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FunctionalCaseModuleService functionalCaseModuleService;
|
||||||
|
|
||||||
|
@GetMapping("/tree/{projectId}")
|
||||||
|
@Operation(summary = "用例管理-功能用例-模块-获取模块树")
|
||||||
|
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ)
|
||||||
|
public List<BaseTreeNode> getTree(@PathVariable String projectId) {
|
||||||
|
return functionalCaseModuleService.getTree(projectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/add")
|
||||||
|
@Operation(summary = "用例管理-功能用例-模块-添加模块")
|
||||||
|
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_ADD)
|
||||||
|
public void add(@RequestBody @Validated FunctionalCaseModuleCreateRequest request) {
|
||||||
|
functionalCaseModuleService.add(request, SessionUtils.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/update")
|
||||||
|
@Operation(summary = "用例管理-功能用例-模块-修改模块")
|
||||||
|
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE)
|
||||||
|
public void list(@RequestBody @Validated FunctionalCaseModuleUpdateRequest request) {
|
||||||
|
functionalCaseModuleService.update(request, SessionUtils.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/move")
|
||||||
|
@Operation(summary = "用例管理-功能用例-模块-移动模块")
|
||||||
|
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE)
|
||||||
|
public void moveNode(@Validated @RequestBody NodeMoveRequest request) {
|
||||||
|
functionalCaseModuleService.moveNode(request, SessionUtils.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/delete/{moduleId}")
|
||||||
|
@Operation(summary = "用例管理-功能用例-模块-删除模块")
|
||||||
|
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_DELETE)
|
||||||
|
public void deleteNode(@PathVariable String moduleId) {
|
||||||
|
functionalCaseModuleService.deleteModule(moduleId, SessionUtils.getUserId());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package io.metersphere.functional.mapper;
|
||||||
|
|
||||||
|
import io.metersphere.functional.domain.FunctionalCaseModule;
|
||||||
|
import io.metersphere.project.dto.NodeSortQueryParam;
|
||||||
|
import io.metersphere.system.dto.sdk.BaseModule;
|
||||||
|
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface ExtFunctionalCaseModuleMapper {
|
||||||
|
List<BaseTreeNode> selectBaseByProjectId(String projectId);
|
||||||
|
|
||||||
|
List<BaseTreeNode> selectIdAndParentIdByProjectId(String projectId);
|
||||||
|
|
||||||
|
List<String> selectChildrenIdsByParentIds(@Param("ids") List<String> deleteIds);
|
||||||
|
|
||||||
|
List<String> selectChildrenIdsSortByPos(String parentId);
|
||||||
|
|
||||||
|
void removeToTrashByIds(@Param("ids") List<String> deleteId);
|
||||||
|
|
||||||
|
Long getMaxPosByParentId(String parentId);
|
||||||
|
|
||||||
|
List<String> selectIdsByProjectId(String projectId);
|
||||||
|
|
||||||
|
FunctionalCaseModule getLastModuleByParentId(String id);
|
||||||
|
|
||||||
|
FunctionalCaseModule getNextModuleInParentId(@Param("parentId") String parentId, @Param("pos") long pos);
|
||||||
|
|
||||||
|
FunctionalCaseModule getPreviousModuleInParentId(@Param("parentId") String parentId, @Param("pos") long pos);
|
||||||
|
|
||||||
|
String selectNameById(String moduleId);
|
||||||
|
|
||||||
|
BaseModule selectBaseModuleById(String dragNodeId);
|
||||||
|
|
||||||
|
BaseModule selectModuleByParentIdAndPosOperator(NodeSortQueryParam nodeSortQueryParam);
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
<?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.functional.mapper.ExtFunctionalCaseModuleMapper">
|
||||||
|
<select id="selectBaseByProjectId" resultType="io.metersphere.system.dto.sdk.BaseTreeNode">
|
||||||
|
SELECT id, name, parent_id AS parentId, 'module' AS type
|
||||||
|
FROM functional_case_module
|
||||||
|
WHERE project_id = #{0}
|
||||||
|
ORDER BY pos
|
||||||
|
</select>
|
||||||
|
<select id="selectIdAndParentIdByProjectId" resultType="io.metersphere.system.dto.sdk.BaseTreeNode">
|
||||||
|
SELECT id, parent_id AS parentId
|
||||||
|
FROM functional_case_module
|
||||||
|
WHERE project_id = #{0}
|
||||||
|
</select>
|
||||||
|
<select id="selectModuleByParentIdAndPosOperator"
|
||||||
|
parameterType="io.metersphere.project.dto.NodeSortQueryParam"
|
||||||
|
resultType="io.metersphere.system.dto.sdk.BaseModule">
|
||||||
|
SELECT id, name, pos, project_Id, parent_id
|
||||||
|
FROM functional_case_module
|
||||||
|
WHERE parent_id = #{parentId}
|
||||||
|
<if test="operator == 'moreThan'">
|
||||||
|
AND pos > #{pos}
|
||||||
|
</if>
|
||||||
|
<if test="operator == 'lessThan'">
|
||||||
|
AND pos < #{pos}
|
||||||
|
</if>
|
||||||
|
ORDER BY pos
|
||||||
|
<if test="operator == 'lessThan' or operator == 'latest'">
|
||||||
|
DESC
|
||||||
|
</if>
|
||||||
|
LIMIT 1
|
||||||
|
</select>
|
||||||
|
<select id="selectIdsByProjectId" resultType="java.lang.String">
|
||||||
|
SELECT id
|
||||||
|
FROM functional_case_module
|
||||||
|
WHERE project_id = #{0}
|
||||||
|
</select>
|
||||||
|
<select id="selectChildrenIdsByParentIds" resultType="java.lang.String">
|
||||||
|
SELECT id FROM functional_case_module WHERE parent_id IN
|
||||||
|
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</select>
|
||||||
|
<delete id="removeToTrashByIds" parameterType="java.lang.String">
|
||||||
|
UPDATE functional_case_module SET deleted = true WHERE id IN
|
||||||
|
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</delete>
|
||||||
|
<select id="getMaxPosByParentId" resultType="java.lang.Long">
|
||||||
|
SELECT max(pos) FROM functional_case_module
|
||||||
|
WHERE parent_id = #{0}
|
||||||
|
</select>
|
||||||
|
<select id="selectChildrenIdsSortByPos" resultType="java.lang.String">
|
||||||
|
SELECT id FROM functional_case_module WHERE parent_id = #{0}
|
||||||
|
ORDER BY pos ASC
|
||||||
|
</select>
|
||||||
|
<select id="getLastModuleByParentId" resultType="io.metersphere.functional.domain.FunctionalCaseModule">
|
||||||
|
SELECT *
|
||||||
|
FROM functional_case_module
|
||||||
|
WHERE parent_id = #{0}
|
||||||
|
ORDER BY pos DESC
|
||||||
|
LIMIT 1
|
||||||
|
</select>
|
||||||
|
<select id="getNextModuleInParentId" resultType="io.metersphere.functional.domain.FunctionalCaseModule">
|
||||||
|
SELECT *
|
||||||
|
from functional_case_module
|
||||||
|
WHERE parent_id = #{parentId}
|
||||||
|
AND pos > #{pos}
|
||||||
|
order by pos asc
|
||||||
|
limit 1
|
||||||
|
</select>
|
||||||
|
<select id="getPreviousModuleInParentId" resultType="io.metersphere.functional.domain.FunctionalCaseModule">
|
||||||
|
SELECT *
|
||||||
|
from functional_case_module
|
||||||
|
WHERE parent_id = #{parentId}
|
||||||
|
AND pos < #{pos}
|
||||||
|
order by pos
|
||||||
|
desc
|
||||||
|
limit 1
|
||||||
|
</select>
|
||||||
|
<select id="selectNameById" resultType="java.lang.String">
|
||||||
|
SELECT name
|
||||||
|
FROM functional_case_module
|
||||||
|
WHERE id = #{0}
|
||||||
|
</select>
|
||||||
|
<select id="selectBaseModuleById" resultType="io.metersphere.system.dto.sdk.BaseModule">
|
||||||
|
SELECT id, name, pos, project_Id, parent_id
|
||||||
|
FROM functional_case_module
|
||||||
|
WHERE id = #{0}
|
||||||
|
</select>
|
||||||
|
</mapper>
|
|
@ -0,0 +1,23 @@
|
||||||
|
package io.metersphere.functional.request;
|
||||||
|
|
||||||
|
import io.metersphere.sdk.constants.ModuleConstants;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FunctionalCaseModuleCreateRequest {
|
||||||
|
@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}")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "父模块ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@NotEmpty(message = "{parent.node.not_blank}")
|
||||||
|
private String parentId = ModuleConstants.ROOT_NODE_PARENT_ID;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package io.metersphere.functional.request;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FunctionalCaseModuleUpdateRequest {
|
||||||
|
@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}")
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
|
|
|
@ -7,10 +7,179 @@
|
||||||
package io.metersphere.functional.service;
|
package io.metersphere.functional.service;
|
||||||
|
|
||||||
|
|
||||||
|
import io.metersphere.functional.domain.FunctionalCaseModule;
|
||||||
|
import io.metersphere.functional.domain.FunctionalCaseModuleExample;
|
||||||
|
import io.metersphere.functional.mapper.ExtFunctionalCaseModuleMapper;
|
||||||
|
import io.metersphere.functional.mapper.FunctionalCaseModuleMapper;
|
||||||
|
import io.metersphere.functional.request.FunctionalCaseModuleCreateRequest;
|
||||||
|
import io.metersphere.functional.request.FunctionalCaseModuleUpdateRequest;
|
||||||
|
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.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.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class FunctionalCaseModuleService {
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public class FunctionalCaseModuleService extends ModuleTreeService {
|
||||||
|
@Resource
|
||||||
|
private FunctionalCaseModuleMapper functionalCaseModuleMapper;
|
||||||
|
@Resource
|
||||||
|
private SqlSessionFactory sqlSessionFactory;
|
||||||
|
@Resource
|
||||||
|
private ExtFunctionalCaseModuleMapper extFunctionalCaseModuleMapper;
|
||||||
|
|
||||||
|
public List<BaseTreeNode> getTree(String projectId) {
|
||||||
|
List<BaseTreeNode> fileModuleList = extFunctionalCaseModuleMapper.selectBaseByProjectId(projectId);
|
||||||
|
return super.buildTreeAndCountResource(fileModuleList, true, Translator.get("default.module"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(FunctionalCaseModuleCreateRequest request, String userId) {
|
||||||
|
FunctionalCaseModule functionalCaseModule = new FunctionalCaseModule();
|
||||||
|
functionalCaseModule.setId(IDGenerator.nextStr());
|
||||||
|
functionalCaseModule.setName(request.getName());
|
||||||
|
functionalCaseModule.setParentId(request.getParentId());
|
||||||
|
functionalCaseModule.setProjectId(request.getProjectId());
|
||||||
|
this.checkDataValidity(functionalCaseModule);
|
||||||
|
functionalCaseModule.setDeleted(false);
|
||||||
|
functionalCaseModule.setCreateTime(System.currentTimeMillis());
|
||||||
|
functionalCaseModule.setUpdateTime(functionalCaseModule.getCreateTime());
|
||||||
|
functionalCaseModule.setPos(this.countPos(request.getParentId()));
|
||||||
|
functionalCaseModule.setCreateUser(userId);
|
||||||
|
functionalCaseModule.setUpdateUser(userId);
|
||||||
|
functionalCaseModuleMapper.insert(functionalCaseModule);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(FunctionalCaseModuleUpdateRequest request, String userId) {
|
||||||
|
FunctionalCaseModule updateModule = functionalCaseModuleMapper.selectByPrimaryKey(request.getId());
|
||||||
|
if (updateModule == null) {
|
||||||
|
throw new MSException(Translator.get("case_module.not.exist"));
|
||||||
|
}
|
||||||
|
updateModule.setName(request.getName());
|
||||||
|
this.checkDataValidity(updateModule);
|
||||||
|
updateModule.setUpdateTime(System.currentTimeMillis());
|
||||||
|
updateModule.setUpdateUser(userId);
|
||||||
|
updateModule.setCreateUser(null);
|
||||||
|
updateModule.setCreateTime(null);
|
||||||
|
functionalCaseModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void moveNode(NodeMoveRequest request, String userId) {
|
||||||
|
NodeSortDTO nodeSortDTO = super.getNodeSortDTO(request,
|
||||||
|
extFunctionalCaseModuleMapper::selectBaseModuleById,
|
||||||
|
extFunctionalCaseModuleMapper::selectModuleByParentIdAndPosOperator);
|
||||||
|
|
||||||
|
FunctionalCaseModuleExample example = new FunctionalCaseModuleExample();
|
||||||
|
example.createCriteria().andParentIdEqualTo(nodeSortDTO.getParent().getId()).andIdEqualTo(request.getDragNodeId());
|
||||||
|
//节点换到了别的节点下,要先更新parent节点再计算sort
|
||||||
|
if (functionalCaseModuleMapper.countByExample(example) == 0) {
|
||||||
|
FunctionalCaseModule functionalCaseModule = new FunctionalCaseModule();
|
||||||
|
functionalCaseModule.setId(request.getDragNodeId());
|
||||||
|
functionalCaseModule.setParentId(nodeSortDTO.getParent().getId());
|
||||||
|
functionalCaseModule.setUpdateUser(userId);
|
||||||
|
functionalCaseModule.setUpdateTime(System.currentTimeMillis());
|
||||||
|
functionalCaseModuleMapper.updateByPrimaryKeySelective(functionalCaseModule);
|
||||||
|
}
|
||||||
|
super.sort(nodeSortDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteModule(String moduleId, String userId) {
|
||||||
|
FunctionalCaseModule deleteModule = functionalCaseModuleMapper.selectByPrimaryKey(moduleId);
|
||||||
|
if (deleteModule != null) {
|
||||||
|
this.deleteModuleByIds(Collections.singletonList(moduleId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteModuleByIds(List<String>deleteIds){
|
||||||
|
if (CollectionUtils.isEmpty(deleteIds)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//TODO:批量移动case到回收站
|
||||||
|
extFunctionalCaseModuleMapper.removeToTrashByIds(deleteIds);
|
||||||
|
List<String> childrenIds = extFunctionalCaseModuleMapper.selectChildrenIdsByParentIds(deleteIds);
|
||||||
|
if (CollectionUtils.isNotEmpty(childrenIds)) {
|
||||||
|
deleteModuleByIds(childrenIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long countPos(String parentId) {
|
||||||
|
Long maxPos = extFunctionalCaseModuleMapper.getMaxPosByParentId(parentId);
|
||||||
|
if (maxPos == null) {
|
||||||
|
return LIMIT_POS;
|
||||||
|
} else {
|
||||||
|
return maxPos + LIMIT_POS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查数据的合法性
|
||||||
|
*/
|
||||||
|
private void checkDataValidity(FunctionalCaseModule functionalCaseModule) {
|
||||||
|
FunctionalCaseModuleExample example = new FunctionalCaseModuleExample();
|
||||||
|
if (!StringUtils.equals(functionalCaseModule.getParentId(), ModuleConstants.ROOT_NODE_PARENT_ID)) {
|
||||||
|
//检查父ID是否存在
|
||||||
|
example.createCriteria().andIdEqualTo(functionalCaseModule.getParentId());
|
||||||
|
if (functionalCaseModuleMapper.countByExample(example) == 0) {
|
||||||
|
throw new MSException(Translator.get("parent.node.not_blank"));
|
||||||
|
}
|
||||||
|
example.clear();
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(functionalCaseModule.getProjectId())) {
|
||||||
|
//检查项目ID是否和父节点ID一致
|
||||||
|
example.createCriteria().andProjectIdEqualTo(functionalCaseModule.getProjectId()).andIdEqualTo(functionalCaseModule.getParentId());
|
||||||
|
if (functionalCaseModuleMapper.countByExample(example) == 0) {
|
||||||
|
throw new MSException(Translator.get("project.cannot.match.parent"));
|
||||||
|
}
|
||||||
|
example.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
example.createCriteria().andParentIdEqualTo(functionalCaseModule.getParentId()).andNameEqualTo(functionalCaseModule.getName()).andIdNotEqualTo(functionalCaseModule.getId());
|
||||||
|
if (functionalCaseModuleMapper.countByExample(example) > 0) {
|
||||||
|
throw new MSException(Translator.get("node.name.repeat"));
|
||||||
|
}
|
||||||
|
example.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updatePos(String id, long pos) {
|
||||||
|
FunctionalCaseModule updateModule = new FunctionalCaseModule();
|
||||||
|
updateModule.setPos(pos);
|
||||||
|
updateModule.setId(id);
|
||||||
|
functionalCaseModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshPos(String parentId) {
|
||||||
|
List<String> childrenIdSortByPos = extFunctionalCaseModuleMapper.selectChildrenIdsSortByPos(parentId);
|
||||||
|
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||||
|
FunctionalCaseModuleMapper batchUpdateMapper = sqlSession.getMapper(FunctionalCaseModuleMapper.class);
|
||||||
|
for (int i = 0; i < childrenIdSortByPos.size(); i++) {
|
||||||
|
String nodeId = childrenIdSortByPos.get(i);
|
||||||
|
FunctionalCaseModule updateModule = new FunctionalCaseModule();
|
||||||
|
updateModule.setId(nodeId);
|
||||||
|
updateModule.setPos((i + 1) * LIMIT_POS);
|
||||||
|
batchUpdateMapper.updateByPrimaryKeySelective(updateModule);
|
||||||
|
}
|
||||||
|
sqlSession.flushStatements();
|
||||||
|
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,736 @@
|
||||||
|
package io.metersphere.functional.controller;
|
||||||
|
|
||||||
|
import io.metersphere.functional.domain.FunctionalCaseModule;
|
||||||
|
import io.metersphere.functional.domain.FunctionalCaseModuleExample;
|
||||||
|
import io.metersphere.functional.mapper.FunctionalCaseModuleMapper;
|
||||||
|
import io.metersphere.functional.request.FunctionalCaseModuleCreateRequest;
|
||||||
|
import io.metersphere.functional.request.FunctionalCaseModuleUpdateRequest;
|
||||||
|
import io.metersphere.functional.service.FunctionalCaseModuleService;
|
||||||
|
import io.metersphere.project.domain.Project;
|
||||||
|
import io.metersphere.project.mapper.ProjectMapper;
|
||||||
|
import io.metersphere.sdk.constants.ModuleConstants;
|
||||||
|
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.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.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 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 FunctionalCaseModuleControllerTests extends BaseTest {
|
||||||
|
|
||||||
|
private static Project project;
|
||||||
|
|
||||||
|
private static List<BaseTreeNode> preliminaryTreeNodes = new ArrayList<>();
|
||||||
|
|
||||||
|
private static final String URL_MODULE_TREE = "/functional/case/module/tree/";
|
||||||
|
private static final String URL_MODULE_TREE_ADD = "/functional/case/module/add";
|
||||||
|
private static final String URL_MODULE_TREE_UPDATE = "/functional/case/module/update";
|
||||||
|
private static final String URL_MODULE_TREE_MOVE = "/functional/case/module/move";
|
||||||
|
private static final String URL_MODULE_TREE_DELETE = "/functional/case/module/delete/";
|
||||||
|
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FunctionalCaseModuleService functionalCaseModuleService;
|
||||||
|
@Resource
|
||||||
|
private FunctionalCaseModuleMapper functionalCaseModuleMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ProjectMapper projectMapper;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void initTestData() {
|
||||||
|
if (project == null) {
|
||||||
|
Project initProject = new Project();
|
||||||
|
initProject.setId(IDGenerator.nextStr());
|
||||||
|
initProject.setNum(null);
|
||||||
|
initProject.setOrganizationId("100001");
|
||||||
|
initProject.setName("caseModuleTestProject");
|
||||||
|
initProject.setDescription("caseModuleTestProject");
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(1)
|
||||||
|
public void emptyDataTest() throws Exception {
|
||||||
|
//空数据下,检查模块树
|
||||||
|
List<BaseTreeNode> treeNodes = this.getFunctionalCaseModuleTreeNode();
|
||||||
|
//检查有没有默认节点
|
||||||
|
boolean hasNode = false;
|
||||||
|
for (BaseTreeNode baseTreeNode : treeNodes) {
|
||||||
|
if (StringUtils.equals(baseTreeNode.getId(), ModuleConstants.DEFAULT_NODE_ID)) {
|
||||||
|
hasNode = true;
|
||||||
|
}
|
||||||
|
Assertions.assertNotNull(baseTreeNode.getParentId());
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(hasNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(2)
|
||||||
|
public void addModuleTestSuccess() throws Exception {
|
||||||
|
//根目录下创建节点(a1)
|
||||||
|
FunctionalCaseModuleCreateRequest request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
request.setProjectId(project.getId());
|
||||||
|
request.setName("a1");
|
||||||
|
MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_MODULE_TREE_ADD, request);
|
||||||
|
String returnId = mvcResult.getResponse().getContentAsString();
|
||||||
|
Assertions.assertNotNull(returnId);
|
||||||
|
List<BaseTreeNode> treeNodes = this.getFunctionalCaseModuleTreeNode();
|
||||||
|
BaseTreeNode a1Node = null;
|
||||||
|
for (BaseTreeNode baseTreeNode : treeNodes) {
|
||||||
|
if (StringUtils.equals(baseTreeNode.getName(), request.getName())) {
|
||||||
|
a1Node = baseTreeNode;
|
||||||
|
}
|
||||||
|
Assertions.assertNotNull(baseTreeNode.getParentId());
|
||||||
|
}
|
||||||
|
Assertions.assertNotNull(a1Node);
|
||||||
|
|
||||||
|
//根目录下创建节点a2和a3,在a1下创建子节点a1-b1
|
||||||
|
request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
request.setProjectId(project.getId());
|
||||||
|
request.setName("a2");
|
||||||
|
this.requestPostWithOkAndReturn(URL_MODULE_TREE_ADD, request);
|
||||||
|
|
||||||
|
request.setName("a3");
|
||||||
|
this.requestPostWithOkAndReturn(URL_MODULE_TREE_ADD, request);
|
||||||
|
|
||||||
|
request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
request.setProjectId(project.getId());
|
||||||
|
request.setName("a1-b1");
|
||||||
|
request.setParentId(a1Node.getId());
|
||||||
|
this.requestPostWithOkAndReturn(URL_MODULE_TREE_ADD, request);
|
||||||
|
|
||||||
|
treeNodes = this.getFunctionalCaseModuleTreeNode();
|
||||||
|
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")) {
|
||||||
|
a1b1Node = childNode;
|
||||||
|
}
|
||||||
|
Assertions.assertNotNull(childNode.getParentId());
|
||||||
|
}
|
||||||
|
} else if (StringUtils.equals(baseTreeNode.getName(), "a2")) {
|
||||||
|
a2Node = baseTreeNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assertions.assertNotNull(a2Node);
|
||||||
|
Assertions.assertNotNull(a1b1Node);
|
||||||
|
|
||||||
|
//a1节点下可以继续添加a1节点
|
||||||
|
request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
request.setProjectId(project.getId());
|
||||||
|
request.setName("a1");
|
||||||
|
request.setParentId(a1Node.getId());
|
||||||
|
this.requestPostWithOkAndReturn(URL_MODULE_TREE_ADD, request);
|
||||||
|
|
||||||
|
//继续创建a1下继续创建a1-a1-b1,
|
||||||
|
treeNodes = this.getFunctionalCaseModuleTreeNode();
|
||||||
|
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")) {
|
||||||
|
a1ChildNode = childNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assertions.assertNotNull(a1ChildNode);
|
||||||
|
|
||||||
|
//a1的子节点a1下继续创建节点a1-a1-c1
|
||||||
|
request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
request.setProjectId(project.getId());
|
||||||
|
request.setName("a1-a1-c1");
|
||||||
|
request.setParentId(a1ChildNode.getId());
|
||||||
|
this.requestPostWithOkAndReturn(URL_MODULE_TREE_ADD, request);
|
||||||
|
treeNodes = this.getFunctionalCaseModuleTreeNode();
|
||||||
|
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")) {
|
||||||
|
a1a1c1Node = thirdNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assertions.assertNotNull(a1a1c1Node);
|
||||||
|
|
||||||
|
//子节点a1-b1下继续创建节点a1-b1-c1
|
||||||
|
request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
request.setProjectId(project.getId());
|
||||||
|
request.setName("a1-b1-c1");
|
||||||
|
request.setParentId(a1b1Node.getId());
|
||||||
|
this.requestPostWithOkAndReturn(URL_MODULE_TREE_ADD, request);
|
||||||
|
treeNodes = this.getFunctionalCaseModuleTreeNode();
|
||||||
|
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")) {
|
||||||
|
a1b1c1Node = thirdNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assertions.assertNotNull(a1b1c1Node);
|
||||||
|
preliminaryTreeNodes = treeNodes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(3)
|
||||||
|
public void addModuleTestError() throws Exception {
|
||||||
|
this.preliminaryData();
|
||||||
|
|
||||||
|
BaseTreeNode a1Node = getNodeByName(preliminaryTreeNodes, "a1");
|
||||||
|
assert a1Node != null;
|
||||||
|
|
||||||
|
//参数校验
|
||||||
|
FunctionalCaseModuleCreateRequest request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
request.setProjectId(project.getId());
|
||||||
|
this.requestPost(URL_MODULE_TREE_ADD, request).andExpect(status().isBadRequest());
|
||||||
|
request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
request.setName("none");
|
||||||
|
this.requestPost(URL_MODULE_TREE_ADD, request).andExpect(status().isBadRequest());
|
||||||
|
request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
this.requestPost(URL_MODULE_TREE_ADD, request).andExpect(status().isBadRequest());
|
||||||
|
request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
request.setParentId(null);
|
||||||
|
this.requestPost(URL_MODULE_TREE_ADD, request).andExpect(status().isBadRequest());
|
||||||
|
|
||||||
|
//父节点ID不存在的
|
||||||
|
request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
request.setProjectId(project.getId());
|
||||||
|
request.setName("ParentIsUUID");
|
||||||
|
request.setParentId(IDGenerator.nextStr());
|
||||||
|
this.requestPost(URL_MODULE_TREE_ADD, request).andExpect(status().is5xxServerError());
|
||||||
|
|
||||||
|
//添加重复的a1节点
|
||||||
|
request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
request.setProjectId(project.getId());
|
||||||
|
request.setName("a1");
|
||||||
|
this.requestPost(URL_MODULE_TREE_ADD, request).andExpect(status().is5xxServerError());
|
||||||
|
|
||||||
|
//a1节点下添加重复的a1-b1节点
|
||||||
|
request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
request.setProjectId(project.getId());
|
||||||
|
request.setName("a1-b1");
|
||||||
|
request.setParentId(a1Node.getId());
|
||||||
|
this.requestPost(URL_MODULE_TREE_ADD, request).andExpect(status().is5xxServerError());
|
||||||
|
|
||||||
|
//子节点的项目ID和父节点的不匹配
|
||||||
|
request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
request.setProjectId(IDGenerator.nextStr());
|
||||||
|
request.setName("RandomUUID");
|
||||||
|
request.setParentId(a1Node.getId());
|
||||||
|
this.requestPost(URL_MODULE_TREE_ADD, request).andExpect(status().is5xxServerError());
|
||||||
|
|
||||||
|
//项目ID和父节点的不匹配
|
||||||
|
request = new FunctionalCaseModuleCreateRequest();
|
||||||
|
request.setProjectId("100001100001");
|
||||||
|
request.setName("RandomUUID");
|
||||||
|
request.setParentId(a1Node.getId());
|
||||||
|
this.requestPost(URL_MODULE_TREE_ADD, request).andExpect(status().is5xxServerError());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BaseTreeNode getNodeByName(List<BaseTreeNode> preliminaryTreeNodes, String nodeName) {
|
||||||
|
for (BaseTreeNode firstLevelNode : preliminaryTreeNodes) {
|
||||||
|
if (StringUtils.equals(firstLevelNode.getName(), nodeName)) {
|
||||||
|
return firstLevelNode;
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(firstLevelNode.getChildren())) {
|
||||||
|
for (BaseTreeNode secondLevelNode : firstLevelNode.getChildren()) {
|
||||||
|
if (StringUtils.equals(secondLevelNode.getName(), nodeName)) {
|
||||||
|
return secondLevelNode;
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(secondLevelNode.getChildren())) {
|
||||||
|
for (BaseTreeNode thirdLevelNode : secondLevelNode.getChildren()) {
|
||||||
|
if (StringUtils.equals(thirdLevelNode.getName(), nodeName)) {
|
||||||
|
return thirdLevelNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
FunctionalCaseModuleUpdateRequest updateRequest = new FunctionalCaseModuleUpdateRequest();
|
||||||
|
updateRequest.setId(a1Node.getId());
|
||||||
|
updateRequest.setName("a1-a1");
|
||||||
|
this.requestPostWithOkAndReturn(URL_MODULE_TREE_UPDATE, updateRequest);
|
||||||
|
|
||||||
|
preliminaryTreeNodes = this.getFunctionalCaseModuleTreeNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(5)
|
||||||
|
public void updateModuleTestError() throws Exception {
|
||||||
|
BaseTreeNode a1Node = getNodeByName(preliminaryTreeNodes, "a1-a1");
|
||||||
|
assert a1Node != null;
|
||||||
|
//反例-参数校验
|
||||||
|
FunctionalCaseModuleUpdateRequest updateRequest = new FunctionalCaseModuleUpdateRequest();
|
||||||
|
this.requestPost(URL_MODULE_TREE_UPDATE, updateRequest).andExpect(status().isBadRequest());
|
||||||
|
|
||||||
|
//id不存在
|
||||||
|
updateRequest = new FunctionalCaseModuleUpdateRequest();
|
||||||
|
updateRequest.setId(IDGenerator.nextStr());
|
||||||
|
updateRequest.setName(IDGenerator.nextStr());
|
||||||
|
this.requestPost(URL_MODULE_TREE_UPDATE, updateRequest).andExpect(status().is5xxServerError());
|
||||||
|
|
||||||
|
//名称重复 a1-a1改为a1-b1
|
||||||
|
updateRequest = new FunctionalCaseModuleUpdateRequest();
|
||||||
|
updateRequest.setId(a1Node.getId());
|
||||||
|
updateRequest.setName("a1-b1");
|
||||||
|
this.requestPost(URL_MODULE_TREE_UPDATE, updateRequest).andExpect(status().is5xxServerError());
|
||||||
|
}
|
||||||
|
|
||||||
|
@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();
|
||||||
|
{
|
||||||
|
request.setDragNodeId(a1Node.getId());
|
||||||
|
request.setDropNodeId(a3Node.getId());
|
||||||
|
request.setDropPosition(1);
|
||||||
|
this.requestPostWithOk(URL_MODULE_TREE_MOVE, request);
|
||||||
|
this.checkModulePos(a3Node.getId(), a1Node.getId(), null, false);
|
||||||
|
}
|
||||||
|
//父节点内移动-移动到末位 在上面的基础上,a1挪到a2上面
|
||||||
|
{
|
||||||
|
request = new NodeMoveRequest();
|
||||||
|
request.setDragNodeId(a1Node.getId());
|
||||||
|
request.setDropNodeId(a2Node.getId());
|
||||||
|
request.setDropPosition(-1);
|
||||||
|
this.requestPostWithOk(URL_MODULE_TREE_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_TREE_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_TREE_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_TREE_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_TREE_MOVE, request);
|
||||||
|
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//跨节点移动-移动到末尾 a3移动到a1-a1后面,然后移动回来;
|
||||||
|
{
|
||||||
|
request = new NodeMoveRequest();
|
||||||
|
request.setDragNodeId(a3Node.getId());
|
||||||
|
request.setDropNodeId(a1a1Node.getId());
|
||||||
|
request.setDropPosition(1);
|
||||||
|
this.requestPostWithOk(URL_MODULE_TREE_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_TREE_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_TREE_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_TREE_MOVE, request);
|
||||||
|
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//父节点内移动-a3移动到首位pos小于2,是否触发计算函数 (先手动更改a1的pos为2,然后移动a3到a1前面)
|
||||||
|
{
|
||||||
|
//更改pos
|
||||||
|
FunctionalCaseModule updateModule = new FunctionalCaseModule();
|
||||||
|
updateModule.setId(a1Node.getId());
|
||||||
|
updateModule.setPos(2L);
|
||||||
|
functionalCaseModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||||
|
|
||||||
|
//开始移动
|
||||||
|
request = new NodeMoveRequest();
|
||||||
|
request.setDragNodeId(a3Node.getId());
|
||||||
|
request.setDropNodeId(a1Node.getId());
|
||||||
|
request.setDropPosition(-1);
|
||||||
|
this.requestPostWithOk(URL_MODULE_TREE_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_TREE_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
|
||||||
|
FunctionalCaseModule updateModule = new FunctionalCaseModule();
|
||||||
|
updateModule.setId(a1Node.getId());
|
||||||
|
updateModule.setPos(3 * 64L);
|
||||||
|
functionalCaseModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||||
|
updateModule.setId(a2Node.getId());
|
||||||
|
updateModule.setPos(3 * 64 + 2L);
|
||||||
|
functionalCaseModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||||
|
|
||||||
|
//开始移动
|
||||||
|
request = new NodeMoveRequest();
|
||||||
|
request.setDragNodeId(a3Node.getId());
|
||||||
|
request.setDropNodeId(a1Node.getId());
|
||||||
|
request.setDropPosition(1);
|
||||||
|
this.requestPostWithOk(URL_MODULE_TREE_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_TREE_MOVE, request);
|
||||||
|
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
|
||||||
|
}
|
||||||
|
//跨节点移动-移动到首位pos小于2,是否触发计算函数(先手动更改a1-b1的pos为2,然后移动a3到a1-b1前面,最后再移动回来)
|
||||||
|
{
|
||||||
|
//更改pos
|
||||||
|
FunctionalCaseModule updateModule = new FunctionalCaseModule();
|
||||||
|
updateModule.setId(a1b1Node.getId());
|
||||||
|
updateModule.setPos(2L);
|
||||||
|
functionalCaseModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||||
|
|
||||||
|
//开始移动
|
||||||
|
request = new NodeMoveRequest();
|
||||||
|
request.setDragNodeId(a3Node.getId());
|
||||||
|
request.setDropNodeId(a1b1Node.getId());
|
||||||
|
request.setDropPosition(-1);
|
||||||
|
this.requestPostWithOk(URL_MODULE_TREE_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_TREE_MOVE, request);
|
||||||
|
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
|
||||||
|
}
|
||||||
|
//跨节点移动-移动到中位,前后节点pos差不大于2,是否触发计算函数先手动更改a1-a1的pos为a1-b1+2,然后移动a3到a1-a1前面,最后再移动回来)
|
||||||
|
{
|
||||||
|
//更改pos
|
||||||
|
FunctionalCaseModule updateModule = new FunctionalCaseModule();
|
||||||
|
updateModule.setId(a1b1Node.getId());
|
||||||
|
updateModule.setPos(3 * 64L);
|
||||||
|
functionalCaseModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||||
|
updateModule.setId(a1a1Node.getId());
|
||||||
|
updateModule.setPos(3 * 64 + 2L);
|
||||||
|
functionalCaseModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||||
|
|
||||||
|
//开始移动
|
||||||
|
request = new NodeMoveRequest();
|
||||||
|
request.setDragNodeId(a3Node.getId());
|
||||||
|
request.setDropNodeId(a1a1Node.getId());
|
||||||
|
request.setDropPosition(-1);
|
||||||
|
this.requestPostWithOk(URL_MODULE_TREE_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_TREE_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_TREE_MOVE, request);
|
||||||
|
FunctionalCaseModule a3Module = functionalCaseModuleMapper.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_TREE_MOVE, request);
|
||||||
|
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
request.setDropNodeId(a1Node.getId());
|
||||||
|
request.setDropPosition(1);
|
||||||
|
this.requestPost(URL_MODULE_TREE_MOVE, request).andExpect(status().isBadRequest());
|
||||||
|
//drag节点不存在
|
||||||
|
request = new NodeMoveRequest();
|
||||||
|
request.setDragNodeId(IDGenerator.nextStr());
|
||||||
|
request.setDropNodeId(a1Node.getId());
|
||||||
|
request.setDropPosition(1);
|
||||||
|
this.requestPost(URL_MODULE_TREE_MOVE, request).andExpect(status().is5xxServerError());
|
||||||
|
|
||||||
|
//drop节点为空
|
||||||
|
request = new NodeMoveRequest();
|
||||||
|
request.setDragNodeId(a1Node.getId());
|
||||||
|
request.setDropNodeId(null);
|
||||||
|
request.setDropPosition(1);
|
||||||
|
this.requestPost(URL_MODULE_TREE_MOVE, request).andExpect(status().isBadRequest());
|
||||||
|
|
||||||
|
//drop节点不存在
|
||||||
|
request = new NodeMoveRequest();
|
||||||
|
request.setDragNodeId(a1Node.getId());
|
||||||
|
request.setDropNodeId(IDGenerator.nextStr());
|
||||||
|
request.setDropPosition(1);
|
||||||
|
this.requestPost(URL_MODULE_TREE_MOVE, request).andExpect(status().is5xxServerError());
|
||||||
|
|
||||||
|
//position为0的时候节点不存在
|
||||||
|
request = new NodeMoveRequest();
|
||||||
|
request.setDragNodeId(a1Node.getId());
|
||||||
|
request.setDropNodeId(IDGenerator.nextStr());
|
||||||
|
request.setDropPosition(0);
|
||||||
|
this.requestPost(URL_MODULE_TREE_MOVE, request).andExpect(status().is5xxServerError());
|
||||||
|
|
||||||
|
//dragNode和dropNode一样
|
||||||
|
request = new NodeMoveRequest();
|
||||||
|
request.setDragNodeId(a1Node.getId());
|
||||||
|
request.setDropNodeId(a1Node.getId());
|
||||||
|
request.setDropPosition(1);
|
||||||
|
this.requestPost(URL_MODULE_TREE_MOVE, request).andExpect(status().is5xxServerError());
|
||||||
|
|
||||||
|
//position不是-1 0 1
|
||||||
|
request = new NodeMoveRequest();
|
||||||
|
request.setDragNodeId(a1Node.getId());
|
||||||
|
request.setDropNodeId(a2Node.getId());
|
||||||
|
request.setDropPosition(4);
|
||||||
|
this.requestPost(URL_MODULE_TREE_MOVE, request).andExpect(status().is5xxServerError());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(8)
|
||||||
|
public void deleteModuleTestSuccess() throws Exception {
|
||||||
|
this.preliminaryData();
|
||||||
|
|
||||||
|
// 删除没有文件的节点a1-b1-c1 检查是否级联删除根节点
|
||||||
|
BaseTreeNode a1b1Node = getNodeByName(this.getFunctionalCaseModuleTreeNode(), "a1-b1");
|
||||||
|
assert a1b1Node != null;
|
||||||
|
this.requestGetWithOk(URL_MODULE_TREE_DELETE+a1b1Node.getId());
|
||||||
|
this.checkModuleIsEmpty(a1b1Node.getId());
|
||||||
|
|
||||||
|
// 删除有文件的节点 a1-a1 检查是否级联删除根节点
|
||||||
|
BaseTreeNode a1a1Node = getNodeByName(this.getFunctionalCaseModuleTreeNode(), "a1-a1");
|
||||||
|
this.requestGetWithOk(URL_MODULE_TREE_DELETE+a1a1Node.getId());
|
||||||
|
this.checkModuleIsEmpty(a1a1Node.getId());
|
||||||
|
|
||||||
|
//删除不存在的节点
|
||||||
|
this.requestGetWithOk(URL_MODULE_TREE_DELETE+IDGenerator.nextNum());
|
||||||
|
// 测试删除根节点
|
||||||
|
this.requestGetWithOk(URL_MODULE_TREE_DELETE+ModuleConstants.DEFAULT_NODE_ID);
|
||||||
|
|
||||||
|
//service层判断:测试删除空集合
|
||||||
|
functionalCaseModuleService.deleteModuleByIds(new ArrayList<>());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkModuleIsEmpty(String id) {
|
||||||
|
FunctionalCaseModuleExample example = new FunctionalCaseModuleExample();
|
||||||
|
example.createCriteria().andParentIdEqualTo(id).andDeletedEqualTo(false);
|
||||||
|
Assertions.assertEquals(functionalCaseModuleMapper.countByExample(example), 0);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<BaseTreeNode> getFunctionalCaseModuleTreeNode() throws Exception {
|
||||||
|
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get(URL_MODULE_TREE+"/"+project.getId()).header(SessionConstants.HEADER_TOKEN, sessionId)
|
||||||
|
.header(SessionConstants.CSRF_TOKEN, csrfToken)
|
||||||
|
.header(SessionConstants.CURRENT_PROJECT, project.getId())
|
||||||
|
.contentType(MediaType.APPLICATION_JSON))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn();
|
||||||
|
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 checkModulePos(String firstNode, String secondNode, String thirdNode, boolean isRecalculate) {
|
||||||
|
FunctionalCaseModule firstModule = functionalCaseModuleMapper.selectByPrimaryKey(firstNode);
|
||||||
|
FunctionalCaseModule secondModule = functionalCaseModuleMapper.selectByPrimaryKey(secondNode);
|
||||||
|
FunctionalCaseModule thirdModule = null;
|
||||||
|
Assertions.assertTrue(firstModule.getPos() < secondModule.getPos());
|
||||||
|
if (StringUtils.isNotBlank(thirdNode)) {
|
||||||
|
thirdModule = functionalCaseModuleMapper.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue