diff --git a/backend/framework/sdk/src/main/resources/i18n/case_en_US.properties b/backend/framework/sdk/src/main/resources/i18n/case_en_US.properties index 75d6184b91..72226a18ca 100644 --- a/backend/framework/sdk/src/main/resources/i18n/case_en_US.properties +++ b/backend/framework/sdk/src/main/resources/i18n/case_en_US.properties @@ -165,3 +165,4 @@ case_review.not.exist=Case review does not exist case_review_content.not.exist = Review comments cannot be empty case_review_history.system=System trigger case_review.viewFlag.not_blank=View flag cannot be empty +functional_case_relationship_edge.type.not_blank=Relationship type cannot be empty \ No newline at end of file diff --git a/backend/framework/sdk/src/main/resources/i18n/case_zh_CN.properties b/backend/framework/sdk/src/main/resources/i18n/case_zh_CN.properties index 5d8027f8a1..ceb663a71c 100644 --- a/backend/framework/sdk/src/main/resources/i18n/case_zh_CN.properties +++ b/backend/framework/sdk/src/main/resources/i18n/case_zh_CN.properties @@ -164,3 +164,4 @@ case_review.not.exist=用例评审不存在 case_review_content.not.exist = 评审意见不能为空 case_review_history.system=系统触发 case_review.viewFlag.not_blank=查看标识不能为空 +functional_case_relationship_edge.type.not_blank=类型不能为空 diff --git a/backend/framework/sdk/src/main/resources/i18n/case_zh_TW.properties b/backend/framework/sdk/src/main/resources/i18n/case_zh_TW.properties index ef28a1ea4a..ba6aa5f090 100644 --- a/backend/framework/sdk/src/main/resources/i18n/case_zh_TW.properties +++ b/backend/framework/sdk/src/main/resources/i18n/case_zh_TW.properties @@ -165,3 +165,4 @@ case_review.not.exist=用例評審不存在 case_review_content.not.exist = 評審意見不能為空 case_review_history.system=系統觸發 case_review.viewFlag.not_blank=查看標誌不能為空 +functional_case_relationship_edge.type.not_blank=類型不能為空 \ No newline at end of file diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalCaseRelationshipController.java b/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalCaseRelationshipController.java new file mode 100644 index 0000000000..3bb3f048c2 --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalCaseRelationshipController.java @@ -0,0 +1,53 @@ +package io.metersphere.functional.controller; + +import com.alibaba.excel.util.StringUtils; +import com.github.pagehelper.Page; +import com.github.pagehelper.PageHelper; +import io.metersphere.functional.dto.FunctionalCasePageDTO; +import io.metersphere.functional.request.RelationshipPageRequest; +import io.metersphere.functional.service.FunctionalCaseRelationshipEdgeService; +import io.metersphere.functional.service.FunctionalCaseService; +import io.metersphere.sdk.constants.PermissionConstants; +import io.metersphere.system.security.CheckOwner; +import io.metersphere.system.utils.PageUtils; +import io.metersphere.system.utils.Pager; +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; + +import java.util.List; + +/** + * @author wx + */ +@Tag(name = "用例管理-功能用例-用例详情-前后置关系") +@RestController +@RequestMapping("/functional/case/relationship") +public class FunctionalCaseRelationshipController { + + @Resource + private FunctionalCaseService functionalCaseService; + @Resource + private FunctionalCaseRelationshipEdgeService functionalCaseRelationshipEdgeService; + + + @PostMapping("/relate/page") + @Operation(summary = "用例管理-功能用例-用例详情-前后置关系-弹窗获取用例列表") + @RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ) + @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") + public Pager> getFunctionalCasePage(@Validated @RequestBody RelationshipPageRequest request) { + List excludeIds = functionalCaseRelationshipEdgeService.getExcludeIds(request.getId()); + request.setExcludeIds(excludeIds); + Page page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), + StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "pos desc"); + return PageUtils.setPageInfo(page, functionalCaseService.getFunctionalCasePage(request, false)); + } + + +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/request/RelationshipAddRequest.java b/backend/services/case-management/src/main/java/io/metersphere/functional/request/RelationshipAddRequest.java new file mode 100644 index 0000000000..db6b10f40b --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/request/RelationshipAddRequest.java @@ -0,0 +1,26 @@ +package io.metersphere.functional.request; + + +import io.metersphere.system.dto.table.TableBatchProcessDTO; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author wx + */ +@Data +public class RelationshipAddRequest extends TableBatchProcessDTO { + + @Schema(description = "用例id", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{functional_case.id.not_blank}") + private String id; + + @Schema(description = "类型前置/后置", requiredMode = Schema.RequiredMode.REQUIRED, allowableValues = {"PRE", "POST"}) + @NotBlank(message = "{functional_case_relationship_edge.type.not_blank}") + private String type; + + @Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{functional_case.project_id.not_blank}") + private String projectId; +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/request/RelationshipPageRequest.java b/backend/services/case-management/src/main/java/io/metersphere/functional/request/RelationshipPageRequest.java new file mode 100644 index 0000000000..2c81ba7f19 --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/request/RelationshipPageRequest.java @@ -0,0 +1,17 @@ +package io.metersphere.functional.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author wx + */ +@Data +public class RelationshipPageRequest extends FunctionalCasePageRequest{ + + @Schema(description = "用例id", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{functional_case.id.not_blank}") + private String id; + +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseRelationshipEdgeService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseRelationshipEdgeService.java new file mode 100644 index 0000000000..9df60db530 --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseRelationshipEdgeService.java @@ -0,0 +1,46 @@ +/** + * @filename:FunctionalCaseRelationshipEdgeServiceImpl 2023年5月17日 + * @project ms V3.x + * Copyright(c) 2018 wx Co. Ltd. + * All right reserved. + */ +package io.metersphere.functional.service; + + +import io.metersphere.functional.domain.FunctionalCaseRelationshipEdge; +import io.metersphere.functional.domain.FunctionalCaseRelationshipEdgeExample; +import io.metersphere.functional.mapper.FunctionalCaseRelationshipEdgeMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + + +@Service +public class FunctionalCaseRelationshipEdgeService { + + @Resource + private FunctionalCaseRelationshipEdgeMapper functionalCaseRelationshipEdgeMapper; + + + public List getExcludeIds(String id) { + List relationshipEdges = getRelationshipEdges(id); + List ids = relationshipEdges.stream().map(FunctionalCaseRelationshipEdge::getTargetId).collect(Collectors.toList()); + ids.addAll(relationshipEdges.stream().map(FunctionalCaseRelationshipEdge::getSourceId).collect(Collectors.toList())); + List list = ids.stream().distinct().toList(); + return list; + } + + private List getRelationshipEdges(String id) { + FunctionalCaseRelationshipEdgeExample example = new FunctionalCaseRelationshipEdgeExample(); + example.createCriteria() + .andSourceIdEqualTo(id); + example.or( + example.createCriteria() + .andTargetIdEqualTo(id) + ); + return functionalCaseRelationshipEdgeMapper.selectByExample(example); + } + +} \ No newline at end of file diff --git a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseRelationshipControllerTests.java b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseRelationshipControllerTests.java new file mode 100644 index 0000000000..9ad82dddd2 --- /dev/null +++ b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseRelationshipControllerTests.java @@ -0,0 +1,47 @@ +package io.metersphere.functional.controller; + +import io.metersphere.functional.request.RelationshipPageRequest; +import io.metersphere.sdk.util.JSON; +import io.metersphere.system.base.BaseTest; +import io.metersphere.system.controller.handler.ResultHolder; +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.HashMap; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@AutoConfigureMockMvc +public class FunctionalCaseRelationshipControllerTests extends BaseTest { + + public static final String RELATE_PAGE = "/functional/case/relationship/relate/page"; + + + @Test + @Order(1) + @Sql(scripts = {"/dml/init_relationship_test.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED)) + public void testRelatePage() throws Exception { + RelationshipPageRequest request = new RelationshipPageRequest(); + request.setId("123"); + request.setProjectId("wx_relationship"); + request.setCurrent(1); + request.setPageSize(10); + MvcResult mvcResult = this.requestPostWithOkAndReturn(RELATE_PAGE, request); + // 获取返回值 + String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); + ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class); + // 返回请求正常 + Assertions.assertNotNull(resultHolder); + request.setId("wx_relationship_1"); + request.setProjectId("wx_relationship"); + request.setSort(new HashMap<>() {{ + put("createTime", "desc"); + }}); + this.requestPostWithOkAndReturn(RELATE_PAGE, request); + } +} diff --git a/backend/services/case-management/src/test/resources/dml/init_relationship_test.sql b/backend/services/case-management/src/test/resources/dml/init_relationship_test.sql new file mode 100644 index 0000000000..81a3eb87cc --- /dev/null +++ b/backend/services/case-management/src/test/resources/dml/init_relationship_test.sql @@ -0,0 +1,37 @@ +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 ('wx_relationship_1', 1, 'TEST_MODULE_ID', 'wx_relationship', '100001', '前后置测试1', 'UN_REVIEWED', NULL, 'STEP', 0, 'v1.0.0', 'v1.0.0', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), +('wx_relationship_2', 2, 'TEST_MODULE_ID', 'wx_relationship', '100001', '前后置测试2', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), +('wx_relationship_3', 2, 'TEST_MODULE_ID', 'wx_relationship', '100001', '前后置测试3', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), +('wx_relationship_4', 2, 'TEST_MODULE_ID', 'wx_relationship', '100001', '前后置测试4', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), +('wx_relationship_5', 2, 'TEST_MODULE_ID', 'wx_relationship', '100001', '前后置测试5', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), +('wx_relationship_6', 2, 'TEST_MODULE_ID', 'wx_relationship', '100001', '前后置测试6', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), +('wx_relationship_7', 2, 'TEST_MODULE_ID', 'wx_relationship', '100001', '前后置测试7', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), +('wx_relationship_8', 2, 'TEST_MODULE_ID', 'wx_relationship', '100001', '前后置测试8', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), +('wx_relationship_9', 2, 'TEST_MODULE_ID', 'wx_relationship', '100001', '前后置测试9', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), +('wx_relationship_10', 2, 'TEST_MODULE_ID', 'wx_relationship', '100001', '前后置测试10', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), +('wx_relationship_11', 2, 'TEST_MODULE_ID', 'wx_relationship', '100001', '前后置测试11', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), +('wx_relationship_12', 2, 'TEST_MODULE_ID', 'wx_relationship', '100001', '前后置测试12', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL), +('wx_relationship_13', 2, 'TEST_MODULE_ID', 'wx_relationship', '100001', '前后置测试13', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', '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 ('wx_relationship_1', 'STEP', '1111', '', '', 'TEST'), + ('wx_relationship_2', 'STEP', '1111', '', '', '1111'), + ('wx_relationship_3', 'STEP', '1111', '', '', '1111'), + ('wx_relationship_4', 'STEP', '1111', '', '', '1111'), + ('wx_relationship_5', 'STEP', '1111', '', '', '1111'), + ('wx_relationship_6', 'STEP', '1111', '', '', '1111'), + ('wx_relationship_7', 'STEP', '1111', '', '', '1111'), + ('wx_relationship_8', 'STEP', '1111', '', '', '1111'), + ('wx_relationship_9', 'STEP', '1111', '', '', '1111'), + ('wx_relationship_10', 'STEP', '1111', '', '', '1111'), + ('wx_relationship_11', 'STEP', '1111', '', '', '1111'), + ('wx_relationship_12', 'STEP', '1111', '', '', '1111'), + ('wx_relationship_13', 'STEP', '1111', '', '', '1111'); + + + +INSERT INTO functional_case_relationship_edge(id, source_id, target_id, graph_id, create_user, update_time, create_time) +VALUES ('relationship_1', 'wx_relationship_1', 'wx_relationship_2', '1', 'admin', 1698058347559, 1698058347559), + ('relationship_3', 'wx_relationship_2', 'wx_relationship_3', '1', 'admin', 1698058347559, 1698058347559);