feat(测试计划): 获取已关联接口用例模块树
This commit is contained in:
parent
44e0fbac10
commit
feb23c0abf
|
@ -6,6 +6,7 @@ import io.metersphere.plan.dto.request.TestPlanApiCaseRequest;
|
||||||
import io.metersphere.plan.dto.response.TestPlanApiCasePageResponse;
|
import io.metersphere.plan.dto.response.TestPlanApiCasePageResponse;
|
||||||
import io.metersphere.plan.service.TestPlanApiCaseService;
|
import io.metersphere.plan.service.TestPlanApiCaseService;
|
||||||
import io.metersphere.sdk.constants.PermissionConstants;
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
|
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||||
import io.metersphere.system.security.CheckOwner;
|
import io.metersphere.system.security.CheckOwner;
|
||||||
import io.metersphere.system.utils.PageUtils;
|
import io.metersphere.system.utils.PageUtils;
|
||||||
import io.metersphere.system.utils.Pager;
|
import io.metersphere.system.utils.Pager;
|
||||||
|
@ -15,10 +16,7 @@ import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
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;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -44,11 +42,20 @@ public class TestPlanApiCaseController {
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/module/count")
|
@PostMapping("/module/count")
|
||||||
@Operation(summary = "测试计划-已关联功能用例模块数量")
|
@Operation(summary = "测试计划-已关联接口用例模块数量")
|
||||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ)
|
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ)
|
||||||
@CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan")
|
@CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan")
|
||||||
public Map<String, Long> moduleCount(@Validated @RequestBody TestPlanApiCaseRequest request) {
|
public Map<String, Long> moduleCount(@Validated @RequestBody TestPlanApiCaseRequest request) {
|
||||||
return testPlanApiCaseService.moduleCount(request);
|
return testPlanApiCaseService.moduleCount(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/tree/{testPlanId}")
|
||||||
|
@Operation(summary = "测试计划-已关联接口用例列表模块树")
|
||||||
|
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ)
|
||||||
|
@CheckOwner(resourceId = "#testPlanId", resourceType = "test_plan")
|
||||||
|
public List<BaseTreeNode> getTree(@PathVariable String testPlanId) {
|
||||||
|
return testPlanApiCaseService.getTree(testPlanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -2,7 +2,9 @@ package io.metersphere.plan.mapper;
|
||||||
|
|
||||||
import io.metersphere.api.dto.definition.ApiDefinitionDTO;
|
import io.metersphere.api.dto.definition.ApiDefinitionDTO;
|
||||||
import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO;
|
import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO;
|
||||||
|
import io.metersphere.functional.dto.ProjectOptionDTO;
|
||||||
import io.metersphere.plan.domain.TestPlanApiCase;
|
import io.metersphere.plan.domain.TestPlanApiCase;
|
||||||
|
import io.metersphere.plan.dto.ApiCaseModuleDTO;
|
||||||
import io.metersphere.plan.dto.ResourceSelectParam;
|
import io.metersphere.plan.dto.ResourceSelectParam;
|
||||||
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
|
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
|
||||||
import io.metersphere.plan.dto.request.TestPlanApiCaseRequest;
|
import io.metersphere.plan.dto.request.TestPlanApiCaseRequest;
|
||||||
|
@ -41,4 +43,8 @@ public interface ExtTestPlanApiCaseMapper {
|
||||||
long caseCount(@Param("request") TestPlanApiCaseRequest request, @Param("deleted") boolean deleted);
|
long caseCount(@Param("request") TestPlanApiCaseRequest request, @Param("deleted") boolean deleted);
|
||||||
|
|
||||||
List<TestPlanApiCase> selectByTestPlanIdAndNotDeleted(String testPlanId);
|
List<TestPlanApiCase> selectByTestPlanIdAndNotDeleted(String testPlanId);
|
||||||
|
|
||||||
|
List<ProjectOptionDTO> selectRootIdByTestPlanId(@Param("testPlanId") String testPlanId);
|
||||||
|
|
||||||
|
List<ApiCaseModuleDTO> selectBaseByProjectIdAndTestPlanId(@Param("testPlanId") String testPlanId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -563,4 +563,25 @@
|
||||||
AND atc.deleted = #{deleted}
|
AND atc.deleted = #{deleted}
|
||||||
<include refid="queryApiCaseWhereCondition"/>
|
<include refid="queryApiCaseWhereCondition"/>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectRootIdByTestPlanId" resultType="io.metersphere.functional.dto.ProjectOptionDTO">
|
||||||
|
SELECT a.module_id as id, atc.project_id as name, p.name as projectName
|
||||||
|
FROM api_test_case atc
|
||||||
|
LEFT JOIN test_plan_api_case tpac ON tpac.api_case_id = atc.id
|
||||||
|
LEFT JOIN project p ON atc.project_id = p.id
|
||||||
|
LEFT JOIN api_definition a on atc.api_definition_id = a.id
|
||||||
|
WHERE tpac.test_plan_id = #{testPlanId}
|
||||||
|
AND atc.deleted = false AND a.module_id = 'root'
|
||||||
|
ORDER BY atc.pos
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectBaseByProjectIdAndTestPlanId" resultType="io.metersphere.plan.dto.ApiCaseModuleDTO">
|
||||||
|
SELECT adm.id, adm.project_id, p.name as projectName
|
||||||
|
FROM api_definition_module adm
|
||||||
|
LEFT JOIN project p ON adm.project_id = p.id
|
||||||
|
WHERE adm.id IN
|
||||||
|
(SELECT ad.module_id FROM api_definition ad LEFT JOIN api_test_case atc on atc.api_definition_id = ad.id LEFT JOIN test_plan_api_case tpac ON tpac.api_case_id = atc.id WHERE tpac.test_plan_id = #{testPlanId} AND atc.deleted = false)
|
||||||
|
ORDER BY pos
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
|
@ -6,8 +6,10 @@ import io.metersphere.api.service.definition.ApiDefinitionModuleService;
|
||||||
import io.metersphere.api.service.definition.ApiDefinitionService;
|
import io.metersphere.api.service.definition.ApiDefinitionService;
|
||||||
import io.metersphere.api.service.definition.ApiTestCaseService;
|
import io.metersphere.api.service.definition.ApiTestCaseService;
|
||||||
import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO;
|
import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO;
|
||||||
|
import io.metersphere.functional.dto.ProjectOptionDTO;
|
||||||
import io.metersphere.plan.domain.TestPlanApiCase;
|
import io.metersphere.plan.domain.TestPlanApiCase;
|
||||||
import io.metersphere.plan.domain.TestPlanApiCaseExample;
|
import io.metersphere.plan.domain.TestPlanApiCaseExample;
|
||||||
|
import io.metersphere.plan.dto.ApiCaseModuleDTO;
|
||||||
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
|
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
|
||||||
import io.metersphere.plan.dto.request.TestPlanApiCaseRequest;
|
import io.metersphere.plan.dto.request.TestPlanApiCaseRequest;
|
||||||
import io.metersphere.plan.dto.request.TestPlanApiRequest;
|
import io.metersphere.plan.dto.request.TestPlanApiRequest;
|
||||||
|
@ -29,6 +31,7 @@ import io.metersphere.system.service.UserLoginService;
|
||||||
import io.metersphere.system.uid.IDGenerator;
|
import io.metersphere.system.uid.IDGenerator;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.collections.MapUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.ibatis.session.ExecutorType;
|
import org.apache.ibatis.session.ExecutorType;
|
||||||
import org.apache.ibatis.session.SqlSession;
|
import org.apache.ibatis.session.SqlSession;
|
||||||
|
@ -269,4 +272,39 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
|
||||||
List<BaseTreeNode> nodeByNodeIds = apiDefinitionModuleService.getNodeByNodeIds(moduleIds);
|
List<BaseTreeNode> nodeByNodeIds = apiDefinitionModuleService.getNodeByNodeIds(moduleIds);
|
||||||
return apiDefinitionModuleService.buildTreeAndCountResource(nodeByNodeIds, moduleCountDTOList, true, Translator.get("functional_case.module.default.name"));
|
return apiDefinitionModuleService.buildTreeAndCountResource(nodeByNodeIds, moduleCountDTOList, true, Translator.get("functional_case.module.default.name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已关联接口用例模块树
|
||||||
|
*
|
||||||
|
* @param testPlanId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<BaseTreeNode> getTree(String testPlanId) {
|
||||||
|
List<BaseTreeNode> returnList = new ArrayList<>();
|
||||||
|
List<ProjectOptionDTO> rootIds = extTestPlanApiCaseMapper.selectRootIdByTestPlanId(testPlanId);
|
||||||
|
Map<String, List<ProjectOptionDTO>> projectRootMap = rootIds.stream().collect(Collectors.groupingBy(ProjectOptionDTO::getName));
|
||||||
|
List<ApiCaseModuleDTO> apiCaseModuleIds = extTestPlanApiCaseMapper.selectBaseByProjectIdAndTestPlanId(testPlanId);
|
||||||
|
Map<String, List<ApiCaseModuleDTO>> 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<String> projectModuleIds = moduleList.stream().map(ApiCaseModuleDTO::getId).toList();
|
||||||
|
List<BaseTreeNode> nodeByNodeIds = apiDefinitionModuleService.getNodeByNodeIds(projectModuleIds);
|
||||||
|
boolean haveVirtualRootNode = CollectionUtils.isEmpty(projectRootMap.get(projectId));
|
||||||
|
List<BaseTreeNode> baseTreeNodes = apiDefinitionModuleService.buildTreeAndCountResource(nodeByNodeIds, !haveVirtualRootNode, Translator.get("functional_case.module.default.name"));
|
||||||
|
for (BaseTreeNode baseTreeNode : baseTreeNodes) {
|
||||||
|
projectNode.addChild(baseTreeNode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return returnList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_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_COUNT = "/test-plan/api/case/module/count";
|
||||||
|
public static final String API_CASE_TREE_MODULE_TREE = "/test-plan/api/case/tree/";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1)
|
@Order(1)
|
||||||
|
@ -58,4 +59,15 @@ public class TestPlanApiCaseControllerTests extends BaseTest {
|
||||||
Assertions.assertNotNull(resultHolder);
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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`)
|
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
|
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_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');
|
('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`)
|
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
|
VALUES
|
||||||
('wxxx_1', 'wxxx_1', 'wxxx_api_case_1', '1', NULL, NULL, 'admin', 1716370415311, 'admin', 2, 'wxxx_1', 1716370415311),
|
('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`)
|
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
|
VALUES
|
||||||
|
@ -43,3 +44,5 @@ VALUES
|
||||||
INSERT INTO `environment`(`id`, `name`, `project_id`, `create_user`, `update_user`, `create_time`, `update_time`, `mock`, `description`, `pos`)
|
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);
|
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');
|
||||||
|
|
Loading…
Reference in New Issue