feat(测试计划): 接口&场景批量移动

This commit is contained in:
WangXu10 2024-06-13 17:22:43 +08:00 committed by Craftsman
parent b523963553
commit 4cb1df43c3
12 changed files with 202 additions and 3 deletions

View File

@ -163,4 +163,14 @@ public class TestPlanApiCaseController {
testPlanApiCaseService.checkReportIsTestPlan(reportId);
return apiReportService.getDetail(reportId, stepId);
}
@PostMapping("/batch/move")
@Operation(summary = "测试计划-计划详情-接口用例-批量移动")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE)
@CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan")
@Log(type = OperationLogType.UPDATE, expression = "#msClass.batchMove(#request)", msClass = TestPlanApiCaseLogService.class)
public void batchMove(@Validated @RequestBody TestPlanApiCaseBatchMoveRequest request) {
testPlanApiCaseService.batchMove(request);
}
}

View File

@ -149,4 +149,13 @@ public class TestPlanApiScenarioController {
public TestPlanOperationResponse sortNode(@Validated @RequestBody ResourceSortRequest request) {
return testPlanApiScenarioService.sortNode(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/api/scenario/sort", HttpMethodConstants.POST.name()));
}
@PostMapping("/batch/move")
@Operation(summary = "测试计划-计划详情-场景用例-批量移动")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE)
@CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan")
@Log(type = OperationLogType.UPDATE, expression = "#msClass.batchMove(#request)", msClass = TestPlanApiScenarioLogService.class)
public void batchMove(@Validated @RequestBody BaseBatchMoveRequest request) {
testPlanApiScenarioService.batchMove(request);
}
}

View File

@ -0,0 +1,18 @@
package io.metersphere.plan.dto.request;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
/**
* @author wx
*/
@Data
public class TestPlanApiCaseBatchMoveRequest extends TestPlanApiCaseBatchRequest {
@Schema(description = "目标计划集id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{targetCollectionId.not_blank}")
private String targetCollectionId;
}

View File

@ -64,4 +64,7 @@ public class TestPlanApiScenarioPageResponse implements Serializable {
@Schema(description = "报告id")
private String lastExecReportId;
@Schema(description = "状态")
private String status;
}

View File

@ -92,6 +92,7 @@
api_scenario.priority,
api_scenario.project_id,
api_scenario.create_user,
api_scenario.status,
test_plan_api_scenario.create_time,
test_plan_api_scenario.environment_id,
api_scenario.module_id,
@ -163,6 +164,12 @@
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
</if>
</when>
<when test="key=='lastExecResult'">
and test_plan_api_scenario.last_exec_result in
<foreach collection="values" item="value" separator="," open="(" close=")">
#{value}
</foreach>
</when>
<when test="key=='status'">
and api_scenario.status in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>

View File

@ -3,12 +3,16 @@ package io.metersphere.plan.service;
import io.metersphere.api.domain.ApiTestCase;
import io.metersphere.api.domain.ApiTestCaseExample;
import io.metersphere.api.mapper.ApiTestCaseMapper;
import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.plan.domain.TestPlanApiCase;
import io.metersphere.plan.domain.TestPlanApiCaseExample;
import io.metersphere.plan.domain.TestPlanFunctionalCase;
import io.metersphere.plan.dto.request.TestPlanApiCaseBatchMoveRequest;
import io.metersphere.plan.dto.request.TestPlanApiCaseUpdateRequest;
import io.metersphere.plan.mapper.TestPlanApiCaseMapper;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.dto.LogDTO;
@ -65,6 +69,38 @@ public class TestPlanApiCaseLogService {
}
}
public void batchMove(TestPlanApiCaseBatchMoveRequest request) {
List<String> ids = testPlanApiCaseService.doSelectIds(request);
if (CollectionUtils.isNotEmpty(ids)) {
TestPlanApiCaseExample example = new TestPlanApiCaseExample();
example.createCriteria().andIdIn(ids);
List<TestPlanApiCase> caseList = testPlanApiCaseMapper.selectByExample(example);
List<String> apiCaseIds = caseList.stream().map(TestPlanApiCase::getApiCaseId).collect(Collectors.toList());
ApiTestCaseExample caseExample = new ApiTestCaseExample();
caseExample.createCriteria().andIdIn(apiCaseIds);
List<ApiTestCase> apiTestCases = apiTestCaseMapper.selectByExample(caseExample);
Map<String, String> caseMap = apiTestCases.stream().collect(Collectors.toMap(ApiTestCase::getId, ApiTestCase::getName));
List<LogDTO> dtoList = new ArrayList<>();
caseList.forEach(item -> {
LogDTO dto = new LogDTO(
null,
null,
item.getApiCaseId(),
null,
OperationLogType.UPDATE.name(),
OperationLogModule.TEST_PLAN,
Translator.get("move") + ":" + caseMap.get(item.getApiCaseId()));
dto.setPath("/test-plan/api/case/batch/move");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(item));
TestPlanApiCase testPlanApiCase = new TestPlanApiCase();
testPlanApiCase.setId(item.getId());
testPlanApiCase.setTestPlanCollectionId(request.getTargetCollectionId());
dto.setModifiedValue(JSON.toJSONBytes(testPlanApiCase));
dtoList.add(dto);
});
}
}
}

