feat(接口测试): 增加接口用例排序

This commit is contained in:
wxg0103 2023-11-28 16:37:33 +08:00 committed by wxg0103
parent c002a6b431
commit 3758474637
16 changed files with 285 additions and 67 deletions

View File

@ -8,6 +8,7 @@ import io.metersphere.api.service.definition.ApiTestCaseLogService;
import io.metersphere.api.service.definition.ApiTestCaseNoticeService; import io.metersphere.api.service.definition.ApiTestCaseNoticeService;
import io.metersphere.api.service.definition.ApiTestCaseService; import io.metersphere.api.service.definition.ApiTestCaseService;
import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.system.dto.sdk.request.PosRequest;
import io.metersphere.system.log.annotation.Log; import io.metersphere.system.log.annotation.Log;
import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.notice.annotation.SendNotice; import io.metersphere.system.notice.annotation.SendNotice;
@ -28,7 +29,7 @@ import java.util.List;
@RestController @RestController
@RequestMapping(value = "/api/testCase") @RequestMapping(value = "/api/case")
@Tag(name = "接口测试-接口管理-接口用例") @Tag(name = "接口测试-接口管理-接口用例")
public class ApiTestCaseController { public class ApiTestCaseController {
@Resource @Resource
@ -142,4 +143,12 @@ public class ApiTestCaseController {
return PageUtils.setPageInfo(page, apiTestCaseService.page(request, true)); return PageUtils.setPageInfo(page, apiTestCaseService.page(request, true));
} }
@PostMapping("edit/pos")
@Operation(summary = "接口测试-接口管理-接口用例-拖拽排序")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_CASE_UPDATE)
public void editPos(@Validated @RequestBody PosRequest request) {
apiTestCaseService.editPos(request);
}
} }

View File

@ -33,7 +33,7 @@ public class ApiDefinitionBatchRequest extends TableBatchProcessDTO implements S
private String protocol = ModuleConstants.NODE_PROTOCOL_HTTP; private String protocol = ModuleConstants.NODE_PROTOCOL_HTTP;
@Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)") @Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)")
private List<String> moduleIds; private List<@NotBlank String> moduleIds;
@Schema(description = "删除列表版本/删除全部版本") @Schema(description = "删除列表版本/删除全部版本")
private Boolean deleteAll = false; private Boolean deleteAll = false;

View File

@ -44,7 +44,7 @@ public class ApiDefinitionPageRequest extends BasePageRequest {
private String refId; private String refId;
@Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)") @Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)")
private List<String> moduleIds; private List<@NotBlank String> moduleIds;
@Schema(description = "删除状态(状态为 1 时为回收站数据)") @Schema(description = "删除状态(状态为 1 时为回收站数据)")
private Boolean deleted = false; private Boolean deleted = false;

View File

@ -11,7 +11,7 @@ import java.util.List;
@Data @Data
public class ApiModuleRequest { public class ApiModuleRequest {
@Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)") @Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)")
private List<String> moduleIds; private List<@NotBlank String> moduleIds;
@Schema(description = "协议", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "协议", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_definition_module.protocol.not_blank}") @NotBlank(message = "{api_definition_module.protocol.not_blank}")

View File

@ -31,7 +31,7 @@ public class ApiTestCaseBatchRequest extends TableBatchProcessDTO implements Ser
private String protocol = ModuleConstants.NODE_PROTOCOL_HTTP; private String protocol = ModuleConstants.NODE_PROTOCOL_HTTP;
@Schema(description = "模块ID") @Schema(description = "模块ID")
private List<String> moduleIds; private List<@NotBlank String> moduleIds;
@Schema(description = "版本fk") @Schema(description = "版本fk")
private String versionId; private String versionId;

View File

@ -0,0 +1,13 @@
package io.metersphere.api.dto.definition;
import io.metersphere.api.domain.ApiTestCase;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class ApiTestCaseLogDTO extends ApiTestCase {
@Schema(description = "请求内容")
private AbstractMsTestElement request;
}

View File

@ -33,7 +33,7 @@ public class ApiTestCasePageRequest extends BasePageRequest {
private String protocol = ModuleConstants.NODE_PROTOCOL_HTTP; private String protocol = ModuleConstants.NODE_PROTOCOL_HTTP;
@Schema(description = "模块ID") @Schema(description = "模块ID")
private List<String> moduleIds; private List<@NotBlank String> moduleIds;
@Schema(description = "版本fk") @Schema(description = "版本fk")
private String versionId; private String versionId;

View File

@ -29,4 +29,8 @@ public interface ExtApiTestCaseMapper {
List<ApiTestCase> getCaseInfoByApiIds(@Param("ids") List<String> apiIds, @Param("deleted") boolean deleted); List<ApiTestCase> getCaseInfoByApiIds(@Param("ids") List<String> apiIds, @Param("deleted") boolean deleted);
List<ApiTestCase> getCaseInfoByIds(@Param("ids") List<String> caseIds, @Param("deleted") boolean deleted); List<ApiTestCase> getCaseInfoByIds(@Param("ids") List<String> caseIds, @Param("deleted") boolean deleted);
Long getPrePos(@Param("projectId") String projectId, @Param("basePos") Long basePos);
Long getLastPos(@Param("projectId") String projectId, @Param("basePos") Long basePos);
} }

