feat(接口测试): 接口通过率开发
This commit is contained in:
parent
35af224764
commit
1f46ee6b9a
|
@ -2,6 +2,7 @@ package io.metersphere.api.controller.definition;
|
|||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.api.constants.ApiScenarioStepType;
|
||||
import io.metersphere.api.domain.ApiDefinition;
|
||||
import io.metersphere.api.dto.ReferenceDTO;
|
||||
import io.metersphere.api.dto.ReferenceRequest;
|
||||
|
@ -10,8 +11,12 @@ import io.metersphere.api.dto.request.ApiEditPosRequest;
|
|||
import io.metersphere.api.dto.request.ApiTransferRequest;
|
||||
import io.metersphere.api.dto.request.ImportRequest;
|
||||
import io.metersphere.api.dto.schema.JsonSchemaItem;
|
||||
import io.metersphere.api.mapper.ExtApiDefinitionMapper;
|
||||
import io.metersphere.api.mapper.ExtApiScenarioStepMapper;
|
||||
import io.metersphere.api.mapper.ExtApiTestCaseMapper;
|
||||
import io.metersphere.api.service.ApiFileResourceService;
|
||||
import io.metersphere.api.service.definition.*;
|
||||
import io.metersphere.api.service.scenario.ApiScenarioService;
|
||||
import io.metersphere.project.service.FileModuleService;
|
||||
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
|
@ -34,6 +39,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.authz.annotation.Logical;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
|
@ -41,6 +47,7 @@ import org.springframework.validation.annotation.Validated;
|
|||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
@ -51,6 +58,14 @@ import java.util.List;
|
|||
@RequestMapping(value = "/api/definition")
|
||||
@Tag(name = "接口测试-接口管理-接口定义")
|
||||
public class ApiDefinitionController {
|
||||
|
||||
@Resource
|
||||
private ExtApiDefinitionMapper extApiDefinitionMapper;
|
||||
@Resource
|
||||
private ExtApiTestCaseMapper extApiTestCaseMapper;
|
||||
@Resource
|
||||
private ExtApiScenarioStepMapper extApiScenarioStepMapper;
|
||||
|
||||
@Resource
|
||||
private ApiDefinitionService apiDefinitionService;
|
||||
@Resource
|
||||
|
@ -61,12 +76,55 @@ public class ApiDefinitionController {
|
|||
private ApiDefinitionImportService apiDefinitionImportService;
|
||||
@Resource
|
||||
private ApiDefinitionExportService apiDefinitionExportService;
|
||||
@Resource
|
||||
private ApiScenarioService apiScenarioService;
|
||||
|
||||
/*
|
||||
接口覆盖率
|
||||
业务注释,误删
|
||||
* 一个接口如果被跨项目的场景给关联了,算不算覆盖? 不算
|
||||
* 自定义请求, 不管它有多少个“/"有多少子域 , 跟接口定义匹配的时候就用末端匹配法。
|
||||
· 例如:https://www.tapd.cn/tapd_fe/my/work?dialog_preview_id=abcdefg
|
||||
·/work能匹配的上
|
||||
·/my/work能匹配的上
|
||||
·/my 不可以
|
||||
·/my/{something}可以匹配的上
|
||||
·/my/{something}/{other-thing}不可以
|
||||
* 剩下的基本上就跟V2一样了. 有用例 or 被场景引用/复制 or 被自定义给命中了 就算覆盖。 且自定义请求可以命中多个接口定义,比如上一点
|
||||
*/
|
||||
@GetMapping("/rage/{projectId}")
|
||||
@Operation(summary = "接口测试-接口管理-接口列表(deleted 状态为 1 时为回收站数据)")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ)
|
||||
@CheckOwner(resourceId = "#projectId", resourceType = "project")
|
||||
public ApiCoverageDTO rage(@PathVariable String projectId) {
|
||||
List<String> apiAllIds = new ArrayList<>();
|
||||
List<ApiDefinition> httpApiList = new ArrayList<>();
|
||||
extApiDefinitionMapper.selectBaseInfoByProjectId(projectId).forEach(apiDefinition -> {
|
||||
if (StringUtils.equalsIgnoreCase(apiDefinition.getProtocol(), "http")) {
|
||||
httpApiList.add(apiDefinition);
|
||||
}
|
||||
apiAllIds.add(apiDefinition.getId());
|
||||
});
|
||||
|
||||
List<String> apiDefinitionIdFromCase = extApiTestCaseMapper.selectApiId(projectId);
|
||||
List<String> apiInScenarioStep = extApiScenarioStepMapper.selectResourceId(projectId, ApiScenarioStepType.API.name());
|
||||
List<String> apiCaseIdInStep = extApiScenarioStepMapper.selectResourceId(projectId, ApiScenarioStepType.API_CASE.name());
|
||||
if (CollectionUtils.isNotEmpty(apiCaseIdInStep)) {
|
||||
List<String> apiCaseIdInScenarioStep = extApiTestCaseMapper.selectApiIdByCaseId(apiCaseIdInStep);
|
||||
apiInScenarioStep.addAll(apiCaseIdInScenarioStep);
|
||||
}
|
||||
|
||||
List<String> apiInStepList = apiScenarioService.selectApiIdInCustomRequest(projectId, httpApiList);
|
||||
apiInStepList.addAll(apiInScenarioStep);
|
||||
|
||||
return new ApiCoverageDTO(apiAllIds, apiDefinitionIdFromCase, apiInStepList);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/add")
|
||||
@Operation(summary = "接口测试-接口管理-添加接口定义")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_ADD)
|
||||
@Log(type = OperationLogType.ADD, expression = "#msClass.addLog(#request)", msClass = ApiDefinitionLogService.class)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
@CheckOwner(resourceId = "#request.getProjectId()s", resourceType = "project")
|
||||
@SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, event = NoticeConstants.Event.CREATE, target = "#targetClass.getApiDTO(#request)", targetClass = ApiDefinitionNoticeService.class)
|
||||
public ApiDefinition add(@Validated @RequestBody ApiDefinitionAddRequest request) {
|
||||
return apiDefinitionService.create(request, SessionUtils.getUserId());
|
||||
|
|
|
@ -3,10 +3,6 @@ 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.*;
|
||||
import io.metersphere.api.dto.scenario.ApiScenarioBatchCopyMoveRequest;
|
||||
import io.metersphere.api.dto.scenario.ApiScenarioBatchEditRequest;
|
||||
import io.metersphere.api.dto.scenario.ApiScenarioBatchRequest;
|
||||
import io.metersphere.api.dto.scenario.ApiScenarioBatchRunRequest;
|
||||
import io.metersphere.api.service.ApiValidateService;
|
||||
import io.metersphere.api.service.scenario.ApiScenarioBatchRunService;
|
||||
import io.metersphere.api.service.scenario.ApiScenarioNoticeService;
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package io.metersphere.api.dto.definition;
|
||||
|
||||
import io.metersphere.sdk.util.CalculateUtils;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lan
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class ApiCoverageDTO {
|
||||
|
||||
@Schema(description = "接口定义总量")
|
||||
private int allApiCount;
|
||||
|
||||
@Schema(description = "接口定义未覆盖")
|
||||
private int unCoverWithApiDefinition;
|
||||
|
||||
@Schema(description = "接口定义已覆盖")
|
||||
private int coverWithApiDefinition;
|
||||
|
||||
@Schema(description = "接口覆盖率 接口(URL)有(用例或场景步骤)数/接口总数*100%")
|
||||
private String apiCoverage;
|
||||
|
||||
@Schema(description = "接口用例未覆盖")
|
||||
private int unCoverWithApiCase;
|
||||
|
||||
@Schema(description = "接口用例已覆盖")
|
||||
private int coverWithApiCase;
|
||||
|
||||
@Schema(description = "用例覆盖率 有用例的接口/接口总数*100%")
|
||||
private String apiCaseCoverage;
|
||||
|
||||
@Schema(description = "接口场景未覆盖")
|
||||
private int unCoverWithApiScenario;
|
||||
|
||||
@Schema(description = "接口场景已覆盖")
|
||||
private int coverWithApiScenario;
|
||||
|
||||
@Schema(description = "场景覆盖率 被场景步骤包含的接口(URL)数/接口总数*100%")
|
||||
private String scenarioCoverage;
|
||||
|
||||
public ApiCoverageDTO(List<String> allApiId, List<String> haveCaseIdList, List<String> apiIdOrUrlInStepList) {
|
||||
// 去重、过滤(只留下apiId中存在的数据,避免已删除的apiId导致统计错误)
|
||||
allApiId = allApiId.stream().distinct().toList();
|
||||
haveCaseIdList = this.elementInList(allApiId, haveCaseIdList.stream().distinct().toList());
|
||||
apiIdOrUrlInStepList = this.elementInList(allApiId, apiIdOrUrlInStepList.stream().distinct().toList());
|
||||
|
||||
this.allApiCount = allApiId.size();
|
||||
// 用例覆盖率: 有用例的接口/接口总数*100%
|
||||
this.coverWithApiCase = haveCaseIdList.size();
|
||||
this.unCoverWithApiCase = this.allApiCount - this.coverWithApiCase;
|
||||
this.apiCaseCoverage = CalculateUtils.reportPercentage(coverWithApiCase, allApiCount);
|
||||
|
||||
// 场景覆盖率: 被场景步骤包含的接口(URL)数/接口总数*100%
|
||||
this.coverWithApiScenario = apiIdOrUrlInStepList.size();
|
||||
this.unCoverWithApiScenario = this.allApiCount - this.coverWithApiScenario;
|
||||
this.scenarioCoverage = CalculateUtils.reportPercentage(coverWithApiScenario, allApiCount);
|
||||
|
||||
// 接口覆盖率
|
||||
apiIdOrUrlInStepList.addAll(haveCaseIdList);
|
||||
List<String> allCoverList = apiIdOrUrlInStepList.stream().distinct().toList();
|
||||
this.coverWithApiDefinition = allCoverList.size();
|
||||
this.unCoverWithApiDefinition = this.allApiCount - this.coverWithApiDefinition;
|
||||
this.apiCoverage = CalculateUtils.reportPercentage(coverWithApiDefinition, allApiCount);
|
||||
}
|
||||
|
||||
private List<String> elementInList(List<String> allList, List<String> compareList) {
|
||||
List<String> returnList = new ArrayList<>();
|
||||
compareList.forEach(item -> {
|
||||
if (allList.contains(item)) {
|
||||
returnList.add(item);
|
||||
}
|
||||
});
|
||||
return returnList;
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ public class ApiScenarioBatchEditRequest extends ApiScenarioBatchRequest impleme
|
|||
|
||||
@Schema(description = "标签")
|
||||
private LinkedHashSet<String> tags;
|
||||
@Schema(description = "批量编辑的类型 用例等级: Priority,状态 :Status,标签: Tags,用例环境: Environment, 定时任务:Schedule")
|
||||
@Schema(description = "批量编辑的类型 用例等级: Priority,状态 :Status,标签: Tags,用例环境: Environment")
|
||||
@NotBlank
|
||||
private String type;
|
||||
@Schema(description = "默认覆盖原标签")
|
||||
|
@ -40,8 +40,6 @@ public class ApiScenarioBatchEditRequest extends ApiScenarioBatchRequest impleme
|
|||
@Schema(description = "用例等级")
|
||||
@Size(max = 50, message = "{api_test_case.priority.length_range}")
|
||||
private String priority;
|
||||
@Schema(description = "定时任务是否开启")
|
||||
private boolean scheduleOpen;
|
||||
public List<String> getTags() {
|
||||
if (tags == null) {
|
||||
return new ArrayList<>(0);
|
||||
|
|
|
@ -2,7 +2,6 @@ package io.metersphere.api.dto.scenario;
|
|||
|
||||
import io.metersphere.sdk.dto.api.task.ApiRunModeConfigDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
|
@ -18,7 +17,6 @@ public class ApiScenarioBatchScheduleConfigRequest extends ApiScenarioBatchReque
|
|||
private boolean enable;
|
||||
|
||||
@Schema(description = "Cron表达式")
|
||||
@NotBlank
|
||||
private String cron;
|
||||
|
||||
@Schema(description = "定时任务配置")
|
||||
|
|
|
@ -129,4 +129,5 @@ public interface ExtApiDefinitionMapper {
|
|||
|
||||
List<ApiDefinition> getCreateApiList(@Param("projectId") String projectId, @Param("startTime") Long startTime, @Param("endTime") Long endTime);
|
||||
|
||||
List<ApiDefinition> selectBaseInfoByProjectId(String projectId);
|
||||
}
|
||||
|
|
|
@ -838,4 +838,10 @@
|
|||
AND api_definition.create_time BETWEEN #{startTime} AND #{endTime}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectBaseInfoByProjectId" resultType="io.metersphere.api.domain.ApiDefinition">
|
||||
SELECT id, path, method, protocol
|
||||
FROM api_definition
|
||||
WHERE project_id = #{0}
|
||||
AND deleted IS FALSE
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.metersphere.api.mapper;
|
||||
|
||||
import io.metersphere.api.domain.ApiScenarioCsvStep;
|
||||
import io.metersphere.api.domain.ApiScenarioStep;
|
||||
import io.metersphere.api.dto.scenario.ApiScenarioStepDTO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
|
@ -25,4 +26,8 @@ public interface ExtApiScenarioStepMapper {
|
|||
* @return
|
||||
*/
|
||||
List<String> getHasBlobRequestStepIds(@Param("scenarioId") String scenarioId);
|
||||
|
||||
List<String> selectResourceId(@Param("projectId") String projectId, @Param("stepType") String stepType);
|
||||
|
||||
List<ApiScenarioStep> selectCustomRequestConfigByProjectId(String projectId);
|
||||
}
|
||||
|
|
|
@ -28,4 +28,21 @@
|
|||
and step_type in ('API', 'API_CASE', 'CUSTOM_REQUEST')
|
||||
and ref_type in ('COPY', 'DIRECT')
|
||||
</select>
|
||||
<select id="selectResourceId" resultType="java.lang.String">
|
||||
select DISTINCT step.resource_id
|
||||
from api_scenario_step step
|
||||
INNER JOIN api_scenario scenario
|
||||
ON step.scenario_id = scenario.id
|
||||
where step.step_type = #{stepType}
|
||||
AND scenario.project_id = #{projectId}
|
||||
AND scenario.deleted IS FALSE
|
||||
</select>
|
||||
<select id="selectCustomRequestConfigByProjectId" resultType="io.metersphere.api.domain.ApiScenarioStep">
|
||||
select step.id, step.config
|
||||
from api_scenario_step step
|
||||
INNER JOIN api_scenario scenario
|
||||
ON step.scenario_id = scenario.id
|
||||
where scenario.project_id = #{0}
|
||||
AND scenario.deleted IS FALSE
|
||||
</select>
|
||||
</mapper>
|
|
@ -139,4 +139,8 @@ public interface ExtApiTestCaseMapper {
|
|||
|
||||
List<ApiTestCase> getSimpleApiCaseList(@Param("projectId") String projectId, @Param("startTime") Long startTime, @Param("endTime") Long endTime);
|
||||
|
||||
|
||||
List<String> selectApiId(String projectId);
|
||||
|
||||
List<String> selectApiIdByCaseId(@Param("ids") List<String> apiCaseIdInStep);
|
||||
}
|
|
@ -1031,4 +1031,18 @@
|
|||
</if>
|
||||
</select>
|
||||
|
||||
<select id="selectApiId" resultType="java.lang.String">
|
||||
SELECT distinct api.id
|
||||
FROM api_test_case apiCase
|
||||
INNER JOIN api_definition api ON apiCase.api_definition_id = api.id
|
||||
WHERE apiCase.deleted is FALSE
|
||||
AND api.deleted is FALSE
|
||||
AND api.project_id = #{0}
|
||||
</select>
|
||||
<select id="selectApiIdByCaseId" resultType="java.lang.String">
|
||||
SELECT api_definition_id FROM api_test_case WHERE deleted is false AND id in
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
</mapper>
|
|
@ -25,10 +25,12 @@ import io.metersphere.api.service.ApiFileResourceService;
|
|||
import io.metersphere.api.service.definition.ApiDefinitionService;
|
||||
import io.metersphere.api.service.definition.ApiTestCaseService;
|
||||
import io.metersphere.api.utils.ApiDataUtils;
|
||||
import io.metersphere.api.utils.ApiDefinitionUtils;
|
||||
import io.metersphere.api.utils.ApiScenarioBatchOperationUtils;
|
||||
import io.metersphere.api.utils.ApiScenarioUtils;
|
||||
import io.metersphere.functional.domain.FunctionalCaseTestExample;
|
||||
import io.metersphere.functional.mapper.FunctionalCaseTestMapper;
|
||||
import io.metersphere.plugin.api.spi.AbstractMsProtocolTestElement;
|
||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||
import io.metersphere.project.domain.*;
|
||||
import io.metersphere.project.dto.MoveNodeSortDTO;
|
||||
|
@ -278,7 +280,6 @@ public class ApiScenarioService extends MoveNodeService {
|
|||
case STATUS -> batchUpdateStatus(example, updateScenario, request.getStatus(), mapper);
|
||||
case TAGS -> batchUpdateTags(example, updateScenario, request, ids, mapper);
|
||||
case ENVIRONMENT -> batchUpdateEnvironment(example, updateScenario, request, mapper);
|
||||
case SCHEDULE -> batchUpdateSchedule(example, request, mapper, userId);
|
||||
default -> throw new MSException(Translator.get("batch_edit_type_error"));
|
||||
}
|
||||
sqlSession.flushStatements();
|
||||
|
@ -288,15 +289,6 @@ public class ApiScenarioService extends MoveNodeService {
|
|||
apiScenarioNoticeService.batchSendNotice(ids, userId, projectId, NoticeConstants.Event.UPDATE);
|
||||
}
|
||||
|
||||
private void batchUpdateSchedule(ApiScenarioExample example, ApiScenarioBatchEditRequest request, ApiScenarioMapper mapper, String userId) {
|
||||
List<ApiScenario> apiScenarioList = mapper.selectByExample(example);
|
||||
//批量编辑定时任务
|
||||
for (ApiScenario apiScenario : apiScenarioList) {
|
||||
scheduleService.updateIfExist(apiScenario.getId(), request.isScheduleOpen(), ApiScenarioScheduleJob.getJobKey(apiScenario.getId()),
|
||||
ApiScenarioScheduleJob.getTriggerKey(apiScenario.getId()), ApiScenarioScheduleJob.class, userId);
|
||||
}
|
||||
}
|
||||
|
||||
private void batchUpdateEnvironment(ApiScenarioExample example, ApiScenario updateScenario,
|
||||
ApiScenarioBatchEditRequest request, ApiScenarioMapper mapper) {
|
||||
if (BooleanUtils.isFalse(request.isGrouped())) {
|
||||
|
@ -2566,30 +2558,42 @@ public class ApiScenarioService extends MoveNodeService {
|
|||
List<ApiScenario> apiScenarios = apiScenarioMapper.selectByExample(example);
|
||||
|
||||
if (CollectionUtils.isNotEmpty(apiScenarios)) {
|
||||
apiScenarios.forEach(apiScenario -> {
|
||||
ScheduleConfig scheduleConfig = ScheduleConfig.builder()
|
||||
.resourceId(apiScenario.getId())
|
||||
.key(apiScenario.getId())
|
||||
.projectId(apiScenario.getProjectId())
|
||||
.name(apiScenario.getName())
|
||||
.enable(request.isEnable())
|
||||
.cron(request.getCron())
|
||||
.resourceType(ScheduleResourceType.API_SCENARIO.name())
|
||||
.config(JSON.toJSONString(request.getConfig()))
|
||||
.build();
|
||||
if (StringUtils.isBlank(request.getCron()) && request.getConfig() == null) {
|
||||
this.batchUpdateSchedule(apiScenarios, request.isEnable(), operator);
|
||||
} else {
|
||||
apiScenarios.forEach(apiScenario -> {
|
||||
ScheduleConfig scheduleConfig = ScheduleConfig.builder()
|
||||
.resourceId(apiScenario.getId())
|
||||
.key(apiScenario.getId())
|
||||
.projectId(apiScenario.getProjectId())
|
||||
.name(apiScenario.getName())
|
||||
.enable(request.isEnable())
|
||||
.cron(request.getCron())
|
||||
.resourceType(ScheduleResourceType.API_SCENARIO.name())
|
||||
.config(JSON.toJSONString(request.getConfig()))
|
||||
.build();
|
||||
|
||||
scheduleService.scheduleConfig(
|
||||
scheduleConfig,
|
||||
ApiScenarioScheduleJob.getJobKey(apiScenario.getId()),
|
||||
ApiScenarioScheduleJob.getTriggerKey(apiScenario.getId()),
|
||||
ApiScenarioScheduleJob.class,
|
||||
operator);
|
||||
});
|
||||
apiScenarioLogService.batchScheduleConfigLog(request.getProjectId(), apiScenarios, operator);
|
||||
scheduleService.scheduleConfig(
|
||||
scheduleConfig,
|
||||
ApiScenarioScheduleJob.getJobKey(apiScenario.getId()),
|
||||
ApiScenarioScheduleJob.getTriggerKey(apiScenario.getId()),
|
||||
ApiScenarioScheduleJob.class,
|
||||
operator);
|
||||
});
|
||||
apiScenarioLogService.batchScheduleConfigLog(request.getProjectId(), apiScenarios, operator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void batchUpdateSchedule(List<ApiScenario> apiScenarioList, boolean isScheudleOpen, String userId) {
|
||||
//批量编辑定时任务
|
||||
for (ApiScenario apiScenario : apiScenarioList) {
|
||||
scheduleService.updateIfExist(apiScenario.getId(), isScheudleOpen, ApiScenarioScheduleJob.getJobKey(apiScenario.getId()),
|
||||
ApiScenarioScheduleJob.getTriggerKey(apiScenario.getId()), ApiScenarioScheduleJob.class, userId);
|
||||
}
|
||||
}
|
||||
|
||||
// 场景统计相关
|
||||
public List<ApiScenarioDTO> calculateRate(List<String> ids) {
|
||||
List<ApiScenarioDTO> result = new ArrayList<>();
|
||||
|
@ -2619,4 +2623,47 @@ public class ApiScenarioService extends MoveNodeService {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<String> selectApiIdInCustomRequest(String projectId, List<ApiDefinition> apiDefinitions) {
|
||||
List<String> returnList = new ArrayList<>();
|
||||
List<ApiScenarioStep> stepConfigList = extApiScenarioStepMapper.selectCustomRequestConfigByProjectId(projectId);
|
||||
List<String> requestIdList = new ArrayList<>();
|
||||
stepConfigList.forEach(step -> requestIdList.add(step.getId()));
|
||||
if (requestIdList.isEmpty()) {
|
||||
return returnList;
|
||||
}
|
||||
ApiScenarioStepBlobExample scenarioStepBlobExample = new ApiScenarioStepBlobExample();
|
||||
scenarioStepBlobExample.createCriteria().andIdIn(requestIdList);
|
||||
List<ApiScenarioStepBlob> httpRequestStopBlobList = apiScenarioStepBlobMapper.selectByExampleWithBLOBs(scenarioStepBlobExample);
|
||||
Map<String, List<String>> methodPathMap = new HashMap<>();
|
||||
httpRequestStopBlobList.forEach(blob -> {
|
||||
if (blob.getContent() != null) {
|
||||
try {
|
||||
AbstractMsProtocolTestElement protocolTestElement = ApiDataUtils.parseObject(new String(blob.getContent()), AbstractMsProtocolTestElement.class);
|
||||
if (protocolTestElement instanceof MsHTTPElement msHTTPElement) {
|
||||
String method = msHTTPElement.getMethod();
|
||||
if (methodPathMap.containsKey(method)) {
|
||||
methodPathMap.get(method).add(msHTTPElement.getPath());
|
||||
} else {
|
||||
List<String> pathList = new ArrayList<>();
|
||||
pathList.add(msHTTPElement.getPath());
|
||||
methodPathMap.put(method, pathList);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtils.error(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
for (ApiDefinition apiDefinition : apiDefinitions) {
|
||||
if (methodPathMap.containsKey(apiDefinition.getMethod())) {
|
||||
String apiPath = apiDefinition.getPath();
|
||||
List<String> customUrlList = methodPathMap.get(apiDefinition.getMethod());
|
||||
if (ApiDefinitionUtils.isUrlInList(apiPath, customUrlList)) {
|
||||
returnList.add(apiDefinition.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
package io.metersphere.api.utils;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class ApiDefinitionUtils {
|
||||
|
||||
public static boolean isUrlInList(String apiUrl, Collection<String> customRequestUrlList) {
|
||||
if (CollectionUtils.isEmpty(customRequestUrlList)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String urlSuffix = apiUrl.trim();
|
||||
if (urlSuffix.startsWith("/")) {
|
||||
urlSuffix = urlSuffix.substring(1);
|
||||
}
|
||||
String[] urlParams = urlSuffix.split("/");
|
||||
|
||||
for (String customRequestUrl : customRequestUrlList) {
|
||||
if (StringUtils.equalsAny(customRequestUrl, apiUrl, "/" + apiUrl)) {
|
||||
return true;
|
||||
} else {
|
||||
if (StringUtils.isEmpty(customRequestUrl)) {
|
||||
continue;
|
||||
}
|
||||
if (customRequestUrl.startsWith("/")) {
|
||||
customRequestUrl = customRequestUrl.substring(1);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(customRequestUrl)) {
|
||||
String[] customUrlArr = customRequestUrl.split("/");
|
||||
|
||||
if (customUrlArr.length >= urlParams.length) {
|
||||
|
||||
boolean isFetch = true;
|
||||
for (int urlIndex = 0; urlIndex < urlParams.length; urlIndex++) {
|
||||
String urlItem = urlParams[urlIndex];
|
||||
String customUrlItem = customUrlArr[customUrlArr.length - urlParams.length + urlIndex];
|
||||
// 不为rest参数的要进行全匹配。 而且忽略大小写
|
||||
if (isRestUrlParam(customUrlItem) && isRestUrlParam(urlItem)) {
|
||||
if (!StringUtils.equalsIgnoreCase(customUrlItem, urlItem)) {
|
||||
isFetch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isFetch) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isRestUrlParam(String urlParam) {
|
||||
return !StringUtils.startsWith(urlParam, "{") || !StringUtils.endsWith(urlParam, "}") || StringUtils.equals(urlParam, "{}");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,237 @@
|
|||
package io.metersphere.api.controller;
|
||||
|
||||
import io.metersphere.api.constants.*;
|
||||
import io.metersphere.api.domain.ApiDefinition;
|
||||
import io.metersphere.api.domain.ApiDefinitionExample;
|
||||
import io.metersphere.api.domain.ApiScenario;
|
||||
import io.metersphere.api.domain.ApiTestCase;
|
||||
import io.metersphere.api.dto.definition.ApiCoverageDTO;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionAddRequest;
|
||||
import io.metersphere.api.dto.definition.ApiTestCaseAddRequest;
|
||||
import io.metersphere.api.dto.definition.HttpResponse;
|
||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||
import io.metersphere.api.dto.scenario.ApiScenarioAddRequest;
|
||||
import io.metersphere.api.dto.scenario.ApiScenarioStepRequest;
|
||||
import io.metersphere.api.dto.scenario.ApiScenarioUpdateRequest;
|
||||
import io.metersphere.api.mapper.ApiDefinitionMapper;
|
||||
import io.metersphere.api.utils.ApiDataUtils;
|
||||
import io.metersphere.project.domain.Project;
|
||||
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
|
||||
import io.metersphere.project.mapper.ProjectMapper;
|
||||
import io.metersphere.sdk.util.CalculateUtils;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.base.BaseTest;
|
||||
import io.metersphere.system.dto.AddProjectRequest;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.service.CommonProjectService;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@AutoConfigureMockMvc
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class ApiCalculateTest extends BaseTest {
|
||||
private static Project project;
|
||||
|
||||
@Resource
|
||||
private CommonProjectService commonProjectService;
|
||||
@Resource
|
||||
private ExtBaseProjectVersionMapper extBaseProjectVersionMapper;
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
|
||||
@Resource
|
||||
private ApiDefinitionMapper apiDefinitionMapper;
|
||||
|
||||
@BeforeEach
|
||||
public void initTestData() throws Exception {
|
||||
//测试计划专用项目
|
||||
if (project == null) {
|
||||
AddProjectRequest initProject = new AddProjectRequest();
|
||||
initProject.setOrganizationId("100001");
|
||||
initProject.setName("文件管理专用项目");
|
||||
initProject.setDescription("建国创建的文件管理专用项目");
|
||||
initProject.setEnable(true);
|
||||
initProject.setUserIds(List.of("admin"));
|
||||
project = commonProjectService.add(initProject, "admin", "/organization-project/add", OperationLogModule.SETTING_ORGANIZATION_PROJECT);
|
||||
|
||||
ArrayList<String> moduleList = new ArrayList<>(List.of(new String[]{"workstation", "testPlan", "bugManagement", "caseManagement", "apiTest", "uiTest", "loadTest"}));
|
||||
Project updateProject = new Project();
|
||||
updateProject.setId(project.getId());
|
||||
updateProject.setModuleSetting(JSON.toJSONString(moduleList));
|
||||
projectMapper.updateByPrimaryKeySelective(updateProject);
|
||||
|
||||
|
||||
ApiScenarioAddRequest apiScenarioAddRequest = new ApiScenarioAddRequest();
|
||||
apiScenarioAddRequest.setProjectId(project.getId());
|
||||
apiScenarioAddRequest.setDescription("desc");
|
||||
apiScenarioAddRequest.setName("test name");
|
||||
apiScenarioAddRequest.setModuleId("default");
|
||||
apiScenarioAddRequest.setGrouped(false);
|
||||
apiScenarioAddRequest.setTags(List.of("tag1", "tag2"));
|
||||
apiScenarioAddRequest.setPriority("P0");
|
||||
apiScenarioAddRequest.setStatus(ApiScenarioStatus.COMPLETED.name());
|
||||
apiScenarioAddRequest.setSteps(new ArrayList<>());
|
||||
MvcResult scenarioMvcResult = this.requestPostWithOkAndReturn("/api/scenario/add", apiScenarioAddRequest);
|
||||
ApiScenario scenario = getResultData(scenarioMvcResult, ApiScenario.class);
|
||||
|
||||
|
||||
// 创建接口定义
|
||||
Map<String, List<String>> methodAndPath = Map.of(
|
||||
"GET", List.of(
|
||||
"/api/get-test/1",
|
||||
"/api/get-test/2",
|
||||
"/api/{/get-test}/3/withCase",
|
||||
"/api/get-test/4/withCase",// 场景关联它的用例
|
||||
"/api/get-test/5/never-compare",
|
||||
"/{api}/{/get-test}/{6}",//这个一定会被匹配到
|
||||
"/api/get-test/{7}",// 这个一定会被匹配到
|
||||
"/api/get-test/8",// 场景关联它的自定义请求
|
||||
"/api/get-test/9",// 场景关联这个接口
|
||||
"/api/get-test/10"),
|
||||
"POST", List.of(
|
||||
"/post/api/test/1",
|
||||
"/post/api/test/2",
|
||||
"/post/api/{test}/3/withCase",
|
||||
"/post/api/test/4/withCase",// 场景关联它的用例
|
||||
"/post/api/test/5/never-compare",
|
||||
"/{post}/{api}/{/get-test}/{6}", //这个一定会被匹配到
|
||||
"/post/api/test/{7}", // 这个一定会被匹配到
|
||||
"/post/api/test/8", // 场景关联它的自定义请求
|
||||
"/post/api/test/9",// 场景关联这个接口
|
||||
"/post/api/test/10"
|
||||
)
|
||||
);
|
||||
|
||||
List<ApiScenarioStepRequest> steps = new ArrayList<>();
|
||||
Map<String, Object> steptDetailMap = new HashMap<>();
|
||||
// 创建接口用例
|
||||
for (Map.Entry<String, List<String>> entry : methodAndPath.entrySet()) {
|
||||
String method = entry.getKey();
|
||||
for (String path : entry.getValue()) {
|
||||
// 创建接口定义
|
||||
String defaultVersion = extBaseProjectVersionMapper.getDefaultVersion(project.getId());
|
||||
ApiDefinitionAddRequest apiDefinitionAddRequest = new ApiDefinitionAddRequest();
|
||||
apiDefinitionAddRequest.setName(method + "_" + path);
|
||||
apiDefinitionAddRequest.setProtocol(ApiConstants.HTTP_PROTOCOL);
|
||||
apiDefinitionAddRequest.setProjectId(project.getId());
|
||||
apiDefinitionAddRequest.setMethod(method);
|
||||
apiDefinitionAddRequest.setPath(path);
|
||||
apiDefinitionAddRequest.setStatus(ApiDefinitionStatus.PROCESSING.name());
|
||||
apiDefinitionAddRequest.setModuleId("default");
|
||||
apiDefinitionAddRequest.setVersionId(defaultVersion);
|
||||
apiDefinitionAddRequest.setDescription("描述内容");
|
||||
apiDefinitionAddRequest.setTags(new LinkedHashSet<>(List.of("tag1", "tag2")));
|
||||
|
||||
MsHTTPElement msHttpElement = MsHTTPElementTest.getMsHttpElement();
|
||||
msHttpElement.setBody(MsHTTPElementTest.getGeneralBody());
|
||||
msHttpElement.setMethod(method);
|
||||
msHttpElement.setPath(path);
|
||||
|
||||
apiDefinitionAddRequest.setRequest(JSON.parseObject(ApiDataUtils.toJSONString(msHttpElement)));
|
||||
List<HttpResponse> msHttpResponse = MsHTTPElementTest.getMsHttpResponse();
|
||||
apiDefinitionAddRequest.setResponse(msHttpResponse);
|
||||
|
||||
MvcResult mvcResult = this.requestPostWithOkAndReturn("/api/definition/add", apiDefinitionAddRequest);
|
||||
ApiDefinition resultData = getResultData(mvcResult, ApiDefinition.class);
|
||||
|
||||
if (path.endsWith("/withCase")) {
|
||||
ApiTestCaseAddRequest request = new ApiTestCaseAddRequest();
|
||||
request.setApiDefinitionId(resultData.getId());
|
||||
request.setName(resultData.getName() + "_case");
|
||||
request.setProjectId(project.getId());
|
||||
request.setPriority("P0");
|
||||
request.setStatus(ApiDefinitionStatus.PROCESSING.name());
|
||||
request.setTags(new LinkedHashSet<>(List.of("tag1", "tag2")));
|
||||
request.setRequest(JSON.parseObject(ApiDataUtils.toJSONString(msHttpElement)));
|
||||
MvcResult testCaseResult = this.requestPostWithOkAndReturn("/api/case/add", request);
|
||||
ApiTestCase apiTestCase = getResultData(testCaseResult, ApiTestCase.class);
|
||||
|
||||
if (path.endsWith("/4/withCase")) {
|
||||
ApiScenarioStepRequest stepRequest = new ApiScenarioStepRequest();
|
||||
stepRequest.setId(IDGenerator.nextStr());
|
||||
stepRequest.setVersionId(extBaseProjectVersionMapper.getDefaultVersion(project.getId()));
|
||||
stepRequest.setConfig(new HashMap<>());
|
||||
stepRequest.setEnable(true);
|
||||
stepRequest.setStepType(ApiScenarioStepType.API_CASE.name());
|
||||
stepRequest.setResourceId(apiTestCase.getId());
|
||||
stepRequest.setName(apiTestCase.getName() + "_step");
|
||||
stepRequest.setRefType(ApiScenarioStepRefType.REF.name());
|
||||
stepRequest.setProjectId(project.getId());
|
||||
steps.add(stepRequest);
|
||||
steptDetailMap.put(stepRequest.getId(), JSON.parseObject(ApiDataUtils.toJSONString(msHttpElement)));
|
||||
}
|
||||
} else if (path.endsWith("/8")) {
|
||||
|
||||
ApiScenarioStepRequest stepRequest = new ApiScenarioStepRequest();
|
||||
stepRequest.setId(IDGenerator.nextStr());
|
||||
stepRequest.setVersionId(extBaseProjectVersionMapper.getDefaultVersion(project.getId()));
|
||||
stepRequest.setConfig(new HashMap<>());
|
||||
stepRequest.setEnable(true);
|
||||
stepRequest.setStepType(ApiScenarioStepType.CUSTOM_REQUEST.name());
|
||||
stepRequest.setName("custom_step");
|
||||
stepRequest.setRefType(ApiScenarioStepRefType.DIRECT.name());
|
||||
stepRequest.setProjectId(project.getId());
|
||||
steps.add(stepRequest);
|
||||
|
||||
MsHTTPElement customElement = MsHTTPElementTest.getMsHttpElement();
|
||||
customElement.setBody(MsHTTPElementTest.getGeneralBody());
|
||||
customElement.setMethod(method);
|
||||
customElement.setPath(path);
|
||||
steptDetailMap.put(stepRequest.getId(), JSON.parseObject(ApiDataUtils.toJSONString(customElement)));
|
||||
} else if (path.endsWith("/9")) {
|
||||
ApiScenarioStepRequest stepRequest = new ApiScenarioStepRequest();
|
||||
stepRequest.setId(IDGenerator.nextStr());
|
||||
stepRequest.setVersionId(extBaseProjectVersionMapper.getDefaultVersion(project.getId()));
|
||||
stepRequest.setConfig(new HashMap<>());
|
||||
stepRequest.setEnable(true);
|
||||
stepRequest.setStepType(ApiScenarioStepType.API.name());
|
||||
stepRequest.setResourceId(resultData.getId());
|
||||
stepRequest.setName(resultData.getName() + "_step");
|
||||
stepRequest.setRefType(ApiScenarioStepRefType.REF.name());
|
||||
stepRequest.setProjectId(project.getId());
|
||||
steps.add(stepRequest);
|
||||
steptDetailMap.put(stepRequest.getId(), JSON.parseObject(ApiDataUtils.toJSONString(msHttpElement)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ApiScenarioUpdateRequest apiScenarioUpdateRequest = new ApiScenarioUpdateRequest();
|
||||
apiScenarioUpdateRequest.setId(scenario.getId());
|
||||
apiScenarioUpdateRequest.setProjectId(project.getId());
|
||||
apiScenarioUpdateRequest.setSteps(steps);
|
||||
apiScenarioUpdateRequest.setStepDetails(steptDetailMap);
|
||||
this.requestPostWithOkAndReturn("/api/scenario/update", apiScenarioUpdateRequest);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calculateTest() throws Exception {
|
||||
ApiDefinitionExample apiDefinitionExample = new ApiDefinitionExample();
|
||||
apiDefinitionExample.createCriteria().andProjectIdEqualTo(project.getId());
|
||||
Assertions.assertEquals(apiDefinitionMapper.countByExample(apiDefinitionExample), 20);
|
||||
|
||||
MvcResult mvcResult = this.requestGetWithOkAndReturn("/api/definition/rage/" + project.getId());
|
||||
ApiCoverageDTO apiCoverageDTO = getResultData(mvcResult, ApiCoverageDTO.class);
|
||||
Assertions.assertEquals(apiCoverageDTO.getAllApiCount(), 20);
|
||||
Assertions.assertEquals(apiCoverageDTO.getCoverWithApiCase(), 4);
|
||||
Assertions.assertEquals(apiCoverageDTO.getUnCoverWithApiCase(), 16);
|
||||
Assertions.assertEquals(apiCoverageDTO.getApiCaseCoverage(), CalculateUtils.reportPercentage(apiCoverageDTO.getCoverWithApiCase(), apiCoverageDTO.getAllApiCount()));
|
||||
|
||||
Assertions.assertEquals(apiCoverageDTO.getCoverWithApiScenario(), 8);
|
||||
Assertions.assertEquals(apiCoverageDTO.getUnCoverWithApiScenario(), 12);
|
||||
Assertions.assertEquals(apiCoverageDTO.getScenarioCoverage(), CalculateUtils.reportPercentage(apiCoverageDTO.getCoverWithApiScenario(), apiCoverageDTO.getAllApiCount()));
|
||||
|
||||
Assertions.assertEquals(apiCoverageDTO.getCoverWithApiDefinition(), 10);
|
||||
Assertions.assertEquals(apiCoverageDTO.getUnCoverWithApiDefinition(), 10);
|
||||
Assertions.assertEquals(apiCoverageDTO.getApiCoverage(), CalculateUtils.reportPercentage(apiCoverageDTO.getCoverWithApiDefinition(), apiCoverageDTO.getAllApiCount()));
|
||||
}
|
||||
|
||||
}
|
|
@ -173,7 +173,7 @@ public class ApiReportControllerTests extends BaseTest {
|
|||
Assertions.assertNotNull(returnPager);
|
||||
//返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(returnPager.getCurrent(), request.getCurrent());
|
||||
;
|
||||
|
||||
//返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertTrue(((List<ApiScenarioDTO>) returnPager.getList()).size() <= request.getPageSize());
|
||||
//过滤
|
||||
|
|
|
@ -2144,6 +2144,18 @@ public class ApiScenarioControllerTests extends BaseTest {
|
|||
batchRequest.setEnable(false);
|
||||
this.requestPostWithOk(batchUrl, batchRequest);
|
||||
apiScenarioBatchOperationTestService.checkSchedule(BATCH_OPERATION_SCENARIO_ID.getFirst(), batchRequest.isEnable());
|
||||
|
||||
// 仅仅是开启/关闭
|
||||
batchRequest = new ApiScenarioBatchScheduleConfigRequest();
|
||||
batchRequest.setProjectId(DEFAULT_PROJECT_ID);
|
||||
batchRequest.setSelectIds(List.of(BATCH_OPERATION_SCENARIO_ID.getFirst()));
|
||||
batchRequest.setEnable(true);
|
||||
this.requestPostWithOk(batchUrl, batchRequest);
|
||||
apiScenarioBatchOperationTestService.checkSchedule(BATCH_OPERATION_SCENARIO_ID.getFirst(), batchRequest.isEnable());
|
||||
batchRequest.setEnable(false);
|
||||
this.requestPostWithOk(batchUrl, batchRequest);
|
||||
apiScenarioBatchOperationTestService.checkSchedule(BATCH_OPERATION_SCENARIO_ID.getFirst(), batchRequest.isEnable());
|
||||
|
||||
//增加日志检查
|
||||
LOG_CHECK_LIST.add(
|
||||
new CheckLogModel(scenarioId, OperationLogType.UPDATE, "/api/scenario/schedule-config")
|
||||
|
@ -2151,17 +2163,6 @@ public class ApiScenarioControllerTests extends BaseTest {
|
|||
LOG_CHECK_LIST.add(
|
||||
new CheckLogModel(BATCH_OPERATION_SCENARIO_ID.getFirst(), OperationLogType.UPDATE, "/api/scenario/batch-operation/schedule-config")
|
||||
);
|
||||
// 批量定时任务的开关
|
||||
ApiScenarioBatchEditRequest batchEditRequest = new ApiScenarioBatchEditRequest();
|
||||
batchEditRequest.setProjectId(DEFAULT_PROJECT_ID);
|
||||
batchEditRequest.setType("Schedule");
|
||||
batchEditRequest.setScheduleOpen(true);
|
||||
batchEditRequest.setSelectIds(List.of(BATCH_OPERATION_SCENARIO_ID.getFirst()));
|
||||
requestPostAndReturn(BATCH_EDIT, batchEditRequest);
|
||||
apiScenarioBatchOperationTestService.checkSchedule(BATCH_OPERATION_SCENARIO_ID.getFirst(), batchEditRequest.isScheduleOpen());
|
||||
batchEditRequest.setScheduleOpen(false);
|
||||
requestPostAndReturn(BATCH_EDIT, batchEditRequest);
|
||||
apiScenarioBatchOperationTestService.checkSchedule(BATCH_OPERATION_SCENARIO_ID.getFirst(), batchEditRequest.isScheduleOpen());
|
||||
//关闭
|
||||
request.setEnable(false);
|
||||
result = this.requestPostAndReturn(testUrl, request);
|
||||
|
@ -2240,11 +2241,6 @@ public class ApiScenarioControllerTests extends BaseTest {
|
|||
request.setScenarioId(IDGenerator.nextStr());
|
||||
this.requestPost(testUrl, request).andExpect(status().is5xxServerError());
|
||||
|
||||
//反例:不配置cron表达式
|
||||
request = new ApiScenarioScheduleConfigRequest();
|
||||
request.setScenarioId(scenarioId);
|
||||
this.requestPost(testUrl, request).andExpect(status().isBadRequest());
|
||||
|
||||
//反例:配置错误的cron表达式,测试是否会关闭定时任务
|
||||
request = new ApiScenarioScheduleConfigRequest();
|
||||
request.setScenarioId(scenarioId);
|
||||
|
|
|
@ -6,18 +6,7 @@
|
|||
class="ms-modal-upload ms-modal-medium"
|
||||
:width="400"
|
||||
>
|
||||
<div class="mb-[16px] flex items-center gap-[16px]">
|
||||
<div
|
||||
v-for="item of platformList"
|
||||
:key="item.value"
|
||||
:class="`import-item ${exportPlatform === item.value ? 'import-item--active' : ''}`"
|
||||
@click="() => setActiveImportFormat(item.value)"
|
||||
>
|
||||
<div class="text-[var(--color-text-1)]">{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="exportPlatform === 'MeterSphere'" class="mb-[16px] flex items-center gap-[8px]">
|
||||
<div class="mb-[16px] flex items-center gap-[8px]">
|
||||
<a-switch v-model:model-value="exportTypeRadio" size="small"></a-switch>
|
||||
{{ t('apiScenario.export.type.all') }}
|
||||
<a-tooltip :content="t('apiScenario.export.simple.tooltip')" position="tl">
|
||||
|
@ -58,18 +47,6 @@
|
|||
import useAppStore from '@/store/modules/app';
|
||||
import { downloadByteFile, getGenerateId } from '@/utils';
|
||||
|
||||
import { RequestImportFormat } from '@/enums/apiEnum';
|
||||
|
||||
const platformList: { name: string; value: RequestImportFormat.MeterSphere | RequestImportFormat.Jmeter }[] = [
|
||||
{
|
||||
name: 'MeterSphere',
|
||||
value: RequestImportFormat.MeterSphere,
|
||||
},
|
||||
{
|
||||
name: 'Jmeter',
|
||||
value: RequestImportFormat.Jmeter,
|
||||
},
|
||||
];
|
||||
const appStore = useAppStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
|
@ -84,13 +61,9 @@
|
|||
|
||||
const exportLoading = ref(false);
|
||||
const exportTypeRadio = ref(false);
|
||||
const exportPlatform = ref(RequestImportFormat.MeterSphere);
|
||||
function cancelExport() {
|
||||
visible.value = false;
|
||||
}
|
||||
function setActiveImportFormat(format: RequestImportFormat.MeterSphere | RequestImportFormat.Jmeter) {
|
||||
exportPlatform.value = format;
|
||||
}
|
||||
const websocket = ref<WebSocket>();
|
||||
const reportId = ref('');
|
||||
const isShowExportingMessage = ref(false); // 正在导出提示显示中
|
||||
|
@ -217,7 +190,7 @@
|
|||
sort: props.sorter || {},
|
||||
fileId: reportId.value,
|
||||
},
|
||||
exportPlatform.value
|
||||
'METERSPHERE'
|
||||
);
|
||||
showExportingMessage(res);
|
||||
visible.value = false;
|
||||
|
|
Loading…
Reference in New Issue