View File

@ -57,6 +57,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
@Service
@ -669,4 +670,32 @@ public class TestPlanApiCaseService extends TestPlanResourceService implements G
throw new MSException("api_case_report_not_exist");
}
}
/**
* 批量移动
*
* @param request
*/
public void batchMove(TestPlanApiCaseBatchMoveRequest request) {
List<String> ids = doSelectIds(request);
if (CollectionUtils.isNotEmpty(ids)) {
moveCaseToCollection(ids, request.getTargetCollectionId());
}
}
private void moveCaseToCollection(List<String> ids, String targetCollectionId) {
AtomicLong nextOrder = new AtomicLong(getNextOrder(targetCollectionId));
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
TestPlanApiCaseMapper testPlanApiCaseMapper = sqlSession.getMapper(TestPlanApiCaseMapper.class);
ids.forEach(id -> {
TestPlanApiCase testPlanApiCase = new TestPlanApiCase();
testPlanApiCase.setId(id);
testPlanApiCase.setPos(nextOrder.get());
testPlanApiCase.setTestPlanCollectionId(targetCollectionId);
nextOrder.addAndGet(DEFAULT_NODE_INTERVAL_POS);
testPlanApiCaseMapper.updateByPrimaryKeySelective(testPlanApiCase);
});
sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
}

View File

@ -10,12 +10,14 @@ import io.metersphere.plan.domain.TestPlanApiCase;
import io.metersphere.plan.domain.TestPlanApiCaseExample;
import io.metersphere.plan.domain.TestPlanApiScenario;
import io.metersphere.plan.domain.TestPlanApiScenarioExample;
import io.metersphere.plan.dto.request.BaseBatchMoveRequest;
import io.metersphere.plan.dto.request.TestPlanApiCaseUpdateRequest;
import io.metersphere.plan.dto.request.TestPlanApiScenarioUpdateRequest;
import io.metersphere.plan.mapper.TestPlanApiCaseMapper;
import io.metersphere.plan.mapper.TestPlanApiScenarioMapper;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.dto.LogDTO;
@ -72,6 +74,40 @@ public class TestPlanApiScenarioLogService {
}
}
public void batchMove(BaseBatchMoveRequest request) {
List<String> ids = testPlanApiScenarioService.doSelectIds(request);
if (CollectionUtils.isNotEmpty(ids)) {
TestPlanApiScenarioExample example = new TestPlanApiScenarioExample();
example.createCriteria().andIdIn(ids);
List<TestPlanApiScenario> caseList = testPlanApiScenarioMapper.selectByExample(example);
List<String> apiScenarioIds = caseList.stream().map(TestPlanApiScenario::getApiScenarioId).collect(Collectors.toList());
ApiScenarioExample scenarioExample = new ApiScenarioExample();
scenarioExample.createCriteria().andIdIn(apiScenarioIds);
List<ApiScenario> apiScenarios = apiScenarioMapper.selectByExample(scenarioExample);
Map<String, String> caseMap = apiScenarios.stream().collect(Collectors.toMap(ApiScenario::getId, ApiScenario::getName));
List<LogDTO> dtoList = new ArrayList<>();
caseList.forEach(item -> {
LogDTO dto = new LogDTO(
null,
null,
item.getApiScenarioId(),
null,
OperationLogType.UPDATE.name(),
OperationLogModule.TEST_PLAN,
Translator.get("move") + ":" + caseMap.get(item.getApiScenarioId()));
dto.setPath("/test-plan/api/scenario/batch/move");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(item));
TestPlanApiScenario testPlanApiScenario = new TestPlanApiScenario();
testPlanApiScenario.setId(item.getId());
testPlanApiScenario.setTestPlanCollectionId(request.getTargetCollectionId());
dto.setModifiedValue(JSON.toJSONBytes(testPlanApiScenario));
dtoList.add(dto);
});
}
}
}

View File

