From feb23c0abf7fbf8ad4085270e956b4cedce5d379 Mon Sep 17 00:00:00 2001 From: WangXu10 Date: Wed, 5 Jun 2024 10:08:23 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92):=20?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=B7=B2=E5=85=B3=E8=81=94=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E7=94=A8=E4=BE=8B=E6=A8=A1=E5=9D=97=E6=A0=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TestPlanApiCaseController.java | 17 ++++++--- .../plan/dto/ApiCaseModuleDTO.java | 15 ++++++++ .../plan/mapper/ExtTestPlanApiCaseMapper.java | 6 +++ .../plan/mapper/ExtTestPlanApiCaseMapper.xml | 21 ++++++++++ .../plan/service/TestPlanApiCaseService.java | 38 +++++++++++++++++++ .../TestPlanApiCaseControllerTests.java | 12 ++++++ .../resources/dml/init_test_plan_api_case.sql | 7 +++- 7 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 backend/services/test-plan/src/main/java/io/metersphere/plan/dto/ApiCaseModuleDTO.java diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java index 1e5b6cd688..5640a34ad6 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java @@ -6,6 +6,7 @@ import io.metersphere.plan.dto.request.TestPlanApiCaseRequest; import io.metersphere.plan.dto.response.TestPlanApiCasePageResponse; import io.metersphere.plan.service.TestPlanApiCaseService; import io.metersphere.sdk.constants.PermissionConstants; +import io.metersphere.system.dto.sdk.BaseTreeNode; import io.metersphere.system.security.CheckOwner; import io.metersphere.system.utils.PageUtils; import io.metersphere.system.utils.Pager; @@ -15,10 +16,7 @@ import jakarta.annotation.Resource; import org.apache.commons.lang3.StringUtils; 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; +import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Map; @@ -44,11 +42,20 @@ public class TestPlanApiCaseController { @PostMapping("/module/count") - @Operation(summary = "测试计划-已关联功能用例模块数量") + @Operation(summary = "测试计划-已关联接口用例模块数量") @RequiresPermissions(PermissionConstants.TEST_PLAN_READ) @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") public Map moduleCount(@Validated @RequestBody TestPlanApiCaseRequest request) { return testPlanApiCaseService.moduleCount(request); } + @GetMapping("/tree/{testPlanId}") + @Operation(summary = "测试计划-已关联接口用例列表模块树") + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ) + @CheckOwner(resourceId = "#testPlanId", resourceType = "test_plan") + public List getTree(@PathVariable String testPlanId) { + return testPlanApiCaseService.getTree(testPlanId); + } + + } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/ApiCaseModuleDTO.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/ApiCaseModuleDTO.java new file mode 100644 index 0000000000..247451c428 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/ApiCaseModuleDTO.java @@ -0,0 +1,15 @@ +package io.metersphere.plan.dto; + +import io.metersphere.api.domain.ApiDefinitionModule; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * @author wx + */ +@Data +public class ApiCaseModuleDTO extends ApiDefinitionModule { + + @Schema(description = "项目名称") + private String projectName; +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.java index bbd999b05e..b1325e33d1 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.java @@ -2,7 +2,9 @@ package io.metersphere.plan.mapper; import io.metersphere.api.dto.definition.ApiDefinitionDTO; import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO; +import io.metersphere.functional.dto.ProjectOptionDTO; import io.metersphere.plan.domain.TestPlanApiCase; +import io.metersphere.plan.dto.ApiCaseModuleDTO; import io.metersphere.plan.dto.ResourceSelectParam; import io.metersphere.plan.dto.TestPlanCaseRunResultCount; import io.metersphere.plan.dto.request.TestPlanApiCaseRequest; @@ -41,4 +43,8 @@ public interface ExtTestPlanApiCaseMapper { long caseCount(@Param("request") TestPlanApiCaseRequest request, @Param("deleted") boolean deleted); List selectByTestPlanIdAndNotDeleted(String testPlanId); + + List selectRootIdByTestPlanId(@Param("testPlanId") String testPlanId); + + List selectBaseByProjectIdAndTestPlanId(@Param("testPlanId") String testPlanId); } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.xml b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.xml index 31eec52844..c6ee435af3 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.xml +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.xml @@ -563,4 +563,25 @@ AND atc.deleted = #{deleted} + + + + + \ No newline at end of file diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java index 5309a73fd6..0b6935a54f 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java @@ -6,8 +6,10 @@ import io.metersphere.api.service.definition.ApiDefinitionModuleService; import io.metersphere.api.service.definition.ApiDefinitionService; import io.metersphere.api.service.definition.ApiTestCaseService; import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO; +import io.metersphere.functional.dto.ProjectOptionDTO; import io.metersphere.plan.domain.TestPlanApiCase; import io.metersphere.plan.domain.TestPlanApiCaseExample; +import io.metersphere.plan.dto.ApiCaseModuleDTO; import io.metersphere.plan.dto.TestPlanCaseRunResultCount; import io.metersphere.plan.dto.request.TestPlanApiCaseRequest; import io.metersphere.plan.dto.request.TestPlanApiRequest; @@ -29,6 +31,7 @@ import io.metersphere.system.service.UserLoginService; import io.metersphere.system.uid.IDGenerator; import jakarta.annotation.Resource; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.SqlSession; @@ -269,4 +272,39 @@ public class TestPlanApiCaseService extends TestPlanResourceService { List nodeByNodeIds = apiDefinitionModuleService.getNodeByNodeIds(moduleIds); return apiDefinitionModuleService.buildTreeAndCountResource(nodeByNodeIds, moduleCountDTOList, true, Translator.get("functional_case.module.default.name")); } + + /** + * 已关联接口用例模块树 + * + * @param testPlanId + * @return + */ + public List getTree(String testPlanId) { + List returnList = new ArrayList<>(); + List rootIds = extTestPlanApiCaseMapper.selectRootIdByTestPlanId(testPlanId); + Map> projectRootMap = rootIds.stream().collect(Collectors.groupingBy(ProjectOptionDTO::getName)); + List apiCaseModuleIds = extTestPlanApiCaseMapper.selectBaseByProjectIdAndTestPlanId(testPlanId); + Map> projectModuleMap = apiCaseModuleIds.stream().collect(Collectors.groupingBy(ApiCaseModuleDTO::getProjectId)); + if (MapUtils.isEmpty(projectModuleMap)) { + projectRootMap.forEach((projectId, projectOptionDTOList) -> { + BaseTreeNode projectNode = new BaseTreeNode(projectId, projectOptionDTOList.get(0).getProjectName(), Project.class.getName()); + returnList.add(projectNode); + BaseTreeNode defaultNode = apiDefinitionModuleService.getDefaultModule(Translator.get("functional_case.module.default.name")); + projectNode.addChild(defaultNode); + }); + return returnList; + } + projectModuleMap.forEach((projectId, moduleList) -> { + BaseTreeNode projectNode = new BaseTreeNode(projectId, moduleList.get(0).getProjectName(), Project.class.getName()); + returnList.add(projectNode); + List projectModuleIds = moduleList.stream().map(ApiCaseModuleDTO::getId).toList(); + List nodeByNodeIds = apiDefinitionModuleService.getNodeByNodeIds(projectModuleIds); + boolean haveVirtualRootNode = CollectionUtils.isEmpty(projectRootMap.get(projectId)); + List baseTreeNodes = apiDefinitionModuleService.buildTreeAndCountResource(nodeByNodeIds, !haveVirtualRootNode, Translator.get("functional_case.module.default.name")); + for (BaseTreeNode baseTreeNode : baseTreeNodes) { + projectNode.addChild(baseTreeNode); + } + }); + return returnList; + } } diff --git a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiCaseControllerTests.java b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiCaseControllerTests.java index f9cfd7be50..e528e36bcb 100644 --- a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiCaseControllerTests.java +++ b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiCaseControllerTests.java @@ -21,6 +21,7 @@ public class TestPlanApiCaseControllerTests extends BaseTest { public static final String API_CASE_PAGE = "/test-plan/api/case/page"; public static final String API_CASE_TREE_COUNT = "/test-plan/api/case/module/count"; + public static final String API_CASE_TREE_MODULE_TREE = "/test-plan/api/case/tree/"; @Test @Order(1) @@ -58,4 +59,15 @@ public class TestPlanApiCaseControllerTests extends BaseTest { Assertions.assertNotNull(resultHolder); } + @Test + @Order(3) + public void testApiCaseModuleTree() throws Exception { + MvcResult mvcResult = this.requestGetWithOkAndReturn(API_CASE_TREE_MODULE_TREE + "wxxx_1"); + String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); + ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class); + Assertions.assertNotNull(resultHolder); + + this.requestGetWithOkAndReturn(API_CASE_TREE_MODULE_TREE + "wxxx_2"); + } + } diff --git a/backend/services/test-plan/src/test/resources/dml/init_test_plan_api_case.sql b/backend/services/test-plan/src/test/resources/dml/init_test_plan_api_case.sql index e9388fb69f..503dd549eb 100644 --- a/backend/services/test-plan/src/test/resources/dml/init_test_plan_api_case.sql +++ b/backend/services/test-plan/src/test/resources/dml/init_test_plan_api_case.sql @@ -13,7 +13,7 @@ VALUES INSERT INTO `api_definition`(`id`, `name`, `protocol`, `method`, `path`, `status`, `num`, `tags`, `pos`, `project_id`, `module_id`, `latest`, `version_id`, `ref_id`, `description`, `create_time`, `create_user`, `update_time`, `update_user`, `delete_user`, `delete_time`, `deleted`) VALUES ('wxxx_api_1', '2222', 'HTTP', 'GET', '/111', 'DEPRECATED', 100003, '[]', 192, 'wxx_1234', 'root', b'1', '100844458962059498', '1086025445195776', '', 1716370415311, 'admin', 1716455838628, 'admin', NULL, NULL, b'0'), - ('wxxx_api_2', '3333', 'HTTP', 'GET', '/111', 'DEPRECATED', 100003, '[]', 192, 'wxx_1234', 'root', b'1', '100844458962059498', '1086025445195776', '', 1716370415311, 'admin', 1716455838628, 'admin', NULL, NULL, b'0'), + ('wxxx_api_2', '3333', 'HTTP', 'GET', '/111', 'DEPRECATED', 100003, '[]', 192, 'wxx_1234', '123', b'1', '100844458962059498', '1086025445195776', '', 1716370415311, 'admin', 1716455838628, 'admin', NULL, NULL, b'0'), ('wxxx_api_3', '4444', 'HTTP', 'GET', '/111', 'DEPRECATED', 100003, '[]', 192, 'wxx_1234', 'root', b'1', '100844458962059498', '1086025445195776', '', 1716370415311, 'admin', 1716455838628, 'admin', NULL, NULL, b'0'); @@ -31,7 +31,8 @@ VALUES INSERT INTO `test_plan_api_case`(`id`, `test_plan_id`, `api_case_id`, `environment_id`, `last_exec_result`, `last_exec_report_id`, `execute_user`, `create_time`, `create_user`, `pos`, `test_plan_collection_id`, `last_exec_time`) VALUES ('wxxx_1', 'wxxx_1', 'wxxx_api_case_1', '1', NULL, NULL, 'admin', 1716370415311, 'admin', 2, 'wxxx_1', 1716370415311), - ('wxxx_2', 'wxxx_1', 'wxxx_api_case_2', '1', NULL, NULL, 'admin', 1716370415311, 'admin', 2, 'wxxx_2', 1716370415311); + ('wxxx_2', 'wxxx_1', 'wxxx_api_case_2', '1', NULL, NULL, 'admin', 1716370415311, 'admin', 2, 'wxxx_2', 1716370415311), + ('wxxx_3', 'wxxx_2', 'wxxx_api_case_3', '1', NULL, NULL, 'admin', 1716370415311, 'admin', 2, 'wxxx_2', 1716370415311); INSERT INTO `test_plan_collection`(`id`, `test_plan_id`, `test_collection_type_id`, `name`, `execute_method`, `grouped`, `environment_id`, `pos`, `create_user`, `create_time`) VALUES @@ -43,3 +44,5 @@ VALUES INSERT INTO `environment`(`id`, `name`, `project_id`, `create_user`, `update_user`, `create_time`, `update_time`, `mock`, `description`, `pos`) VALUES ('123', 'Mock环境', 'wxx_1234', 'admin', 'admin', 1716175907000, 1716175907000, b'1', NULL, 64); +INSERT INTO `api_definition_module`(`id`, `name`, `parent_id`, `project_id`, `pos`, `create_time`, `update_time`, `update_user`, `create_user`) +VALUES ('123', 'Halo', 'NONE', 'wxx_1234', 384, 1716280762025, 1716280762025, '805048669970432', '805048669970432');