From 46afc6c124009753e876acf52916a73bfe1cd46a Mon Sep 17 00:00:00 2001 From: guoyuqi Date: Mon, 29 Apr 2024 09:19:00 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E7=94=A8=E4=BE=8B=E7=AE=A1=E7=90=86):=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=84=91=E5=9B=BE=E7=82=B9=E5=87=BB=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E8=8E=B7=E5=8F=96=E7=94=A8=E4=BE=8B=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...e_user_key.sql => V3.0.0_12__beta_ddl.sql} | 3 + .../FunctionalCaseMinderController.java | 27 +- .../functional/dto/FunctionalCaseMindDTO.java | 61 ++++ .../mapper/ExtFunctionalCaseMapper.java | 13 +- .../mapper/ExtFunctionalCaseMapper.xml | 22 ++ .../request/FunctionalCaseMindRequest.java | 16 ++ .../service/FunctionalCaseMinderService.java | 272 ++++-------------- .../FunctionalCaseMinderControllerTest.java | 59 +--- .../resources/dml/init_file_minder_test.sql | 6 +- 9 files changed, 188 insertions(+), 291 deletions(-) rename backend/framework/domain/src/main/resources/migration/3.0.0/ddl/{V3.0.0_12__update_user_key.sql => V3.0.0_12__beta_ddl.sql} (74%) create mode 100644 backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseMindDTO.java create mode 100644 backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseMindRequest.java diff --git a/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_12__update_user_key.sql b/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_12__beta_ddl.sql similarity index 74% rename from backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_12__update_user_key.sql rename to backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_12__beta_ddl.sql index 4abe620041..5f8d17cea4 100644 --- a/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_12__update_user_key.sql +++ b/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_12__beta_ddl.sql @@ -5,6 +5,9 @@ ALTER TABLE user_key MODIFY COLUMN description VARCHAR(1000); ALTER TABLE api_definition_mock ADD COLUMN status_code INT(50) ; +CREATE INDEX idx_scene ON custom_field (scene); +CREATE INDEX idx_internal ON custom_field (internal); + -- set innodb lock wait timeout to default SET SESSION innodb_lock_wait_timeout = DEFAULT; diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalCaseMinderController.java b/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalCaseMinderController.java index 6a67039cde..c8d5cf4a0f 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalCaseMinderController.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalCaseMinderController.java @@ -1,13 +1,10 @@ package io.metersphere.functional.controller; -import com.alibaba.excel.util.StringUtils; import io.metersphere.functional.dto.FunctionalMinderTreeDTO; -import io.metersphere.functional.request.FunctionalCasePageRequest; -import io.metersphere.functional.request.MinderReviewFunctionalCasePageRequest; +import io.metersphere.functional.request.FunctionalCaseMindRequest; import io.metersphere.functional.service.FunctionalCaseMinderService; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.system.security.CheckOwner; -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; @@ -18,6 +15,8 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + /** * @author guoyuqi */ @@ -30,23 +29,11 @@ public class FunctionalCaseMinderController { private FunctionalCaseMinderService functionalCaseMinderService; @PostMapping("/list") - @Operation(summary = "用例管理-功能用例-脑图用例列表查询") + @Operation(summary = "用例管理-功能用例-脑图用例跟根据模块ID查询列表") @RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_MINDER) - @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") - public FunctionalMinderTreeDTO getFunctionalCaseMinderTree(@Validated @RequestBody FunctionalCasePageRequest request) { - return functionalCaseMinderService.getFunctionalCasePage(request, false); - } - - @PostMapping("/review/list") - @Operation(summary = "用例管理-用例评审-脑图用例列表查询") - @RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_MINDER) - @CheckOwner(resourceId = "#request.getReviewId()", resourceType = "case_review") - public FunctionalMinderTreeDTO getFunctionalReviewCaseMinderTree(@Validated @RequestBody MinderReviewFunctionalCasePageRequest request) { - String userId = StringUtils.EMPTY; - if (request.isViewFlag()) { - userId = SessionUtils.getUserId(); - } - return functionalCaseMinderService.getReviewFunctionalCasePage(request, false, userId); + @CheckOwner(resourceId = "#projectId()", resourceType = "project") + public List getFunctionalCaseMinderTree(@Validated @RequestBody FunctionalCaseMindRequest request) { + return functionalCaseMinderService.getMindFunctionalCase(request, false); } } diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseMindDTO.java b/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseMindDTO.java new file mode 100644 index 0000000000..38ea775d9c --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseMindDTO.java @@ -0,0 +1,61 @@ +package io.metersphere.functional.dto; + +import io.metersphere.validation.groups.Created; +import io.metersphere.validation.groups.Updated; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class FunctionalCaseMindDTO { + + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{functional_case.id.not_blank}", groups = {Updated.class}) + @Size(min = 1, max = 50, message = "{functional_case.id.length_range}", groups = {Created.class, Updated.class}) + private String id; + + @Schema(description = "模块ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{functional_case.module_id.not_blank}", groups = {Created.class}) + @Size(min = 1, max = 50, message = "{functional_case.module_id.length_range}", groups = {Created.class, Updated.class}) + private String moduleId; + + @Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{functional_case.project_id.not_blank}", groups = {Created.class}) + @Size(min = 1, max = 50, message = "{functional_case.project_id.length_range}", groups = {Created.class, Updated.class}) + private String projectId; + + @Schema(description = "模板ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{functional_case.template_id.not_blank}", groups = {Created.class}) + @Size(min = 1, max = 50, message = "{functional_case.template_id.length_range}", groups = {Created.class, Updated.class}) + private String templateId; + + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{functional_case.name.not_blank}", groups = {Created.class}) + @Size(min = 1, max = 255, message = "{functional_case.name.length_range}", groups = {Created.class, Updated.class}) + private String name; + + @Schema(description = "评审状态:未评审/评审中/通过/不通过/重新提审", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{functional_case.review_status.not_blank}", groups = {Created.class}) + @Size(min = 1, max = 64, message = "{functional_case.review_status.length_range}", groups = {Created.class, Updated.class}) + private String reviewStatus; + + @Schema(description = "用例等级") + private String priority; + + @Schema(description = "用例步骤(JSON),step_model 为 Step 时启用") + private byte[] steps; + + @Schema(description = "预期结果,step_model 为 Text 时启用") + private byte[] expectedResult; + + @Schema(description = "前置条件") + private byte[] prerequisite; + + @Schema(description = "备注") + private byte[] description; + + +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.java b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.java index f3d8ca2c47..950dd03ce4 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.java @@ -3,9 +3,11 @@ package io.metersphere.functional.mapper; import io.metersphere.dto.TestCaseProviderDTO; import io.metersphere.functional.domain.FunctionalCase; import io.metersphere.functional.dto.BaseFunctionalCaseBatchDTO; +import io.metersphere.functional.dto.FunctionalCaseMindDTO; import io.metersphere.functional.dto.FunctionalCasePageDTO; import io.metersphere.functional.dto.FunctionalCaseVersionDTO; import io.metersphere.functional.request.FunctionalCaseBatchMoveRequest; +import io.metersphere.functional.request.FunctionalCaseMindRequest; import io.metersphere.functional.request.FunctionalCasePageRequest; import io.metersphere.project.dto.ModuleCountDTO; import io.metersphere.request.AssociateOtherCaseRequest; @@ -63,18 +65,25 @@ public interface ExtFunctionalCaseMapper { /** * 获取缺陷未关联的功能用例列表 + * * @param request provider参数 * @param deleted 是否删除状态 - * @param sort 排序 + * @param sort 排序 * @return 通用的列表Case集合 */ List listUnRelatedCaseWithBug(@Param("request") TestCasePageProviderRequest request, @Param("deleted") boolean deleted, @Param("sort") String sort); /** * 根据关联条件获取关联的用例ID + * * @param request 关联参数 * @param deleted 是否删除状态 * @return 关联的用例ID集合 */ - List getSelectIdsByAssociateParam(@Param("request")AssociateOtherCaseRequest request, @Param("deleted") boolean deleted); + List getSelectIdsByAssociateParam(@Param("request") AssociateOtherCaseRequest request, @Param("deleted") boolean deleted); + + /** + * 根据模块ID获取脑图展示数据 + */ + List getMinderCaseList(@Param("request") FunctionalCaseMindRequest request, @Param("deleted") boolean deleted); } diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.xml b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.xml index f1cbcd1eaa..bf9908ec9c 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.xml +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.xml @@ -779,4 +779,26 @@ + + + \ No newline at end of file diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseMindRequest.java b/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseMindRequest.java new file mode 100644 index 0000000000..fd5270fc4b --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseMindRequest.java @@ -0,0 +1,16 @@ +package io.metersphere.functional.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class FunctionalCaseMindRequest { + @Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{functional_case.project_id.not_blank}") + private String projectId; + + @Schema(description = "模块ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{file_module.id.not_blank}") + private String moduleId; +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseMinderService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseMinderService.java index 3e729b8402..a0e0dcf7a0 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseMinderService.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseMinderService.java @@ -1,26 +1,19 @@ package io.metersphere.functional.service; -import io.metersphere.functional.constants.CaseReviewPassRule; import io.metersphere.functional.constants.MinderLabel; -import io.metersphere.functional.domain.CaseReview; -import io.metersphere.functional.domain.FunctionalCase; -import io.metersphere.functional.dto.*; -import io.metersphere.functional.mapper.CaseReviewMapper; -import io.metersphere.functional.request.FunctionalCasePageRequest; -import io.metersphere.functional.request.MinderReviewFunctionalCasePageRequest; -import io.metersphere.sdk.constants.ModuleConstants; -import io.metersphere.sdk.util.Translator; -import io.metersphere.system.dto.sdk.BaseTreeNode; +import io.metersphere.functional.dto.FunctionalCaseMindDTO; +import io.metersphere.functional.dto.FunctionalMinderTreeDTO; +import io.metersphere.functional.dto.FunctionalMinderTreeNodeDTO; +import io.metersphere.functional.mapper.ExtFunctionalCaseMapper; +import io.metersphere.functional.request.FunctionalCaseMindRequest; import jakarta.annotation.Resource; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; /** * 功能用例脑图 @@ -32,217 +25,70 @@ import java.util.stream.Collectors; public class FunctionalCaseMinderService { @Resource - private FunctionalCaseService functionalCaseService; - @Resource - private FunctionalCaseModuleService functionalCaseModuleService; - @Resource - private CaseReviewFunctionalCaseService caseReviewFunctionalCaseService; - @Resource - private CaseReviewMapper caseReviewMapper; + private ExtFunctionalCaseMapper extFunctionalCaseMapper; /** * 功能用例-脑图用例列表查询 * - * @param request FunctionalCasePageRequest * @param deleted 用例是否删除 * @return FunctionalMinderTreeDTO */ - public FunctionalMinderTreeDTO getFunctionalCasePage(FunctionalCasePageRequest request, boolean deleted) { - //根据查询条件查询出所有符合的功能用例 - List functionalCasePage = functionalCaseService.getFunctionalCasePage(request, deleted); - //根据功能用例的模块ID,查出每个模块id父级直到根节点 - List moduleIds = functionalCasePage.stream().map(FunctionalCase::getModuleId).distinct().toList(); - Map> moduleCaseMap = functionalCasePage.stream().collect(Collectors.groupingBy(FunctionalCasePageDTO::getModuleId)); - List baseTreeNodes = getBaseTreeNodes(moduleIds); - //判断虚拟节点有无数据 - if (moduleCaseMap.get(ModuleConstants.DEFAULT_NODE_ID) == null && CollectionUtils.isEmpty(baseTreeNodes.get(0).getChildren())) { - baseTreeNodes.remove(0); + public List getMindFunctionalCase(FunctionalCaseMindRequest request, boolean deleted) { + List list = new ArrayList<>(); + //查出当前模块下的所有用例 + List functionalCaseMindDTOList = extFunctionalCaseMapper.getMinderCaseList(request, deleted); + //构造父子级数据 + for (FunctionalCaseMindDTO functionalCaseMindDTO : functionalCaseMindDTOList) { + FunctionalMinderTreeDTO root = new FunctionalMinderTreeDTO(); + FunctionalMinderTreeNodeDTO rootData = new FunctionalMinderTreeNodeDTO(); + rootData.setId(functionalCaseMindDTO.getId()); + rootData.setText(functionalCaseMindDTO.getName()); + rootData.setPriority(functionalCaseMindDTO.getPriority()); + rootData.setStatus(functionalCaseMindDTO.getReviewStatus()); + rootData.setResource(List.of(MinderLabel.CASE.toString(), functionalCaseMindDTO.getPriority())); + List children = buildChildren(functionalCaseMindDTO); + root.setChildren(children); + root.setData(rootData); + list.add(root); } - //构建返回数据,主层级应与模块树层级相同 - List functionalMinderTreeNodeDTOs = new ArrayList<>(); - buildCaseTree(baseTreeNodes, moduleCaseMap, functionalMinderTreeNodeDTOs); - return getRoot(functionalMinderTreeNodeDTOs); + return list; } - private static FunctionalMinderTreeDTO getRoot(List functionalMinderTreeDTOs) { - FunctionalMinderTreeDTO root = new FunctionalMinderTreeDTO(); + private List buildChildren(FunctionalCaseMindDTO functionalCaseMindDTO) { + List children = new ArrayList<>(); + if (functionalCaseMindDTO.getSteps() != null) { + String stepText = new String(functionalCaseMindDTO.getSteps(), StandardCharsets.UTF_8); + FunctionalMinderTreeDTO stepFunctionalMinderTreeDTO = getFunctionalMinderTreeDTO(stepText, MinderLabel.TEXT_DESCRIPTION.toString()); + children.add(stepFunctionalMinderTreeDTO); + } + if (functionalCaseMindDTO.getExpectedResult() != null) { + String expectedResultText = new String(functionalCaseMindDTO.getExpectedResult(), StandardCharsets.UTF_8); + FunctionalMinderTreeDTO expectedResultFunctionalMinderTreeDTO = getFunctionalMinderTreeDTO(expectedResultText, MinderLabel.EXPECTED_RESULT.toString()); + children.add(expectedResultFunctionalMinderTreeDTO); + } + if (functionalCaseMindDTO.getPrerequisite() != null) { + String prerequisiteText = new String(functionalCaseMindDTO.getPrerequisite(), StandardCharsets.UTF_8); + FunctionalMinderTreeDTO prerequisiteFunctionalMinderTreeDTO = getFunctionalMinderTreeDTO(prerequisiteText, MinderLabel.PREREQUISITE.toString()); + children.add(prerequisiteFunctionalMinderTreeDTO); + } + if (functionalCaseMindDTO.getDescription() != null) { + String descriptionText = new String(functionalCaseMindDTO.getDescription(), StandardCharsets.UTF_8); + FunctionalMinderTreeDTO descriptionFunctionalMinderTreeDTO = getFunctionalMinderTreeDTO(descriptionText, MinderLabel.DESCRIPTION.toString()); + children.add(descriptionFunctionalMinderTreeDTO); + } + return children; + } + + @NotNull + private static FunctionalMinderTreeDTO getFunctionalMinderTreeDTO(String text, String resource) { + FunctionalMinderTreeDTO functionalMinderTreeDTO = new FunctionalMinderTreeDTO(); FunctionalMinderTreeNodeDTO rootData = new FunctionalMinderTreeNodeDTO(); - rootData.setResource(List.of(MinderLabel.MODULE.toString())); - rootData.setText(Translator.get("case.minder.all.case")); - root.setChildren(functionalMinderTreeDTOs); - root.setData(rootData); - return root; + rootData.setText(text); + rootData.setResource(List.of(resource)); + functionalMinderTreeDTO.setChildren(new ArrayList<>()); + functionalMinderTreeDTO.setData(rootData); + return functionalMinderTreeDTO; } - private List getBaseTreeNodes(List moduleIds) { - List nodeByNodeIds = functionalCaseModuleService.getNodeByNodeIds(moduleIds); - //根据模块节点构造模块树 - return functionalCaseModuleService.buildTreeAndCountResource(nodeByNodeIds, true, Translator.get("functional_case.module.default.name")); - } - - private static void buildCaseTree(List baseTreeNodes, Map> moduleCaseMap, List functionalMinderTreeNodeDTOs) { - baseTreeNodes.forEach(t -> { - //构建根节点 - FunctionalMinderTreeDTO functionalMinderTreeDTO = new FunctionalMinderTreeDTO(); - FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTO = getFunctionalMinderTreeNodeDTO(t); - functionalMinderTreeDTO.setData(functionalMinderTreeNodeDTO); - - List children = new ArrayList<>(); - //如果当前节点有用例,则用例是他的子节点 - buildCaseChild(moduleCaseMap, t, children); - //查询当前节点下的子模块节点 - buildModuleChild(moduleCaseMap, t, children); - functionalMinderTreeDTO.setChildren(children); - functionalMinderTreeNodeDTOs.add(functionalMinderTreeDTO); - }); - } - - private static FunctionalMinderTreeNodeDTO getFunctionalMinderTreeNodeDTO(BaseTreeNode t) { - FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTO = new FunctionalMinderTreeNodeDTO(); - functionalMinderTreeNodeDTO.setId(t.getId()); - functionalMinderTreeNodeDTO.setText(t.getName()); - functionalMinderTreeNodeDTO.setResource(List.of(MinderLabel.MODULE.toString())); - return functionalMinderTreeNodeDTO; - } - - private static void buildCaseChild(Map> moduleCaseMap, BaseTreeNode t, List children) { - if (moduleCaseMap.get(t.getId()) != null && CollectionUtils.isNotEmpty(moduleCaseMap.get(t.getId()))) { - List functionalCasePageDTOS = moduleCaseMap.get(t.getId()); - functionalCasePageDTOS.forEach(functionalCasePageDTO -> { - FunctionalMinderTreeDTO functionalMinderTreeChild = new FunctionalMinderTreeDTO(); - //加载用例为children - FunctionalMinderTreeNodeDTO functionalMinderTreeNodeChild = new FunctionalMinderTreeNodeDTO(); - functionalMinderTreeNodeChild.setId(functionalCasePageDTO.getId()); - functionalMinderTreeNodeChild.setText(functionalCasePageDTO.getName()); - if (CollectionUtils.isNotEmpty(functionalCasePageDTO.getCustomFields())) { - List list = functionalCasePageDTO.getCustomFields().stream().filter(customField -> customField.getFieldName().equals(Translator.get("custom_field.functional_priority"))).toList(); - if (CollectionUtils.isNotEmpty(list)) { - functionalMinderTreeNodeChild.setPriority(list.get(0).getDefaultValue()); - } - } - functionalMinderTreeNodeChild.setResource(List.of(MinderLabel.CASE.toString())); - functionalMinderTreeChild.setData(functionalMinderTreeNodeChild); - //将用例的blob记为Case的children - children.add(functionalMinderTreeChild); - }); - } - } - - private static void buildModuleChild(Map> moduleCaseMap, BaseTreeNode t, List children) { - if (CollectionUtils.isNotEmpty(t.getChildren())) { - t.getChildren().forEach(child -> { - FunctionalMinderTreeDTO functionalMinderTreeDTOChild = new FunctionalMinderTreeDTO(); - FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTOChild = getFunctionalMinderTreeNodeDTO(child); - functionalMinderTreeDTOChild.setData(functionalMinderTreeNodeDTOChild); - - List childChildren = new ArrayList<>(); - buildCaseChild(moduleCaseMap, child, childChildren); - functionalMinderTreeDTOChild.setChildren(childChildren); - children.add(functionalMinderTreeDTOChild); - buildModuleChild(moduleCaseMap, child, childChildren); - }); - } - - } - - /** - * 用例评审-脑图用例列表查询 - * - * @param request MinderReviewFunctionalCasePageRequest - * @param deleted 用例是否删除 - * @param userId userId 只看我的 - * @return FunctionalMinderTreeDTO - */ - public FunctionalMinderTreeDTO getReviewFunctionalCasePage(MinderReviewFunctionalCasePageRequest request, boolean deleted, String userId) { - CaseReview caseReview = caseReviewMapper.selectByPrimaryKey(request.getReviewId()); - List page = caseReviewFunctionalCaseService.page(request, deleted, userId, null); - List caseIds = page.stream().map(ReviewFunctionalCaseDTO::getCaseId).toList(); - List moduleIds = page.stream().map(ReviewFunctionalCaseDTO::getModuleId).toList(); - List baseTreeNodes = getBaseTreeNodes(moduleIds); - //判断虚拟节点有无数据 - Map> moduleCaseMap = page.stream().collect(Collectors.groupingBy(ReviewFunctionalCaseDTO::getModuleId)); - if (moduleCaseMap.get(ModuleConstants.DEFAULT_NODE_ID) == null && CollectionUtils.isEmpty(baseTreeNodes.get(0).getChildren())) { - baseTreeNodes.remove(0); - } - //自定义字段 - Map> caseCustomFiledMap = functionalCaseService.getCaseCustomFiledMap(caseIds,request.getProjectId()); - //构建返回数据,主层级应与模块树层级相同 - MinderSearchDTO minderSearchDTO = new MinderSearchDTO(); - minderSearchDTO.setBaseTreeNodes(baseTreeNodes); - minderSearchDTO.setModuleCaseMap(moduleCaseMap); - minderSearchDTO.setCustomFieldMap(caseCustomFiledMap); - minderSearchDTO.setReviewPassRule(caseReview.getReviewPassRule()); - minderSearchDTO.setViewFlag(request.isViewFlag()); - minderSearchDTO.setViewResult(request.isViewResult()); - List functionalMinderTreeDTOs = buildReviewCaseTree(minderSearchDTO); - return getRoot(functionalMinderTreeDTOs); - - } - - private List buildReviewCaseTree(MinderSearchDTO minderSearchDTO) { - List functionalMinderTreeNodeDTOs = new ArrayList<>(); - minderSearchDTO.getBaseTreeNodes().forEach(t -> { - //构建根节点 - FunctionalMinderTreeDTO functionalMinderTreeDTO = new FunctionalMinderTreeDTO(); - FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTO = getFunctionalMinderTreeNodeDTO(t); - functionalMinderTreeDTO.setData(functionalMinderTreeNodeDTO); - - List children = new ArrayList<>(); - //如果当前节点有用例,则用例是他的子节点 - minderSearchDTO.setBaseTreeNode(t); - buildReviewCaseChild(minderSearchDTO, children); - //查询当前节点下的子模块节点 - buildReviewModuleChild(minderSearchDTO, children); - functionalMinderTreeDTO.setChildren(children); - functionalMinderTreeNodeDTOs.add(functionalMinderTreeDTO); - }); - return functionalMinderTreeNodeDTOs; - } - - private void buildReviewModuleChild(MinderSearchDTO minderSearchDTO, List children) { - List baseTreeNodes = minderSearchDTO.getBaseTreeNode().getChildren(); - if (CollectionUtils.isNotEmpty(baseTreeNodes)) { - baseTreeNodes.forEach(child -> { - FunctionalMinderTreeDTO functionalMinderTreeDTOChild = new FunctionalMinderTreeDTO(); - FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTOChild = getFunctionalMinderTreeNodeDTO(child); - functionalMinderTreeDTOChild.setData(functionalMinderTreeNodeDTOChild); - minderSearchDTO.setBaseTreeNode(child); - List childChildren = new ArrayList<>(); - buildReviewCaseChild(minderSearchDTO, childChildren); - functionalMinderTreeDTOChild.setChildren(childChildren); - children.add(functionalMinderTreeDTOChild); - buildReviewModuleChild(minderSearchDTO, childChildren); - }); - } - } - - private void buildReviewCaseChild(MinderSearchDTO minderSearchDTO, List children) { - Map> moduleCaseMap = minderSearchDTO.getModuleCaseMap(); - BaseTreeNode baseTreeNode = minderSearchDTO.getBaseTreeNode(); - String baseTreeNodeId = baseTreeNode.getId(); - if (moduleCaseMap.get(baseTreeNodeId) != null && CollectionUtils.isNotEmpty(moduleCaseMap.get(baseTreeNodeId))) { - List reviewFunctionalCaseDTOS = moduleCaseMap.get(baseTreeNodeId); - reviewFunctionalCaseDTOS.forEach(reviewFunctionalCaseDTO -> { - FunctionalMinderTreeDTO functionalMinderTreeChild = new FunctionalMinderTreeDTO(); - //加载用例为children - FunctionalMinderTreeNodeDTO functionalMinderTreeNodeChild = new FunctionalMinderTreeNodeDTO(); - functionalMinderTreeNodeChild.setId(reviewFunctionalCaseDTO.getCaseId()); - functionalMinderTreeNodeChild.setText(reviewFunctionalCaseDTO.getName()); - List functionalCaseCustomFieldDTOS = minderSearchDTO.getCustomFieldMap().get(reviewFunctionalCaseDTO.getCaseId()); - if (CollectionUtils.isNotEmpty(functionalCaseCustomFieldDTOS)) { - List list = functionalCaseCustomFieldDTOS.stream().filter(customField -> customField.getFieldName().equals(Translator.get("custom_field.functional_priority"))).toList(); - if (CollectionUtils.isNotEmpty(list)) { - functionalMinderTreeNodeChild.setPriority(list.get(0).getDefaultValue()); - } - } - if (minderSearchDTO.isViewFlag() && minderSearchDTO.isViewResult() && StringUtils.equalsIgnoreCase(minderSearchDTO.getReviewPassRule(), CaseReviewPassRule.MULTIPLE.toString())) { - functionalMinderTreeNodeChild.setStatus(reviewFunctionalCaseDTO.getStatus()); - } - functionalMinderTreeNodeChild.setResource(List.of(MinderLabel.CASE.toString())); - functionalMinderTreeChild.setData(functionalMinderTreeNodeChild); - children.add(functionalMinderTreeChild); - }); - } - } } diff --git a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseMinderControllerTest.java b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseMinderControllerTest.java index 33a81bb70f..bbf84e6a63 100644 --- a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseMinderControllerTest.java +++ b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseMinderControllerTest.java @@ -1,8 +1,7 @@ package io.metersphere.functional.controller; import io.metersphere.functional.dto.FunctionalMinderTreeDTO; -import io.metersphere.functional.request.FunctionalCasePageRequest; -import io.metersphere.functional.request.MinderReviewFunctionalCasePageRequest; +import io.metersphere.functional.request.FunctionalCaseMindRequest; import io.metersphere.sdk.util.JSON; import io.metersphere.system.base.BaseTest; import io.metersphere.system.controller.handler.ResultHolder; @@ -14,76 +13,30 @@ import org.springframework.test.context.jdbc.SqlConfig; import org.springframework.test.web.servlet.MvcResult; import java.nio.charset.StandardCharsets; -import java.util.HashMap; +import java.util.List; @SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @AutoConfigureMockMvc public class FunctionalCaseMinderControllerTest extends BaseTest { - public static final String FUNCTIONAL_CASE_LIST_URL = "/functional/mind/case/list"; - public static final String REViEW_FUNCTIONAL_CASE_LIST_URL = "/functional/mind/case/review/list"; - - @Test @Order(1) @Sql(scripts = {"/dml/init_file_minder_test.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED)) public void testGetPageList() throws Exception { - FunctionalCasePageRequest request = new FunctionalCasePageRequest(); + FunctionalCaseMindRequest request = new FunctionalCaseMindRequest(); request.setProjectId("project-case-minder-test"); - request.setCurrent(1); - request.setPageSize(10); - request.setSort(new HashMap<>() {{ - put("createTime", "desc"); - }}); + request.setModuleId("TEST_MINDER_MODULE_ID_GYQ"); MvcResult mvcResultPage = this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_LIST_URL, request); String contentAsString = mvcResultPage.getResponse().getContentAsString(StandardCharsets.UTF_8); ResultHolder resultHolder = JSON.parseObject(contentAsString, ResultHolder.class); - FunctionalMinderTreeDTO baseTreeNodes = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), FunctionalMinderTreeDTO.class); + List baseTreeNodes = JSON.parseArray(JSON.toJSONString(resultHolder.getData()), FunctionalMinderTreeDTO.class); Assertions.assertNotNull(baseTreeNodes); String jsonString = JSON.toJSONString(baseTreeNodes); System.out.println(jsonString); + Assertions.assertEquals(2,baseTreeNodes.size()); } - - @Test - @Order(2) - public void testGetReviewPageList() throws Exception { - /* Map map = new HashMap<>(); - map.put("customs", Arrays.asList(new LinkedHashMap() {{ - put("id", "TEST_FIELD_ID"); - put("operator", "in"); - put("value", "222"); - put("type", "List"); - }})); - request.setCombine(map);*/ - MinderReviewFunctionalCasePageRequest request = new MinderReviewFunctionalCasePageRequest(); - request.setProjectId("project-case-minder-test"); - request.setCurrent(1); - request.setPageSize(10); - request.setSort(new HashMap<>() {{ - put("createTime", "desc"); - }}); - request.setReviewId("TEST_MINDER_REVIEW_ID_GYQ"); - request.setViewFlag(true); - request.setViewResult(true); - - MvcResult mvcResultPage = this.requestPostWithOkAndReturn(REViEW_FUNCTIONAL_CASE_LIST_URL, request); - String contentAsString = mvcResultPage.getResponse().getContentAsString(StandardCharsets.UTF_8); - ResultHolder resultHolder = JSON.parseObject(contentAsString, ResultHolder.class); - FunctionalMinderTreeDTO baseTreeNodes = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), FunctionalMinderTreeDTO.class); - Assertions.assertNotNull(baseTreeNodes); - //String jsonString = JSON.toJSONString(baseTreeNodes); - //System.out.println(jsonString); - request.setReviewId("TEST_MINDER_REVIEW_ID_GYQ2"); - mvcResultPage = this.requestPostWithOkAndReturn(REViEW_FUNCTIONAL_CASE_LIST_URL, request); - contentAsString = mvcResultPage.getResponse().getContentAsString(StandardCharsets.UTF_8); - resultHolder = JSON.parseObject(contentAsString, ResultHolder.class); - baseTreeNodes = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), FunctionalMinderTreeDTO.class); - Assertions.assertNotNull(baseTreeNodes); - //jsonString = JSON.toJSONString(baseTreeNodes); - //System.out.println(jsonString); - } } diff --git a/backend/services/case-management/src/test/resources/dml/init_file_minder_test.sql b/backend/services/case-management/src/test/resources/dml/init_file_minder_test.sql index c7ea4c79f4..be96706f99 100644 --- a/backend/services/case-management/src/test/resources/dml/init_file_minder_test.sql +++ b/backend/services/case-management/src/test/resources/dml/init_file_minder_test.sql @@ -11,12 +11,12 @@ VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_1', 1, 'TEST_MINDER_MODULE_ID_GYQ', 'pro INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_1', NULL, NULL, NULL, NULL, NULL); -INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_2', NULL, NULL, NULL, NULL, NULL); +INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_2', 0x504B03041400080808002B826D58000000000000000000000000030000007A69708BAE56CA2BCD55B232D0514A492D4E56B2527A366DC3D3DDBB9E4F59F1645FB7B1A1311AF7E9A495682826CF100A62F262F29E4DD909444A3A4A45A9C5A5392584CD5BDFF67C412384CCCD05998030CF10661CD4D05A1DA8630DE18E353236343246B60DC83532040A2AD5C60200504B0708159DEE336E000000DB000000504B010214001400080808002B826D58159DEE336E000000DB0000000300000000000000000000000000000000007A6970504B05060000000001000100310000009F0000000000, 0x504B03041400080808002B826D58000000000000000000000000030000007A69700300504B0708000000000200000000000000504B010214001400080808002B826D580000000002000000000000000300000000000000000000000000000000007A6970504B0506000000000100010031000000330000000000, 0x504B03041400080808002B826D58000000000000000000000000030000007A69700300504B0708000000000200000000000000504B010214001400080808002B826D580000000002000000000000000300000000000000000000000000000000007A6970504B0506000000000100010031000000330000000000, 0x504B03041400080808002B826D58000000000000000000000000030000007A69700300504B0708000000000200000000000000504B010214001400080808002B826D580000000002000000000000000300000000000000000000000000000000007A6970504B0506000000000100010031000000330000000000, 0x504B03041400080808002B826D58000000000000000000000000030000007A69700300504B0708000000000200000000000000504B010214001400080808002B826D580000000002000000000000000300000000000000000000000000000000007A6970504B0506000000000100010031000000330000000000); INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_3', NULL, NULL, NULL, NULL, NULL); INSERT INTO functional_case_custom_field(case_id, field_id, value) VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_1', 'custom_field_minder_gyq_id_3', 'P0'); - +INSERT INTO functional_case_custom_field(case_id, field_id, value) VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_2', 'custom_field_minder_gyq_id_3', 'P3'); INSERT INTO functional_case_module(id, project_id, name, parent_id, pos, create_time, update_time, create_user, update_user) @@ -29,7 +29,7 @@ VALUES INSERT INTO custom_field (id, name, scene, type, remark, internal, scope_type, create_time, update_time, create_user, scope_id) VALUE - ('custom_field_minder_gyq_id_3', '用例等级', 'FUNCTIONAL', 'SELECT', '', 0, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', '100001'); + ('custom_field_minder_gyq_id_3', 'functional_priority', 'FUNCTIONAL', 'SELECT', '', true, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', '100001'); INSERT INTO case_review(id, num, name, module_id, project_id, status, review_pass_rule, pos, start_time, end_time, case_count, pass_rate, tags, description, create_time, create_user, update_time, update_user)