@ -58,6 +58,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
@Service
@ -589,4 +590,32 @@ public class TestPlanApiScenarioService extends TestPlanResourceService implemen
}
}
/**
* 批量移动
* @param request
*/
public void batchMove(BaseBatchMoveRequest request) {
List<String> ids = doSelectIds(request);
if (CollectionUtils.isNotEmpty(ids)) {
moveCaseToCollection(ids,request.getTargetCollectionId());
}
}
private void moveCaseToCollection(List<String> ids, String targetCollectionId) {
AtomicLong nextOrder = new AtomicLong(getNextOrder(targetCollectionId));
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
TestPlanApiScenarioMapper testPlanApiScenarioMapper = sqlSession.getMapper(TestPlanApiScenarioMapper.class);
ids.forEach(id -> {
TestPlanApiScenario testPlanApiScenario = new TestPlanApiScenario();
testPlanApiScenario.setId(id);
testPlanApiScenario.setPos(nextOrder.get());
testPlanApiScenario.setTestPlanCollectionId(targetCollectionId);
nextOrder.addAndGet(DEFAULT_NODE_INTERVAL_POS);
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
});
sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
}

View File

@ -780,12 +780,13 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
/**
* 批量移动
*
* @param request
*/
public void batchMove(BaseBatchMoveRequest request) {
List<String> ids = doSelectIds(request);
if (CollectionUtils.isNotEmpty(ids)) {
moveCaseToCollection(ids,request.getTargetCollectionId());
moveCaseToCollection(ids, request.getTargetCollectionId());
}
}
@ -793,7 +794,7 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
AtomicLong nextOrder = new AtomicLong(getNextOrder(targetCollectionId));
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
TestPlanFunctionalCaseMapper functionalBatchMapper = sqlSession.getMapper(TestPlanFunctionalCaseMapper.class);
ids.forEach(id ->{
ids.forEach(id -> {
TestPlanFunctionalCase testPlanFunctionalCase = new TestPlanFunctionalCase();
testPlanFunctionalCase.setId(id);
testPlanFunctionalCase.setPos(nextOrder.get());

View File

@ -70,6 +70,7 @@ public class TestPlanApiCaseControllerTests extends BaseTest {
public static final String RUN = "run/{0}";
public static final String BATCH_RUN = "batch/run";
public static final String RUN_WITH_REPORT_ID = "run/{0}?reportId={1}";
private static final String API_CASE_BATCH_MOVE = "/batch/move";
@Resource
private TestPlanApiCaseService testPlanApiCaseService;
@ -457,5 +458,13 @@ public class TestPlanApiCaseControllerTests extends BaseTest {
requestGetPermissionTest(PermissionConstants.TEST_PLAN_READ, "/report/get/detail/plan-test-report-id" + "/" + "plan-test-report-step-id1");
}
@Test
@Order(11)
public void testApiCaseBatchMove() throws Exception {
TestPlanApiCaseBatchMoveRequest request = new TestPlanApiCaseBatchMoveRequest();
request.setTestPlanId("wxxx_1");
request.setTargetCollectionId("wxxx_2");
request.setSelectAll(true);
this.requestPostWithOk(API_CASE_BATCH_MOVE, request);
}
}

View File

@ -24,6 +24,7 @@ import io.metersphere.plan.domain.TestPlanApiScenarioExample;
import io.metersphere.plan.dto.request.*;
import io.metersphere.plan.dto.response.TestPlanOperationResponse;
import io.metersphere.plan.mapper.TestPlanApiScenarioMapper;
import io.metersphere.plan.service.TestPlanApiScenarioLogService;
import io.metersphere.plan.service.TestPlanApiScenarioService;
import io.metersphere.project.api.assertion.MsResponseCodeAssertion;
import io.metersphere.project.api.assertion.MsScriptAssertion;
@ -71,6 +72,7 @@ public class TestPlanApiScenarioControllerTests extends BaseTest {
public static final String API_SCENARIO_BATCH_DISASSOCIATE = "batch/disassociate";
public static final String API_SCENARIO_BATCH_UPDATE_EXECUTOR_URL = "batch/update/executor";
private static final String URL_POST_RESOURCE_API_SCENARIO_SORT = "/sort";
private static final String API_SCENARIO_BATCH_MOVE_URL = "/batch/move";
@Resource
private TestPlanApiScenarioService testPlanApiScenarioService;
@ -272,6 +274,16 @@ public class TestPlanApiScenarioControllerTests extends BaseTest {
testPlanApiScenarioService.associateCollection("wxxx_plan_2", collectionAssociates, "wx");
}
@Test
@Order(5)
public void testApiScenarioBatchMove() throws Exception {
BaseBatchMoveRequest request = new BaseBatchMoveRequest();
request.setTestPlanId("wxxx_plan_1");
request.setTargetCollectionId("wxxx_collection_2");
request.setSelectAll(true);
this.requestPostWithOk(API_SCENARIO_BATCH_MOVE_URL, request);
}
@Test
@Order(4)