View File

@ -75,6 +75,23 @@
</foreach> </foreach>
</select> </select>
<select id="getPrePos" resultType="java.lang.Long">
select `pos` from api_test_case where project_id = #{projectId}
<if test="basePos != null">
and `pos` &lt; #{basePos}
</if>
order by `pos` desc limit 1;
</select>
<select id="getLastPos" resultType="java.lang.Long">
select `pos` from api_test_case where project_id = #{projectId}
<if test="basePos != null">
and `pos` &gt; #{basePos}
</if>
order by `pos` desc limit 1;
</select>
<sql id="queryWhereConditionByBatch"> <sql id="queryWhereConditionByBatch">
<if test="request.protocol != null and request.protocol!=''"> <if test="request.protocol != null and request.protocol!=''">
and a.protocol = #{request.protocol} and a.protocol = #{request.protocol}

View File

@ -1,12 +1,20 @@
package io.metersphere.api.service.definition; package io.metersphere.api.service.definition;
import io.metersphere.api.domain.ApiTestCase; import io.metersphere.api.domain.ApiTestCase;
import io.metersphere.api.domain.ApiTestCaseBlob;
import io.metersphere.api.domain.ApiTestCaseBlobExample;
import io.metersphere.api.domain.ApiTestCaseExample;
import io.metersphere.api.dto.definition.ApiTestCaseAddRequest; import io.metersphere.api.dto.definition.ApiTestCaseAddRequest;
import io.metersphere.api.dto.definition.ApiTestCaseLogDTO;
import io.metersphere.api.dto.definition.ApiTestCaseUpdateRequest; import io.metersphere.api.dto.definition.ApiTestCaseUpdateRequest;
import io.metersphere.api.mapper.ApiTestCaseBlobMapper;
import io.metersphere.api.mapper.ApiTestCaseMapper; import io.metersphere.api.mapper.ApiTestCaseMapper;
import io.metersphere.api.util.ApiDataUtils;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.project.domain.Project; import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.util.BeanUtils;
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.builder.LogDTOBuilder; import io.metersphere.system.dto.builder.LogDTOBuilder;
@ -19,6 +27,8 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service @Service
public class ApiTestCaseLogService { public class ApiTestCaseLogService {
@ -29,6 +39,8 @@ public class ApiTestCaseLogService {
private ProjectMapper projectMapper; private ProjectMapper projectMapper;
@Resource @Resource
private OperationLogService operationLogService; private OperationLogService operationLogService;
@Resource
private ApiTestCaseBlobMapper apiTestCaseBlobMapper;
/** /**
* 添加接口日志 * 添加接口日志
@ -47,7 +59,7 @@ public class ApiTestCaseLogService {
OperationLogModule.API_DEFINITION_CASE, OperationLogModule.API_DEFINITION_CASE,
request.getName()); request.getName());
dto.setPath("/api/testCase/add"); dto.setPath("/api/case/add");
dto.setMethod(HttpMethodConstants.POST.name()); dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(request)); dto.setOriginalValue(JSON.toJSONBytes(request));
return dto; return dto;
@ -65,7 +77,7 @@ public class ApiTestCaseLogService {
OperationLogModule.API_DEFINITION_CASE, OperationLogModule.API_DEFINITION_CASE,
apiTestCase.getName()); apiTestCase.getName());
dto.setPath("/api/testCase/delete/" + id); dto.setPath("/api/case/delete/" + id);
dto.setMethod(HttpMethodConstants.GET.name()); dto.setMethod(HttpMethodConstants.GET.name());
dto.setOriginalValue(JSON.toJSONBytes(apiTestCase)); dto.setOriginalValue(JSON.toJSONBytes(apiTestCase));
return dto; return dto;
@ -83,7 +95,7 @@ public class ApiTestCaseLogService {
OperationLogModule.API_DEFINITION_CASE, OperationLogModule.API_DEFINITION_CASE,
apiTestCase.getName()); apiTestCase.getName());
dto.setPath("/api/testCase/move-gc/" + id); dto.setPath("/api/case/move-gc/" + id);
dto.setMethod(HttpMethodConstants.GET.name()); dto.setMethod(HttpMethodConstants.GET.name());
dto.setOriginalValue(JSON.toJSONBytes(apiTestCase)); dto.setOriginalValue(JSON.toJSONBytes(apiTestCase));
return dto; return dto;
@ -101,7 +113,7 @@ public class ApiTestCaseLogService {
OperationLogModule.API_DEFINITION_CASE, OperationLogModule.API_DEFINITION_CASE,
apiTestCase.getName()); apiTestCase.getName());
dto.setPath("/api/testCase/recover/" + id); dto.setPath("/api/case/recover/" + id);
dto.setMethod(HttpMethodConstants.GET.name()); dto.setMethod(HttpMethodConstants.GET.name());
dto.setOriginalValue(JSON.toJSONBytes(apiTestCase)); dto.setOriginalValue(JSON.toJSONBytes(apiTestCase));
return dto; return dto;
@ -119,7 +131,7 @@ public class ApiTestCaseLogService {
OperationLogModule.API_DEFINITION_CASE, OperationLogModule.API_DEFINITION_CASE,
Translator.get("follow") + apiTestCase.getName()); Translator.get("follow") + apiTestCase.getName());
dto.setPath("/api/testCase/follow/" + id); dto.setPath("/api/case/follow/" + id);
dto.setMethod(HttpMethodConstants.GET.name()); dto.setMethod(HttpMethodConstants.GET.name());
dto.setOriginalValue(JSON.toJSONBytes(apiTestCase)); dto.setOriginalValue(JSON.toJSONBytes(apiTestCase));
return dto; return dto;
@ -137,7 +149,7 @@ public class ApiTestCaseLogService {
OperationLogModule.API_DEFINITION_CASE, OperationLogModule.API_DEFINITION_CASE,
Translator.get("unfollow") + apiTestCase.getName()); Translator.get("unfollow") + apiTestCase.getName());
dto.setPath("/api/testCase/unfollow/" + id); dto.setPath("/api/case/unfollow/" + id);
dto.setMethod(HttpMethodConstants.GET.name()); dto.setMethod(HttpMethodConstants.GET.name());
dto.setOriginalValue(JSON.toJSONBytes(apiTestCase)); dto.setOriginalValue(JSON.toJSONBytes(apiTestCase));
return dto; return dto;
@ -145,6 +157,7 @@ public class ApiTestCaseLogService {
public LogDTO updateLog(ApiTestCaseUpdateRequest request) { public LogDTO updateLog(ApiTestCaseUpdateRequest request) {
ApiTestCase apiTestCase = apiTestCaseMapper.selectByPrimaryKey(request.getId()); ApiTestCase apiTestCase = apiTestCaseMapper.selectByPrimaryKey(request.getId());
ApiTestCaseBlob apiTestCaseBlob = apiTestCaseBlobMapper.selectByPrimaryKey(request.getId());
Project project = projectMapper.selectByPrimaryKey(apiTestCase.getProjectId()); Project project = projectMapper.selectByPrimaryKey(apiTestCase.getProjectId());
LogDTO dto = new LogDTO( LogDTO dto = new LogDTO(
apiTestCase.getProjectId(), apiTestCase.getProjectId(),
@ -155,14 +168,18 @@ public class ApiTestCaseLogService {
OperationLogModule.API_DEFINITION_CASE, OperationLogModule.API_DEFINITION_CASE,
request.getName()); request.getName());
dto.setPath("/api/testCase/update"); dto.setPath("/api/case/update");
dto.setMethod(HttpMethodConstants.POST.name()); dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(request)); ApiTestCaseLogDTO apiTestCaseDTO = new ApiTestCaseLogDTO();
BeanUtils.copyBean(apiTestCaseDTO, apiTestCase);
apiTestCaseDTO.setRequest(ApiDataUtils.parseObject(new String(apiTestCaseBlob.getRequest()), AbstractMsTestElement.class));
dto.setOriginalValue(JSON.toJSONBytes(apiTestCaseDTO));
return dto; return dto;
} }
public LogDTO updateLog(String id) { public LogDTO updateLog(String id) {
ApiTestCase apiTestCase = apiTestCaseMapper.selectByPrimaryKey(id); ApiTestCase apiTestCase = apiTestCaseMapper.selectByPrimaryKey(id);
ApiTestCaseBlob apiTestCaseBlob = apiTestCaseBlobMapper.selectByPrimaryKey(id);
Project project = projectMapper.selectByPrimaryKey(apiTestCase.getProjectId()); Project project = projectMapper.selectByPrimaryKey(apiTestCase.getProjectId());
LogDTO dto = new LogDTO( LogDTO dto = new LogDTO(
apiTestCase.getProjectId(), apiTestCase.getProjectId(),
@ -173,9 +190,12 @@ public class ApiTestCaseLogService {
OperationLogModule.API_DEFINITION_CASE, OperationLogModule.API_DEFINITION_CASE,
apiTestCase.getName()); apiTestCase.getName());
dto.setPath("/api/testCase/update"); dto.setPath("/api/case/update");
dto.setMethod(HttpMethodConstants.POST.name()); dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(apiTestCase)); ApiTestCaseLogDTO apiTestCaseDTO = new ApiTestCaseLogDTO();
BeanUtils.copyBean(apiTestCaseDTO, apiTestCase);
apiTestCaseDTO.setRequest(ApiDataUtils.parseObject(new String(apiTestCaseBlob.getRequest()), AbstractMsTestElement.class));
dto.setOriginalValue(JSON.toJSONBytes(apiTestCaseDTO));
return dto; return dto;
} }
@ -189,7 +209,7 @@ public class ApiTestCaseLogService {
.type(OperationLogType.DELETE.name()) .type(OperationLogType.DELETE.name())
.module(OperationLogModule.API_DEFINITION_CASE) .module(OperationLogModule.API_DEFINITION_CASE)
.method(HttpMethodConstants.POST.name()) .method(HttpMethodConstants.POST.name())
.path("/api/testCase/batch/delete") .path("/api/case/batch/delete")
.sourceId(item.getId()) .sourceId(item.getId())
.content(item.getName()) .content(item.getName())
.createUser(operator) .createUser(operator)
@ -210,7 +230,7 @@ public class ApiTestCaseLogService {
.type(OperationLogType.DELETE.name()) .type(OperationLogType.DELETE.name())
.module(OperationLogModule.API_DEFINITION_CASE) .module(OperationLogModule.API_DEFINITION_CASE)
.method(HttpMethodConstants.POST.name()) .method(HttpMethodConstants.POST.name())
.path("/api/testCase/batch/move-gc") .path("/api/case/batch/move-gc")
.sourceId(item.getId()) .sourceId(item.getId())
.content(item.getName()) .content(item.getName())
.createUser(operator) .createUser(operator)
@ -223,18 +243,36 @@ public class ApiTestCaseLogService {
public void batchEditLog(List<ApiTestCase> apiTestCases, String operator, String projectId) { public void batchEditLog(List<ApiTestCase> apiTestCases, String operator, String projectId) {
Project project = projectMapper.selectByPrimaryKey(projectId); Project project = projectMapper.selectByPrimaryKey(projectId);
//取出apiTestCases所有的id为新的list
List<String> caseId = apiTestCases.stream().map(ApiTestCase::getId).distinct().toList();
ApiTestCaseExample example = new ApiTestCaseExample();
example.createCriteria().andIdIn(caseId);
List<ApiTestCase> apiTestCaseList = apiTestCaseMapper.selectByExample(example);
//apiTestCaseList按id生成新的map key为id value为ApiTestCase
Map<String, ApiTestCase> caseMap = apiTestCaseList.stream().collect(Collectors.toMap(ApiTestCase::getId, a -> a));
ApiTestCaseBlobExample blobExample = new ApiTestCaseBlobExample();
blobExample.createCriteria().andIdIn(caseId);
List<ApiTestCaseBlob> blobList = apiTestCaseBlobMapper.selectByExampleWithBLOBs(blobExample);
//blobList按id生成新的map key为id value为ApiTestCaseBlob
Map<String, ApiTestCaseBlob> blobMap = blobList.stream().collect(Collectors.toMap(ApiTestCaseBlob::getId, a -> a));
List<LogDTO> logs = new ArrayList<>(); List<LogDTO> logs = new ArrayList<>();
apiTestCases.forEach(item -> { apiTestCases.forEach(item -> {
LogDTO dto = LogDTOBuilder.builder() ApiTestCaseLogDTO apiTestCaseDTO = new ApiTestCaseLogDTO();
BeanUtils.copyBean(apiTestCaseDTO, caseMap.get(item.getId()));
if (blobMap.get(item.getId()) != null) {
apiTestCaseDTO.setRequest(ApiDataUtils.parseObject(new String(blobMap.get(item.getId()).getRequest()), AbstractMsTestElement.class));
}
LogDTO dto = LogDTOBuilder.builder()
.projectId(project.getId()) .projectId(project.getId())
.organizationId(project.getOrganizationId()) .organizationId(project.getOrganizationId())
.type(OperationLogType.DELETE.name()) .type(OperationLogType.DELETE.name())
.module(OperationLogModule.API_DEFINITION_CASE) .module(OperationLogModule.API_DEFINITION_CASE)
.method(HttpMethodConstants.POST.name()) .method(HttpMethodConstants.POST.name())
.path("/api/testCase/batch/move-gc") .path("/api/case/batch/edit")
.sourceId(item.getId()) .sourceId(item.getId())
.content(item.getName()) .content(item.getName())
.createUser(operator) .createUser(operator)
.originalValue(JSON.toJSONBytes(apiTestCaseDTO))
.build().getLogDTO(); .build().getLogDTO();
logs.add(dto); logs.add(dto);
} }

View File

@ -18,11 +18,13 @@ import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.mapper.EnvironmentMapper; import io.metersphere.sdk.mapper.EnvironmentMapper;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.SubListUtils;
import io.metersphere.sdk.util.Translator; import io.metersphere.sdk.util.Translator;
import io.metersphere.system.file.MinioRepository; import io.metersphere.system.dto.sdk.request.PosRequest;
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 jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils; import org.apache.commons.collections.MapUtils;
@ -65,8 +67,6 @@ public class ApiTestCaseService {
@Resource @Resource
private ApiTestCaseFollowerMapper apiTestCaseFollowerMapper; private ApiTestCaseFollowerMapper apiTestCaseFollowerMapper;
@Resource @Resource
private MinioRepository minioRepository;
@Resource
private UserLoginService userLoginService; private UserLoginService userLoginService;
@Resource @Resource
private EnvironmentMapper environmentMapper; private EnvironmentMapper environmentMapper;
@ -315,15 +315,9 @@ public class ApiTestCaseService {
if (CollectionUtils.isEmpty(ids)) { if (CollectionUtils.isEmpty(ids)) {
return; return;
} }
while (!ids.isEmpty()) { SubListUtils.dealForSubList(ids, 2000, subList -> {
if (ids.size() <= 2000) {
deleteResourceByIds(ids, request.getProjectId(), userId);
break;
}
List<String> subList = ids.subList(0, 2000);
deleteResourceByIds(subList, request.getProjectId(), userId); deleteResourceByIds(subList, request.getProjectId(), userId);
ids.removeAll(subList); });
}
} }
public void deleteResourceByIds(List<String> ids, String projectId, String userId) { public void deleteResourceByIds(List<String> ids, String projectId, String userId) {
@ -374,15 +368,9 @@ public class ApiTestCaseService {
if (CollectionUtils.isEmpty(ids)) { if (CollectionUtils.isEmpty(ids)) {
return; return;
} }
while (!ids.isEmpty()) { SubListUtils.dealForSubList(ids, 2000, subList -> {
if (ids.size() <= 2000) {
batchMoveToGc(ids, userId, projectId, saveLog);
break;
}
List<String> subList = ids.subList(0, 2000);
batchMoveToGc(subList, userId, projectId, saveLog); batchMoveToGc(subList, userId, projectId, saveLog);
ids.removeAll(subList); });
}
} }
private void batchMoveToGc(List<String> ids, String userId, String projectId, boolean saveLog) { private void batchMoveToGc(List<String> ids, String userId, String projectId, boolean saveLog) {
@ -398,15 +386,9 @@ public class ApiTestCaseService {
if (CollectionUtils.isEmpty(ids)) { if (CollectionUtils.isEmpty(ids)) {
return; return;
} }
while (!ids.isEmpty()) { SubListUtils.dealForSubList(ids, 2000, subList -> {
if (ids.size() <= 2000) {
batchEditByType(request, ids, userId, request.getProjectId());
break;
}
List<String> subList = ids.subList(0, 2000);
batchEditByType(request, subList, userId, request.getProjectId()); batchEditByType(request, subList, userId, request.getProjectId());
ids.removeAll(subList); });
}
} }
private void batchEditByType(ApiCaseBatchEditRequest request, List<String> ids, String userId, String projectId) { private void batchEditByType(ApiCaseBatchEditRequest request, List<String> ids, String userId, String projectId) {
@ -487,4 +469,13 @@ public class ApiTestCaseService {
updateCase.setPriority(priority); updateCase.setPriority(priority);
apiTestCaseMapper.updateByExampleSelective(updateCase, example); apiTestCaseMapper.updateByExampleSelective(updateCase, example);
} }
public void editPos(PosRequest request) {
ServiceUtils.updatePosField(request,
ApiTestCase.class,
apiTestCaseMapper::selectByPrimaryKey,
extApiTestCaseMapper::getPrePos,
extApiTestCaseMapper::getLastPos,
apiTestCaseMapper::updateByPrimaryKeySelective);
}
} }

View File

@ -5,16 +5,14 @@ import io.metersphere.api.dto.debug.ApiDebugRequest;
import io.metersphere.api.dto.debug.ModuleCreateRequest; import io.metersphere.api.dto.debug.ModuleCreateRequest;
import io.metersphere.api.dto.debug.ModuleUpdateRequest; import io.metersphere.api.dto.debug.ModuleUpdateRequest;
import io.metersphere.api.dto.definition.ApiModuleRequest; import io.metersphere.api.dto.definition.ApiModuleRequest;
import io.metersphere.api.mapper.ApiDefinitionBlobMapper; import io.metersphere.api.mapper.*;
import io.metersphere.api.mapper.ApiDefinitionMapper;
import io.metersphere.api.mapper.ApiDefinitionModuleMapper;
import io.metersphere.api.mapper.ApiTestCaseMapper;
import io.metersphere.api.service.definition.ApiDefinitionModuleService; import io.metersphere.api.service.definition.ApiDefinitionModuleService;
import io.metersphere.project.domain.Project; import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.ApplicationNumScope; import io.metersphere.sdk.constants.ApplicationNumScope;
import io.metersphere.sdk.constants.ModuleConstants; import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.dto.api.request.http.MsHTTPElement;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest; import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder; import io.metersphere.system.controller.handler.ResultHolder;
@ -26,7 +24,11 @@ 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;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.jupiter.api.*; import org.junit.jupiter.api.*;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@ -70,7 +72,7 @@ public class ApiDefinitionModuleControllerTests extends BaseTest {
@Resource @Resource
private ApiDefinitionModuleService apiDefinitionModuleService; private ApiDefinitionModuleService apiDefinitionModuleService;
@Resource @Resource
private ApiTestCaseMapper apiTestCaseMapper; private SqlSessionFactory sqlSessionFactory;
@Autowired @Autowired
public ApiDefinitionModuleControllerTests(ProjectServiceInvoker serviceInvoker) { public ApiDefinitionModuleControllerTests(ProjectServiceInvoker serviceInvoker) {
@ -148,7 +150,10 @@ public class ApiDefinitionModuleControllerTests extends BaseTest {
apiDefinitionBlob.setResponse(new byte[0]); apiDefinitionBlob.setResponse(new byte[0]);
apiDefinitionBlobMapper.insertSelective(apiDefinitionBlob); apiDefinitionBlobMapper.insertSelective(apiDefinitionBlob);
List<ApiTestCase> apiTestCasesList = new ArrayList<>(); MsHTTPElement msHttpElement = MsHTTPElementTest.getMsHttpElement();
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiTestCaseMapper caseMapper = sqlSession.getMapper(ApiTestCaseMapper.class);
ApiTestCaseBlobMapper caseBlobMapper = sqlSession.getMapper(ApiTestCaseBlobMapper.class);
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
ApiTestCase apiTestCase = new ApiTestCase(); ApiTestCase apiTestCase = new ApiTestCase();
apiTestCase.setId(IDGenerator.nextStr()); apiTestCase.setId(IDGenerator.nextStr());
@ -165,9 +170,14 @@ public class ApiDefinitionModuleControllerTests extends BaseTest {
apiTestCase.setUpdateUser("admin"); apiTestCase.setUpdateUser("admin");
apiTestCase.setVersionId("1.0"); apiTestCase.setVersionId("1.0");
apiTestCase.setDeleted(false); apiTestCase.setDeleted(false);
apiTestCasesList.add(apiTestCase); caseMapper.insert(apiTestCase);
ApiTestCaseBlob apiTestCaseBlob = new ApiTestCaseBlob();
apiTestCaseBlob.setId(apiTestCase.getId());
apiTestCaseBlob.setRequest(JSON.toJSONBytes(msHttpElement));
caseBlobMapper.insert(apiTestCaseBlob);
} }
apiTestCaseMapper.batchInsert(apiTestCasesList); sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
} }
@Test @Test

View File

@ -20,14 +20,20 @@ import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest; import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder; import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.dto.sdk.request.PosRequest;
import io.metersphere.system.file.FileRequest; import io.metersphere.system.file.FileRequest;
import io.metersphere.system.file.MinioRepository; import io.metersphere.system.file.MinioRepository;
import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.uid.NumGenerator; import io.metersphere.system.uid.NumGenerator;
import io.metersphere.system.utils.Pager; import io.metersphere.system.utils.Pager;
import io.metersphere.system.utils.ServiceUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.jupiter.api.*; import org.junit.jupiter.api.*;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@ -53,7 +59,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@AutoConfigureMockMvc @AutoConfigureMockMvc
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class ApiTestCaseControllerTests extends BaseTest { public class ApiTestCaseControllerTests extends BaseTest {
private static final String BASE_PATH = "/api/testCase/"; private static final String BASE_PATH = "/api/case/";
private static final String ADD = BASE_PATH + "add"; private static final String ADD = BASE_PATH + "add";
private static final String GET = BASE_PATH + "get-detail/"; private static final String GET = BASE_PATH + "get-detail/";
private static final String MOVE_TO_GC = BASE_PATH + "move-gc/"; private static final String MOVE_TO_GC = BASE_PATH + "move-gc/";
@ -68,6 +74,7 @@ public class ApiTestCaseControllerTests extends BaseTest {
private static final String BATCH_EDIT = BASE_PATH + "batch/edit"; private static final String BATCH_EDIT = BASE_PATH + "batch/edit";
private static final String BATCH_DELETE = BASE_PATH + "batch/delete"; private static final String BATCH_DELETE = BASE_PATH + "batch/delete";
private static final String BATCH_MOVE_GC = BASE_PATH + "batch/move-gc"; private static final String BATCH_MOVE_GC = BASE_PATH + "batch/move-gc";
private static final String POS_URL = BASE_PATH + "/edit/pos";
private static final ResultMatcher ERROR_REQUEST_MATCHER = status().is5xxServerError(); private static final ResultMatcher ERROR_REQUEST_MATCHER = status().is5xxServerError();
private static ApiTestCase apiTestCase; private static ApiTestCase apiTestCase;
@ -87,6 +94,10 @@ public class ApiTestCaseControllerTests extends BaseTest {
private EnvironmentMapper environmentMapper; private EnvironmentMapper environmentMapper;
@Resource @Resource
private ApiFileResourceService apiFileResourceService; private ApiFileResourceService apiFileResourceService;
@Resource
private SqlSessionFactory sqlSessionFactory;
@Resource
private ExtApiTestCaseMapper extApiTestCaseMapper;
public static <T> T parseObjectFromMvcResult(MvcResult mvcResult, Class<T> parseClass) { public static <T> T parseObjectFromMvcResult(MvcResult mvcResult, Class<T> parseClass) {
try { try {
@ -142,7 +153,10 @@ public class ApiTestCaseControllerTests extends BaseTest {
public void initCaseData() { public void initCaseData() {
//2000条数据 //2000条数据
List<ApiTestCase> apiTestCasesList = new ArrayList<>(); MsHTTPElement msHttpElement = MsHTTPElementTest.getMsHttpElement();
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiTestCaseMapper caseMapper = sqlSession.getMapper(ApiTestCaseMapper.class);
ApiTestCaseBlobMapper caseBlobMapper = sqlSession.getMapper(ApiTestCaseBlobMapper.class);
for (int i = 0; i < 2100; i++) { for (int i = 0; i < 2100; i++) {
ApiTestCase apiTestCase = new ApiTestCase(); ApiTestCase apiTestCase = new ApiTestCase();
apiTestCase.setId("apiTestCaseId" + i); apiTestCase.setId("apiTestCaseId" + i);
@ -159,10 +173,14 @@ public class ApiTestCaseControllerTests extends BaseTest {
apiTestCase.setUpdateUser("admin"); apiTestCase.setUpdateUser("admin");
apiTestCase.setVersionId("1.0"); apiTestCase.setVersionId("1.0");
apiTestCase.setDeleted(false); apiTestCase.setDeleted(false);
apiTestCasesList.add(apiTestCase); caseMapper.insert(apiTestCase);
ApiTestCaseBlob apiTestCaseBlob = new ApiTestCaseBlob();
apiTestCaseBlob.setId(apiTestCase.getId());
apiTestCaseBlob.setRequest(JSON.toJSONBytes(msHttpElement));
caseBlobMapper.insert(apiTestCaseBlob);
} }
apiTestCaseMapper.batchInsert(apiTestCasesList); sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
} }
@ -408,6 +426,38 @@ public class ApiTestCaseControllerTests extends BaseTest {
@Test @Test
@Order(8) @Order(8)
public void testPos() throws Exception {
PosRequest posRequest = new PosRequest();
posRequest.setProjectId(DEFAULT_PROJECT_ID);
posRequest.setTargetId(apiTestCase.getId());
posRequest.setMoveId(anotherApiTestCase.getId());
posRequest.setMoveMode("AFTER");
this.requestPostWithOkAndReturn(POS_URL, posRequest);
posRequest.setMoveMode("BEFORE");
this.requestPostWithOkAndReturn(POS_URL, posRequest);
}
@Test
@Order(9)
public void test() throws Exception {
PosRequest request = new PosRequest();
request.setProjectId(DEFAULT_PROJECT_ID);
request.setTargetId(apiTestCase.getId());
request.setMoveId(anotherApiTestCase.getId());
request.setMoveMode("AFTER");
ServiceUtils.updatePosField(request,
ApiTestCase.class,
apiTestCaseMapper::selectByPrimaryKey,
extApiTestCaseMapper::getPrePos,
extApiTestCaseMapper::getLastPos,
apiTestCaseMapper::updateByPrimaryKeySelective);
}
@Test
@Order(10)
public void page() throws Exception { public void page() throws Exception {
// @@请求成功 // @@请求成功
ApiTestCaseAddRequest request = new ApiTestCaseAddRequest(); ApiTestCaseAddRequest request = new ApiTestCaseAddRequest();
@ -469,7 +519,7 @@ public class ApiTestCaseControllerTests extends BaseTest {
} }
@Test @Test
@Order(9) @Order(11)
public void updateStatus() throws Exception { public void updateStatus() throws Exception {
// @@请求成功 // @@请求成功
this.requestGetWithOk(UPDATE_STATUS + "/" + apiTestCase.getId() + "/Underway"); this.requestGetWithOk(UPDATE_STATUS + "/" + apiTestCase.getId() + "/Underway");
@ -483,7 +533,7 @@ public class ApiTestCaseControllerTests extends BaseTest {
} }
@Test @Test
@Order(10) @Order(12)
public void batchEdit() throws Exception { public void batchEdit() throws Exception {
// 追加标签 // 追加标签
ApiCaseBatchEditRequest request = new ApiCaseBatchEditRequest(); ApiCaseBatchEditRequest request = new ApiCaseBatchEditRequest();
@ -586,7 +636,7 @@ public class ApiTestCaseControllerTests extends BaseTest {
} }
@Test @Test
@Order(11) @Order(13)
public void batchMoveGc() throws Exception { public void batchMoveGc() throws Exception {
// @@请求成功 // @@请求成功
ApiTestCaseBatchRequest request = new ApiTestCaseBatchRequest(); ApiTestCaseBatchRequest request = new ApiTestCaseBatchRequest();
@ -616,7 +666,7 @@ public class ApiTestCaseControllerTests extends BaseTest {
} }
@Test @Test
@Order(12) @Order(14)
public void trashPage() throws Exception { public void trashPage() throws Exception {
// @@请求成功 // @@请求成功
ApiTestCasePageRequest pageRequest = new ApiTestCasePageRequest(); ApiTestCasePageRequest pageRequest = new ApiTestCasePageRequest();

View File

@ -85,6 +85,6 @@ minio.endpoint=http://${embedded.minio.host}:${embedded.minio.port}
minio.access-key=${embedded.minio.accessKey} minio.access-key=${embedded.minio.accessKey}
minio.secret-key=${embedded.minio.secretKey} minio.secret-key=${embedded.minio.secretKey}
logging.level.org.springframework.jdbc.core=info logging.level.org.springframework.jdbc.core=debug
logging.level.io.metersphere.sdk.mapper=info logging.level.io.metersphere.sdk.mapper=debug
logging.level.io.metersphere.project.mapper=info logging.level.io.metersphere.project.mapper=debug

View File

@ -0,0 +1,17 @@
package io.metersphere.system.controller;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;
@Service
public class ExtGetPosService {
public Long getPrePos(@Param("projectId") String projectId, @Param("basePos") Long basePos) {
return 100L;
}
public Long getLastPos(@Param("projectId") String projectId, @Param("basePos") Long basePos) {
return 120L;
}
}

View File

@ -1,5 +1,7 @@
package io.metersphere.system.controller; package io.metersphere.system.controller;
import io.metersphere.api.domain.ApiTestCase;
import io.metersphere.api.mapper.ApiTestCaseMapper;
import io.metersphere.project.domain.Project; import io.metersphere.project.domain.Project;
import io.metersphere.project.domain.ProjectExample; import io.metersphere.project.domain.ProjectExample;
import io.metersphere.project.domain.ProjectTestResourcePool; import io.metersphere.project.domain.ProjectTestResourcePool;
@ -18,6 +20,7 @@ import io.metersphere.system.dto.request.ProjectAddMemberRequest;
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.sdk.request.CustomFieldOptionRequest; import io.metersphere.system.dto.sdk.request.CustomFieldOptionRequest;
import io.metersphere.system.dto.sdk.request.PosRequest;
import io.metersphere.system.dto.sdk.request.TemplateCustomFieldRequest; import io.metersphere.system.dto.sdk.request.TemplateCustomFieldRequest;
import io.metersphere.system.dto.sdk.request.TemplateUpdateRequest; import io.metersphere.system.dto.sdk.request.TemplateUpdateRequest;
import io.metersphere.system.dto.user.UserExtendDTO; import io.metersphere.system.dto.user.UserExtendDTO;
@ -28,7 +31,9 @@ import io.metersphere.system.mapper.OrganizationParameterMapper;
import io.metersphere.system.mapper.UserMapper; import io.metersphere.system.mapper.UserMapper;
import io.metersphere.system.mapper.UserRoleRelationMapper; import io.metersphere.system.mapper.UserRoleRelationMapper;
import io.metersphere.system.service.*; import io.metersphere.system.service.*;
import io.metersphere.system.uid.NumGenerator;
import io.metersphere.system.utils.Pager; import io.metersphere.system.utils.Pager;
import io.metersphere.system.utils.ServiceUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.BooleanUtils;
@ -109,6 +114,10 @@ public class SystemProjectControllerTests extends BaseTest {
@Resource @Resource
private CleanProjectJob cleanProjectJob; private CleanProjectJob cleanProjectJob;
private final ProjectServiceInvoker serviceInvoker; private final ProjectServiceInvoker serviceInvoker;
@Resource
private ApiTestCaseMapper apiTestCaseMapper;
@Resource
private ExtGetPosService extGetPosService;
@Autowired @Autowired
public SystemProjectControllerTests(ProjectServiceInvoker serviceInvoker) { public SystemProjectControllerTests(ProjectServiceInvoker serviceInvoker) {
@ -1147,4 +1156,64 @@ public class SystemProjectControllerTests extends BaseTest {
this.requestPost(updateName, project, ERROR_REQUEST_MATCHER); this.requestPost(updateName, project, ERROR_REQUEST_MATCHER);
} }
@Test
@Order(26)
public void test() throws Exception {
ApiTestCase apiTestCase = new ApiTestCase();
apiTestCase.setId("test-apiTestCaseId");
apiTestCase.setApiDefinitionId("apiDefinitionId");
apiTestCase.setProjectId(DEFAULT_PROJECT_ID);
apiTestCase.setName("test-apiTestCaseName");
apiTestCase.setPriority("P0");
apiTestCase.setStatus("Underway");
apiTestCase.setNum(NumGenerator.nextNum(DEFAULT_PROJECT_ID + "_" + "100001", ApplicationNumScope.API_TEST_CASE));
apiTestCase.setPos(100L);
apiTestCase.setCreateTime(System.currentTimeMillis());
apiTestCase.setUpdateTime(System.currentTimeMillis());
apiTestCase.setCreateUser("admin");
apiTestCase.setUpdateUser("admin");
apiTestCase.setVersionId("1.0");
apiTestCase.setDeleted(false);
apiTestCaseMapper.insert(apiTestCase);
ApiTestCase anotherCase = new ApiTestCase();
anotherCase.setId("test-apiTestCaseId1");
anotherCase.setApiDefinitionId("apiDefinitionId");
anotherCase.setProjectId(DEFAULT_PROJECT_ID);
anotherCase.setName("test-apiTestCaseName1");
anotherCase.setPriority("P0");
anotherCase.setStatus("Underway");
anotherCase.setNum(NumGenerator.nextNum(DEFAULT_PROJECT_ID + "_" + "100001", ApplicationNumScope.API_TEST_CASE));
anotherCase.setPos(120L);
anotherCase.setCreateTime(System.currentTimeMillis());
anotherCase.setUpdateTime(System.currentTimeMillis());
anotherCase.setCreateUser("admin");
anotherCase.setUpdateUser("admin");
anotherCase.setVersionId("1.0");
anotherCase.setDeleted(false);
apiTestCaseMapper.insert(anotherCase);
PosRequest request = new PosRequest();
request.setProjectId(DEFAULT_PROJECT_ID);
request.setTargetId(apiTestCase.getId());
request.setMoveId(anotherCase.getId());
request.setMoveMode("AFTER");
ServiceUtils.updatePosField(request,
ApiTestCase.class,
apiTestCaseMapper::selectByPrimaryKey,
extGetPosService::getPrePos,
extGetPosService::getLastPos,
apiTestCaseMapper::updateByPrimaryKeySelective);
request.setMoveMode("BEFORE");
ServiceUtils.updatePosField(request,
ApiTestCase.class,
apiTestCaseMapper::selectByPrimaryKey,
extGetPosService::getPrePos,
extGetPosService::getLastPos,
apiTestCaseMapper::updateByPrimaryKeySelective);
apiTestCaseMapper.deleteByPrimaryKey(apiTestCase.getId());
apiTestCaseMapper.deleteByPrimaryKey(anotherCase.getId());
}
} }