diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/constants/AssociateCaseType.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/constants/AssociateCaseType.java new file mode 100644 index 0000000000..7e8a185eb4 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/constants/AssociateCaseType.java @@ -0,0 +1,16 @@ +package io.metersphere.plan.constants; + +public class AssociateCaseType { + /** + * 接口用例 + */ + public static final String API = "API"; + /** + * 场景用例 + */ + public static final String API_SCENARIO = "API_SCENARIO"; + /** + * 功能用例 + */ + public static final String FUNCTIONAL = "FUNCTIONAL"; +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/constants/AssociateType.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/constants/AssociateType.java new file mode 100644 index 0000000000..8e0f1e6edc --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/constants/AssociateType.java @@ -0,0 +1,16 @@ +package io.metersphere.plan.constants; + +public class AssociateType { + /** + * 接口用例 + */ + public static final String PROJECT = "PROJECT"; + /** + * 场景用例 + */ + public static final String TEST_PLAN = "TEST_PLAN"; + /** + * 功能用例 + */ + public static final String CASE_REVIEW = "CASE_REVIEW"; +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java index 6bc9a7ed29..46d384f28b 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java @@ -1,10 +1,7 @@ package io.metersphere.plan.controller; import io.metersphere.plan.constants.TestPlanResourceConfig; -import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest; -import io.metersphere.plan.dto.request.TestPlanCreateRequest; -import io.metersphere.plan.dto.request.TestPlanTableRequest; -import io.metersphere.plan.dto.request.TestPlanUpdateRequest; +import io.metersphere.plan.dto.request.*; import io.metersphere.plan.dto.response.TestPlanCountResponse; import io.metersphere.plan.dto.response.TestPlanResponse; import io.metersphere.plan.service.TestPlanManagementService; @@ -96,7 +93,7 @@ public class TestPlanController { @PostMapping(value = "/batch-delete") @Operation(summary = "测试计划-批量删除") - @RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_DELETE) + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_DELETE) @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") public void delete(@Validated @RequestBody TestPlanBatchProcessRequest request) throws Exception { testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN)); @@ -104,6 +101,16 @@ public class TestPlanController { } + @PostMapping("/edit/follower") + @Operation(summary = "测试计划-关注/取消关注") + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE) + @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") + public void editFollower(@Validated @RequestBody TestPlanFollowerRequest request) { + String userId = SessionUtils.getUserId(); + testPlanService.editFollower(request.getTestPlanId(), userId); + } + + //todo 关注测试计划接口 //todo 取消关注测试计划接口 diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanFollowerRequest.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanFollowerRequest.java new file mode 100644 index 0000000000..33f3291c88 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanFollowerRequest.java @@ -0,0 +1,25 @@ +package io.metersphere.plan.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author wx + */ +@Data +public class TestPlanFollowerRequest implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + + @Schema(description = "用户id", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{test_plan_follower.user_id.not_blank}") + private String userId; + + @Schema(description = "用例id", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{test_plan.id.not_blank}") + private String testPlanId; +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java index 42805fb210..7f8dd2f3ea 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java @@ -1,7 +1,6 @@ package io.metersphere.plan.service; import io.metersphere.plan.domain.*; -import io.metersphere.plan.dto.TestPlanQueryConditions; import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest; import io.metersphere.plan.dto.request.TestPlanCreateRequest; import io.metersphere.plan.dto.request.TestPlanUpdateRequest; @@ -17,7 +16,6 @@ import io.metersphere.sdk.constants.TestPlanConstants; import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.CommonBeanFactory; -import io.metersphere.sdk.util.LogUtils; import io.metersphere.sdk.util.Translator; import io.metersphere.system.domain.TestPlanModuleExample; import io.metersphere.system.mapper.TestPlanModuleMapper; @@ -72,6 +70,16 @@ public class TestPlanService { } } + + /** + * 创建测试计划 + * + * @param testPlanCreateRequest + * @param operator + * @param requestUrl + * @param requestMethod + * @return + */ public String add(TestPlanCreateRequest testPlanCreateRequest, String operator, String requestUrl, String requestMethod) { //检查模块的合法性 this.checkModule(testPlanCreateRequest.getModuleId()); @@ -130,6 +138,15 @@ public class TestPlanService { } } + + /** + * 删除测试计划 + * + * @param id + * @param operator + * @param requestUrl + * @param requestMethod + */ public void delete(String id, String operator, String requestUrl, String requestMethod) { TestPlan testPlan = testPlanMapper.selectByPrimaryKey(id); if (StringUtils.equals(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) { @@ -170,6 +187,14 @@ public class TestPlanService { } + /** + * 批量删除测试计划 + * + * @param request + * @param operator + * @param requestUrl + * @param requestMethod + */ public void batchDelete(TestPlanBatchProcessRequest request, String operator, String requestUrl, String requestMethod) { List deleteIdList = request.getSelectIds(); if (request.isSelectAll()) { @@ -234,6 +259,16 @@ public class TestPlanService { return response; } + + /** + * 更新测试计划 + * + * @param request + * @param userId + * @param requestUrl + * @param requestMethod + * @return + */ public String update(TestPlanUpdateRequest request, String userId, String requestUrl, String requestMethod) { TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getId()); if (!ObjectUtils.allNull(request.getName(), request.getModuleId(), request.getTags(), request.getPlannedEndTime(), request.getPlannedStartTime(), request.getDescription(), request.getTestPlanGroupId())) { @@ -278,4 +313,23 @@ public class TestPlanService { return request.getId(); } + + /** + * 关注/取消关注 测试计划 + * + * @param testPlanId + * @param userId + */ + public void editFollower(String testPlanId, String userId) { + TestPlanFollowerExample example = new TestPlanFollowerExample(); + example.createCriteria().andTestPlanIdEqualTo(testPlanId).andUserIdEqualTo(userId); + if (testPlanFollowerMapper.countByExample(example) > 0) { + testPlanFollowerMapper.deleteByPrimaryKey(testPlanId, userId); + } else { + TestPlanFollower testPlanFollower = new TestPlanFollower(); + testPlanFollower.setTestPlanId(testPlanId); + testPlanFollower.setUserId(userId); + testPlanFollowerMapper.insert(testPlanFollower); + } + } } diff --git a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java index bbb3c900ae..8af17040bb 100644 --- a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java +++ b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java @@ -43,6 +43,8 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.jdbc.SqlConfig; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -117,6 +119,8 @@ public class TestPlanTests extends BaseTest { private static final String URL_POST_RESOURCE_API_SCENARIO_ASSOCIATION = "/test-plan/api/scenario/association"; private static final String URL_POST_RESOURCE_API_SCENARIO_SORT = "/test-plan/api/scenario/sort"; + private static final String URL_TEST_PLAN_EDIT_FOLLOWER = "/test-plan/edit/follower"; + private static String groupTestPlanId7 = null; private static String groupTestPlanId15 = null; @@ -2026,4 +2030,25 @@ public class TestPlanTests extends BaseTest { } Assertions.assertTrue(methodHasError); } + + + @Test + @Order(300) + @Sql(scripts = {"/dml/init_test_plan_test.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED)) + public void testEditFollower() throws Exception { + TestPlanFollowerRequest testPlanFollowerRequest = new TestPlanFollowerRequest(); + testPlanFollowerRequest.setTestPlanId("wx_test_plan_id_1"); + testPlanFollowerRequest.setUserId("wx"); + //关注 + MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_TEST_PLAN_EDIT_FOLLOWER, testPlanFollowerRequest); + String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); + ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class); + Assertions.assertNotNull(resultHolder); + + //取消关注 + MvcResult editMvcResult = this.requestPostWithOkAndReturn(URL_TEST_PLAN_EDIT_FOLLOWER, testPlanFollowerRequest); + String editReturnData = editMvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); + ResultHolder editResultHolder = JSON.parseObject(editReturnData, ResultHolder.class); + Assertions.assertNotNull(editResultHolder); + } } diff --git a/backend/services/test-plan/src/test/resources/dml/init_test_plan_test.sql b/backend/services/test-plan/src/test/resources/dml/init_test_plan_test.sql new file mode 100644 index 0000000000..e698805c17 --- /dev/null +++ b/backend/services/test-plan/src/test/resources/dml/init_test_plan_test.sql @@ -0,0 +1,3 @@ +INSERT INTO `test_plan`(`id`, `num`, `project_id`, `group_id`, `module_id`, `name`, `status`, `type`, `tags`, `create_time`, `create_user`, `update_time`, `update_user`, `planned_start_time`, `planned_end_time`, `actual_start_time`, `actual_end_time`, `description`) +VALUES + ('wx_test_plan_id_1', 5000, 'wx', 'NONE', '1', '测试一下计划', 'PREPARED', 'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11');