feat(接口测试): 接口场景的批量复制功能开发
This commit is contained in:
parent
a7509b47dc
commit
797929cea4
|
@ -381,6 +381,8 @@ message.domain.test_plan_plannedStartTime=计划开始时间
|
||||||
message.domain.test_plan_plannedEndTime=计划结束时间
|
message.domain.test_plan_plannedEndTime=计划结束时间
|
||||||
message.domain.test_plan_actualStartTime=实际开始时间
|
message.domain.test_plan_actualStartTime=实际开始时间
|
||||||
message.domain.test_plan_actualEndTime=实际结束时间
|
message.domain.test_plan_actualEndTime=实际结束时间
|
||||||
|
message.domain.test_plan_num=编号
|
||||||
|
message.domain.test_plan_type=类型
|
||||||
# 用例评审
|
# 用例评审
|
||||||
message.domain.case_review_name=名称
|
message.domain.case_review_name=名称
|
||||||
message.domain.case_review_status=评审状态
|
message.domain.case_review_status=评审状态
|
||||||
|
|
|
@ -417,6 +417,8 @@ message.domain.test_plan_plannedStartTime=Planned start time
|
||||||
message.domain.test_plan_plannedEndTime=Planned end time
|
message.domain.test_plan_plannedEndTime=Planned end time
|
||||||
message.domain.test_plan_actualStartTime=Actual start time
|
message.domain.test_plan_actualStartTime=Actual start time
|
||||||
message.domain.test_plan_actualEndTime=Actual end time
|
message.domain.test_plan_actualEndTime=Actual end time
|
||||||
|
message.domain.test_plan_num=Num
|
||||||
|
message.domain.test_plan_type=Type
|
||||||
# case Review
|
# case Review
|
||||||
message.domain.case_review_name=Name
|
message.domain.case_review_name=Name
|
||||||
message.domain.case_review_status=Review status
|
message.domain.case_review_status=Review status
|
||||||
|
|
|
@ -416,6 +416,8 @@ message.domain.test_plan_plannedStartTime=计划开始时间
|
||||||
message.domain.test_plan_plannedEndTime=计划结束时间
|
message.domain.test_plan_plannedEndTime=计划结束时间
|
||||||
message.domain.test_plan_actualStartTime=实际开始时间
|
message.domain.test_plan_actualStartTime=实际开始时间
|
||||||
message.domain.test_plan_actualEndTime=实际结束时间
|
message.domain.test_plan_actualEndTime=实际结束时间
|
||||||
|
message.domain.test_plan_num=编号
|
||||||
|
message.domain.test_plan_type=类型
|
||||||
# 用例评审
|
# 用例评审
|
||||||
message.domain.case_review_name=名称
|
message.domain.case_review_name=名称
|
||||||
message.domain.case_review_status=评审状态
|
message.domain.case_review_status=评审状态
|
||||||
|
|
|
@ -417,6 +417,8 @@ message.domain.test_plan_plannedStartTime=計劃開始時間
|
||||||
message.domain.test_plan_plannedEndTime=計劃結束時間
|
message.domain.test_plan_plannedEndTime=計劃結束時間
|
||||||
message.domain.test_plan_actualStartTime=實際開始時間
|
message.domain.test_plan_actualStartTime=實際開始時間
|
||||||
message.domain.test_plan_actualEndTime=實際結束時間
|
message.domain.test_plan_actualEndTime=實際結束時間
|
||||||
|
message.domain.test_plan_num=編號
|
||||||
|
message.domain.test_plan_type=類型
|
||||||
# 用例評審
|
# 用例評審
|
||||||
message.domain.case_review_name=名稱
|
message.domain.case_review_name=名稱
|
||||||
message.domain.case_review_status=評審狀態
|
message.domain.case_review_status=評審狀態
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package io.metersphere.api.constants;
|
||||||
|
|
||||||
|
public enum ApiResource {
|
||||||
|
PROJECT,
|
||||||
|
API_DEFINITION,
|
||||||
|
API_TEST_CASE,
|
||||||
|
API_SCENARIO
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
package io.metersphere.api.controller.scenario;
|
||||||
|
|
||||||
|
import io.metersphere.api.constants.ApiResource;
|
||||||
|
import io.metersphere.api.dto.response.ApiScenarioBatchOperationResponse;
|
||||||
|
import io.metersphere.api.dto.scenario.ApiScenarioBatchCopyRequest;
|
||||||
|
import io.metersphere.api.dto.scenario.ApiScenarioBatchEditRequest;
|
||||||
|
import io.metersphere.api.service.ApiValidateService;
|
||||||
|
import io.metersphere.api.service.scenario.ApiScenarioService;
|
||||||
|
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||||
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
|
import io.metersphere.system.dto.LogInsertModule;
|
||||||
|
import io.metersphere.system.security.CheckOwner;
|
||||||
|
import io.metersphere.system.utils.SessionUtils;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping(value = "/api/scenario")
|
||||||
|
@Tag(name = "接口测试-接口场景批量操作")
|
||||||
|
public class ApiScenarioBatchOperationController {
|
||||||
|
@Resource
|
||||||
|
private ApiValidateService apiValidateService;
|
||||||
|
@Resource
|
||||||
|
private ApiScenarioService apiScenarioService;
|
||||||
|
|
||||||
|
@PostMapping("/batch-operation/edit")
|
||||||
|
@Operation(summary = "接口测试-接口场景批量操作-批量编辑")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_UPDATE)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
public void batchUpdate(@Validated @RequestBody ApiScenarioBatchEditRequest request) {
|
||||||
|
apiValidateService.validateApiMenuInProject(request.getProjectId(), ApiResource.PROJECT.name());
|
||||||
|
apiScenarioService.batchEdit(request, SessionUtils.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
todo:
|
||||||
|
@PostMapping("/gc-batch-delete")
|
||||||
|
@Operation(summary = "接口测试-接口场景批量操作-回收站列表-批量删除")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_UPDATE)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
@SendNotice(taskType = NoticeConstants.TaskType.API_SCENARIO_TASK, event = NoticeConstants.Event.UPDATE, target = "#targetClass.getCaseDTO(#request)", targetClass = ApiTestCaseNoticeService.class)
|
||||||
|
public void deleteFromGC(@Validated @RequestBody ApiScenarioBatchEditRequest request) {
|
||||||
|
apiValidateService.validateApiMenuInProject(request.getProjectId(), ApiResource.PROJECT.name());
|
||||||
|
apiScenarioService.deleteFromGC(request, SessionUtils.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
todo
|
||||||
|
@PostMapping("/gc-batch-restore")
|
||||||
|
@Operation(summary = "接口测试-接口场景批量操作-回收站列表-批量恢复")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_UPDATE)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
public void restoreFromGC(@Validated @RequestBody ApiScenarioBatchEditRequest request) {
|
||||||
|
apiValidateService.validateApiMenuInProject(request.getProjectId(), ApiResource.PROJECT.name());
|
||||||
|
apiScenarioService.restoreFromGC(request, SessionUtils.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
todo
|
||||||
|
@PostMapping("/batch-delete")
|
||||||
|
@Operation(summary = "接口测试-接口场景批量操作-场景列表操作-批量删除")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_UPDATE)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
public void batchDelete(@Validated @RequestBody ApiScenarioBatchEditRequest request) {
|
||||||
|
apiValidateService.validateApiMenuInProject(request.getProjectId(), ApiResource.PROJECT.name());
|
||||||
|
apiScenarioService.batchDelete(request, SessionUtils.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
todo
|
||||||
|
@PostMapping("/batch-move")
|
||||||
|
@Operation(summary = "接口测试-接口场景批量操作-场景列表操作-批量移动")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_UPDATE)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
public void batchMove(@Validated @RequestBody ApiScenarioBatchEditRequest request) {
|
||||||
|
apiValidateService.validateApiMenuInProject(request.getProjectId(), ApiResource.PROJECT.name());
|
||||||
|
apiScenarioService.batchMove(request, new LogInsertModule(SessionUtils.getUserId(), "/api/scenario/batch-operation/batch-move", HttpMethodConstants.POST.name()));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/batch-operation/copy")
|
||||||
|
@Operation(summary = "接口测试-接口场景批量操作-场景列表操作-批量复制")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_UPDATE)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
public ApiScenarioBatchOperationResponse batchCopy(@Validated @RequestBody ApiScenarioBatchCopyRequest request) {
|
||||||
|
apiValidateService.validateApiMenuInProject(request.getProjectId(), ApiResource.PROJECT.name());
|
||||||
|
return apiScenarioService.batchCopy(request, new LogInsertModule(SessionUtils.getUserId(), "/api/scenario/batch-operation/copy", HttpMethodConstants.POST.name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,8 +2,10 @@ package io.metersphere.api.controller.scenario;
|
||||||
|
|
||||||
import com.github.pagehelper.Page;
|
import com.github.pagehelper.Page;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import io.metersphere.api.constants.ApiResource;
|
||||||
import io.metersphere.api.domain.ApiScenario;
|
import io.metersphere.api.domain.ApiScenario;
|
||||||
import io.metersphere.api.dto.scenario.*;
|
import io.metersphere.api.dto.scenario.*;
|
||||||
|
import io.metersphere.api.service.ApiValidateService;
|
||||||
import io.metersphere.api.service.scenario.ApiScenarioLogService;
|
import io.metersphere.api.service.scenario.ApiScenarioLogService;
|
||||||
import io.metersphere.api.service.scenario.ApiScenarioService;
|
import io.metersphere.api.service.scenario.ApiScenarioService;
|
||||||
import io.metersphere.sdk.constants.PermissionConstants;
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
|
@ -31,6 +33,8 @@ import java.util.List;
|
||||||
public class ApiScenarioController {
|
public class ApiScenarioController {
|
||||||
@Resource
|
@Resource
|
||||||
private ApiScenarioService apiScenarioService;
|
private ApiScenarioService apiScenarioService;
|
||||||
|
@Resource
|
||||||
|
private ApiValidateService apiValidateService;
|
||||||
|
|
||||||
@PostMapping("/page")
|
@PostMapping("/page")
|
||||||
@Operation(summary = "接口测试-接口场景管理-场景列表(deleted 状态为 1 时为回收站数据)")
|
@Operation(summary = "接口测试-接口场景管理-场景列表(deleted 状态为 1 时为回收站数据)")
|
||||||
|
@ -53,14 +57,6 @@ public class ApiScenarioController {
|
||||||
return PageUtils.setPageInfo(page, apiScenarioService.getScenarioPage(request));
|
return PageUtils.setPageInfo(page, apiScenarioService.getScenarioPage(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/batch/edit")
|
|
||||||
@Operation(summary = "接口测试-接口场景管理-批量编辑")
|
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_UPDATE)
|
|
||||||
@CheckOwner(resourceId = "#request.getSelectIds()", resourceType = "api_scenario")
|
|
||||||
public void batchUpdate(@Validated @RequestBody ApiScenarioBatchEditRequest request) {
|
|
||||||
apiScenarioService.batchEdit(request, SessionUtils.getUserId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("follow/{id}")
|
@GetMapping("follow/{id}")
|
||||||
@Operation(summary = "接口测试-接口场景管理-关注/ 取消关注")
|
@Operation(summary = "接口测试-接口场景管理-关注/ 取消关注")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_UPDATE)
|
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_UPDATE)
|
||||||
|
@ -126,6 +122,16 @@ public class ApiScenarioController {
|
||||||
return apiScenarioService.getStepDetail(stepId);
|
return apiScenarioService.getStepDetail(stepId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/restore/{id}")
|
||||||
|
@Operation(summary = "接口测试-接口场景管理-删除场景到回收站")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_DELETE)
|
||||||
|
@Log(type = OperationLogType.RESTORE, expression = "#msClass.restoreLog(#id)", msClass = ApiScenarioLogService.class)
|
||||||
|
@CheckOwner(resourceId = "#id", resourceType = "api_scenario")
|
||||||
|
public void recover(@PathVariable String id) {
|
||||||
|
apiValidateService.validateApiMenuInProject(id, ApiResource.API_SCENARIO.name());
|
||||||
|
apiScenarioService.restore(id);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/debug")
|
@PostMapping("/debug")
|
||||||
@Operation(summary = "接口测试-接口场景管理-场景调试")
|
@Operation(summary = "接口测试-接口场景管理-场景调试")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_EXECUTE)
|
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_EXECUTE)
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package io.metersphere.api.dto.response;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ApiScenarioBatchOperationResponse {
|
||||||
|
@Schema(description = "成功的数据")
|
||||||
|
private long success;
|
||||||
|
@Schema(description = "失败的数据量")
|
||||||
|
private long error;
|
||||||
|
@Schema(description = "成功数据")
|
||||||
|
List<OperationDataInfo> successData = new ArrayList<>();
|
||||||
|
@Schema(description = "失败数据")
|
||||||
|
Map<String, List<OperationDataInfo>> errorInfo = new HashMap<>();
|
||||||
|
|
||||||
|
public void addSuccessData(String id, Long num, String name) {
|
||||||
|
OperationDataInfo operationData = new OperationDataInfo(id, num, name);
|
||||||
|
successData.add(operationData);
|
||||||
|
this.success = successData.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addErrorData(String errorMessage, String id, Long num, String name) {
|
||||||
|
OperationDataInfo errorData = new OperationDataInfo(id, num, name);
|
||||||
|
if (!errorInfo.containsKey(errorMessage)) {
|
||||||
|
this.errorInfo.put(errorMessage, new ArrayList<>());
|
||||||
|
}
|
||||||
|
this.errorInfo.get(errorMessage).add(errorData);
|
||||||
|
this.error++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void merge(ApiScenarioBatchOperationResponse response) {
|
||||||
|
this.successData.addAll(response.getSuccessData());
|
||||||
|
this.success = successData.size();
|
||||||
|
response.getErrorInfo().forEach((errorMessage, errorDataList) -> {
|
||||||
|
if (!this.errorInfo.containsKey(errorMessage)) {
|
||||||
|
this.errorInfo.put(errorMessage, new ArrayList<>());
|
||||||
|
}
|
||||||
|
this.errorInfo.get(errorMessage).addAll(errorDataList);
|
||||||
|
this.error += errorDataList.size();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package io.metersphere.api.dto.response;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class OperationDataInfo {
|
||||||
|
@Schema(description = "数据id")
|
||||||
|
private String id;
|
||||||
|
@Schema(description = "数据编号")
|
||||||
|
private Long num;
|
||||||
|
@Schema(description = "数据名称")
|
||||||
|
private String name;
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package io.metersphere.api.dto.scenario;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class ApiScenarioBatchCopyRequest extends ApiScenarioBatchRequest implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "复制的目标模块ID")
|
||||||
|
@NotBlank
|
||||||
|
private String targetModuleId;
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package io.metersphere.api.mapper;
|
package io.metersphere.api.mapper;
|
||||||
|
|
||||||
import io.metersphere.api.domain.ApiScenario;
|
import io.metersphere.api.domain.ApiScenario;
|
||||||
import io.metersphere.api.dto.scenario.ApiScenarioBatchEditRequest;
|
import io.metersphere.api.dto.scenario.ApiScenarioBatchRequest;
|
||||||
import io.metersphere.api.dto.scenario.ApiScenarioDTO;
|
import io.metersphere.api.dto.scenario.ApiScenarioDTO;
|
||||||
import io.metersphere.api.dto.scenario.ApiScenarioPageRequest;
|
import io.metersphere.api.dto.scenario.ApiScenarioPageRequest;
|
||||||
import io.metersphere.system.dto.taskcenter.TaskCenterDTO;
|
import io.metersphere.system.dto.taskcenter.TaskCenterDTO;
|
||||||
|
@ -18,7 +18,7 @@ import java.util.List;
|
||||||
public interface ExtApiScenarioMapper {
|
public interface ExtApiScenarioMapper {
|
||||||
List<ApiScenarioDTO> list(@Param("request") ApiScenarioPageRequest request);
|
List<ApiScenarioDTO> list(@Param("request") ApiScenarioPageRequest request);
|
||||||
|
|
||||||
List<String> getIds(@Param("request") ApiScenarioBatchEditRequest request, @Param("deleted") boolean deleted);
|
List<String> getIds(@Param("request") ApiScenarioBatchRequest request, @Param("deleted") boolean deleted);
|
||||||
|
|
||||||
List<ApiScenario> getInfoByIds(@Param("ids") List<String> ids, @Param("deleted") boolean deleted);
|
List<ApiScenario> getInfoByIds(@Param("ids") List<String> ids, @Param("deleted") boolean deleted);
|
||||||
|
|
||||||
|
|
|
@ -98,14 +98,23 @@
|
||||||
|
|
||||||
<select id="getTestCaseByProvider" resultType="io.metersphere.api.domain.ApiScenario">
|
<select id="getTestCaseByProvider" resultType="io.metersphere.api.domain.ApiScenario">
|
||||||
SELECT
|
SELECT
|
||||||
t1.id, t1.version_id
|
id, version_id
|
||||||
FROM
|
FROM
|
||||||
api_scenario t1
|
api_scenario
|
||||||
WHERE t1.deleted =#{deleted}
|
WHERE deleted =#{deleted}
|
||||||
<include refid="queryWhereConditionByBaseQueryRequest"/>
|
<include refid="queryWhereConditionByBaseQueryRequest"/>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<sql id="queryWhereConditionByBaseQueryRequest">
|
<sql id="queryWhereConditionByBaseQueryRequest">
|
||||||
|
<if test="request.projectId != null and request.projectId != ''">
|
||||||
|
and api_scenario.project_id = #{request.projectId}
|
||||||
|
</if>
|
||||||
|
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
|
||||||
|
and api_scenario.module_id in
|
||||||
|
<foreach collection="request.moduleIds" item="nodeId" separator="," open="(" close=")">
|
||||||
|
#{nodeId}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
<if test="request.condition.combine != null">
|
<if test="request.condition.combine != null">
|
||||||
<include refid="combine">
|
<include refid="combine">
|
||||||
<property name="condition" value="request.condition.combine"/>
|
<property name="condition" value="request.condition.combine"/>
|
||||||
|
|
|
@ -277,4 +277,14 @@ public class ApiFileResourceService {
|
||||||
apiFileResourceMapper.batchInsert(apiFileResources);
|
apiFileResourceMapper.batchInsert(apiFileResources);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ApiFileResource> selectByApiScenarioId(List<String> scenarioIds) {
|
||||||
|
ApiFileResourceExample example = new ApiFileResourceExample();
|
||||||
|
example.createCriteria().andResourceIdIn(scenarioIds);
|
||||||
|
return apiFileResourceMapper.selectByExample(example);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void batchInsert(List<ApiFileResource> insertApiFileResourceList) {
|
||||||
|
apiFileResourceMapper.batchInsert(insertApiFileResourceList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package io.metersphere.api.service;
|
||||||
|
|
||||||
|
import io.metersphere.api.constants.ApiResource;
|
||||||
|
import io.metersphere.project.constants.ProjectMenuConstants;
|
||||||
|
import io.metersphere.system.service.CommonProjectService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ApiValidateService {
|
||||||
|
@Resource
|
||||||
|
private CommonProjectService commonProjectService;
|
||||||
|
|
||||||
|
//校验接口菜单是否开启
|
||||||
|
public void validateApiMenuInProject(String resourceId, String resourceType) {
|
||||||
|
String tableName = null;
|
||||||
|
if (StringUtils.equals(resourceType, ApiResource.PROJECT.name())) {
|
||||||
|
tableName = "project";
|
||||||
|
} else if (StringUtils.equals(resourceType, ApiResource.API_DEFINITION.name())) {
|
||||||
|
tableName = "api_definition";
|
||||||
|
} else if (StringUtils.equals(resourceType, ApiResource.API_TEST_CASE.name())) {
|
||||||
|
tableName = "api_test_case";
|
||||||
|
} else if (StringUtils.equals(resourceType, ApiResource.API_SCENARIO.name())) {
|
||||||
|
tableName = "api_scenario";
|
||||||
|
}
|
||||||
|
commonProjectService.checkProjectHasModuleMenu(Collections.singletonList(ProjectMenuConstants.MODULE_MENU_API_TEST), resourceId, tableName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -158,10 +158,6 @@ public class ApiDebugModuleService extends ModuleTreeService {
|
||||||
throw new MSException(Translator.get("node.name.repeat"));
|
throw new MSException(Translator.get("node.name.repeat"));
|
||||||
}
|
}
|
||||||
example.clear();
|
example.clear();
|
||||||
//非默认节点,检查该节点所在分支的总长度,确保不超过阈值
|
|
||||||
if (!StringUtils.equals(apiDebugModule.getId(), ModuleConstants.DEFAULT_NODE_ID)) {
|
|
||||||
this.checkBranchModules(this.getRootNodeId(apiDebugModule), extApiDebugModuleMapper::selectChildrenIdsByParentIds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getRootNodeId(ApiDebugModule module) {
|
private String getRootNodeId(ApiDebugModule module) {
|
||||||
|
|
|
@ -124,11 +124,6 @@ public class ApiDefinitionModuleService extends ModuleTreeService {
|
||||||
throw new MSException(Translator.get("node.name.repeat"));
|
throw new MSException(Translator.get("node.name.repeat"));
|
||||||
}
|
}
|
||||||
example.clear();
|
example.clear();
|
||||||
|
|
||||||
//非默认节点,检查该节点所在分支的总长度,确保不超过阈值
|
|
||||||
if (!StringUtils.equals(module.getId(), ModuleConstants.DEFAULT_NODE_ID)) {
|
|
||||||
this.checkBranchModules(this.getRootNodeId(module), extApiDefinitionModuleMapper::selectChildrenIdsByParentIds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getRootNodeId(ApiDefinitionModule module) {
|
private String getRootNodeId(ApiDefinitionModule module) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.api.service.scenario;
|
||||||
|
|
||||||
import io.metersphere.api.domain.ApiScenario;
|
import io.metersphere.api.domain.ApiScenario;
|
||||||
import io.metersphere.api.domain.ApiScenarioExample;
|
import io.metersphere.api.domain.ApiScenarioExample;
|
||||||
|
import io.metersphere.api.dto.response.ApiScenarioBatchOperationResponse;
|
||||||
import io.metersphere.api.dto.scenario.ApiScenarioAddRequest;
|
import io.metersphere.api.dto.scenario.ApiScenarioAddRequest;
|
||||||
import io.metersphere.api.dto.scenario.ApiScenarioUpdateRequest;
|
import io.metersphere.api.dto.scenario.ApiScenarioUpdateRequest;
|
||||||
import io.metersphere.api.mapper.ApiScenarioMapper;
|
import io.metersphere.api.mapper.ApiScenarioMapper;
|
||||||
|
@ -10,6 +11,7 @@ import io.metersphere.project.mapper.ProjectMapper;
|
||||||
import io.metersphere.sdk.constants.HttpMethodConstants;
|
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||||
import io.metersphere.sdk.util.JSON;
|
import io.metersphere.sdk.util.JSON;
|
||||||
import io.metersphere.sdk.util.Translator;
|
import io.metersphere.sdk.util.Translator;
|
||||||
|
import io.metersphere.system.dto.LogInsertModule;
|
||||||
import io.metersphere.system.dto.builder.LogDTOBuilder;
|
import io.metersphere.system.dto.builder.LogDTOBuilder;
|
||||||
import io.metersphere.system.log.constants.OperationLogModule;
|
import io.metersphere.system.log.constants.OperationLogModule;
|
||||||
import io.metersphere.system.log.constants.OperationLogType;
|
import io.metersphere.system.log.constants.OperationLogType;
|
||||||
|
@ -160,4 +162,43 @@ public class ApiScenarioLogService {
|
||||||
dto.setOriginalValue(JSON.toJSONBytes(apiScenario));
|
dto.setOriginalValue(JSON.toJSONBytes(apiScenario));
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LogDTO restoreLog(String id) {
|
||||||
|
ApiScenario apiScenario = apiScenarioMapper.selectByPrimaryKey(id);
|
||||||
|
LogDTO dto = new LogDTO(
|
||||||
|
apiScenario.getProjectId(),
|
||||||
|
null,
|
||||||
|
apiScenario.getId(),
|
||||||
|
null,
|
||||||
|
OperationLogType.RESTORE.name(),
|
||||||
|
OperationLogModule.API_SCENARIO,
|
||||||
|
apiScenario.getName());
|
||||||
|
dto.setOriginalValue(JSON.toJSONBytes(apiScenario));
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveBatchCopyLog(ApiScenarioBatchOperationResponse response, String projectId, LogInsertModule logInsertModule) {
|
||||||
|
|
||||||
|
Project project = projectMapper.selectByPrimaryKey(projectId);
|
||||||
|
//取出apiTestCases所有的id为新的list
|
||||||
|
List<LogDTO> logs = new ArrayList<>();
|
||||||
|
response.getSuccessData().forEach(item -> {
|
||||||
|
|
||||||
|
LogDTO dto = LogDTOBuilder.builder()
|
||||||
|
.projectId(project.getId())
|
||||||
|
.organizationId(project.getOrganizationId())
|
||||||
|
.type(OperationLogType.COPY.name())
|
||||||
|
.module(OperationLogModule.API_SCENARIO)
|
||||||
|
.method(logInsertModule.getRequestMethod())
|
||||||
|
.path(logInsertModule.getRequestUrl())
|
||||||
|
.sourceId(item.getId())
|
||||||
|
.content(item.getName())
|
||||||
|
.createUser(logInsertModule.getOperator())
|
||||||
|
.build().getLogDTO();
|
||||||
|
dto.setHistory(false);
|
||||||
|
logs.add(dto);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
operationLogService.batchAdd(logs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,11 +111,6 @@ public class ApiScenarioModuleService extends ModuleTreeService {
|
||||||
throw new MSException(Translator.get("node.name.repeat"));
|
throw new MSException(Translator.get("node.name.repeat"));
|
||||||
}
|
}
|
||||||
example.clear();
|
example.clear();
|
||||||
|
|
||||||
//非默认节点,检查该节点所在分支的总长度,确保不超过阈值
|
|
||||||
if (!StringUtils.equals(module.getId(), ModuleConstants.DEFAULT_NODE_ID)) {
|
|
||||||
this.checkBranchModules(this.getRootNodeId(module), extApiScenarioModuleMapper::selectChildrenIdsByParentIds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getRootNodeId(ApiScenarioModule module) {
|
private String getRootNodeId(ApiScenarioModule module) {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import io.metersphere.api.domain.*;
|
||||||
import io.metersphere.api.dto.debug.ApiFileResourceUpdateRequest;
|
import io.metersphere.api.dto.debug.ApiFileResourceUpdateRequest;
|
||||||
import io.metersphere.api.dto.debug.ApiResourceRunRequest;
|
import io.metersphere.api.dto.debug.ApiResourceRunRequest;
|
||||||
import io.metersphere.api.dto.request.MsScenario;
|
import io.metersphere.api.dto.request.MsScenario;
|
||||||
|
import io.metersphere.api.dto.response.ApiScenarioBatchOperationResponse;
|
||||||
import io.metersphere.api.dto.scenario.*;
|
import io.metersphere.api.dto.scenario.*;
|
||||||
import io.metersphere.api.mapper.*;
|
import io.metersphere.api.mapper.*;
|
||||||
import io.metersphere.api.parser.step.StepParser;
|
import io.metersphere.api.parser.step.StepParser;
|
||||||
|
@ -15,6 +16,7 @@ import io.metersphere.api.service.ApiExecuteService;
|
||||||
import io.metersphere.api.service.ApiFileResourceService;
|
import io.metersphere.api.service.ApiFileResourceService;
|
||||||
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.api.utils.ApiScenarioBatchOperationUtils;
|
||||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
import io.metersphere.project.domain.FileMetadata;
|
import io.metersphere.project.domain.FileMetadata;
|
||||||
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
|
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
|
||||||
|
@ -24,24 +26,29 @@ import io.metersphere.project.service.ProjectService;
|
||||||
import io.metersphere.sdk.constants.ApiExecuteRunMode;
|
import io.metersphere.sdk.constants.ApiExecuteRunMode;
|
||||||
import io.metersphere.sdk.constants.ApplicationNumScope;
|
import io.metersphere.sdk.constants.ApplicationNumScope;
|
||||||
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
||||||
|
import io.metersphere.sdk.constants.ModuleConstants;
|
||||||
import io.metersphere.sdk.domain.Environment;
|
import io.metersphere.sdk.domain.Environment;
|
||||||
import io.metersphere.sdk.domain.EnvironmentExample;
|
import io.metersphere.sdk.domain.EnvironmentExample;
|
||||||
import io.metersphere.sdk.domain.EnvironmentGroup;
|
import io.metersphere.sdk.domain.EnvironmentGroup;
|
||||||
import io.metersphere.sdk.domain.EnvironmentGroupExample;
|
import io.metersphere.sdk.domain.EnvironmentGroupExample;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.file.FileCenter;
|
import io.metersphere.sdk.file.FileCenter;
|
||||||
|
import io.metersphere.sdk.file.FileCopyRequest;
|
||||||
import io.metersphere.sdk.file.FileRequest;
|
import io.metersphere.sdk.file.FileRequest;
|
||||||
|
import io.metersphere.sdk.file.MinioRepository;
|
||||||
import io.metersphere.sdk.mapper.EnvironmentGroupMapper;
|
import io.metersphere.sdk.mapper.EnvironmentGroupMapper;
|
||||||
import io.metersphere.sdk.mapper.EnvironmentMapper;
|
import io.metersphere.sdk.mapper.EnvironmentMapper;
|
||||||
import io.metersphere.sdk.util.*;
|
import io.metersphere.sdk.util.*;
|
||||||
|
import io.metersphere.system.dto.LogInsertModule;
|
||||||
import io.metersphere.system.log.constants.OperationLogModule;
|
import io.metersphere.system.log.constants.OperationLogModule;
|
||||||
import io.metersphere.system.service.UserLoginService;
|
import io.metersphere.system.service.UserLoginService;
|
||||||
import io.metersphere.system.uid.IDGenerator;
|
import io.metersphere.system.uid.IDGenerator;
|
||||||
import io.metersphere.system.uid.NumGenerator;
|
import io.metersphere.system.uid.NumGenerator;
|
||||||
import io.metersphere.system.utils.ServiceUtils;
|
import io.metersphere.system.utils.ServiceUtils;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import org.apache.commons.collections.MapUtils;
|
import org.apache.commons.collections.MapUtils;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.collections4.ListUtils;
|
import org.apache.commons.collections4.ListUtils;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -270,13 +277,16 @@ public class ApiScenarioService {
|
||||||
mapper.updateByExampleSelective(updateScenario, example);
|
mapper.updateByExampleSelective(updateScenario, example);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> doSelectIds(ApiScenarioBatchEditRequest request, boolean deleted) {
|
public List<String> doSelectIds(ApiScenarioBatchRequest request, boolean deleted) {
|
||||||
if (request.isSelectAll()) {
|
if (request.isSelectAll()) {
|
||||||
List<String> ids = extApiScenarioMapper.getIds(request, deleted);
|
List<String> ids = extApiScenarioMapper.getIds(request, deleted);
|
||||||
|
if (CollectionUtils.isNotEmpty(request.getSelectIds())) {
|
||||||
|
ids.addAll(request.getSelectIds());
|
||||||
|
}
|
||||||
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
||||||
ids.removeAll(request.getExcludeIds());
|
ids.removeAll(request.getExcludeIds());
|
||||||
}
|
}
|
||||||
return ids;
|
return new ArrayList<>(ids.stream().distinct().toList());
|
||||||
} else {
|
} else {
|
||||||
return request.getSelectIds();
|
return request.getSelectIds();
|
||||||
}
|
}
|
||||||
|
@ -811,6 +821,14 @@ public class ApiScenarioService {
|
||||||
deleteStepDetailByScenarioId(id);
|
deleteStepDetailByScenarioId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void restore(String id) {
|
||||||
|
ApiScenario apiScenario = new ApiScenario();
|
||||||
|
apiScenario.setId(id);
|
||||||
|
apiScenario.setDeleted(false);
|
||||||
|
apiScenarioMapper.updateByPrimaryKeySelective(apiScenario);
|
||||||
|
}
|
||||||
|
|
||||||
public void deleteToGc(String id) {
|
public void deleteToGc(String id) {
|
||||||
checkResourceExist(id);
|
checkResourceExist(id);
|
||||||
ApiScenario apiScenario = new ApiScenario();
|
ApiScenario apiScenario = new ApiScenario();
|
||||||
|
@ -1271,4 +1289,182 @@ public class ApiScenarioService {
|
||||||
private ApiScenarioStep checkStepExist(String id) {
|
private ApiScenarioStep checkStepExist(String id) {
|
||||||
return ServiceUtils.checkResourceExist(apiScenarioStepMapper.selectByPrimaryKey(id), "permission.api_step.name");
|
return ServiceUtils.checkResourceExist(apiScenarioStepMapper.selectByPrimaryKey(id), "permission.api_step.name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ApiScenarioBatchOperationResponse batchCopy(ApiScenarioBatchCopyRequest request, LogInsertModule logInsertModule) {
|
||||||
|
if (!StringUtils.equals(request.getTargetModuleId(), ModuleConstants.DEFAULT_NODE_ID)) {
|
||||||
|
ApiScenarioModule module = apiScenarioModuleMapper.selectByPrimaryKey(request.getTargetModuleId());
|
||||||
|
if (module == null || !StringUtils.equals(module.getProjectId(), request.getProjectId())) {
|
||||||
|
throw new MSException(Translator.get("module.not.exist"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> scenarioIds = doSelectIds(request, false);
|
||||||
|
if (CollectionUtils.isEmpty(scenarioIds)) {
|
||||||
|
return new ApiScenarioBatchOperationResponse();
|
||||||
|
}
|
||||||
|
request.setSelectIds(scenarioIds);
|
||||||
|
ApiScenarioBatchOperationResponse response =
|
||||||
|
ApiScenarioBatchOperationUtils.executeWithBatchOperationResponse(scenarioIds, sublist -> copyAndInsert(sublist, request, logInsertModule.getOperator()));
|
||||||
|
apiScenarioLogService.saveBatchCopyLog(response, request.getProjectId(), logInsertModule);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getScenarioCopyName(String oldName, long oldNum, long newNum, String moduleId) {
|
||||||
|
String newScenarioName = oldName;
|
||||||
|
if (!StringUtils.startsWith(newScenarioName, "copy_")) {
|
||||||
|
newScenarioName = "copy_" + newScenarioName;
|
||||||
|
}
|
||||||
|
// 限制名称长度 (数据库里最大的长度是255,这里判断超过250时截取到200附近)
|
||||||
|
if (newScenarioName.length() > 250) {
|
||||||
|
newScenarioName = newScenarioName.substring(0, 200) + "...";
|
||||||
|
}
|
||||||
|
if (StringUtils.endsWith(newScenarioName, "_" + oldNum)) {
|
||||||
|
newScenarioName = StringUtils.substringBeforeLast(newScenarioName, "_" + oldNum);
|
||||||
|
}
|
||||||
|
newScenarioName = newScenarioName + "_" + newNum;
|
||||||
|
int indexLength = 1;
|
||||||
|
while (true) {
|
||||||
|
ApiScenarioExample example = new ApiScenarioExample();
|
||||||
|
example.createCriteria().andModuleIdEqualTo(moduleId).andNameEqualTo(newScenarioName);
|
||||||
|
if (apiScenarioMapper.countByExample(example) == 0) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
newScenarioName = newScenarioName + "_" + indexLength;
|
||||||
|
indexLength++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newScenarioName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApiScenarioBatchOperationResponse copyAndInsert(List<String> scenarioIds, ApiScenarioBatchCopyRequest request, String operator) {
|
||||||
|
ApiScenarioBatchOperationResponse response = new ApiScenarioBatchOperationResponse();
|
||||||
|
|
||||||
|
ApiScenarioExample example = new ApiScenarioExample();
|
||||||
|
example.createCriteria().andIdIn(scenarioIds);
|
||||||
|
List<ApiScenario> operationList = apiScenarioMapper.selectByExample(example);
|
||||||
|
List<String> operationIdList = operationList.stream().map(ApiScenario::getId).collect(Collectors.toList());
|
||||||
|
|
||||||
|
Map<String, ApiScenarioBlob> apiScenarioBlobMap = this.selectBlobByScenarioIds(operationIdList).stream().collect(Collectors.toMap(ApiScenarioBlob::getId, Function.identity()));
|
||||||
|
Map<String, List<ApiFileResource>> apiFileResourceMap = this.selectApiFileResourceByScenarioIds(operationIdList).stream().collect(Collectors.groupingBy(ApiFileResource::getResourceId));
|
||||||
|
Map<String, List<ApiScenarioStep>> apiScenarioStepMap = this.selectStepByScenarioIds(operationIdList).stream().collect(Collectors.groupingBy(ApiScenarioStep::getScenarioId));
|
||||||
|
Map<String, ApiScenarioStepBlob> apiScenarioStepBlobMap = this.selectStepBlobByScenarioIds(operationIdList).stream().collect(Collectors.toMap(ApiScenarioStepBlob::getId, Function.identity()));
|
||||||
|
|
||||||
|
List<ApiScenario> insertApiScenarioList = new ArrayList<>();
|
||||||
|
List<ApiScenarioBlob> insertApiScenarioBlobList = new ArrayList<>();
|
||||||
|
List<ApiScenarioStep> insertApiScenarioStepList = new ArrayList<>();
|
||||||
|
List<ApiScenarioStepBlob> insertApiScenarioStepBlobList = new ArrayList<>();
|
||||||
|
List<ApiFileResource> insertApiFileResourceList = new ArrayList<>();
|
||||||
|
|
||||||
|
MinioRepository minioRepository = CommonBeanFactory.getBean(MinioRepository.class);
|
||||||
|
|
||||||
|
operationList.forEach(apiScenario -> {
|
||||||
|
ApiScenario copyScenario = new ApiScenario();
|
||||||
|
BeanUtils.copyBean(copyScenario, apiScenario);
|
||||||
|
copyScenario.setId(IDGenerator.nextStr());
|
||||||
|
copyScenario.setNum(getNextNum(copyScenario.getProjectId()));
|
||||||
|
copyScenario.setPos(getNextOrder(copyScenario.getProjectId()));
|
||||||
|
copyScenario.setModuleId(request.getTargetModuleId());
|
||||||
|
copyScenario.setName(this.getScenarioCopyName(copyScenario.getName(), apiScenario.getNum(), copyScenario.getNum(), request.getTargetModuleId()));
|
||||||
|
copyScenario.setCreateUser(operator);
|
||||||
|
copyScenario.setUpdateUser(operator);
|
||||||
|
copyScenario.setCreateTime(System.currentTimeMillis());
|
||||||
|
copyScenario.setUpdateTime(System.currentTimeMillis());
|
||||||
|
copyScenario.setRefId(copyScenario.getId());
|
||||||
|
copyScenario.setLastReportStatus(StringUtils.EMPTY);
|
||||||
|
copyScenario.setRequestPassRate("0");
|
||||||
|
|
||||||
|
insertApiScenarioList.add(copyScenario);
|
||||||
|
|
||||||
|
ApiScenarioBlob apiScenarioBlob = apiScenarioBlobMap.get(apiScenario.getId());
|
||||||
|
if (apiScenarioBlob != null) {
|
||||||
|
ApiScenarioBlob copyApiScenarioBlob = new ApiScenarioBlob();
|
||||||
|
BeanUtils.copyBean(copyApiScenarioBlob, apiScenarioBlob);
|
||||||
|
copyApiScenarioBlob.setId(copyScenario.getId());
|
||||||
|
insertApiScenarioBlobList.add(copyApiScenarioBlob);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ApiFileResource> apiFileResourceList = apiFileResourceMap.get(apiScenario.getId());
|
||||||
|
if (CollectionUtils.isNotEmpty(apiFileResourceList)) {
|
||||||
|
apiFileResourceList.forEach(apiFileResource -> {
|
||||||
|
ApiFileResource copyApiFileResource = new ApiFileResource();
|
||||||
|
BeanUtils.copyBean(copyApiFileResource, apiFileResource);
|
||||||
|
copyApiFileResource.setResourceId(copyScenario.getId());
|
||||||
|
insertApiFileResourceList.add(copyApiFileResource);
|
||||||
|
|
||||||
|
try {
|
||||||
|
FileCopyRequest fileCopyRequest = new FileCopyRequest();
|
||||||
|
fileCopyRequest.setCopyFolder(DefaultRepositoryDir.getApiScenarioDir(apiScenario.getProjectId(), apiScenario.getId()));
|
||||||
|
fileCopyRequest.setCopyfileName(copyApiFileResource.getFileId());
|
||||||
|
fileCopyRequest.setFileName(copyApiFileResource.getFileId());
|
||||||
|
fileCopyRequest.setFolder(DefaultRepositoryDir.getApiScenarioDir(copyScenario.getProjectId(), copyScenario.getId()));
|
||||||
|
minioRepository.copyFile(fileCopyRequest);
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ApiScenarioStep> stepList = apiScenarioStepMap.get(apiScenario.getId());
|
||||||
|
if (CollectionUtils.isNotEmpty(stepList)) {
|
||||||
|
stepList.forEach(step -> {
|
||||||
|
ApiScenarioStep copyStep = new ApiScenarioStep();
|
||||||
|
BeanUtils.copyBean(copyStep, step);
|
||||||
|
copyStep.setId(IDGenerator.nextStr());
|
||||||
|
copyStep.setScenarioId(copyScenario.getId());
|
||||||
|
insertApiScenarioStepList.add(copyStep);
|
||||||
|
|
||||||
|
//todo 刚の没提交的CSV关联表
|
||||||
|
|
||||||
|
ApiScenarioStepBlob stepBlob = apiScenarioStepBlobMap.get(step.getId());
|
||||||
|
if (stepBlob != null) {
|
||||||
|
ApiScenarioStepBlob copyStepBlob = new ApiScenarioStepBlob();
|
||||||
|
BeanUtils.copyBean(copyStepBlob, stepBlob);
|
||||||
|
copyStepBlob.setId(copyStep.getId());
|
||||||
|
copyStepBlob.setScenarioId(copyScenario.getId());
|
||||||
|
insertApiScenarioStepBlobList.add(copyStepBlob);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
response.addSuccessData(copyScenario.getId(), copyScenario.getNum(), copyScenario.getName());
|
||||||
|
});
|
||||||
|
|
||||||
|
response.setSuccess(apiScenarioMapper.batchInsert(insertApiScenarioList));
|
||||||
|
if (CollectionUtils.isNotEmpty(insertApiScenarioBlobList)) {
|
||||||
|
apiScenarioBlobMapper.batchInsert(insertApiScenarioBlobList);
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(insertApiScenarioStepList)) {
|
||||||
|
apiScenarioStepMapper.batchInsert(insertApiScenarioStepList);
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(insertApiScenarioStepBlobList)) {
|
||||||
|
apiScenarioStepBlobMapper.batchInsert(insertApiScenarioStepBlobList);
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(insertApiFileResourceList)) {
|
||||||
|
apiFileResourceService.batchInsert(insertApiFileResourceList);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<ApiScenarioBlob> selectBlobByScenarioIds(@NotEmpty List<String> scenarioIds) {
|
||||||
|
ApiScenarioBlobExample example = new ApiScenarioBlobExample();
|
||||||
|
example.createCriteria().andIdIn(scenarioIds);
|
||||||
|
return apiScenarioBlobMapper.selectByExampleWithBLOBs(example);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ApiScenarioStep> selectStepByScenarioIds(@NotEmpty List<String> scenarioIds) {
|
||||||
|
ApiScenarioStepExample example = new ApiScenarioStepExample();
|
||||||
|
example.createCriteria().andScenarioIdIn(scenarioIds);
|
||||||
|
return apiScenarioStepMapper.selectByExample(example);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ApiFileResource> selectApiFileResourceByScenarioIds(@NotEmpty List<String> scenarioIds) {
|
||||||
|
return apiFileResourceService.selectByApiScenarioId(scenarioIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ApiScenarioStepBlob> selectStepBlobByScenarioIds(@NotEmpty List<String> scenarioIds) {
|
||||||
|
ApiScenarioStepBlobExample example = new ApiScenarioStepBlobExample();
|
||||||
|
example.createCriteria().andScenarioIdIn(scenarioIds);
|
||||||
|
return apiScenarioStepBlobMapper.selectByExampleWithBLOBs(example);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package io.metersphere.api.utils;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.response.ApiScenarioBatchOperationResponse;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
//场景批量操作工具类
|
||||||
|
public class ApiScenarioBatchOperationUtils {
|
||||||
|
private static int MAX_OPERATION_SIZE = 100;
|
||||||
|
|
||||||
|
public static <T> ApiScenarioBatchOperationResponse executeWithBatchOperationResponse(List<T> totalList, Function<List<T>, ApiScenarioBatchOperationResponse> subFunc) {
|
||||||
|
ApiScenarioBatchOperationResponse response = new ApiScenarioBatchOperationResponse();
|
||||||
|
List<T> operationList = new ArrayList<>(totalList);
|
||||||
|
while (operationList.size() > 100) {
|
||||||
|
List<T> subList = operationList.subList(0, MAX_OPERATION_SIZE);
|
||||||
|
response.merge(
|
||||||
|
subFunc.apply(subList));
|
||||||
|
subList.clear();
|
||||||
|
operationList.removeAll(subList);
|
||||||
|
}
|
||||||
|
if (!operationList.isEmpty()) {
|
||||||
|
response.merge(
|
||||||
|
subFunc.apply(operationList));
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
|
@ -315,9 +315,6 @@ public class ApiDebugModuleControllerTests extends BaseTest {
|
||||||
//到20换下一层级
|
//到20换下一层级
|
||||||
parentId = holder.getData().toString();
|
parentId = holder.getData().toString();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//测试超过500会报错
|
|
||||||
this.requestPost(URL_MODULE_ADD, perfRequest).andExpect(status().is5xxServerError());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
treeNodes = this.getDebugModuleTreeNode();
|
treeNodes = this.getDebugModuleTreeNode();
|
||||||
|
|
|
@ -347,9 +347,6 @@ public class ApiDefinitionModuleControllerTests extends BaseTest {
|
||||||
//到20换下一层级
|
//到20换下一层级
|
||||||
parentId = holder.getData().toString();
|
parentId = holder.getData().toString();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//测试超过500会报错
|
|
||||||
this.requestPost(URL_MODULE_ADD, perfRequest).andExpect(status().is5xxServerError());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
treeNodes = this.getModuleTreeNode();
|
treeNodes = this.getModuleTreeNode();
|
||||||
|
|
|
@ -10,8 +10,11 @@ import io.metersphere.api.dto.definition.ApiTestCaseAddRequest;
|
||||||
import io.metersphere.api.dto.request.assertion.MsAssertionConfig;
|
import io.metersphere.api.dto.request.assertion.MsAssertionConfig;
|
||||||
import io.metersphere.api.dto.request.assertion.MsScriptAssertion;
|
import io.metersphere.api.dto.request.assertion.MsScriptAssertion;
|
||||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||||
|
import io.metersphere.api.dto.response.ApiScenarioBatchOperationResponse;
|
||||||
|
import io.metersphere.api.dto.response.OperationDataInfo;
|
||||||
import io.metersphere.api.dto.scenario.*;
|
import io.metersphere.api.dto.scenario.*;
|
||||||
import io.metersphere.api.mapper.*;
|
import io.metersphere.api.mapper.*;
|
||||||
|
import io.metersphere.api.service.ApiScenarioBatchOperationTestService;
|
||||||
import io.metersphere.api.service.BaseResourcePoolTestService;
|
import io.metersphere.api.service.BaseResourcePoolTestService;
|
||||||
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;
|
||||||
|
@ -22,6 +25,7 @@ import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
|
||||||
import io.metersphere.project.service.FileMetadataService;
|
import io.metersphere.project.service.FileMetadataService;
|
||||||
import io.metersphere.sdk.constants.ApplicationNumScope;
|
import io.metersphere.sdk.constants.ApplicationNumScope;
|
||||||
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
||||||
|
import io.metersphere.sdk.constants.ModuleConstants;
|
||||||
import io.metersphere.sdk.constants.PermissionConstants;
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
import io.metersphere.sdk.domain.Environment;
|
import io.metersphere.sdk.domain.Environment;
|
||||||
import io.metersphere.sdk.domain.EnvironmentExample;
|
import io.metersphere.sdk.domain.EnvironmentExample;
|
||||||
|
@ -49,6 +53,7 @@ import org.springframework.test.web.servlet.MvcResult;
|
||||||
import org.springframework.test.web.servlet.ResultMatcher;
|
import org.springframework.test.web.servlet.ResultMatcher;
|
||||||
import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils;
|
import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -62,7 +67,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||||
public class ApiScenarioControllerTests extends BaseTest {
|
public class ApiScenarioControllerTests extends BaseTest {
|
||||||
private static final String BASE_PATH = "/api/scenario/";
|
private static final String BASE_PATH = "/api/scenario/";
|
||||||
private static final String TRASH_PAGE = "trash/page";
|
private static final String TRASH_PAGE = "trash/page";
|
||||||
private static final String BATCH_EDIT = "batch/edit";
|
private static final String BATCH_EDIT = "batch-operation/edit";
|
||||||
private static final String FOLLOW = "follow/";
|
private static final String FOLLOW = "follow/";
|
||||||
protected static final String UPLOAD_TEMP_FILE = "upload/temp/file";
|
protected static final String UPLOAD_TEMP_FILE = "upload/temp/file";
|
||||||
protected static final String DELETE_TO_GC = "delete-to-gc/{0}";
|
protected static final String DELETE_TO_GC = "delete-to-gc/{0}";
|
||||||
|
@ -71,6 +76,9 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
private static final String UPDATE_STATUS = "update-status";
|
private static final String UPDATE_STATUS = "update-status";
|
||||||
private static final String UPDATE_PRIORITY = "update-priority";
|
private static final String UPDATE_PRIORITY = "update-priority";
|
||||||
|
|
||||||
|
private static final Map<String, String> BATCH_OPERATION_SCENARIO_MODULE_MAP = new HashMap<>();
|
||||||
|
private static final List<String> BATCH_OPERATION_SCENARIO_ID = new ArrayList<>();
|
||||||
|
|
||||||
private static final ResultMatcher ERROR_REQUEST_MATCHER = status().is5xxServerError();
|
private static final ResultMatcher ERROR_REQUEST_MATCHER = status().is5xxServerError();
|
||||||
@Resource
|
@Resource
|
||||||
private ApiScenarioMapper apiScenarioMapper;
|
private ApiScenarioMapper apiScenarioMapper;
|
||||||
|
@ -97,6 +105,8 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
@Resource
|
@Resource
|
||||||
private ApiTestCaseService apiTestCaseService;
|
private ApiTestCaseService apiTestCaseService;
|
||||||
@Resource
|
@Resource
|
||||||
|
private ApiScenarioBatchOperationTestService apiScenarioBatchOperationTestService;
|
||||||
|
@Resource
|
||||||
private BaseResourcePoolTestService baseResourcePoolTestService;
|
private BaseResourcePoolTestService baseResourcePoolTestService;
|
||||||
@Resource
|
@Resource
|
||||||
private FileMetadataService fileMetadataService;
|
private FileMetadataService fileMetadataService;
|
||||||
|
@ -827,7 +837,7 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
requestPostAndReturn(BATCH_EDIT, request);
|
requestPostAndReturn(BATCH_EDIT, request);
|
||||||
//判断数据的优先级是不是P3
|
//判断数据的优先级是不是P3
|
||||||
example.clear();
|
example.clear();
|
||||||
example.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID).andDeletedEqualTo(false);
|
example.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID).andDeletedEqualTo(false).andModuleIdEqualTo("scenario-moduleId");
|
||||||
List<ApiScenario> apiScenarios = apiScenarioMapper.selectByExample(example);
|
List<ApiScenario> apiScenarios = apiScenarioMapper.selectByExample(example);
|
||||||
|
|
||||||
apiScenarios.forEach(apiTestCase -> Assertions.assertEquals(apiTestCase.getPriority(), "P3"));
|
apiScenarios.forEach(apiTestCase -> Assertions.assertEquals(apiTestCase.getPriority(), "P3"));
|
||||||
|
@ -947,4 +957,302 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
//校验权限
|
//校验权限
|
||||||
requestPostPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_READ, TRASH_PAGE, pageRequest);
|
requestPostPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_READ, TRASH_PAGE, pageRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
要价格与批量测试的数据结构:
|
||||||
|
建国批量测试场景模块_1 ->50条数据 有标签和环境组
|
||||||
|
|
|
||||||
|
|
|
||||||
|
建国批量测试场景模块_51 ->50条数据 有环境
|
||||||
|
|
|
||||||
|
|
|
||||||
|
建国批量测试场景模块_101 ->50条数据 有blob
|
||||||
|
|
|
||||||
|
|
|
||||||
|
建国批量测试场景模块_151 ->50条数据 有step
|
||||||
|
|
|
||||||
|
|
|
||||||
|
建国批量测试场景模块_201 ->50条数据 有step和blob
|
||||||
|
|
|
||||||
|
|
|
||||||
|
建国批量测试场景模块_251 ->250条数据 有文件
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(20)
|
||||||
|
public void batchCopy() throws Exception {
|
||||||
|
String testUrl = "/batch-operation/copy";
|
||||||
|
if (CollectionUtils.isEmpty(BATCH_OPERATION_SCENARIO_ID)) {
|
||||||
|
this.batchCreateScenarios();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
正例测试 1.超过300条的批量复制
|
||||||
|
2.移动到新模块
|
||||||
|
|
||||||
|
测试数据:使用建国批量测试场景模块_200模块为查询条件,和建国批量测试场景模块_250里的所有id,复制到 【建国批量测试场景模块_1】中
|
||||||
|
*/
|
||||||
|
ApiScenarioBatchCopyRequest request = new ApiScenarioBatchCopyRequest();
|
||||||
|
request.setSelectIds(BATCH_OPERATION_SCENARIO_ID.subList(250, 500));
|
||||||
|
request.setModuleIds(List.of(BATCH_OPERATION_SCENARIO_MODULE_MAP.get("建国批量测试场景模块_201")));
|
||||||
|
request.setTargetModuleId(BATCH_OPERATION_SCENARIO_MODULE_MAP.get("建国批量测试场景模块_1"));
|
||||||
|
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||||
|
request.setSelectAll(true);
|
||||||
|
|
||||||
|
//先测试一下没有开启模块时接口能否使用
|
||||||
|
apiScenarioBatchOperationTestService.removeApiModule(DEFAULT_PROJECT_ID);
|
||||||
|
this.requestPost(testUrl, request).andExpect(status().is5xxServerError());
|
||||||
|
//恢复
|
||||||
|
apiScenarioBatchOperationTestService.resetProjectModule(DEFAULT_PROJECT_ID);
|
||||||
|
|
||||||
|
MvcResult result = this.requestPostAndReturn(testUrl, request);
|
||||||
|
ResultHolder resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class);
|
||||||
|
ApiScenarioBatchOperationResponse resultResponse = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), ApiScenarioBatchOperationResponse.class);
|
||||||
|
//检查返回值
|
||||||
|
Assertions.assertEquals(resultResponse.getSuccess(), 300);
|
||||||
|
//数据库级别的检查
|
||||||
|
apiScenarioBatchOperationTestService.checkBatchCopy(BATCH_OPERATION_SCENARIO_ID.subList(200, 500), resultResponse.getSuccessData().stream().map(OperationDataInfo::getId).toList(), 50, request);
|
||||||
|
|
||||||
|
// 2.没有数据
|
||||||
|
request = new ApiScenarioBatchCopyRequest();
|
||||||
|
request.setTargetModuleId(BATCH_OPERATION_SCENARIO_MODULE_MAP.get("建国批量测试场景模块_1"));
|
||||||
|
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||||
|
result = this.requestPostAndReturn(testUrl, request);
|
||||||
|
resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class);
|
||||||
|
resultResponse = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), ApiScenarioBatchOperationResponse.class);
|
||||||
|
//检查返回值
|
||||||
|
Assertions.assertEquals(resultResponse.getSuccess(), 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
正例测试
|
||||||
|
3.移动到当前模块
|
||||||
|
4.移动到新模块
|
||||||
|
5.移动的场景中,有名字以copy开头的。 不会重复生成copy_copy_
|
||||||
|
6.要移动的场景中,有名字以"_"+自身num结尾的
|
||||||
|
|
||||||
|
测试数据:建国批量测试场景模块_1中所有的数据(350条)再复制到当前数据里
|
||||||
|
*/
|
||||||
|
ApiScenarioExample example = new ApiScenarioExample();
|
||||||
|
example.createCriteria().andModuleIdEqualTo(BATCH_OPERATION_SCENARIO_MODULE_MAP.get("建国批量测试场景模块_1"));
|
||||||
|
List<ApiScenario> reCopyScenarios = apiScenarioMapper.selectByExample(example);
|
||||||
|
|
||||||
|
|
||||||
|
request = new ApiScenarioBatchCopyRequest();
|
||||||
|
request.setModuleIds(List.of(BATCH_OPERATION_SCENARIO_MODULE_MAP.get("建国批量测试场景模块_1")));
|
||||||
|
request.setTargetModuleId(BATCH_OPERATION_SCENARIO_MODULE_MAP.get("建国批量测试场景模块_1"));
|
||||||
|
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||||
|
request.setSelectAll(true);
|
||||||
|
|
||||||
|
result = this.requestPostAndReturn(testUrl, request);
|
||||||
|
resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class);
|
||||||
|
resultResponse = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), ApiScenarioBatchOperationResponse.class);
|
||||||
|
//检查返回值
|
||||||
|
Assertions.assertEquals(resultResponse.getSuccess(), reCopyScenarios.size());
|
||||||
|
//数据库级别的检查
|
||||||
|
apiScenarioBatchOperationTestService.checkBatchCopy(new ArrayList<>(reCopyScenarios.stream().map(ApiScenario::getId).toList()), resultResponse.getSuccessData().stream().map(OperationDataInfo::getId).toList(), 350, request);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
正例测试
|
||||||
|
5.移动的场景中,有名字长度在250以上的
|
||||||
|
|
||||||
|
测试数据:【建国批量测试场景模块_101】的用例修改名字长度为255. 然后复制到【建国批量测试场景模块_101】中
|
||||||
|
*/
|
||||||
|
apiScenarioBatchOperationTestService.updateNameToTestByModuleId(BATCH_OPERATION_SCENARIO_MODULE_MAP.get("建国批量测试场景模块_101"));
|
||||||
|
|
||||||
|
request = new ApiScenarioBatchCopyRequest();
|
||||||
|
request.setModuleIds(List.of(BATCH_OPERATION_SCENARIO_MODULE_MAP.get("建国批量测试场景模块_101")));
|
||||||
|
request.setTargetModuleId(BATCH_OPERATION_SCENARIO_MODULE_MAP.get("建国批量测试场景模块_101"));
|
||||||
|
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||||
|
request.setSelectAll(true);
|
||||||
|
|
||||||
|
result = this.requestPostAndReturn(testUrl, request);
|
||||||
|
resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class);
|
||||||
|
resultResponse = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), ApiScenarioBatchOperationResponse.class);
|
||||||
|
//检查返回值
|
||||||
|
Assertions.assertEquals(resultResponse.getSuccess(), 50);
|
||||||
|
//数据库级别的检查
|
||||||
|
apiScenarioBatchOperationTestService.checkBatchCopy(BATCH_OPERATION_SCENARIO_ID.subList(100, 150), resultResponse.getSuccessData().stream().map(OperationDataInfo::getId).toList(), 50, request);
|
||||||
|
|
||||||
|
//1.反例测试 ->模块不存在
|
||||||
|
request = new ApiScenarioBatchCopyRequest();
|
||||||
|
request.setTargetModuleId(IDGenerator.nextStr());
|
||||||
|
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||||
|
request.setSelectAll(true);
|
||||||
|
this.requestPost(testUrl, request).andExpect(status().is5xxServerError());
|
||||||
|
//2.反例测试 ->要移动的模块是别的项目下的
|
||||||
|
String otherProjectModuleId = this.createModule(500, IDGenerator.nextStr(), ModuleConstants.ROOT_NODE_PARENT_ID);
|
||||||
|
request = new ApiScenarioBatchCopyRequest();
|
||||||
|
request.setTargetModuleId(otherProjectModuleId);
|
||||||
|
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||||
|
request.setSelectAll(true);
|
||||||
|
this.requestPost(testUrl, request).andExpect(status().is5xxServerError());
|
||||||
|
//3.反例测试 ->参数校验:项目ID为空 模块ID为空
|
||||||
|
request = new ApiScenarioBatchCopyRequest();
|
||||||
|
request.setTargetModuleId(otherProjectModuleId);
|
||||||
|
this.requestPost(testUrl, request).andExpect(status().isBadRequest());
|
||||||
|
|
||||||
|
request = new ApiScenarioBatchCopyRequest();
|
||||||
|
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||||
|
this.requestPost(testUrl, request).andExpect(status().isBadRequest());
|
||||||
|
}
|
||||||
|
|
||||||
|
//30开始是关于删除和恢复的
|
||||||
|
@Test
|
||||||
|
@Order(30)
|
||||||
|
public void restore() throws Exception {
|
||||||
|
if (CollectionUtils.isEmpty(BATCH_OPERATION_SCENARIO_ID)) {
|
||||||
|
this.batchCreateScenarios();
|
||||||
|
}
|
||||||
|
this.requestGetWithOk("/restore/" + BATCH_OPERATION_SCENARIO_ID.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createModule(int i, String projectId, String parentId) {
|
||||||
|
ApiScenarioModule apiScenarioModule = new ApiScenarioModule();
|
||||||
|
apiScenarioModule.setId(IDGenerator.nextStr());
|
||||||
|
apiScenarioModule.setProjectId(projectId);
|
||||||
|
apiScenarioModule.setName("建国批量测试场景模块_" + i);
|
||||||
|
apiScenarioModule.setCreateTime(System.currentTimeMillis());
|
||||||
|
apiScenarioModule.setUpdateTime(System.currentTimeMillis());
|
||||||
|
apiScenarioModule.setCreateUser("admin");
|
||||||
|
apiScenarioModule.setUpdateUser("admin");
|
||||||
|
apiScenarioModule.setParentId(parentId);
|
||||||
|
apiScenarioModule.setPos(i * 64L);
|
||||||
|
apiScenarioModuleMapper.insertSelective(apiScenarioModule);
|
||||||
|
return apiScenarioModule.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
创建模块树。结构:
|
||||||
|
建国批量测试场景模块_1 ->50条数据 有标签和环境组
|
||||||
|
|
|
||||||
|
|
|
||||||
|
建国批量测试场景模块_51 ->50条数据 有环境
|
||||||
|
|
|
||||||
|
|
|
||||||
|
建国批量测试场景模块_101 ->50条数据 有blob
|
||||||
|
|
|
||||||
|
|
|
||||||
|
建国批量测试场景模块_151 ->50条数据 有step
|
||||||
|
|
|
||||||
|
|
|
||||||
|
建国批量测试场景模块_201 ->50条数据 有step和blob
|
||||||
|
|
|
||||||
|
|
|
||||||
|
建国批量测试场景模块_251 ->250条数据 有文件
|
||||||
|
*/
|
||||||
|
private void batchCreateScenarios() {
|
||||||
|
int size = 500;
|
||||||
|
String moduleId = null;
|
||||||
|
EnvironmentExample environmentExample = new EnvironmentExample();
|
||||||
|
environmentExample.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID).andMockEqualTo(true);
|
||||||
|
List<Environment> environments = environmentMapper.selectByExample(environmentExample);
|
||||||
|
String parentModuleId = ModuleConstants.ROOT_NODE_PARENT_ID;
|
||||||
|
|
||||||
|
for (int i = 1; i <= size; i++) {
|
||||||
|
if (moduleId == null) {
|
||||||
|
moduleId = createModule(i, DEFAULT_PROJECT_ID, parentModuleId);
|
||||||
|
BATCH_OPERATION_SCENARIO_MODULE_MAP.put("建国批量测试场景模块_" + i, moduleId);
|
||||||
|
} else if (i == 51) {
|
||||||
|
moduleId = createModule(i, DEFAULT_PROJECT_ID, parentModuleId);
|
||||||
|
BATCH_OPERATION_SCENARIO_MODULE_MAP.put("建国批量测试场景模块_" + i, moduleId);
|
||||||
|
} else if (i == 101) {
|
||||||
|
parentModuleId = moduleId;
|
||||||
|
moduleId = createModule(i, DEFAULT_PROJECT_ID, parentModuleId);
|
||||||
|
BATCH_OPERATION_SCENARIO_MODULE_MAP.put("建国批量测试场景模块_" + i, moduleId);
|
||||||
|
} else if (i == 151) {
|
||||||
|
parentModuleId = moduleId;
|
||||||
|
moduleId = createModule(i, DEFAULT_PROJECT_ID, parentModuleId);
|
||||||
|
BATCH_OPERATION_SCENARIO_MODULE_MAP.put("建国批量测试场景模块_" + i, moduleId);
|
||||||
|
} else if (i == 201) {
|
||||||
|
parentModuleId = moduleId;
|
||||||
|
moduleId = createModule(i, DEFAULT_PROJECT_ID, parentModuleId);
|
||||||
|
BATCH_OPERATION_SCENARIO_MODULE_MAP.put("建国批量测试场景模块_" + i, moduleId);
|
||||||
|
} else if (i == 251) {
|
||||||
|
//本次创建的模块和 _200 属于同一级
|
||||||
|
moduleId = createModule(i, DEFAULT_PROJECT_ID, parentModuleId);
|
||||||
|
BATCH_OPERATION_SCENARIO_MODULE_MAP.put("建国批量测试场景模块_" + i, moduleId);
|
||||||
|
}
|
||||||
|
ApiScenario apiScenario = new ApiScenario();
|
||||||
|
apiScenario.setId(IDGenerator.nextStr());
|
||||||
|
apiScenario.setProjectId(DEFAULT_PROJECT_ID);
|
||||||
|
apiScenario.setNum(NumGenerator.nextNum(DEFAULT_PROJECT_ID, ApplicationNumScope.API_SCENARIO));
|
||||||
|
apiScenario.setName(StringUtils.join("建国批量测试接口场景-", apiScenario.getId()));
|
||||||
|
apiScenario.setModuleId(moduleId);
|
||||||
|
apiScenario.setStatus("未规划");
|
||||||
|
apiScenario.setPos(i * 64L);
|
||||||
|
apiScenario.setPriority("P0");
|
||||||
|
apiScenario.setLatest(true);
|
||||||
|
apiScenario.setVersionId("1.0");
|
||||||
|
apiScenario.setRefId(apiScenario.getId());
|
||||||
|
apiScenario.setCreateTime(System.currentTimeMillis());
|
||||||
|
apiScenario.setUpdateTime(System.currentTimeMillis());
|
||||||
|
apiScenario.setCreateUser("admin");
|
||||||
|
apiScenario.setUpdateUser("admin");
|
||||||
|
if (i <= 50) {
|
||||||
|
apiScenario.setTags(new ArrayList<>(List.of("tag1", "tag2")));
|
||||||
|
apiScenario.setGrouped(true);
|
||||||
|
apiScenario.setEnvironmentId("scenario-environment-group-id");
|
||||||
|
} else if (i <= 100) {
|
||||||
|
apiScenario.setGrouped(false);
|
||||||
|
apiScenario.setEnvironmentId(environments.get(0).getId());
|
||||||
|
} else if (i <= 150) {
|
||||||
|
//带blob
|
||||||
|
ApiScenarioBlob apiScenarioBlob = new ApiScenarioBlob();
|
||||||
|
apiScenarioBlob.setId(apiScenario.getId());
|
||||||
|
apiScenarioBlobMapper.insertSelective(apiScenarioBlob);
|
||||||
|
} else if (i <= 200) {
|
||||||
|
ApiScenarioStep step1 = new ApiScenarioStep();
|
||||||
|
step1.setId(IDGenerator.nextStr());
|
||||||
|
step1.setScenarioId(apiScenario.getId());
|
||||||
|
step1.setName(apiScenario.getName() + "_" + IDGenerator.nextStr());
|
||||||
|
step1.setSort(0L);
|
||||||
|
step1.setEnable(true);
|
||||||
|
apiScenarioStepMapper.insertSelective(step1);
|
||||||
|
|
||||||
|
ApiScenarioStep step2 = new ApiScenarioStep();
|
||||||
|
step2.setId(IDGenerator.nextStr());
|
||||||
|
step2.setScenarioId(apiScenario.getId());
|
||||||
|
step2.setName(apiScenario.getName() + "_" + IDGenerator.nextStr());
|
||||||
|
step2.setSort(1L);
|
||||||
|
step1.setEnable(false);
|
||||||
|
apiScenarioStepMapper.insertSelective(step2);
|
||||||
|
} else if (i <= 250) {
|
||||||
|
//带步骤和详情的
|
||||||
|
ApiScenarioStep step1 = new ApiScenarioStep();
|
||||||
|
step1.setId(IDGenerator.nextStr());
|
||||||
|
step1.setScenarioId(apiScenario.getId());
|
||||||
|
step1.setName(apiScenario.getName() + "_" + IDGenerator.nextStr());
|
||||||
|
step1.setSort(0L);
|
||||||
|
step1.setEnable(true);
|
||||||
|
apiScenarioStepMapper.insertSelective(step1);
|
||||||
|
ApiScenarioStepBlob step1Blob = new ApiScenarioStepBlob();
|
||||||
|
step1Blob.setId(step1.getId());
|
||||||
|
step1Blob.setScenarioId(apiScenario.getId());
|
||||||
|
apiScenarioStepBlobMapper.insertSelective(step1Blob);
|
||||||
|
|
||||||
|
ApiScenarioStep step2 = new ApiScenarioStep();
|
||||||
|
step2.setId(IDGenerator.nextStr());
|
||||||
|
step2.setScenarioId(apiScenario.getId());
|
||||||
|
step2.setName(apiScenario.getName() + "_" + IDGenerator.nextStr());
|
||||||
|
step2.setSort(1L);
|
||||||
|
step1.setEnable(false);
|
||||||
|
apiScenarioStepMapper.insertSelective(step2);
|
||||||
|
ApiScenarioStepBlob step2Blob = new ApiScenarioStepBlob();
|
||||||
|
step2Blob.setId(step2.getId());
|
||||||
|
step2Blob.setScenarioId(apiScenario.getId());
|
||||||
|
apiScenarioStepBlobMapper.insertSelective(step2Blob);
|
||||||
|
} else if (i <= 300) {
|
||||||
|
//带文件的
|
||||||
|
ApiFileResource apiFileResource = new ApiFileResource();
|
||||||
|
apiFileResource.setResourceId(apiScenario.getId());
|
||||||
|
apiFileResource.setFileId(IDGenerator.nextStr());
|
||||||
|
apiFileResource.setFileName("test");
|
||||||
|
apiFileResource.setResourceType("API_SCENARIO");
|
||||||
|
apiFileResource.setCreateTime(System.currentTimeMillis());
|
||||||
|
apiFileResource.setProjectId(apiScenario.getProjectId());
|
||||||
|
}
|
||||||
|
apiScenarioMapper.insertSelective(apiScenario);
|
||||||
|
BATCH_OPERATION_SCENARIO_ID.add(apiScenario.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -303,9 +303,6 @@ public class ApiScenarioModuleControllerTests extends BaseTest {
|
||||||
//到20换下一层级
|
//到20换下一层级
|
||||||
parentId = holder.getData().toString();
|
parentId = holder.getData().toString();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//测试超过500会报错
|
|
||||||
this.requestPost(URL_MODULE_ADD, perfRequest).andExpect(status().is5xxServerError());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
treeNodes = this.getModuleTreeNode();
|
treeNodes = this.getModuleTreeNode();
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
package io.metersphere.api.service;
|
||||||
|
|
||||||
|
import io.metersphere.api.domain.*;
|
||||||
|
import io.metersphere.api.dto.scenario.ApiScenarioBatchCopyRequest;
|
||||||
|
import io.metersphere.api.mapper.*;
|
||||||
|
import io.metersphere.project.domain.Project;
|
||||||
|
import io.metersphere.project.mapper.ProjectMapper;
|
||||||
|
import io.metersphere.sdk.util.JSON;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
public class ApiScenarioBatchOperationTestService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ApiScenarioMapper apiScenarioMapper;
|
||||||
|
@Resource
|
||||||
|
private ApiScenarioBlobMapper apiScenarioBlobMapper;
|
||||||
|
@Resource
|
||||||
|
private ApiScenarioStepMapper apiScenarioStepMapper;
|
||||||
|
@Resource
|
||||||
|
private ApiScenarioStepBlobMapper apiScenarioStepBlobMapper;
|
||||||
|
@Resource
|
||||||
|
private ApiFileResourceMapper apiFileResourceMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ProjectMapper projectMapper;
|
||||||
|
|
||||||
|
public void removeApiModule(String projectId) {
|
||||||
|
String[] projectModule = new String[]{"workstation", "testPlan", "bugManagement", "caseManagement", "uiTest", "loadTest"};
|
||||||
|
Project updateProject = new Project();
|
||||||
|
updateProject.setId(projectId);
|
||||||
|
updateProject.setModuleSetting(JSON.toJSONString(projectModule));
|
||||||
|
projectMapper.updateByPrimaryKeySelective(updateProject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetProjectModule(String projectId) {
|
||||||
|
String[] projectModule = new String[]{"workstation", "testPlan", "bugManagement", "caseManagement", "apiTest", "uiTest", "loadTest"};
|
||||||
|
Project updateProject = new Project();
|
||||||
|
updateProject.setId(projectId);
|
||||||
|
updateProject.setModuleSetting(JSON.toJSONString(projectModule));
|
||||||
|
projectMapper.updateByPrimaryKeySelective(updateProject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查批量编辑
|
||||||
|
*
|
||||||
|
* @param sourceScenarioIds 涉及到的场景id
|
||||||
|
* @param reCopyCountInModule 关联之前模块里是数据数量
|
||||||
|
* @param request
|
||||||
|
*/
|
||||||
|
public void checkBatchCopy(List<String> sourceScenarioIds, List<String> copyScenarioIdList, int reCopyCountInModule, ApiScenarioBatchCopyRequest request) {
|
||||||
|
ApiScenarioExample example = new ApiScenarioExample();
|
||||||
|
example.createCriteria().andModuleIdEqualTo(request.getTargetModuleId()).andIdIn(copyScenarioIdList);
|
||||||
|
List<ApiScenario> copyScenarios = apiScenarioMapper.selectByExample(example);
|
||||||
|
Assertions.assertEquals(copyScenarios.size(), sourceScenarioIds.size());
|
||||||
|
//检查总数据量
|
||||||
|
example.clear();
|
||||||
|
example.createCriteria().andModuleIdEqualTo(request.getTargetModuleId());
|
||||||
|
List<ApiScenario> allScenarioList = apiScenarioMapper.selectByExample(example);
|
||||||
|
Assertions.assertEquals(allScenarioList.size(), reCopyCountInModule + sourceScenarioIds.size());
|
||||||
|
|
||||||
|
//不存在copy_copy_开头的数据、复制之前如果存在 -num 会把这个num去掉
|
||||||
|
for (ApiScenario apiScenario : allScenarioList) {
|
||||||
|
String name = apiScenario.getName();
|
||||||
|
Assertions.assertTrue(name.length() <= 255);
|
||||||
|
Assertions.assertFalse(name.startsWith("copy_copy_"));
|
||||||
|
if (name.startsWith("copy_")) {
|
||||||
|
Assertions.assertFalse(name.split("_").length > 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> copyScenarioIds = copyScenarios.stream().map(ApiScenario::getId).toList();
|
||||||
|
//检查blob
|
||||||
|
ApiScenarioBlobExample sourceBlobExample = new ApiScenarioBlobExample();
|
||||||
|
sourceBlobExample.createCriteria().andIdIn(sourceScenarioIds);
|
||||||
|
ApiScenarioBlobExample copyBlobExample = new ApiScenarioBlobExample();
|
||||||
|
copyBlobExample.createCriteria().andIdIn(copyScenarioIds);
|
||||||
|
Assertions.assertEquals(apiScenarioBlobMapper.countByExample(sourceBlobExample), apiScenarioBlobMapper.countByExample(copyBlobExample));
|
||||||
|
|
||||||
|
//检查step
|
||||||
|
ApiScenarioStepExample sourceStepExample = new ApiScenarioStepExample();
|
||||||
|
sourceStepExample.createCriteria().andScenarioIdIn(sourceScenarioIds);
|
||||||
|
ApiScenarioStepExample copyStepExample = new ApiScenarioStepExample();
|
||||||
|
copyStepExample.createCriteria().andScenarioIdIn(copyScenarioIds);
|
||||||
|
Assertions.assertEquals(apiScenarioStepMapper.countByExample(sourceStepExample), apiScenarioStepMapper.countByExample(copyStepExample));
|
||||||
|
|
||||||
|
//检查step_blob
|
||||||
|
ApiScenarioStepBlobExample sourceStepBlobExample = new ApiScenarioStepBlobExample();
|
||||||
|
sourceStepBlobExample.createCriteria().andScenarioIdIn(sourceScenarioIds);
|
||||||
|
ApiScenarioStepBlobExample copyStepBlobExample = new ApiScenarioStepBlobExample();
|
||||||
|
copyStepBlobExample.createCriteria().andScenarioIdIn(copyScenarioIds);
|
||||||
|
Assertions.assertEquals(apiScenarioStepBlobMapper.countByExample(sourceStepBlobExample), apiScenarioStepBlobMapper.countByExample(copyStepBlobExample));
|
||||||
|
|
||||||
|
//检查fileRequest
|
||||||
|
ApiFileResourceExample sourceFileExample = new ApiFileResourceExample();
|
||||||
|
sourceFileExample.createCriteria().andResourceIdIn(sourceScenarioIds);
|
||||||
|
ApiFileResourceExample copyFileExample = new ApiFileResourceExample();
|
||||||
|
copyFileExample.createCriteria().andResourceIdIn(copyScenarioIds);
|
||||||
|
Assertions.assertEquals(apiFileResourceMapper.countByExample(sourceFileExample), apiFileResourceMapper.countByExample(copyFileExample));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateNameToTestByModuleId(String moduleId) {
|
||||||
|
ApiScenarioExample example = new ApiScenarioExample();
|
||||||
|
example.createCriteria().andModuleIdEqualTo(moduleId);
|
||||||
|
List<ApiScenario> allScenarioList = apiScenarioMapper.selectByExample(example);
|
||||||
|
List<ApiScenario> updateList = new ArrayList<>();
|
||||||
|
for (ApiScenario apiScenario : allScenarioList) {
|
||||||
|
String name = apiScenario.getName();
|
||||||
|
while (name.length() < 255) {
|
||||||
|
name = name + "_";
|
||||||
|
}
|
||||||
|
ApiScenario updateScenario = new ApiScenario();
|
||||||
|
updateScenario.setModuleId(apiScenario.getId());
|
||||||
|
updateScenario.setName(name);
|
||||||
|
updateList.add(updateScenario);
|
||||||
|
}
|
||||||
|
for (ApiScenario apiScenario : updateList) {
|
||||||
|
apiScenarioMapper.updateByPrimaryKeySelective(apiScenario);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,8 +7,12 @@
|
||||||
package io.metersphere.functional.service;
|
package io.metersphere.functional.service;
|
||||||
|
|
||||||
|
|
||||||
import io.metersphere.functional.domain.*;
|
import io.metersphere.functional.domain.CaseReview;
|
||||||
import io.metersphere.functional.mapper.*;
|
import io.metersphere.functional.domain.CaseReviewModule;
|
||||||
|
import io.metersphere.functional.domain.CaseReviewModuleExample;
|
||||||
|
import io.metersphere.functional.mapper.CaseReviewModuleMapper;
|
||||||
|
import io.metersphere.functional.mapper.ExtCaseReviewMapper;
|
||||||
|
import io.metersphere.functional.mapper.ExtCaseReviewModuleMapper;
|
||||||
import io.metersphere.functional.request.CaseReviewModuleCreateRequest;
|
import io.metersphere.functional.request.CaseReviewModuleCreateRequest;
|
||||||
import io.metersphere.functional.request.CaseReviewModuleUpdateRequest;
|
import io.metersphere.functional.request.CaseReviewModuleUpdateRequest;
|
||||||
import io.metersphere.project.dto.ModuleCountDTO;
|
import io.metersphere.project.dto.ModuleCountDTO;
|
||||||
|
@ -212,11 +216,6 @@ public class CaseReviewModuleService extends ModuleTreeService {
|
||||||
throw new MSException(Translator.get("node.name.repeat"));
|
throw new MSException(Translator.get("node.name.repeat"));
|
||||||
}
|
}
|
||||||
example.clear();
|
example.clear();
|
||||||
|
|
||||||
//非默认节点,检查该节点所在分支的总长度,确保不超过阈值
|
|
||||||
if (!StringUtils.equals(caseReviewModule.getId(), ModuleConstants.DEFAULT_NODE_ID)) {
|
|
||||||
this.checkBranchModules(this.getRootNodeId(caseReviewModule), extCaseReviewModuleMapper::selectChildrenIdsByParentIds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getRootNodeId(CaseReviewModule caseReviewModule) {
|
private String getRootNodeId(CaseReviewModule caseReviewModule) {
|
||||||
|
|
|
@ -214,11 +214,6 @@ public class FunctionalCaseModuleService extends ModuleTreeService {
|
||||||
throw new MSException(Translator.get("node.name.repeat"));
|
throw new MSException(Translator.get("node.name.repeat"));
|
||||||
}
|
}
|
||||||
example.clear();
|
example.clear();
|
||||||
|
|
||||||
//非默认节点,检查该节点所在分支的总长度,确保不超过阈值
|
|
||||||
if (!StringUtils.equals(functionalCaseModule.getId(), ModuleConstants.DEFAULT_NODE_ID)) {
|
|
||||||
this.checkBranchModules(this.getRootNodeId(functionalCaseModule), extFunctionalCaseModuleMapper::selectChildrenIdsByParentIds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getRootNodeId(FunctionalCaseModule functionalCaseModule) {
|
private String getRootNodeId(FunctionalCaseModule functionalCaseModule) {
|
||||||
|
|
|
@ -244,9 +244,6 @@ public class CaseReviewModuleControllerTests extends BaseTest {
|
||||||
//到20换下一层级
|
//到20换下一层级
|
||||||
parentId = holder.getData().toString();
|
parentId = holder.getData().toString();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//测试超过500会报错
|
|
||||||
this.requestPost(URL_MODULE_TREE_ADD, perfRequest).andExpect(status().is5xxServerError());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
treeNodes = this.getCaseReviewModuleTreeNode();
|
treeNodes = this.getCaseReviewModuleTreeNode();
|
||||||
|
|
|
@ -246,9 +246,6 @@ public class FunctionalCaseModuleControllerTests extends BaseTest {
|
||||||
//到20换下一层级
|
//到20换下一层级
|
||||||
parentId = holder.getData().toString();
|
parentId = holder.getData().toString();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//测试超过500会报错
|
|
||||||
this.requestPost(URL_MODULE_TREE_ADD, perfRequest).andExpect(status().is5xxServerError());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
treeNodes = this.getFunctionalCaseModuleTreeNode();
|
treeNodes = this.getFunctionalCaseModuleTreeNode();
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package io.metersphere.project.constants;
|
||||||
|
|
||||||
|
public class ProjectMenuConstants {
|
||||||
|
public static final String MODULE_MENU_WORKSTATION = "workstation";
|
||||||
|
public static final String MODULE_MENU_TEST_PLAN = "testPlan";
|
||||||
|
public static final String MODULE_MENU_BUG = "bugManagement";
|
||||||
|
public static final String MODULE_MENU_FUNCTIONAL_CASE = "caseManagement";
|
||||||
|
public static final String MODULE_MENU_API_TEST = "apiTest";
|
||||||
|
public static final String MODULE_MENU_UI = "uiTest";
|
||||||
|
public static final String MODULE_MENU_LOAD_TEST = "loadTest";
|
||||||
|
}
|
|
@ -12,5 +12,4 @@ public interface ExtProjectMapper {
|
||||||
String getModuleSetting(@Param("projectId") String projectId);
|
String getModuleSetting(@Param("projectId") String projectId);
|
||||||
|
|
||||||
List<Project> getProject(@Param("userId") String userId);
|
List<Project> getProject(@Param("userId") String userId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,11 +114,6 @@ public class FileModuleService extends ModuleTreeService implements CleanupProje
|
||||||
throw new MSException(Translator.get("node.name.repeat"));
|
throw new MSException(Translator.get("node.name.repeat"));
|
||||||
}
|
}
|
||||||
example.clear();
|
example.clear();
|
||||||
|
|
||||||
//非默认节点,检查该节点所在分支的总长度,确保不超过阈值
|
|
||||||
if (!StringUtils.equals(fileModule.getId(), ModuleConstants.DEFAULT_NODE_ID)) {
|
|
||||||
this.checkBranchModules(this.getRootNodeId(fileModule), extFileModuleMapper::selectChildrenIdsByParentIds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getRootNodeId(FileModule fileModule) {
|
private String getRootNodeId(FileModule fileModule) {
|
||||||
|
|
|
@ -16,7 +16,10 @@ import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -32,19 +35,6 @@ public abstract class ModuleTreeService {
|
||||||
return new BaseTreeNode(ModuleConstants.DEFAULT_NODE_ID, name, ModuleConstants.NODE_TYPE_DEFAULT, ModuleConstants.ROOT_NODE_PARENT_ID);
|
return new BaseTreeNode(ModuleConstants.DEFAULT_NODE_ID, name, ModuleConstants.NODE_TYPE_DEFAULT, ModuleConstants.ROOT_NODE_PARENT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkBranchModules(String rootNodeId, Function<List<String>, List<String>> selectIdByParentIdFunc) {
|
|
||||||
long count = 1;
|
|
||||||
List<String> child = selectIdByParentIdFunc.apply(Collections.singletonList(rootNodeId));
|
|
||||||
while (CollectionUtils.isNotEmpty(child)) {
|
|
||||||
count += child.size();
|
|
||||||
if (count < MAX_BRANCHES_NODE_SIZE) {
|
|
||||||
child = selectIdByParentIdFunc.apply(child);
|
|
||||||
} else {
|
|
||||||
throw new MSException(Translator.getWithArgs("module.branches.size.limit", MAX_BRANCHES_NODE_SIZE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//构建树结构,并为每个节点计算资源数量
|
//构建树结构,并为每个节点计算资源数量
|
||||||
public List<BaseTreeNode> buildTreeAndCountResource(List<BaseTreeNode> traverseList, @NotNull List<ModuleCountDTO> moduleCountDTOList, boolean haveVirtualRootNode, String virtualRootName) {
|
public List<BaseTreeNode> buildTreeAndCountResource(List<BaseTreeNode> traverseList, @NotNull List<ModuleCountDTO> moduleCountDTOList, boolean haveVirtualRootNode, String virtualRootName) {
|
||||||
//构建模块树
|
//构建模块树
|
||||||
|
|
|
@ -300,7 +300,7 @@ public class FileManagementControllerTests extends BaseTest {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
测试能否正常做200个节点
|
创建210个节点
|
||||||
*/
|
*/
|
||||||
String parentId = null;
|
String parentId = null;
|
||||||
for (int i = 0; i < 210; i++) {
|
for (int i = 0; i < 210; i++) {
|
||||||
|
@ -317,9 +317,6 @@ public class FileManagementControllerTests extends BaseTest {
|
||||||
//到20换下一层级
|
//到20换下一层级
|
||||||
parentId = holder.getData().toString();
|
parentId = holder.getData().toString();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//测试超过500会报错
|
|
||||||
this.requestPost(FileManagementRequestUtils.URL_MODULE_ADD, perfRequest).andExpect(status().is5xxServerError());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
treeNodes = this.getFileModuleTreeNode();
|
treeNodes = this.getFileModuleTreeNode();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package io.metersphere.plan.dto;
|
package io.metersphere.system.dto;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
|
@ -1,11 +1,11 @@
|
||||||
package io.metersphere.system.mapper;
|
package io.metersphere.system.mapper;
|
||||||
|
|
||||||
import io.metersphere.system.dto.user.UserExtendDTO;
|
|
||||||
import io.metersphere.system.dto.OrganizationProjectOptionsDTO;
|
import io.metersphere.system.dto.OrganizationProjectOptionsDTO;
|
||||||
import io.metersphere.system.dto.ProjectDTO;
|
import io.metersphere.system.dto.ProjectDTO;
|
||||||
import io.metersphere.system.dto.ProjectResourcePoolDTO;
|
import io.metersphere.system.dto.ProjectResourcePoolDTO;
|
||||||
import io.metersphere.system.dto.request.ProjectMemberRequest;
|
import io.metersphere.system.dto.request.ProjectMemberRequest;
|
||||||
import io.metersphere.system.dto.request.ProjectRequest;
|
import io.metersphere.system.dto.request.ProjectRequest;
|
||||||
|
import io.metersphere.system.dto.user.UserExtendDTO;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -27,4 +27,6 @@ public interface ExtSystemProjectMapper {
|
||||||
List<ProjectDTO> getProjectExtendDTOList(@Param("projectIds") List<String> projectIds);
|
List<ProjectDTO> getProjectExtendDTOList(@Param("projectIds") List<String> projectIds);
|
||||||
|
|
||||||
List<ProjectResourcePoolDTO> getProjectResourcePoolDTOList(@Param("projectIds") List<String> projectIds);
|
List<ProjectResourcePoolDTO> getProjectResourcePoolDTOList(@Param("projectIds") List<String> projectIds);
|
||||||
|
|
||||||
|
String selectModuleSettingsByResourceIdAndTable(@Param("resourceId") String resourceId, @Param("resourceTable") String resourceTable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,6 +181,19 @@
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
</select>
|
</select>
|
||||||
|
<select id="selectModuleSettingsByResourceIdAndTable" resultType="java.lang.String">
|
||||||
|
SELECT module_setting FROM project
|
||||||
|
<where>
|
||||||
|
<if test="resourceTable == 'project' ">
|
||||||
|
id = #{resourceId}
|
||||||
|
</if>
|
||||||
|
<if test="resourceTable != 'project' ">
|
||||||
|
id IN (
|
||||||
|
SELECT project_id FROM ${resourceTable} WHERE id = #{resourceId}
|
||||||
|
)
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
|
@ -545,5 +545,6 @@ public interface NoticeConstants {
|
||||||
String resourceId = "resourceId";
|
String resourceId = "resourceId";
|
||||||
String platformBugId = "platformBugId";
|
String platformBugId = "platformBugId";
|
||||||
String handleUsers = "handleUsers";
|
String handleUsers = "handleUsers";
|
||||||
|
String groupId = "groupId";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -663,4 +663,16 @@ public class CommonProjectService {
|
||||||
// 校验组织是否有权限
|
// 校验组织是否有权限
|
||||||
return testResourcePoolService.validateOrgResourcePool(resourcePool, project.getOrganizationId());
|
return testResourcePoolService.validateOrgResourcePool(resourcePool, project.getOrganizationId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//检测资源所在的项目是否含有模块菜单
|
||||||
|
public void checkProjectHasModuleMenu(List<String> moduleMenus, String resourceId, String resourceTable) {
|
||||||
|
String moduleSettings = extSystemProjectMapper.selectModuleSettingsByResourceIdAndTable(resourceId, resourceTable);
|
||||||
|
if (StringUtils.isEmpty(moduleSettings)) {
|
||||||
|
throw new MSException(Translator.get("project.module_menu.check.error"));
|
||||||
|
}
|
||||||
|
List<String> projectModuleMenus = JSON.parseArray(moduleSettings, String.class);
|
||||||
|
if (!projectModuleMenus.containsAll(moduleMenus)) {
|
||||||
|
throw new MSException(Translator.get("project.module_menu.check.error"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package io.metersphere.plan.controller;
|
package io.metersphere.plan.controller;
|
||||||
|
|
||||||
import io.metersphere.plan.constants.TestPlanResourceConfig;
|
import io.metersphere.plan.constants.TestPlanResourceConfig;
|
||||||
import io.metersphere.plan.dto.LogInsertModule;
|
|
||||||
import io.metersphere.plan.dto.request.ResourceSortRequest;
|
import io.metersphere.plan.dto.request.ResourceSortRequest;
|
||||||
import io.metersphere.plan.dto.request.TestPlanAssociationRequest;
|
import io.metersphere.plan.dto.request.TestPlanAssociationRequest;
|
||||||
import io.metersphere.plan.dto.response.TestPlanAssociationResponse;
|
import io.metersphere.plan.dto.response.TestPlanAssociationResponse;
|
||||||
|
@ -10,6 +9,7 @@ import io.metersphere.plan.service.TestPlanApiCaseService;
|
||||||
import io.metersphere.plan.service.TestPlanManagementService;
|
import io.metersphere.plan.service.TestPlanManagementService;
|
||||||
import io.metersphere.sdk.constants.HttpMethodConstants;
|
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||||
import io.metersphere.sdk.constants.PermissionConstants;
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
|
import io.metersphere.system.dto.LogInsertModule;
|
||||||
import io.metersphere.system.security.CheckOwner;
|
import io.metersphere.system.security.CheckOwner;
|
||||||
import io.metersphere.system.utils.SessionUtils;
|
import io.metersphere.system.utils.SessionUtils;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package io.metersphere.plan.controller;
|
package io.metersphere.plan.controller;
|
||||||
|
|
||||||
import io.metersphere.plan.constants.TestPlanResourceConfig;
|
import io.metersphere.plan.constants.TestPlanResourceConfig;
|
||||||
import io.metersphere.plan.dto.LogInsertModule;
|
|
||||||
import io.metersphere.plan.dto.request.ResourceSortRequest;
|
import io.metersphere.plan.dto.request.ResourceSortRequest;
|
||||||
import io.metersphere.plan.dto.request.TestPlanAssociationRequest;
|
import io.metersphere.plan.dto.request.TestPlanAssociationRequest;
|
||||||
import io.metersphere.plan.dto.response.TestPlanAssociationResponse;
|
import io.metersphere.plan.dto.response.TestPlanAssociationResponse;
|
||||||
|
@ -10,6 +9,7 @@ import io.metersphere.plan.service.TestPlanApiScenarioService;
|
||||||
import io.metersphere.plan.service.TestPlanManagementService;
|
import io.metersphere.plan.service.TestPlanManagementService;
|
||||||
import io.metersphere.sdk.constants.HttpMethodConstants;
|
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||||
import io.metersphere.sdk.constants.PermissionConstants;
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
|
import io.metersphere.system.dto.LogInsertModule;
|
||||||
import io.metersphere.system.security.CheckOwner;
|
import io.metersphere.system.security.CheckOwner;
|
||||||
import io.metersphere.system.utils.SessionUtils;
|
import io.metersphere.system.utils.SessionUtils;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package io.metersphere.plan.controller;
|
package io.metersphere.plan.controller;
|
||||||
|
|
||||||
import io.metersphere.plan.constants.TestPlanResourceConfig;
|
import io.metersphere.plan.constants.TestPlanResourceConfig;
|
||||||
import io.metersphere.plan.dto.LogInsertModule;
|
|
||||||
import io.metersphere.plan.dto.request.ResourceSortRequest;
|
import io.metersphere.plan.dto.request.ResourceSortRequest;
|
||||||
import io.metersphere.plan.dto.request.TestPlanAssociationRequest;
|
import io.metersphere.plan.dto.request.TestPlanAssociationRequest;
|
||||||
import io.metersphere.plan.dto.response.TestPlanAssociationResponse;
|
import io.metersphere.plan.dto.response.TestPlanAssociationResponse;
|
||||||
|
@ -10,6 +9,7 @@ import io.metersphere.plan.service.TestPlanFunctionalCaseService;
|
||||||
import io.metersphere.plan.service.TestPlanManagementService;
|
import io.metersphere.plan.service.TestPlanManagementService;
|
||||||
import io.metersphere.sdk.constants.HttpMethodConstants;
|
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||||
import io.metersphere.sdk.constants.PermissionConstants;
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
|
import io.metersphere.system.dto.LogInsertModule;
|
||||||
import io.metersphere.system.security.CheckOwner;
|
import io.metersphere.system.security.CheckOwner;
|
||||||
import io.metersphere.system.utils.SessionUtils;
|
import io.metersphere.system.utils.SessionUtils;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.metersphere.plan.dto;
|
package io.metersphere.plan.dto;
|
||||||
|
|
||||||
|
import io.metersphere.system.dto.LogInsertModule;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import io.metersphere.plan.domain.TestPlan;
|
||||||
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.AssociationNodeSortDTO;
|
import io.metersphere.plan.dto.AssociationNodeSortDTO;
|
||||||
import io.metersphere.plan.dto.LogInsertModule;
|
|
||||||
import io.metersphere.plan.dto.ResourceLogInsertModule;
|
import io.metersphere.plan.dto.ResourceLogInsertModule;
|
||||||
import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
|
import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
|
||||||
import io.metersphere.plan.dto.request.ResourceSortRequest;
|
import io.metersphere.plan.dto.request.ResourceSortRequest;
|
||||||
|
@ -17,6 +16,7 @@ import io.metersphere.plan.mapper.TestPlanMapper;
|
||||||
import io.metersphere.sdk.constants.ApplicationNumScope;
|
import io.metersphere.sdk.constants.ApplicationNumScope;
|
||||||
import io.metersphere.sdk.constants.TestPlanResourceConstants;
|
import io.metersphere.sdk.constants.TestPlanResourceConstants;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
|
import io.metersphere.system.dto.LogInsertModule;
|
||||||
import io.metersphere.system.uid.IDGenerator;
|
import io.metersphere.system.uid.IDGenerator;
|
||||||
import io.metersphere.system.uid.NumGenerator;
|
import io.metersphere.system.uid.NumGenerator;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
|
|
@ -4,7 +4,6 @@ import io.metersphere.plan.domain.TestPlan;
|
||||||
import io.metersphere.plan.domain.TestPlanApiScenario;
|
import io.metersphere.plan.domain.TestPlanApiScenario;
|
||||||
import io.metersphere.plan.domain.TestPlanApiScenarioExample;
|
import io.metersphere.plan.domain.TestPlanApiScenarioExample;
|
||||||
import io.metersphere.plan.dto.AssociationNodeSortDTO;
|
import io.metersphere.plan.dto.AssociationNodeSortDTO;
|
||||||
import io.metersphere.plan.dto.LogInsertModule;
|
|
||||||
import io.metersphere.plan.dto.ResourceLogInsertModule;
|
import io.metersphere.plan.dto.ResourceLogInsertModule;
|
||||||
import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
|
import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
|
||||||
import io.metersphere.plan.dto.request.ResourceSortRequest;
|
import io.metersphere.plan.dto.request.ResourceSortRequest;
|
||||||
|
@ -18,6 +17,7 @@ import io.metersphere.plan.mapper.TestPlanMapper;
|
||||||
import io.metersphere.sdk.constants.ApplicationNumScope;
|
import io.metersphere.sdk.constants.ApplicationNumScope;
|
||||||
import io.metersphere.sdk.constants.TestPlanResourceConstants;
|
import io.metersphere.sdk.constants.TestPlanResourceConstants;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
|
import io.metersphere.system.dto.LogInsertModule;
|
||||||
import io.metersphere.system.uid.IDGenerator;
|
import io.metersphere.system.uid.IDGenerator;
|
||||||
import io.metersphere.system.uid.NumGenerator;
|
import io.metersphere.system.uid.NumGenerator;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
|
|
@ -4,7 +4,6 @@ import io.metersphere.plan.domain.TestPlan;
|
||||||
import io.metersphere.plan.domain.TestPlanFunctionalCase;
|
import io.metersphere.plan.domain.TestPlanFunctionalCase;
|
||||||
import io.metersphere.plan.domain.TestPlanFunctionalCaseExample;
|
import io.metersphere.plan.domain.TestPlanFunctionalCaseExample;
|
||||||
import io.metersphere.plan.dto.AssociationNodeSortDTO;
|
import io.metersphere.plan.dto.AssociationNodeSortDTO;
|
||||||
import io.metersphere.plan.dto.LogInsertModule;
|
|
||||||
import io.metersphere.plan.dto.ResourceLogInsertModule;
|
import io.metersphere.plan.dto.ResourceLogInsertModule;
|
||||||
import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
|
import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
|
||||||
import io.metersphere.plan.dto.request.ResourceSortRequest;
|
import io.metersphere.plan.dto.request.ResourceSortRequest;
|
||||||
|
@ -18,6 +17,7 @@ import io.metersphere.sdk.constants.ApplicationNumScope;
|
||||||
import io.metersphere.sdk.constants.TestPlanResourceConstants;
|
import io.metersphere.sdk.constants.TestPlanResourceConstants;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.util.Translator;
|
import io.metersphere.sdk.util.Translator;
|
||||||
|
import io.metersphere.system.dto.LogInsertModule;
|
||||||
import io.metersphere.system.uid.IDGenerator;
|
import io.metersphere.system.uid.IDGenerator;
|
||||||
import io.metersphere.system.uid.NumGenerator;
|
import io.metersphere.system.uid.NumGenerator;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
|
|
@ -28,10 +28,8 @@ import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
@ -111,28 +109,10 @@ public class TestPlanModuleService extends ModuleTreeService implements CleanupP
|
||||||
throw new MSException(Translator.get("node.name.repeat"));
|
throw new MSException(Translator.get("node.name.repeat"));
|
||||||
}
|
}
|
||||||
example.clear();
|
example.clear();
|
||||||
|
|
||||||
//非默认节点,检查该节点所在分支的总长度,确保不超过阈值
|
|
||||||
if (!StringUtils.equals(module.getId(), ModuleConstants.DEFAULT_NODE_ID)) {
|
|
||||||
this.checkBranchModules(this.getRootNodeId(module), extTestPlanModuleMapper::selectChildrenIdsByParentIds);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private String getRootNodeId(TestPlanModule module) {
|
|
||||||
if (StringUtils.equals(module.getParentId(), ModuleConstants.ROOT_NODE_PARENT_ID)) {
|
|
||||||
return module.getId();
|
|
||||||
} else {
|
|
||||||
TestPlanModule parentModule = testPlanModuleMapper.selectByPrimaryKey(module.getParentId());
|
|
||||||
return this.getRootNodeId(parentModule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void update(TestPlanModuleUpdateRequest request, String userId,String requestUrl,String requestMethod) {
|
public void update(TestPlanModuleUpdateRequest request, String userId,String requestUrl,String requestMethod) {
|
||||||
TestPlanModule module = testPlanModuleMapper.selectByPrimaryKey(request.getId());
|
TestPlanModule module = testPlanModuleMapper.selectByPrimaryKey(request.getId());
|
||||||
if (module == null) {
|
|
||||||
throw new MSException("module.not.exist");
|
|
||||||
}
|
|
||||||
TestPlanModule updateModule = new TestPlanModule();
|
TestPlanModule updateModule = new TestPlanModule();
|
||||||
updateModule.setId(request.getId());
|
updateModule.setId(request.getId());
|
||||||
updateModule.setName(request.getName().trim());
|
updateModule.setName(request.getName().trim());
|
||||||
|
@ -244,17 +224,6 @@ public class TestPlanModuleService extends ModuleTreeService implements CleanupP
|
||||||
// nothing to do
|
// nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getModuleNameMapByIds(List<String> moduleIds) {
|
|
||||||
if (CollectionUtils.isEmpty(moduleIds)) {
|
|
||||||
return new HashMap<>();
|
|
||||||
} else {
|
|
||||||
TestPlanModuleExample example = new TestPlanModuleExample();
|
|
||||||
example.createCriteria().andIdIn(moduleIds);
|
|
||||||
List<TestPlanModule> moduleList = testPlanModuleMapper.selectByExample(example);
|
|
||||||
return moduleList.stream().collect(Collectors.toMap(TestPlanModule::getId, TestPlanModule::getName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNameById(String id) {
|
public String getNameById(String id) {
|
||||||
return extTestPlanModuleMapper.selectNameById(id);
|
return extTestPlanModuleMapper.selectNameById(id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import io.metersphere.project.dto.NodeSortQueryParam;
|
||||||
import io.metersphere.project.utils.NodeSortUtils;
|
import io.metersphere.project.utils.NodeSortUtils;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.util.Translator;
|
import io.metersphere.sdk.util.Translator;
|
||||||
|
import io.metersphere.system.dto.LogInsertModule;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
|
@ -371,9 +371,6 @@ public class TestPlanTests extends BaseTest {
|
||||||
//到20换下一层级
|
//到20换下一层级
|
||||||
parentId = holder.getData().toString();
|
parentId = holder.getData().toString();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//测试超过500会报错
|
|
||||||
this.requestPost(URL_POST_MODULE_ADD, perfRequest).andExpect(status().is5xxServerError());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
treeNodes = this.getFileModuleTreeNode();
|
treeNodes = this.getFileModuleTreeNode();
|
||||||
|
|
Loading…
Reference in New Issue