From 8b5bdefe4fb3fbd445b906c90394f7a876eb3585 Mon Sep 17 00:00:00 2001 From: guoyuqi Date: Fri, 19 Jan 2024 18:23:32 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=8A=9F=E8=83=BD=E7=94=A8=E4=BE=8B):=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=8E=B7=E5=8F=96=E8=84=91=E5=9B=BE=E7=94=A8?= =?UTF-8?q?=E4=BE=8B=E7=9A=84=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sdk/util/FilterChainUtils.java | 6 + .../FunctionalCaseMinderController.java | 37 ++++ .../functional/dto/FunctionalCaseStepDTO.java | 13 ++ .../dto/FunctionalMinderTreeDTO.java | 19 ++ .../dto/FunctionalMinderTreeNodeDTO.java | 28 +++ .../mapper/ExtFunctionalCaseMapper.xml | 1 + .../service/FunctionalCaseMinderService.java | 208 ++++++++++++++++++ .../service/FunctionalCaseModuleService.java | 5 +- .../FunctionalCaseMinderControllerTest.java | 116 ++++++++++ .../resources/dml/init_file_minder_test.sql | 37 ++++ 10 files changed, 468 insertions(+), 2 deletions(-) create mode 100644 backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalCaseMinderController.java create mode 100644 backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseStepDTO.java create mode 100644 backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalMinderTreeDTO.java create mode 100644 backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalMinderTreeNodeDTO.java create mode 100644 backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseMinderService.java create mode 100644 backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseMinderControllerTest.java create mode 100644 backend/services/case-management/src/test/resources/dml/init_file_minder_test.sql diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/FilterChainUtils.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/FilterChainUtils.java index ca102ff387..daadb7a2a9 100644 --- a/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/FilterChainUtils.java +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/FilterChainUtils.java @@ -27,7 +27,13 @@ public class FilterChainUtils { filterChainDefinitionMap.put("/authsource/list/allenable", "anon"); filterChainDefinitionMap.put("/sso/callback/**", "anon"); filterChainDefinitionMap.put("/license/validate", "anon"); + //功能用例副文本访问 + filterChainDefinitionMap.put("/attachment/download/file/**", "anon"); + //用例评审副文本访问 + filterChainDefinitionMap.put("/review/functional/case/download/file/**", "anon"); + filterChainDefinitionMap.put("/system/version/current", "anon"); + //用户通过邮箱邀请自行注册的接口 filterChainDefinitionMap.put("/system/user/register-by-invite", "anon"); 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 new file mode 100644 index 0000000000..b5d36d38ee --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalCaseMinderController.java @@ -0,0 +1,37 @@ +package io.metersphere.functional.controller; + +import io.metersphere.functional.dto.FunctionalMinderTreeDTO; +import io.metersphere.functional.request.FunctionalCasePageRequest; +import io.metersphere.functional.service.FunctionalCaseMinderService; +import io.metersphere.sdk.constants.PermissionConstants; +import io.metersphere.system.security.CheckOwner; +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.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author guoyuqi + */ +@Tag(name = "用例管理-功能用例-脑图") +@RestController +@RequestMapping("/functional/mind/case") +public class FunctionalCaseMinderController { + + @Resource + private FunctionalCaseMinderService functionalCaseMinderService; + + @PostMapping("/list") + @Operation(summary = "用例管理-功能用例-脑图用例列表查询") + @RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_MINDER) + @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") + public FunctionalMinderTreeDTO getFunctionalCaseMinderTree(@Validated @RequestBody FunctionalCasePageRequest request) { + return functionalCaseMinderService.getFunctionalCasePage(request, false); + } + +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseStepDTO.java b/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseStepDTO.java new file mode 100644 index 0000000000..ad6eef386f --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseStepDTO.java @@ -0,0 +1,13 @@ +package io.metersphere.functional.dto; + +import lombok.Data; + +@Data +public class FunctionalCaseStepDTO { + + private Integer num; + + private String desc; + + private String result; +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalMinderTreeDTO.java b/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalMinderTreeDTO.java new file mode 100644 index 0000000000..155ad7d6f8 --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalMinderTreeDTO.java @@ -0,0 +1,19 @@ +package io.metersphere.functional.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Data +@NoArgsConstructor +public class FunctionalMinderTreeDTO { + + @Schema(description = "节点data数据") + private FunctionalMinderTreeNodeDTO data; + + @Schema(description = "节点children数据") + private List children = new ArrayList<>(); +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalMinderTreeNodeDTO.java b/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalMinderTreeNodeDTO.java new file mode 100644 index 0000000000..6a9f4423a5 --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalMinderTreeNodeDTO.java @@ -0,0 +1,28 @@ +package io.metersphere.functional.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +public class FunctionalMinderTreeNodeDTO { + + @Schema(description = "节点ID") + private String id; + + @Schema(description = "节点名称") + private String text; + + @Schema(description = "用例等级") + private String priority; + + @Schema(description = "节点标签") + private List resource; + + @Schema(description = "节点标签") + private String expandState = "expand"; + +} 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 bc349969b2..0d4820cb4d 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 @@ -105,6 +105,7 @@ NAME, module_id, version_id, + case_edit_type, create_user, create_time, update_user, 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 new file mode 100644 index 0000000000..cf1012658e --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseMinderService.java @@ -0,0 +1,208 @@ +package io.metersphere.functional.service; + +import io.metersphere.functional.domain.FunctionalCase; +import io.metersphere.functional.domain.FunctionalCaseBlob; +import io.metersphere.functional.domain.FunctionalCaseBlobExample; +import io.metersphere.functional.dto.*; +import io.metersphere.functional.mapper.FunctionalCaseBlobMapper; +import io.metersphere.functional.request.FunctionalCasePageRequest; +import io.metersphere.sdk.constants.ModuleConstants; +import io.metersphere.sdk.util.JSON; +import io.metersphere.sdk.util.Translator; +import io.metersphere.system.dto.sdk.BaseTreeNode; +import jakarta.annotation.Resource; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +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; + +/** + * 功能用例脑图 + * + * @date : 2023-5-17 + */ +@Service +@Transactional(rollbackFor = Exception.class) +public class FunctionalCaseMinderService { + + @Resource + private FunctionalCaseService functionalCaseService; + + @Resource + private FunctionalCaseModuleService functionalCaseModuleService; + @Resource + private FunctionalCaseBlobMapper functionalCaseBlobMapper; + + + public FunctionalMinderTreeDTO getFunctionalCasePage(FunctionalCasePageRequest request, boolean deleted) { + //根据查询条件查询出所有符合的功能用例 + List functionalCasePage = functionalCaseService.getFunctionalCasePage(request, deleted); + List caseIds = functionalCasePage.stream().map(FunctionalCase::getId).distinct().toList(); + FunctionalCaseBlobExample functionalCaseBlobExample = new FunctionalCaseBlobExample(); + functionalCaseBlobExample.createCriteria().andIdIn(caseIds); + List functionalCaseBlobs = functionalCaseBlobMapper.selectByExampleWithBLOBs(functionalCaseBlobExample); + Map blobMap = functionalCaseBlobs.stream().collect(Collectors.toMap(FunctionalCaseBlob::getId, t -> t)); + //根据功能用例的模块ID,查出每个模块id父级直到根节点 + List moduleIds = functionalCasePage.stream().map(FunctionalCase::getModuleId).distinct().toList(); + Map> moduleCaseMap = functionalCasePage.stream().collect(Collectors.groupingBy(FunctionalCasePageDTO::getModuleId)); + List nodeByNodeIds = functionalCaseModuleService.getNodeByNodeIds(moduleIds); + //根据模块节点构造模块树 + List baseTreeNodes = functionalCaseModuleService.buildTreeAndCountResource(nodeByNodeIds, true, Translator.get("default.module")); + //判断虚拟节点有无数据 + if (moduleCaseMap.get(ModuleConstants.DEFAULT_NODE_ID) == null && CollectionUtils.isEmpty(baseTreeNodes.get(0).getChildren())) { + baseTreeNodes.remove(0); + } + //构建返回数据,主层级应与模块树层级相同 + List functionalMinderTreeNodeDTOs = new ArrayList<>(); + buildCaseTree(baseTreeNodes, moduleCaseMap, functionalMinderTreeNodeDTOs, blobMap); + FunctionalMinderTreeDTO root = new FunctionalMinderTreeDTO(); + FunctionalMinderTreeNodeDTO rootData = new FunctionalMinderTreeNodeDTO(); + rootData.setResource(List.of("模块")); + rootData.setText("全部用例"); + root.setChildren(functionalMinderTreeNodeDTOs); + root.setData(rootData); + return root; + } + + private static void buildCaseTree(List baseTreeNodes, Map> moduleCaseMap, List functionalMinderTreeNodeDTOs, Map blobMap) { + baseTreeNodes.forEach(t -> { + //构建根节点 + FunctionalMinderTreeDTO functionalMinderTreeDTO = new FunctionalMinderTreeDTO(); + FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTO = new FunctionalMinderTreeNodeDTO(); + functionalMinderTreeNodeDTO.setId(t.getId()); + functionalMinderTreeNodeDTO.setText(t.getName()); + functionalMinderTreeNodeDTO.setResource(List.of("模块")); + functionalMinderTreeDTO.setData(functionalMinderTreeNodeDTO); + + List children = new ArrayList<>(); + //如果当前节点有用例,则用例是他的子节点 + buildCaseChild(moduleCaseMap, blobMap, t, children); + //查询当前节点下的子模块节点 + buildModuleChild(moduleCaseMap, blobMap, t, children); + functionalMinderTreeDTO.setChildren(children); + functionalMinderTreeNodeDTOs.add(functionalMinderTreeDTO); + }); + } + + private static void buildCaseChild(Map> moduleCaseMap, Map blobMap, 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("用例")); + //将用例的blob记为Case的children + List functionalMinderTreeNodeChildChild = new ArrayList<>(); + FunctionalCaseBlob functionalCaseBlob = blobMap.get(functionalCasePageDTO.getId()); + if (functionalCaseBlob != null) { + if (functionalCaseBlob.getPrerequisite() != null) { + FunctionalMinderTreeDTO functionalMinderTreeDTOPre = new FunctionalMinderTreeDTO(); + //前置条件 + FunctionalMinderTreeNodeDTO functionalMinderTreeNodeChildPre = new FunctionalMinderTreeNodeDTO(); + String prerequisite = new String(functionalCaseBlob.getPrerequisite(), StandardCharsets.UTF_8); + functionalMinderTreeNodeChildPre.setText(prerequisite); + functionalMinderTreeNodeChildPre.setResource(List.of("前置条件")); + functionalMinderTreeDTOPre.setData(functionalMinderTreeNodeChildPre); + functionalMinderTreeNodeChildChild.add(functionalMinderTreeDTOPre); + } + + //步骤描述 + if (StringUtils.equalsIgnoreCase(functionalCasePageDTO.getCaseEditType(),"TEXT") ) { + if (functionalCaseBlob.getTextDescription()!=null) { + //1.文本描述(一个) + FunctionalMinderTreeDTO functionalMinderTreeDTOText = new FunctionalMinderTreeDTO(); + FunctionalMinderTreeNodeDTO functionalMinderTreeNodeChildText= new FunctionalMinderTreeNodeDTO(); + String textDescription = new String(functionalCaseBlob.getTextDescription(), StandardCharsets.UTF_8); + functionalMinderTreeNodeChildText.setText(textDescription); + functionalMinderTreeNodeChildText.setResource(List.of("步骤描述")); + functionalMinderTreeDTOText.setData(functionalMinderTreeNodeChildText); + ListfunctionalMinderTreeNodeChildTextChildren = new ArrayList<>(); + FunctionalMinderTreeDTO functionalMinderTreeNodeChildTextChild = new FunctionalMinderTreeDTO(); + FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTOChildTextChild= new FunctionalMinderTreeNodeDTO(); + String expectedResult = new String(functionalCaseBlob.getExpectedResult(), StandardCharsets.UTF_8); + functionalMinderTreeNodeDTOChildTextChild.setText(expectedResult); + functionalMinderTreeNodeDTOChildTextChild.setResource(List.of("预期结果")); + functionalMinderTreeNodeChildTextChild.setData(functionalMinderTreeNodeDTOChildTextChild); + functionalMinderTreeNodeChildTextChildren.add(functionalMinderTreeNodeChildTextChild); + functionalMinderTreeDTOText.setChildren(functionalMinderTreeNodeChildTextChildren); + } + }else { + if (functionalCaseBlob.getSteps() != null) { + //2.步骤描述(多个) + String steps = new String(functionalCaseBlob.getSteps(), StandardCharsets.UTF_8); + List functionalCaseStepDTOS = JSON.parseArray(steps, FunctionalCaseStepDTO.class); + for (FunctionalCaseStepDTO functionalCaseStepDTO : functionalCaseStepDTOS) { + FunctionalMinderTreeDTO functionalMinderTreeDTOText = new FunctionalMinderTreeDTO(); + FunctionalMinderTreeNodeDTO functionalMinderTreeNodeChildStep = new FunctionalMinderTreeNodeDTO(); + functionalMinderTreeNodeChildStep.setText(functionalCaseStepDTO.getDesc()); + functionalMinderTreeNodeChildStep.setResource(List.of("步骤描述")); + + ListfunctionalMinderTreeNodeChildTextChildren = new ArrayList<>(); + FunctionalMinderTreeDTO functionalMinderTreeNodeChildTextChild = new FunctionalMinderTreeDTO(); + FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTOChildTextChild= new FunctionalMinderTreeNodeDTO(); + functionalMinderTreeNodeDTOChildTextChild.setText(functionalCaseStepDTO.getResult()); + functionalMinderTreeNodeDTOChildTextChild.setResource(List.of("预期结果")); + functionalMinderTreeNodeChildTextChild.setData(functionalMinderTreeNodeDTOChildTextChild); + functionalMinderTreeNodeChildTextChildren.add(functionalMinderTreeNodeChildTextChild); + + functionalMinderTreeDTOText.setData(functionalMinderTreeNodeChildStep); + functionalMinderTreeDTOText.setChildren(functionalMinderTreeNodeChildTextChildren); + functionalMinderTreeNodeChildChild.add(functionalMinderTreeDTOText); + } + } + } + + //备注 + if (functionalCaseBlob.getDescription() != null) { + FunctionalMinderTreeDTO functionalMinderTreeDTORemark = new FunctionalMinderTreeDTO(); + FunctionalMinderTreeNodeDTO functionalMinderTreeNodeChildRemark = new FunctionalMinderTreeNodeDTO(); + String description = new String(functionalCaseBlob.getDescription(), StandardCharsets.UTF_8); + functionalMinderTreeNodeChildRemark.setText(description); + functionalMinderTreeNodeChildRemark.setResource(List.of("备注")); + functionalMinderTreeDTORemark.setData(functionalMinderTreeNodeChildRemark); + functionalMinderTreeNodeChildChild.add(functionalMinderTreeDTORemark); + } + } + functionalMinderTreeChild.setData(functionalMinderTreeNodeChild); + functionalMinderTreeChild.setChildren(functionalMinderTreeNodeChildChild); + children.add(functionalMinderTreeChild); + }); + } + } + + private static void buildModuleChild(Map> moduleCaseMap, Map blobMap, BaseTreeNode t, List children) { + if (CollectionUtils.isNotEmpty(t.getChildren())) { + t.getChildren().forEach(child->{ + FunctionalMinderTreeDTO functionalMinderTreeDTOChild = new FunctionalMinderTreeDTO(); + FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTOChild = new FunctionalMinderTreeNodeDTO(); + functionalMinderTreeNodeDTOChild.setId(child.getId()); + functionalMinderTreeNodeDTOChild.setText(child.getName()); + functionalMinderTreeNodeDTOChild.setResource(List.of("模块")); + functionalMinderTreeDTOChild.setData(functionalMinderTreeNodeDTOChild); + + List childChildren = new ArrayList<>(); + buildCaseChild(moduleCaseMap, blobMap, child, childChildren); + functionalMinderTreeDTOChild.setChildren(childChildren); + children.add(functionalMinderTreeDTOChild); + buildModuleChild(moduleCaseMap, blobMap, child, childChildren); + }); + } + + } + +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseModuleService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseModuleService.java index 015e2e587c..ac4d96e6d2 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseModuleService.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseModuleService.java @@ -275,9 +275,10 @@ public class FunctionalCaseModuleService extends ModuleTreeService { while (CollectionUtils.isNotEmpty(finalModuleIds)) { List modules = extFunctionalCaseModuleMapper.selectBaseByIds(finalModuleIds); totalList.addAll(modules); - List parentModuleIds = modules.stream().map(BaseTreeNode::getParentId).filter(parentId -> !StringUtils.equalsIgnoreCase(parentId,ModuleConstants.ROOT_NODE_PARENT_ID)).toList(); + List finalModuleIdList = finalModuleIds; + List parentModuleIds = modules.stream().map(BaseTreeNode::getParentId).filter(parentId -> !StringUtils.equalsIgnoreCase(parentId,ModuleConstants.ROOT_NODE_PARENT_ID) && !finalModuleIdList.contains(parentId)).toList(); finalModuleIds.clear(); - finalModuleIds = parentModuleIds; + finalModuleIds = new ArrayList<>(parentModuleIds); } return totalList.stream().distinct().toList(); } 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 new file mode 100644 index 0000000000..27f3cb5248 --- /dev/null +++ b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseMinderControllerTest.java @@ -0,0 +1,116 @@ +package io.metersphere.functional.controller; + +import io.metersphere.functional.domain.FunctionalCaseBlob; +import io.metersphere.functional.dto.FunctionalCaseStepDTO; +import io.metersphere.functional.dto.FunctionalMinderTreeDTO; +import io.metersphere.functional.mapper.FunctionalCaseBlobMapper; +import io.metersphere.functional.request.FunctionalCasePageRequest; +import io.metersphere.sdk.util.JSON; +import io.metersphere.system.base.BaseTest; +import io.metersphere.system.controller.handler.ResultHolder; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.*; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.jdbc.SqlConfig; +import org.springframework.test.web.servlet.MvcResult; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +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"; + + @Resource + private FunctionalCaseBlobMapper functionalCaseBlobMapper; + + @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 { + Listblobs = new ArrayList<>(); + FunctionalCaseBlob blob = new FunctionalCaseBlob(); + blob.setId("TEST_FUNCTIONAL_MINDER_CASE_ID_4"); + List stepDTOList = new ArrayList<>(); + FunctionalCaseStepDTO functionalCaseStepDTO = new FunctionalCaseStepDTO(); + functionalCaseStepDTO.setNum(1); + functionalCaseStepDTO.setDesc("用例4的步骤描述"); + functionalCaseStepDTO.setResult("用例4的步骤预期"); + stepDTOList.add(functionalCaseStepDTO); + FunctionalCaseStepDTO functionalCaseStepDTOTwo = new FunctionalCaseStepDTO(); + functionalCaseStepDTOTwo.setNum(2); + functionalCaseStepDTOTwo.setDesc("用例4的步骤描述2"); + functionalCaseStepDTOTwo.setResult("用例4的步骤预期1"); + stepDTOList.add(functionalCaseStepDTOTwo); + blob.setSteps(JSON.toJSONString(stepDTOList).getBytes(StandardCharsets.UTF_8)); + String prerequisite = "用例4的前置"; + blob.setPrerequisite(prerequisite.getBytes(StandardCharsets.UTF_8)); + String description = "用例4的备注"; + blob.setDescription(description.getBytes(StandardCharsets.UTF_8)); + blobs.add(blob); + FunctionalCaseBlob blob5 = new FunctionalCaseBlob(); + blob5.setId("TEST_FUNCTIONAL_MINDER_CASE_ID_5"); + List stepDTOList5 = new ArrayList<>(); + FunctionalCaseStepDTO functionalCaseStepDTO5 = new FunctionalCaseStepDTO(); + functionalCaseStepDTO5.setNum(1); + functionalCaseStepDTO5.setDesc("用例5的步骤描述"); + functionalCaseStepDTO5.setResult("用例5的步骤预期"); + stepDTOList5.add(functionalCaseStepDTO5); + FunctionalCaseStepDTO functionalCaseStepDTOTwo5= new FunctionalCaseStepDTO(); + functionalCaseStepDTOTwo5.setNum(2); + functionalCaseStepDTOTwo5.setDesc("用例5的步骤描述2"); + functionalCaseStepDTOTwo5.setResult("用例5的步骤预期1"); + stepDTOList5.add(functionalCaseStepDTOTwo5); + blob5.setSteps(JSON.toJSONString(stepDTOList5).getBytes(StandardCharsets.UTF_8)); + String prerequisite5 = "用例5的前置"; + blob5.setPrerequisite(prerequisite5.getBytes(StandardCharsets.UTF_8)); + String description5 = "用例5的备注"; + blob5.setDescription(description5.getBytes(StandardCharsets.UTF_8)); + blobs.add(blob5); + FunctionalCaseBlob blob6 = new FunctionalCaseBlob(); + blob6.setId("TEST_FUNCTIONAL_MINDER_CASE_ID_6"); + String textDescription = "用例6的步骤描述"; + blob6.setTextDescription(textDescription.getBytes(StandardCharsets.UTF_8)); + String expectedResult = "用例6的步骤预期"; + blob6.setExpectedResult(expectedResult.getBytes(StandardCharsets.UTF_8)); + String prerequisite6 = "用例6的前置"; + blob6.setPrerequisite(prerequisite6.getBytes(StandardCharsets.UTF_8)); + String description6 = "用例6的备注"; + blob6.setDescription(description6.getBytes(StandardCharsets.UTF_8)); + blobs.add(blob6); + functionalCaseBlobMapper.batchInsert(blobs); + + FunctionalCasePageRequest request = new FunctionalCasePageRequest(); + request.setProjectId("project-case-minder-test"); + request.setCurrent(1); + request.setPageSize(10); + request.setSort(new HashMap<>() {{ + put("createTime", "desc"); + }}); + /*//自定义字段 测试 + 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);*/ + 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); + Assertions.assertNotNull(baseTreeNodes); + String 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 new file mode 100644 index 0000000000..30543b0827 --- /dev/null +++ b/backend/services/case-management/src/test/resources/dml/init_file_minder_test.sql @@ -0,0 +1,37 @@ +INSERT INTO project (id, num, organization_id, name, description, create_user, update_user, create_time, update_time) VALUES + ('project-case-minder-test', null, '100001', '用例脑图项目', '系统默认创建的项目', 'admin', 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000); + +INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time) +VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_1', 1, 'TEST_MINDER_MODULE_ID_GYQ', 'project-case-minder-test', '100001', '测试', 'UN_REVIEWED', NULL, 'STEP', 0, 'v1.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_1', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), + ('TEST_FUNCTIONAL_MINDER_CASE_ID_2', 2, 'TEST_MINDER_MODULE_ID_GYQ', 'project-case-minder-test', '100001', '测试多版本', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 5000, 'v1.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_2', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), + ('TEST_FUNCTIONAL_MINDER_CASE_ID_3', 3, 'TEST_MINDER_MODULE_ID_GYQ2', 'project-case-minder-test', '100001', 'copy_测试多版本', 'UN_REVIEWED', NULL, 'STEP', 25000, 'v3.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_3', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), + ('TEST_FUNCTIONAL_MINDER_CASE_ID_4', 4, 'TEST_MINDER_MODULE_ID_GYQ3', 'project-case-minder-test', '100001', 'copy_测试多版本', 'UN_REVIEWED', NULL, 'STEP', 40000, 'v3.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_4', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), + ('TEST_FUNCTIONAL_MINDER_CASE_ID_5', 5, 'TEST_MINDER_MODULE_ID_GYQ4', 'project-case-minder-test', '100001', 'copy_测试多版本', 'UN_REVIEWED', NULL, 'STEP', 45000, 'v3.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_5', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), + ('TEST_FUNCTIONAL_MINDER_CASE_ID_6', 6, 'TEST_MINDER_MODULE_ID_GYQ5', 'project-case-minder-test', '100001', 'copy_测试多版本', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_6', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL); + + +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_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_module(id, project_id, name, parent_id, pos, create_time, update_time, create_user, update_user) +VALUES + ('TEST_MINDER_MODULE_ID_GYQ', 'project-case-minder-test', '测试所属模块', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin'), + ('TEST_MINDER_MODULE_ID_GYQ2', 'project-case-minder-test', '测试所属模块2', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin'), + ('TEST_MINDER_MODULE_ID_GYQ3', 'project-case-minder-test', '测试所属模块3', 'TEST_MINDER_MODULE_ID_GYQ2', 0, 1669174143999, 1669174143999, 'admin', 'admin'), + ('TEST_MINDER_MODULE_ID_GYQ4', 'project-case-minder-test', '测试所属模块4', 'TEST_MINDER_MODULE_ID_GYQ3', 0, 1669174143999, 1669174143999, 'admin', 'admin'), + ('TEST_MINDER_MODULE_ID_GYQ5', 'project-case-minder-test', '测试所属模块5', 'TEST_MINDER_MODULE_ID_GYQ4', 0, 1669174143999, 1669174143999, 'admin', 'admin'); + + +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_priority', 'FUNCTIONAL', 'SELECT', '', 0, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', '100001'); + + + + +