feat(接口测试): 接口case关系引用

【【接口测试】接口CASE引用关系查看】
https://www.tapd.cn/55049933/prong/stories/view/1155049933001009305
This commit is contained in:
wxg0103 2022-11-07 15:42:56 +08:00 committed by wxg0103
parent 7a68ede810
commit 90e71f7e62
43 changed files with 989 additions and 454 deletions

View File

@ -0,0 +1,12 @@
package io.metersphere.api.dto;
import io.metersphere.request.ProjectRequest;
import lombok.Data;
import java.util.List;
@Data
public class ApiProjectRequest extends ProjectRequest {
private List<String> workspaceIds;
}

View File

@ -14,4 +14,7 @@ import java.util.List;
public class DeleteCheckResult {
boolean deleteFlag;
List<String> checkMsg;
int refCount;
int scenarioCount;
int planCount;
}

View File

@ -1,13 +1,16 @@
package io.metersphere.api.dto;
import io.metersphere.request.BaseQueryRequest;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class QueryReferenceRequest {
public class QueryReferenceRequest extends BaseQueryRequest {
private String scenarioId;
private String apiId;
private String loadId;
private String projectId;
private String workspaceId;
private String id;
}

View File

@ -33,4 +33,6 @@ public class ApiScenarioDTO extends ApiScenarioWithBLOBs {
private String env;
private Map<String, String> environmentMap;
private String creator;
private String workspaceName;
private String workspaceId;
}

View File

@ -34,4 +34,5 @@ public class TestPlanDTO extends TestPlanWithBLOBs {
* 定时任务下一次执行时间
*/
private Long scheduleExecuteTime;
private String workspaceName;
}

View File

@ -0,0 +1,12 @@
package io.metersphere.base.mapper.ext;
import io.metersphere.api.dto.ApiProjectRequest;
import io.metersphere.dto.ProjectDTO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface ExtApiProjectMapper {
List<ProjectDTO> getUserProject(@Param("proRequest") ApiProjectRequest request);
}

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="io.metersphere.base.mapper.ext.ExtApiProjectMapper">
<select id="getUserProject" resultType="io.metersphere.dto.ProjectDTO">
SELECT DISTINCT p.*
FROM `group` g
JOIN user_group ug ON g.id = ug.group_id
JOIN project p ON p.id = ug.source_id
<where>
g.type = 'PROJECT'
AND ug.user_id = #{proRequest.userId}
<if test="proRequest.workspaceId != null and proRequest.workspaceId != ''">
AND p.workspace_id = #{proRequest.workspaceId}
</if>
<if test="proRequest.name != null and proRequest.name != ''">
AND p.name LIKE #{proRequest.name, jdbcType=VARCHAR}
</if>
<if test="proRequest.workspaceIds != null and proRequest.workspaceIds.size() > 0">
and p.workspace_id in
<foreach collection="proRequest.workspaceIds" item="workspaceId" separator="," open="(" close=")">
#{workspaceId}
</foreach>
</if>
</where>
</select>
</mapper>

View File

@ -32,7 +32,7 @@ public interface ExtApiScenarioMapper {
List<ApiScenarioWithBLOBs> selectByIds(@Param("ids") String ids, @Param("order") String order);
List<ApiScenario> selectReference(@Param("request") ApiScenarioRequest request);
List<ApiScenarioDTO> selectReference(@Param("request") ApiScenarioRequest request);
int removeToGcByExample(ApiScenarioExampleWithOperation example);

View File

@ -460,18 +460,41 @@
ORDER BY FIND_IN_SET(id, ${order})
</select>
<select id="selectReference" resultType="io.metersphere.base.domain.ApiScenario">
select * from api_scenario
<select id="selectReference" resultType="io.metersphere.api.dto.automation.ApiScenarioDTO">
select a.id, a.name , a.num,p.name AS projectName, a.update_time, a.create_time,
w.name AS workspaceName, p.workspace_id AS workspaceId, p.id AS projectId from api_scenario a
LEFT JOIN project p ON a.project_id = p.id
LEFT JOIN `workspace` w ON p.workspace_id = w.id
<where>
<if test="request.workspaceId != null">
AND project.workspace_id = #{request.workspaceId}
a.status != 'Trash'
<if test="request.ids != null and request.ids.size() > 0">
and a.id in
<foreach collection="request.ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</if>
<if test="request.moduleId != null">
AND api_scenario_module_id = #{request.moduleId}
<if test="request.filters != null and request.filters.size() > 0">
<foreach collection="request.filters.entrySet()" index="key" item="values">
<if test="values != null and values.size() > 0">
<choose>
<when test="key=='project_id'">
and a.project_id in
<foreach collection="values" item="value" separator="," open="(" close=")">
#{value}
</foreach>
</when>
<when test="key=='workspace_id'">
and p.workspace_id in
<foreach collection="values" item="value" separator="," open="(" close=")">
#{value}
</foreach>
</when>
</choose>
</if>
</foreach>
</if>
and status != 'Trash'
and scenario_definition like CONCAT('%', #{request.id},'%') and id != #{request.id}
</where>
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
</select>
<update id="removeToGcByExample" parameterType="io.metersphere.base.domain.ApiScenarioExample">
update api_scenario

View File

@ -6,4 +6,6 @@ import java.util.List;
public interface ExtApiScenarioReferenceIdMapper {
List<ApiScenarioReferenceId> selectUrlByProjectId(String projectId);
List<ApiScenarioReferenceId> selectReferenceIdByIds(List<String> ids);
}

View File

@ -12,5 +12,19 @@
AND latest = 1)
AND reference_id IS NOT NULL
</select>
<select id="selectReferenceIdByIds" resultType="io.metersphere.base.domain.ApiScenarioReferenceId">
SELECT api_scenario_reference_id.*
from api_scenario_reference_id
left join api_scenario on api_scenario.id = api_scenario_reference_id.api_scenario_id
<where>
<if test="ids != null and ids.size() > 0">
api_scenario_reference_id.reference_id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</if>
and api_scenario.status != 'Trash' and api_scenario_reference_id.reference_type = 'REF'
</where>
</select>
</mapper>

View File

@ -55,6 +55,10 @@ public interface ExtTestPlanApiCaseMapper {
List<TestPlanApiCase> selectByIdsAndStatusIsNotTrash(@Param("ids") List<String> ids);
List<String> selectNameByIdIn(@Param("ids") List<String> ids);
String selectProjectId(String id);
List<TestPlanApiCase> selectByRefIds(@Param("ids") List<String> ids);
}

View File

@ -479,8 +479,13 @@
</select>
<select id="selectTestPlanByRelevancy" resultType="io.metersphere.api.dto.automation.TestPlanDTO"
parameterType="io.metersphere.api.dto.QueryReferenceRequest">
SELECT * FROM test_plan p
SELECT p.id , p.name, project.name as projectName , w.name as workspaceName ,p.workspace_id AS workspaceId, p.project_id AS projectId FROM test_plan p
LEFT JOIN project ON p.project_id = project.id
LEFT JOIN `workspace` w ON p.workspace_id = w.id
<where>
<if test="request.workspaceId != null">
and p.workspace_id = #{request.workspaceId}
</if>
<if test="request.scenarioId != null">
AND p.id IN (SELECT test_plan_id FROM test_plan_api_scenario WHERE api_scenario_id =
#{request.scenarioId} )
@ -491,6 +496,52 @@
<if test="request.loadId != null">
AND p.id IN (SELECT test_plan_id FROM test_plan_load_case WHERE load_case_id = #{request.loadId})
</if>
<if test="request.filters != null and request.filters.size() > 0">
<foreach collection="request.filters.entrySet()" index="key" item="values">
<if test="values != null and values.size() > 0">
<choose>
<when test="key=='project_id'">
and p.project_id in
<foreach collection="values" item="value" separator="," open="(" close=")">
#{value}
</foreach>
</when>
<when test="key=='workspace_id'">
and p.workspace_id in
<foreach collection="values" item="value" separator="," open="(" close=")">
#{value}
</foreach>
</when>
</choose>
</if>
</foreach>
</if>
</where>
<if test="request.orders != null and request.orders.size() > 0">
order by
<foreach collection="request.orders" separator="," item="order">
<if test="order.name != ''">
p.${order.name} ${order.type}
</if>
</foreach>
</if>
</select>
<select id="selectNameByIdIn" resultType="java.lang.String">
select name from test_plan where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</select>
<select id="selectByRefIds" resultType="io.metersphere.base.domain.TestPlanApiCase">
SELECT
plan.*
FROM
test_plan_api_case plan
INNER JOIN test_plan on plan.test_plan_id = test_plan.id
WHERE
plan.api_case_id IN
<foreach collection="ids" item="v" separator="," open="(" close=")">
#{v}
</foreach>
</select>
</mapper>

View File

@ -10,4 +10,5 @@ public interface ExtTestPlanApiScenarioMapper {
List<TestPlanApiScenario> selectPlanByIdsAndStatusIsNotTrash(@Param("ids") List<String> ids);
List<TestPlanApiScenario> selectByScenarioIds(@Param("ids") List<String> ids);
}

View File

@ -26,4 +26,16 @@
#{v}
</foreach>
</select>
<select id="selectByScenarioIds" resultType="io.metersphere.base.domain.TestPlanApiScenario">
SELECT
plan.*
FROM
test_plan_api_scenario plan
INNER JOIN test_plan on plan.test_plan_id = test_plan.id
WHERE
plan.api_scenario_id IN
<foreach collection="ids" item="v" separator="," open="(" close=")">
#{v}
</foreach>
</select>
</mapper>

View File

@ -1,10 +1,12 @@
package io.metersphere.base.mapper.plan.ext;
import io.metersphere.api.dto.plan.TestPlanApiScenarioInfoDTO;
import io.metersphere.api.dto.automation.ApiScenarioDTO;
import io.metersphere.api.dto.automation.TestPlanFailureScenarioDTO;
import io.metersphere.api.dto.automation.TestPlanScenarioRequest;
import io.metersphere.api.dto.plan.TestPlanApiScenarioInfoDTO;
import io.metersphere.base.domain.TestPlanApiScenario;
import io.metersphere.dto.PlanReportCaseDTO;
import org.apache.ibatis.annotations.Param;
@ -22,9 +24,9 @@ public interface ExtTestPlanScenarioCaseMapper {
List<String> getNotRelevanceCaseIds(String planId, List<String> relevanceProjectIds);
List<String> selectIds(@Param("request") TestPlanScenarioRequest request);
List<String> selectIds(@Param("request")TestPlanScenarioRequest request);
List<TestPlanApiScenario> selectByIds(@Param("ids") String ids, @Param("order") String order);
List<TestPlanApiScenario> selectByIds(@Param("ids")String ids ,@Param("order")String order );
List<TestPlanApiScenarioInfoDTO> selectLegalDataByTestPlanId(String planId);
@ -32,7 +34,7 @@ public interface ExtTestPlanScenarioCaseMapper {
List<TestPlanFailureScenarioDTO> getFailureList(@Param("planId") String planId, @Param("status") String status);
List<TestPlanFailureScenarioDTO> getFailureListByIds(@Param("ids") Collection<String> ids, @Param("status") String status);
List<TestPlanFailureScenarioDTO> getFailureListByIds(@Param("ids") Collection<String> ids,@Param("status") String status);
List<Integer> getUnderwaySteps(@Param("ids") List<String> underwayIds);
@ -46,5 +48,6 @@ public interface ExtTestPlanScenarioCaseMapper {
Long getLastOrder(@Param("planId") String planId, @Param("baseOrder") Long baseOrder);
List<String> selectNameByIdIn(List<String> ids);
String selectProjectId(String testPlanId);
}

View File

@ -3,8 +3,8 @@ package io.metersphere.controller.definition;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.api.dto.*;
import io.metersphere.api.dto.automation.ApiScenarioDTO;
import io.metersphere.api.dto.automation.ApiScenarioRequest;
import io.metersphere.api.dto.automation.ReferenceDTO;
import io.metersphere.api.dto.automation.TcpTreeTableDataStruct;
import io.metersphere.api.dto.definition.*;
import io.metersphere.api.dto.definition.request.assertions.document.DocumentElement;
@ -262,9 +262,11 @@ public class ApiDefinitionController {
apiDefinitionService.deleteSchedule(request);
}
@PostMapping("/get-reference")
public ReferenceDTO getReference(@RequestBody ApiScenarioRequest request) {
return apiDefinitionService.getReference(request);
@PostMapping("/get-reference/{goPage}/{pageSize}")
public Pager<List<ApiScenarioDTO>> getReference(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ApiScenarioRequest request) {
apiDefinitionService.getReferenceIds(request);
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, apiDefinitionService.getReference(request));
}
@PostMapping("/batch/edit")

View File

@ -2,6 +2,7 @@ package io.metersphere.controller.ext;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.api.dto.ApiProjectRequest;
import io.metersphere.commons.constants.PermissionConstants;
import io.metersphere.commons.utils.PageUtils;
import io.metersphere.commons.utils.Pager;
@ -11,12 +12,7 @@ import io.metersphere.service.BaseCheckPermissionService;
import io.metersphere.service.BaseProjectService;
import io.metersphere.service.ext.ExtProjectApplicationService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Collection;
@ -58,4 +54,9 @@ public class ExtProjectController {
public void updateCurrentUserByResourceId(@PathVariable String resourceId) {
extProjectApplicationService.updateCurrentUserByResourceId(resourceId);
}
@PostMapping("/list/related")
public List<ProjectDTO> getUserProject(@RequestBody ApiProjectRequest request) {
return extProjectApplicationService.getUserProject(request);
}
}

View File

@ -2,10 +2,11 @@ package io.metersphere.controller.plan;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.api.dto.QueryReferenceRequest;
import io.metersphere.api.dto.automation.TestPlanDTO;
import io.metersphere.api.dto.automation.TestPlanFailureApiDTO;
import io.metersphere.api.dto.definition.*;
import io.metersphere.api.dto.plan.TestPlanApiCaseBatchRequest;
import io.metersphere.api.dto.automation.TestPlanFailureApiDTO;
import io.metersphere.service.plan.TestPlanApiCaseService;
import io.metersphere.commons.constants.OperLogConstants;
import io.metersphere.commons.constants.OperLogModule;
import io.metersphere.commons.constants.PermissionConstants;
@ -15,6 +16,7 @@ import io.metersphere.dto.MsExecResponseDTO;
import io.metersphere.dto.RunModeConfigDTO;
import io.metersphere.log.annotation.MsAuditLog;
import io.metersphere.request.ResetOrderRequest;
import io.metersphere.service.plan.TestPlanApiCaseService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.*;
@ -185,4 +187,10 @@ public class TestPlanApiCaseController {
testPlanApiCaseService.buildApiResponse(cases);
return cases;
}
@PostMapping("/get-reference/{goPage}/{pageSize}")
public Pager<List<TestPlanDTO>> getReference(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryReferenceRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, testPlanApiCaseService.getReference(request));
}
}

View File

@ -273,11 +273,6 @@ public class ApiScenarioController {
apiAutomationService.batchUpdateEnv(request);
}
@PostMapping("/getReference")
public ReferenceDTO getReference(@RequestBody ApiScenarioRequest request) {
return apiAutomationService.getReference(request);
}
@PostMapping("/scenario/plan")
public String addScenarioToPlan(@RequestBody SaveApiPlanRequest request) {
return apiAutomationService.addScenarioToPlan(request);

View File

@ -8,8 +8,8 @@ import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.github.ningyu.jmeter.plugin.dubbo.sample.ProviderService;
import io.metersphere.api.dto.*;
import io.metersphere.api.dto.automation.ApiScenarioDTO;
import io.metersphere.api.dto.automation.ApiScenarioRequest;
import io.metersphere.api.dto.automation.ReferenceDTO;
import io.metersphere.api.dto.automation.TcpTreeTableDataStruct;
import io.metersphere.api.dto.datacount.ApiDataCountResult;
import io.metersphere.api.dto.definition.*;
@ -1908,14 +1908,20 @@ public class ApiDefinitionService {
}
public ReferenceDTO getReference(ApiScenarioRequest request) {
ReferenceDTO dto = new ReferenceDTO();
dto.setScenarioList(extApiScenarioMapper.selectReference(request));
QueryReferenceRequest planRequest = new QueryReferenceRequest();
planRequest.setApiId(request.getId());
planRequest.setProjectId(request.getProjectId());
dto.setTestPlanList(extTestPlanApiCaseMapper.selectTestPlanByRelevancy(planRequest));
return dto;
public List<ApiScenarioDTO> getReference(ApiScenarioRequest request) {
if (CollectionUtils.isEmpty(request.getIds())) {
return new ArrayList<>();
} else {
return extApiScenarioMapper.selectReference(request);
}
}
public void getReferenceIds(ApiScenarioRequest request) {
ApiScenarioReferenceIdExample example = new ApiScenarioReferenceIdExample();
example.createCriteria().andReferenceIdEqualTo(request.getId()).andReferenceTypeEqualTo(MsTestElementConstants.REF.name());
List<ApiScenarioReferenceId> scenarioReferenceIds = apiScenarioReferenceIdMapper.selectByExample(example);
List<String> scenarioIds = scenarioReferenceIds.stream().map(ApiScenarioReferenceId::getApiScenarioId).collect(Collectors.toList());
request.setIds(scenarioIds);
}
public void editApiBath(ApiBatchRequest request) {

View File

@ -16,6 +16,7 @@ import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.*;
import io.metersphere.base.mapper.plan.ext.ExtTestPlanApiCaseMapper;
import io.metersphere.commons.constants.*;
import io.metersphere.commons.enums.ApiReportStatus;
import io.metersphere.commons.enums.ApiTestDataStatus;
@ -36,12 +37,12 @@ import io.metersphere.service.BaseUserService;
import io.metersphere.service.ServiceUtils;
import io.metersphere.service.ext.ExtFileAssociationService;
import io.metersphere.service.plan.TestPlanApiCaseService;
import io.metersphere.service.scenario.ApiScenarioReferenceIdService;
import io.metersphere.xpack.api.service.ApiCaseBatchSyncService;
import io.metersphere.xpack.api.service.ApiTestCaseSyncService;
import io.metersphere.xpack.version.service.ProjectVersionService;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.collections4.comparators.FixedOrderComparator;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
@ -83,8 +84,6 @@ public class ApiTestCaseService {
@Resource
private EsbApiParamService esbApiParamService;
@Resource
private ApiScenarioReferenceIdService apiScenarioReferenceIdService;
@Resource
private ExtApiScenarioMapper extApiScenarioMapper;
@Resource
private ApiTestEnvironmentMapper apiTestEnvironmentMapper;
@ -108,6 +107,10 @@ public class ApiTestCaseService {
private ApiScenarioReferenceIdMapper apiScenarioReferenceIdMapper;
@Resource
private TestPlanApiCaseService testPlanApiCaseService;
@Resource
private ExtTestPlanApiCaseMapper extTestPlanApiCaseMapper;
@Resource
private ExtApiScenarioReferenceIdMapper extApiScenarioReferenceIdMapper;
private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR;
@ -966,54 +969,63 @@ public class ApiTestCaseService {
}
public DeleteCheckResult checkDeleteData(ApiTestBatchRequest request) {
DeleteCheckResult result = new DeleteCheckResult();
List<String> deleteIds = request.getIds();
if (request.isSelectAll()) {
deleteIds = this.getAllApiCaseIdsByFrontedSelect(request.getFilters(), request.getModuleIds(), request.getName(), request.getProjectId(), request.getProtocol(), request.getUnSelectIds(), request.getStatus(), request.getApiDefinitionId(), request.getCombine());
}
DeleteCheckResult result = new DeleteCheckResult();
List<String> checkMsgList = new ArrayList<>();
if (CollectionUtils.isNotEmpty(deleteIds)) {
List<ApiScenarioReferenceId> apiScenarioReferenceIdList = apiScenarioReferenceIdService.findByReferenceIdsAndRefType(deleteIds, MsTestElementConstants.REF.name());
//场景引用
List<ApiScenarioReferenceId> apiScenarioReferenceIdList = extApiScenarioReferenceIdMapper.selectReferenceIdByIds(deleteIds);
Map<String, List<String>> scenarioDic = new HashMap<>();
if (CollectionUtils.isNotEmpty(apiScenarioReferenceIdList)) {
Map<String, List<String>> scenarioDic = new HashMap<>();
apiScenarioReferenceIdList.forEach(item -> {
String refreceID = item.getReferenceId();
String referenceId = item.getReferenceId();
String scenarioId = item.getApiScenarioId();
if (scenarioDic.containsKey(refreceID)) {
scenarioDic.get(refreceID).add(scenarioId);
if (scenarioDic.containsKey(referenceId)) {
scenarioDic.get(referenceId).add(scenarioId);
} else {
List<String> list = new ArrayList<>();
list.add(scenarioId);
scenarioDic.put(refreceID, list);
scenarioDic.put(referenceId, list);
}
});
for (Map.Entry<String, List<String>> entry : scenarioDic.entrySet()) {
String refreceId = entry.getKey();
List<String> scenarioIdList = entry.getValue();
if (CollectionUtils.isNotEmpty(scenarioIdList)) {
List<String> scenarioNameList = extApiScenarioMapper.selectNameByIdIn(scenarioIdList);
String deleteCaseName = extApiTestCaseMapper.selectNameById(refreceId);
if (StringUtils.isNotEmpty(deleteCaseName) && CollectionUtils.isNotEmpty(scenarioNameList)) {
String nameListStr = "[";
for (String name : scenarioNameList) {
nameListStr += name + ",";
}
if (nameListStr.length() > 1) {
nameListStr = nameListStr.substring(0, nameListStr.length() - 1) + "]";
}
String msg = deleteCaseName + StringUtils.SPACE + Translator.get("delete_check_reference_by") + ": " + nameListStr + StringUtils.SPACE;
checkMsgList.add(msg);
}
}
//测试计划引用
List<TestPlanApiCase> testPlanApiCases = extTestPlanApiCaseMapper.selectByRefIds(deleteIds);
Map<String, List<String>> planList = new HashMap<>();
if (CollectionUtils.isNotEmpty(testPlanApiCases)) {
testPlanApiCases.forEach(item -> {
String referenceId = item.getApiCaseId();
String testPlanId = item.getTestPlanId();
if (planList.containsKey(referenceId)) {
planList.get(referenceId).add(testPlanId);
} else {
List<String> list = new ArrayList<>();
list.add(testPlanId);
planList.put(referenceId, list);
}
});
}
if (MapUtils.isNotEmpty(scenarioDic) || MapUtils.isNotEmpty(planList)) {
if (StringUtils.equals("batch", request.getType())) {
Map<String, List<String>> map = scenarioDic.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v2, () -> new HashMap<>(planList)));
result.setRefCount(map.size());
result.setCheckMsg(new ArrayList<>(map.keySet()));
} else {
ArrayList<List<String>> scenarioList = new ArrayList<>(scenarioDic.values());
if (CollectionUtils.isNotEmpty(scenarioList)) {
result.setScenarioCount(new TreeSet<String>(scenarioList.get(0)).size());
}
ArrayList<List<String>> testPlanList = new ArrayList<>(planList.values());
if (CollectionUtils.isNotEmpty(testPlanList)) {
result.setPlanCount(new TreeSet<String>(testPlanList.get(0)).size());
}
}
result.setDeleteFlag(scenarioDic.size() > 0 || planList.size() > 0);
}
}
result.setDeleteFlag(checkMsgList.isEmpty());
result.setCheckMsg(checkMsgList);
return result;
}
@ -1287,4 +1299,5 @@ public class ApiTestCaseService {
private ApiCaseBasicInfoDTO selectApiCaseBasicInfoById(String id) {
return extApiTestCaseMapper.selectApiCaseBasicInfoById(id);
}
}

View File

@ -1,5 +1,6 @@
package io.metersphere.service.ext;
import io.metersphere.api.dto.ApiProjectRequest;
import io.metersphere.api.tcp.TCPPool;
import io.metersphere.base.domain.Project;
import io.metersphere.base.domain.ProjectApplication;
@ -8,22 +9,26 @@ import io.metersphere.base.mapper.ProjectApplicationMapper;
import io.metersphere.base.mapper.ProjectMapper;
import io.metersphere.base.mapper.UserMapper;
import io.metersphere.base.mapper.ext.BaseProjectMapper;
import io.metersphere.base.mapper.ext.ExtApiProjectMapper;
import io.metersphere.commons.constants.ProjectApplicationType;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.user.SessionUser;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.dto.ProjectConfig;
import io.metersphere.dto.ProjectDTO;
import io.metersphere.environment.service.BaseEnvironmentService;
import io.metersphere.i18n.Translator;
import io.metersphere.request.AddProjectRequest;
import io.metersphere.service.BaseProjectApplicationService;
import io.metersphere.service.BaseProjectService;
import io.metersphere.service.ServiceUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class ExtProjectApplicationService {
@ -41,6 +46,8 @@ public class ExtProjectApplicationService {
private BaseProjectMapper baseProjectMapper;
@Resource
private UserMapper userMapper;
@Resource
private ExtApiProjectMapper extApiProjectMapper;
public void createOrUpdateConfig(String projectId, String type, String value) {
ProjectApplication conf = new ProjectApplication();
@ -161,6 +168,7 @@ public class ExtProjectApplicationService {
TCPPool.closeTcp(tcpPort);
}
}
public void updateCurrentUserByResourceId(String resourceId) {
Project project = baseProjectMapper.selectProjectByResourceId(resourceId);
if (project == null) {
@ -171,4 +179,12 @@ public class ExtProjectApplicationService {
user.setLastWorkspaceId(project.getWorkspaceId());
userMapper.updateByPrimaryKeySelective(user);
}
public List<ProjectDTO> getUserProject(ApiProjectRequest request) {
if (StringUtils.isNotBlank(request.getName())) {
request.setName(StringUtils.wrapIfMissing(request.getName(), "%"));
}
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
return extApiProjectMapper.getUserProject(request);
}
}

View File

@ -5,6 +5,8 @@ import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.api.dto.ApiCaseRelevanceRequest;
import io.metersphere.api.dto.EnvironmentType;
import io.metersphere.api.dto.QueryReferenceRequest;
import io.metersphere.api.dto.automation.TestPlanDTO;
import io.metersphere.api.dto.automation.TestPlanFailureApiDTO;
import io.metersphere.api.dto.definition.*;
import io.metersphere.api.dto.plan.TestPlanApiCaseBatchRequest;
@ -18,10 +20,7 @@ import io.metersphere.base.mapper.ApiTestCaseMapper;
import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.plan.TestPlanApiCaseMapper;
import io.metersphere.base.mapper.plan.ext.ExtTestPlanApiCaseMapper;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.CommonConstants;
import io.metersphere.commons.constants.ExtendedParameter;
import io.metersphere.commons.constants.TriggerMode;
import io.metersphere.commons.constants.*;
import io.metersphere.commons.enums.ApiReportStatus;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.*;
@ -29,6 +28,7 @@ import io.metersphere.dto.MsExecResponseDTO;
import io.metersphere.dto.RunModeConfigDTO;
import io.metersphere.environment.service.BaseEnvGroupProjectService;
import io.metersphere.log.vo.OperatingLogDetails;
import io.metersphere.request.OrderRequest;
import io.metersphere.request.ResetOrderRequest;
import io.metersphere.service.BaseProjectService;
import io.metersphere.service.ServiceUtils;
@ -770,4 +770,23 @@ public class TestPlanApiCaseService {
example.createCriteria().andIdIn(list);
return testPlanApiCaseMapper.selectByExample(example);
}
//获取case和测试计划引用关系
public List<TestPlanDTO> getReference(QueryReferenceRequest request) {
if (CollectionUtils.isEmpty(request.getOrders())) {
OrderRequest req = new OrderRequest();
req.setName("name");
req.setType("asc");
request.setOrders(new ArrayList<>() {{
this.add(req);
}});
}
QueryReferenceRequest planRequest = new QueryReferenceRequest();
if (StringUtils.equals(request.getScenarioType(), ReportTypeConstants.API.name())) {
planRequest.setApiId(request.getId());
} else {
planRequest.setScenarioId(request.getId());
}
return extTestPlanApiCaseMapper.selectTestPlanByRelevancy(planRequest);
}
}

View File

@ -21,12 +21,10 @@ import io.metersphere.api.parse.scenario.ScenarioImport;
import io.metersphere.api.parse.scenario.ScenarioImportParserFactory;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.BaseProjectVersionMapper;
import io.metersphere.base.mapper.ext.ExtApiScenarioMapper;
import io.metersphere.base.mapper.ext.ExtApiTestCaseMapper;
import io.metersphere.base.mapper.ext.ExtScheduleMapper;
import io.metersphere.base.mapper.ext.*;
import io.metersphere.base.mapper.plan.TestPlanApiScenarioMapper;
import io.metersphere.base.mapper.plan.ext.ExtTestPlanApiCaseMapper;
import io.metersphere.base.mapper.plan.ext.ExtTestPlanApiScenarioMapper;
import io.metersphere.base.mapper.plan.ext.ExtTestPlanScenarioCaseMapper;
import io.metersphere.commons.constants.*;
import io.metersphere.commons.enums.ApiReportStatus;
@ -158,6 +156,10 @@ public class ApiScenarioService {
private ExtTestPlanScenarioCaseMapper extTestPlanScenarioCaseMapper;
@Resource
private JMeterService jMeterService;
@Resource
private ExtApiScenarioReferenceIdMapper extApiScenarioReferenceIdMapper;
@Resource
private ExtTestPlanApiScenarioMapper extTestPlanApiScenarioMapper;
private ThreadLocal<Long> currentScenarioOrder = new ThreadLocal<>();
@ -932,7 +934,7 @@ public class ApiScenarioService {
public ReferenceDTO getReference(ApiScenarioRequest request) {
ReferenceDTO dto = new ReferenceDTO();
dto.setScenarioList(extApiScenarioMapper.selectReference(request));
//dto.setScenarioList(extApiScenarioMapper.selectReference(request));
QueryReferenceRequest planRequest = new QueryReferenceRequest();
planRequest.setScenarioId(request.getId());
planRequest.setProjectId(request.getProjectId());
@ -1965,49 +1967,58 @@ public class ApiScenarioService {
ServiceUtils.getSelectAllIds(request, request.getCondition(), (query) -> extApiScenarioMapper.selectIdsByQuery(query));
List<String> deleteIds = request.getIds();
DeleteCheckResult result = new DeleteCheckResult();
List<String> checkMsgList = new ArrayList<>();
if (CollectionUtils.isNotEmpty(deleteIds)) {
List<ApiScenarioReferenceId> apiScenarioReferenceIdList = apiScenarioReferenceIdService.findByReferenceIdsAndRefType(deleteIds, MsTestElementConstants.REF.name());
Map<String, List<String>> scenarioDic = new HashMap<>();
List<ApiScenarioReferenceId> apiScenarioReferenceIdList = extApiScenarioReferenceIdMapper.selectReferenceIdByIds(deleteIds);
if (CollectionUtils.isNotEmpty(apiScenarioReferenceIdList)) {
Map<String, List<String>> scenarioDic = new HashMap<>();
apiScenarioReferenceIdList.forEach(item -> {
String refreceID = item.getReferenceId();
String referenceId = item.getReferenceId();
String scenarioId = item.getApiScenarioId();
if (scenarioDic.containsKey(refreceID)) {
scenarioDic.get(refreceID).add(scenarioId);
if (scenarioDic.containsKey(referenceId)) {
scenarioDic.get(referenceId).add(scenarioId);
} else {
List<String> list = new ArrayList<>();
list.add(scenarioId);
scenarioDic.put(refreceID, list);
scenarioDic.put(referenceId, list);
}
});
for (Map.Entry<String, List<String>> entry : scenarioDic.entrySet()) {
String refreceId = entry.getKey();
List<String> scenarioIdList = entry.getValue();
if (CollectionUtils.isNotEmpty(scenarioIdList)) {
String deleteScenarioName = extApiScenarioMapper.selectNameById(refreceId);
List<String> scenarioNames = extApiScenarioMapper.selectNameByIdIn(scenarioIdList);
if (StringUtils.isNotEmpty(deleteScenarioName) && CollectionUtils.isNotEmpty(scenarioNames)) {
String nameListStr = StringUtils.SPACE;
for (String name : scenarioNames) {
nameListStr += name + ",";
}
if (nameListStr.length() > 1) {
nameListStr = nameListStr.substring(0, nameListStr.length() - 1) + StringUtils.SPACE;
}
String msg = deleteScenarioName + StringUtils.SPACE + Translator.get("delete_check_reference_by") + ": " + nameListStr + StringUtils.SPACE;
checkMsgList.add(msg);
}
}
//测试计划引用
List<TestPlanApiScenario> testPlanApiScenarios = extTestPlanApiScenarioMapper.selectByScenarioIds(deleteIds);
Map<String, List<String>> planList = new HashMap<>();
if (CollectionUtils.isNotEmpty(testPlanApiScenarios)) {
testPlanApiScenarios.forEach(item -> {
String referenceId = item.getApiScenarioId();
String testPlanId = item.getTestPlanId();
if (planList.containsKey(referenceId)) {
planList.get(referenceId).add(testPlanId);
} else {
List<String> list = new ArrayList<>();
list.add(testPlanId);
planList.put(referenceId, list);
}
});
}
if (MapUtils.isNotEmpty(scenarioDic) || MapUtils.isNotEmpty(planList)) {
if (StringUtils.equals("batch", request.getType())) {
Map<String, List<String>> map = scenarioDic.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v2, () -> new HashMap<>(planList)));
result.setRefCount(map.size());
result.setCheckMsg(new ArrayList<>(map.keySet()));
} else {
ArrayList<List<String>> scenarioList = new ArrayList<>(scenarioDic.values());
if (CollectionUtils.isNotEmpty(scenarioList)) {
result.setScenarioCount(new TreeSet<String>(scenarioList.get(0)).size());
}
ArrayList<List<String>> testPlanList = new ArrayList<>(planList.values());
if (CollectionUtils.isNotEmpty(testPlanList)) {
result.setPlanCount(new TreeSet<String>(testPlanList.get(0)).size());
}
}
result.setDeleteFlag(scenarioDic.size() > 0 || planList.size() > 0);
}
}
result.setDeleteFlag(checkMsgList.isEmpty());
result.setCheckMsg(checkMsgList);
return result;
}

View File

@ -343,4 +343,5 @@ api_case_create_notice=Interface use case new notification
update_api_case=Updated interface use case
api_case_update_notice=Interface use case update notification
error_xml_struct=Data is not xml
case_name_is_already_exist=Duplicate Case name
case_name_is_already_exist=Duplicate Case name
delete_check_reference_by_plan=referenced by the test plan

View File

@ -363,3 +363,4 @@ update_api_case=更新了接口用例
api_case_update_notice=接口用例更新通知
error_xml_struct=错误的xml数据
case_name_is_already_exist=用例名称不能重复
delete_check_reference_by_plan=被测试计划引用

View File

@ -363,3 +363,4 @@ update_api_case=更新了接口用例
api_case_update_notice=接口用例更新通知
error_xml_struct=錯誤的xml數據
case_name_is_already_exist=用例名稱不能重復
delete_check_reference_by_plan=被測試計劃引用

View File

@ -121,8 +121,12 @@ export function jsonGenerator(params) {
return post('/api/definition/generator', params);
}
export function getDefinitionReference(params) {
return post('/api/definition/get-reference', params);
export function getDefinitionReference(currentPage, pageSize, params) {
return post('/api/definition/get-reference/' + currentPage + '/' + pageSize, params);
}
export function getPlanReference(currentPage, pageSize, params) {
return post('/test/plan/api/case/get-reference/' + currentPage + '/' + pageSize, params);
}
export function deleteBatchByParams(params) {

View File

@ -62,10 +62,6 @@ export function getApiScenarios(params) {
return post('/api/automation/get-scenario-list', params);
}
export function getReference(params) {
return post('/api/automation/getReference', params);
}
export function genPerformanceTestJmx(params) {
return post('/api/automation/gen-jmx', params);
}

View File

@ -262,6 +262,7 @@
:row="scope.row"
@openSchedule="openSchedule(scope.row)"
@openScenario="openScenario"
@showCaseRef="showScenarioRef"
v-if="!trashEnable" style="display: contents"/>
</template>
@ -317,7 +318,16 @@
<ms-task-center ref="taskCenter" :show-menu="false"/>
<mx-relationship-graph-drawer v-xpack :graph-data="graphData" ref="relationshipGraph"/>
<!-- 删除接口提示 -->
<list-item-delete-confirm ref="apiDeleteConfirm" @handleDelete="_handleDelete"/>
<scenario-delete-confirm ref="apiDeleteConfirmVersion" @handleDelete="_handleDelete"/>
<!-- 删除场景弹窗 -->
<api-delete-confirm
:has-ref="hasRef"
:show-scenario="showScenario"
@showCaseRef="showScenarioRef"
@handleDeleteCase="handleDeleteScenario"
ref="apiDeleteConfirm"/>
<!-- 引用场景弹窗 -->
<ms-show-reference ref="viewRef" @showCaseRef="showScenarioRef" @openScenario="openScenario"/>
</div>
</template>
@ -350,7 +360,7 @@ import {
import {getMaintainer, getProject} from "@/api/project";
import {getProjectVersions, versionEnableByProjectId} from "@/api/xpack";
import {getCurrentProjectID, getCurrentUserId} from "metersphere-frontend/src/utils/token";
import {downloadFile, getUUID, objToStrMap, operationConfirm, strMapToObj} from "metersphere-frontend/src/utils";
import {downloadFile, getUUID, objToStrMap, strMapToObj} from "metersphere-frontend/src/utils";
import {hasLicense, hasPermission} from "metersphere-frontend/src/utils/permission";
import {API_SCENARIO_CONFIGS} from "metersphere-frontend/src/components/search/search-components";
import {API_SCENARIO_LIST} from "metersphere-frontend/src/utils/constants";
@ -370,6 +380,7 @@ import {API_SCENARIO_CONFIGS_TRASH, TYPE_TO_C} from "@/business/automation/scena
import MsTableSearchBar from "metersphere-frontend/src/components/MsTableSearchBar";
import MsTableAdvSearchBar from "metersphere-frontend/src/components/search/MsTableAdvSearchBar";
import ListItemDeleteConfirm from "metersphere-frontend/src/components/ListItemDeleteConfirm";
import ScenarioDeleteConfirm from "@/business/automation/scenario/ScenarioDeleteConfirm";
import {$error} from "metersphere-frontend/src/plugins/message"
import MsSearch from "metersphere-frontend/src/components/search/MsSearch";
import {buildNodePath} from "metersphere-frontend/src/model/NodeTree";
@ -379,6 +390,8 @@ import {usePerformanceStore} from "@/store";
import {request} from "metersphere-frontend/src/plugins/request"
import {parseEnvironment} from "@/business/environment/model/EnvironmentModel";
import MsApiRunMode from "@/business/automation/scenario/common/ApiRunMode";
import ApiDeleteConfirm from "@/business/definition/components/list/ApiDeleteConfirm";
import MsShowReference from "@/business/definition/components/reference/ShowReference";
const performanceStore = usePerformanceStore();
export default {
@ -392,6 +405,9 @@ export default {
HeaderLabelOperate,
MsSearch,
MsApiRunMode,
ApiDeleteConfirm,
MsShowReference,
ScenarioDeleteConfirm,
MsApiReportStatus: () => import("../report/ApiReportStatus"),
HeaderCustom: () => import("metersphere-frontend/src/components/head/HeaderCustom"),
BatchMove: () => import("@/business/commons/BatchMove"),
@ -630,6 +646,8 @@ export default {
resultFilters: REPORT_STATUS,
runRequest: {},
versionEnable: false,
hasRef: false,
showScenario: false,
};
},
created() {
@ -1086,26 +1104,17 @@ export default {
} else {
let param = {};
this.buildBatchParam(param);
param.type = 'batch';
this.showScenario = false;
this.hasRef = false;
checkBeforeDelete(param).then(response => {
let checkResult = response.data;
let alertMsg = this.$t('load_test.delete_threadgroup_confirm') + " ";
if (!checkResult.deleteFlag) {
alertMsg = "";
checkResult.checkMsg.forEach(item => {
alertMsg += item + ";";
});
if (alertMsg === "") {
alertMsg = this.$t('load_test.delete_threadgroup_confirm') + " ";
} else {
alertMsg += this.$t('api_test.is_continue') + this.$t('commons.delete') + " ";
}
if (checkResult.deleteFlag) {
alertMsg = this.$t('api_definition.scenario_is_referenced', [checkResult.refCount]) + ', ' + this.$t('api_test.is_continue') + " ";
this.showScenario = true;
}
operationConfirm(this, alertMsg, () => {
removeScenarioToGcByBatch(param).then(() => {
this.$success(this.$t('commons.delete_success'));
this.search();
});
});
this.$refs.apiDeleteConfirm.open(alertMsg, this.$t('permission.project_api_definition.delete_case'), param, checkResult.checkMsg);
});
}
},
@ -1234,6 +1243,15 @@ export default {
this.selectDataRange = dataRange;
this.selectDataType = dataType;
}
if (this.$route.query && this.$route.params.dataSelectRange === 'ref') {
if (this.$route.query.ids) {
if (typeof this.$route.query.ids === 'string') {
this.condition.ids = [this.$route.query.ids];
} else {
this.condition.ids = this.$route.query.ids;
}
}
}
},
changeSelectDataRangeAll() {
this.$emit("changeSelectDataRangeAll");
@ -1249,40 +1267,47 @@ export default {
let param = {};
this.buildBatchParam(param);
param.ids = [row.id];
this.showScenario = false;
this.hasRef = false;
checkBeforeDelete(param).then(response => {
let checkResult = response.data;
let alertMsg = this.$t('load_test.delete_threadgroup_confirm');
if (!checkResult.deleteFlag) {
alertMsg = "";
checkResult.checkMsg.forEach(item => {
alertMsg += item;
});
if (alertMsg === "") {
alertMsg = this.$t('load_test.delete_threadgroup_confirm');
} else {
alertMsg += this.$t('api_test.is_continue') + this.$t('commons.delete');
}
let alertMsg = this.$t('load_test.delete_threadgroup_confirm') + '[' + row.name + ']' + '?';
if (checkResult.deleteFlag) {
alertMsg = '[' + row.name + '] ' + this.$t('api_definition.scenario_is') + (checkResult.scenarioCount > 0 ? this.$t('api_definition.scenario_count', [checkResult.scenarioCount]) : '') +
(checkResult.planCount > 0 && checkResult.scenarioCount > 0 ? '、 ' : '') +
(checkResult.planCount > 0 ? this.$t('api_definition.plan_count', [checkResult.planCount]) : '') + this.$t('api_test.scenario.reference') + ', ' +
this.$t('api_test.is_continue') + " ";
this.hasRef = true;
}
//
getScenarioVersions(row.id).then(response => {
if (hasLicense() && this.versionEnable && response.data.length > 1) {
//
this.$refs.apiDeleteConfirm.open(row, alertMsg);
this.$refs.apiDeleteConfirmVersion.open(row, alertMsg);
} else {
operationConfirm(this, alertMsg, () => {
this._handleDelete(row, false);
});
this.$refs.apiDeleteConfirm.open(alertMsg, this.$t('permission.project_api_scenario.delete'), row, null);
}
});
});
}
},
handleDeleteScenario(row) {
this.$refs.apiDeleteConfirm.close();
if (row.type === 'batch') {
removeScenarioToGcByBatch(row).then(() => {
this.$success(this.$t('commons.delete_success'));
this.search();
});
} else {
this._handleDelete(row, false);
}
},
_handleDelete(api, deleteCurrentVersion) {
//
if (deleteCurrentVersion) {
delByScenarioIdAndRefId(api.versionId, api.refId).then(() => {
this.$success(this.$t('commons.delete_success'));
this.$refs.apiDeleteConfirm.close();
this.$refs.apiDeleteConfirmVersion.close();
this.search();
});
}
@ -1293,7 +1318,7 @@ export default {
param.ids = [api.id];
removeScenarioToGcByBatch(param).then(() => {
this.$success(this.$t('commons.delete_success'));
this.$refs.apiDeleteConfirm.close();
this.$refs.apiDeleteConfirmVersion.close();
this.search();
});
}
@ -1429,7 +1454,10 @@ export default {
this.$set(data, "isStop", false);
}
}
}
},
showScenarioRef(row) {
this.$refs.viewRef.open(row, 'SCENARIO');
},
}
};
</script>

View File

@ -1,95 +0,0 @@
<template>
<el-dialog :close-on-click-modal="false" :title="$t('api_test.automation.scenario_ref')" :visible.sync="visible"
width="45%" :destroy-on-close="true">
<span>{{ $t('api_test.automation.scenario_ref') }}</span>
<div class="refs" v-loading="scenarioLoading">
<div v-for="(item, index) in scenarioRefs" :key="index" class="el-button--text">
<el-link @click="openScenario(item)" v-if="item.status === 'Trash'">
{{ item.name }}
<el-tag size="mini">{{ $t('commons.trash') }}</el-tag>
</el-link>
<el-link @click="openScenario(item)" v-else>
{{ item.name }}
</el-link>
</div>
</div>
<span>{{ $t('api_test.automation.plan_ref') }}</span>
<div class="refs">
<div v-for="(item, index) in planRefs" :key="index" class="el-button--text">
<el-link @click="openTestPlan(item)">
{{ item.name }}
</el-link>
</div>
</div>
<template v-slot:footer>
<div class="dialog-footer">
<el-button type="primary" @click="visible = false" @keydown.enter.native.prevent>
{{ $t('commons.confirm') }}
</el-button>
</div>
</template>
</el-dialog>
</template>
<script>
import {getReference} from "@/api/scenario";
export default {
name: "MsReferenceView",
components: {},
data() {
return {
visible: false,
scenarioLoading: false,
scenarioRefs: [],
planRefs: []
}
},
methods: {
getReferenceData(row) {
this.scenarioLoading = true;
this.scenarioRefs = [];
getReference(row).then(response => {
this.scenarioRefs = response.data.scenarioList;
this.planRefs = response.data.testPlanList;
this.scenarioLoading = false;
})
},
open(row) {
this.getReferenceData(row);
this.visible = true
},
openScenario(item) {
this.$emit('openScenario', item);
this.visible = false;
},
openTestPlan(item) {
let automationData = this.$router.resolve({
path: '/track/plan/view/' + item.id,
query: {workspaceId: item.workspaceId, projectId: item.projectId, charType: 'scenario'}
});
window.open(automationData.href, '_blank');
}
}
}
</script>
<style scoped>
.refs {
min-height: 50px;
max-height: 200px;
overflow-y: auto;
font-size: 12px;
padding-bottom: 10px;
}
.el-button--text .el-link.el-link--default {
font-size: 12px;
color: #4b1980;
font-weight: 400;
text-decoration: underline;
}
</style>

View File

@ -0,0 +1,55 @@
<template>
<el-dialog
:title="title"
:visible.sync="deleteApiVisible"
:show-close="false"
width="30%"
>
<el-radio-group v-model="deleteCurrentVersion">
<el-radio :label="true">{{ $t('commons.delete_current_version') }}</el-radio>
<el-radio :label="false">{{ $t('commons.delete_all_version') }}</el-radio>
</el-radio-group>
<template v-slot:footer>
<ms-dialog-footer
@cancel="close"
@confirm="handleDelete">
</ms-dialog-footer>
</template>
</el-dialog>
</template>
<script>
import MsDialogFooter from "metersphere-frontend/src/components/MsDialogFooter";
export default {
name: "ListItemDeleteConfirm",
components: {MsDialogFooter},
data() {
return {
deleteApiVisible: false,
title: null,
deleteCurrentVersion: true,
api: {}
};
},
methods: {
open(api, title) {
this.api = api;
this.deleteCurrentVersion = true;
this.title = title;
this.deleteApiVisible = true;
},
close() {
this.deleteApiVisible = false;
},
handleDelete() {
this.$emit('handleDelete', this.api, this.deleteCurrentVersion);
},
}
};
</script>
<style scoped>
</style>

View File

@ -15,7 +15,7 @@
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<ms-reference-view @openScenario="openScenario" ref="viewRef"/>
<ms-schedule-maintain ref="scheduleMaintain" @refreshTable="refreshTable" :request="request"/>
</div>
@ -23,7 +23,6 @@
<script>
import {genPerformanceTestJmx} from "@/api/scenario";
import MsReferenceView from "@/business/automation/scenario/ReferenceView";
import MsScheduleMaintain from "@/business/automation/schedule/ScheduleMaintain";
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
import {hasPermission} from "metersphere-frontend/src/utils/permission";
@ -34,7 +33,7 @@ const performanceStore = usePerformanceStore();
export default {
name: "MsScenarioExtendButtons",
components: {MsReferenceView, MsScheduleMaintain},
components: {MsScheduleMaintain},
props: {
row: Object,
request: {}
@ -44,7 +43,7 @@ export default {
handleCommand(cmd) {
switch (cmd) {
case "ref":
this.$refs.viewRef.open(this.row);
this.$emit("showCaseRef", this.row);
break;
case "schedule":
this.$emit('openSchedule');

View File

@ -242,7 +242,7 @@
<!--选择环境(当创建性能测试的时候)-->
<ms-set-environment ref="setEnvironment" :testCase="clickRow" @createPerformance="createPerformance"/>
<!--查看引用-->
<ms-reference-view ref="viewRef"/>
<ms-show-reference ref="viewRef"/>
<ms-task-center ref="taskCenter" :show-menu="false"/>
@ -268,6 +268,14 @@
<el-button type="primary" @click="batchSync()">{{ $t('commons.confirm') }}</el-button>
</span>
</el-dialog>
<!-- 删除接口提示 -->
<api-delete-confirm
:has-ref="hasRef"
:show-case="showCase"
@showCaseRef="showCaseRef"
@handleDeleteCase="handleDeleteCase"
ref="apiDeleteConfirm"
/>
</span>
</template>
@ -306,14 +314,14 @@ import MsContainer from "metersphere-frontend/src/components/MsContainer";
import MsBottomContainer from "../BottomContainer";
import ShowMoreBtn from "@/business/commons/ShowMoreBtn";
import MsBatchEdit from "../basis/BatchEdit";
import {getUUID, operationConfirm} from "metersphere-frontend/src/utils";
import {getUUID} from "metersphere-frontend/src/utils";
import {API_METHOD_COLOUR, CASE_PRIORITY, DUBBO_METHOD, REQ_METHOD, SQL_METHOD, TCP_METHOD} from "../../model/JsonData";
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
import {hasLicense} from "metersphere-frontend/src/utils/permission";
import {getBodyUploadFiles} from "@/business/definition/api-definition";
import PriorityTableItem from "@/business/commons/PriorityTableItem";
import MsApiCaseTableExtendBtns from "../reference/ApiCaseTableExtendBtns";
import MsReferenceView from "../reference/ReferenceView";
import MsShowReference from "../reference/ShowReference";
import MsSetEnvironment from "@/business/definition/components/basis/SetEnvironment";
import TestPlan from "@/business/definition/components/jmeter/components/test-plan";
import ThreadGroup from "@/business/definition/components/jmeter/components/thread-group";
@ -341,6 +349,8 @@ import {getEnvironmentByProjectId} from "metersphere-frontend/src/api/environmen
import {useApiStore, usePerformanceStore} from "@/store";
import {REPORT_STATUS} from "@/business/commons/js/commons";
import MsApiRunMode from "@/business/automation/scenario/common/ApiRunMode";
import ApiDeleteConfirm from "@/business/definition/components/list/ApiDeleteConfirm";
const performanceStore = usePerformanceStore();
const store = useApiStore();
@ -363,7 +373,6 @@ export default {
ShowMoreBtn,
MsBatchEdit,
MsApiCaseTableExtendBtns,
MsReferenceView,
MsTableAdvSearchBar,
MsTable,
MsTableColumn,
@ -371,6 +380,8 @@ export default {
MsApiRunMode,
MsSearch,
SyncSetting,
MsShowReference,
ApiDeleteConfirm,
MsApiReportStatus: () => import("../../../automation/report/ApiReportStatus"),
PlanStatusTableItem: () => import("@/business/commons/PlanStatusTableItem"),
MsTaskCenter: () => import("metersphere-frontend/src/components/task/TaskCenter"),
@ -407,27 +418,11 @@ export default {
handleClick: this.handleRunBatch,
permissions: ['PROJECT_API_DEFINITION:READ+RUN']
},
],
batchButtons: [
{
name: this.$t('api_test.definition.request.batch_delete'),
handleClick: this.handleDeleteToGcBatch,
permissions: ['PROJECT_API_DEFINITION:READ+DELETE_CASE']
},
{
name: this.$t('api_test.definition.request.batch_edit'),
handleClick: this.handleEditBatch,
permissions: ['PROJECT_API_DEFINITION:READ+EDIT_CASE']
},
{
name: this.$t('api_test.automation.batch_execute'),
handleClick: this.handleRunBatch,
permissions: ['PROJECT_API_DEFINITION:READ+RUN']
},
{
name: this.$t('commons.batch') + this.$t('workstation.sync'),
handleClick: this.openBatchSync,
permissions: ['PROJECT_TRACK_PLAN:READ+SCHEDULE']
permissions: ['PROJECT_TRACK_PLAN:READ+SCHEDULE'],
isXPack: true,
},
],
trashButtons: [
@ -523,6 +518,8 @@ export default {
userFilters: [],
environmentsFilters: [],
batchSyncCaseVisible: false,
hasRef: false,
showCase: false,
};
},
props: {
@ -563,12 +560,7 @@ export default {
this.buttons = this.trashButtons;
} else {
this.operators = this.simpleOperators;
if (hasLicense()) {
this.buttons = this.batchButtons;
} else {
this.buttons = this.simpleButtons;
}
this.buttons = this.simpleButtons;
}
// tab
this.condition.versionId = this.currentVersion;
@ -994,28 +986,17 @@ export default {
obj.unSelectIds = this.unSelection;
obj = Object.assign(obj, this.condition);
obj.ids = Array.from(this.selectRows).map(row => row.id);
obj.type = 'batch';
this.showCase = false;
this.hasRef = false;
checkDeleteData(obj).then(response => {
let checkResult = response.data;
let alertMsg = this.$t('api_test.definition.request.delete_case_confirm') + " ";
if (!checkResult.deleteFlag) {
alertMsg = "";
checkResult.checkMsg.forEach(item => {
alertMsg += item + ";";
});
if (alertMsg === "") {
alertMsg = this.$t('api_test.definition.request.delete_case_confirm') + " ";
} else {
alertMsg += this.$t('api_test.is_continue') + " ";
}
if (checkResult.deleteFlag) {
alertMsg = this.$t('api_definition.case_is_referenced', [checkResult.refCount]) + ', ' + this.$t('api_test.is_continue') + " ";
this.showCase = true;
}
operationConfirm(this, alertMsg, () => {
delCaseToGcByParam(obj).then(() => {
this.$refs.caseTable.clearSelectRows();
this.initTable();
this.$success(this.$t('commons.delete_success'));
this.$emit('refreshTable');
});
});
this.$refs.apiDeleteConfirm.open(alertMsg, this.$t('permission.project_api_definition.delete_case'), obj, checkResult.checkMsg);
});
},
handleEditBatch() {
@ -1081,34 +1062,43 @@ export default {
});
return;
},
handleDeleteCase(apiCase) {
this.$refs.apiDeleteConfirm.close();
if (apiCase.type === 'batch') {
delCaseToGcByParam(apiCase).then(() => {
this.$refs.caseTable.clearSelectRows();
this.initTable();
this.$success(this.$t('commons.delete_success'));
this.$emit('refreshTable');
});
} else {
deleteToGc(apiCase.id).then(() => {
this.$success(this.$t('commons.delete_success'));
this.initTable();
this.$emit("refreshTree");
this.$emit('refreshTable');
});
}
},
deleteToGc(apiCase) {
let obj = {};
obj.projectId = this.projectId;
obj.selectAllDate = false;
obj.ids = [apiCase.id];
obj = Object.assign(obj, this.condition);
this.showCase = false;
this.hasRef = false;
checkDeleteData(obj).then(response => {
let checkResult = response.data;
let alertMsg = this.$t('api_test.definition.request.delete_case_confirm') + ' ' + apiCase.name + " ";
if (!checkResult.deleteFlag) {
alertMsg = "";
checkResult.checkMsg.forEach(item => {
alertMsg += item + ";";
});
if (alertMsg === "") {
alertMsg = this.$t('api_test.definition.request.delete_case_confirm') + ' ' + apiCase.name + " ";
} else {
alertMsg += this.$t('api_test.is_continue') + " ";
}
let alertMsg = this.$t('api_test.definition.request.delete_case_confirm') + '[' + apiCase.name + ']' + '?';
if (checkResult.deleteFlag) {
alertMsg = '[' + apiCase.name + '] ' + this.$t('api_definition.case_is') + (checkResult.scenarioCount > 0 ? this.$t('api_definition.scenario_count', [checkResult.scenarioCount]) : '') +
(checkResult.planCount > 0 && checkResult.scenarioCount > 0 ? '、 ' : '') +
(checkResult.planCount > 0 ? this.$t('api_definition.plan_count', [checkResult.planCount]) : '') + this.$t('api_test.scenario.reference') + ', ' +
this.$t('api_test.is_continue') + " ";
this.hasRef = true;
}
operationConfirm(this, alertMsg, () => {
deleteToGc(apiCase.id).then(() => {
this.$success(this.$t('commons.delete_success'));
this.initTable();
this.$emit("refreshTree");
this.$emit('refreshTable');
});
});
this.$refs.apiDeleteConfirm.open(alertMsg, this.$t('permission.project_api_definition.delete_case'), apiCase, null);
});
},
reduction(row) {
@ -1182,6 +1172,15 @@ export default {
if (dataType === 'apiTestCase') {
this.selectDataRange = routeParam;
}
if (this.$route.query && this.$route.params.dataSelectRange === 'ref') {
if (this.$route.query.ids) {
if (typeof this.$route.query.ids === 'string') {
this.condition.ids = [this.$route.query.ids];
} else {
this.condition.ids = this.$route.query.ids;
}
}
}
},
changeSelectDataRangeAll() {
this.$emit("changeSelectDataRangeAll", "testCase");
@ -1195,7 +1194,7 @@ export default {
let param = {};
Object.assign(param, row);
param.moduleId = undefined;
this.$refs.viewRef.open(param);
this.$refs.viewRef.open(param, 'API');
},
showEnvironment(row) {
if (this.projectId) {

View File

@ -0,0 +1,105 @@
<template>
<el-dialog
:title="title"
:visible.sync="deleteApiVisible"
class="delete-body"
width="30%">
<p> {{ this.content }}</p>
<el-link style="color: #6c327a" @click="showRef" v-if="hasRef">{{ $t('api_test.automation.view_ref') }}</el-link>
<el-link style="color: #6c327a" v-if="showCase" @click="redirectPage('api', 'apiTestCase', 'ref')">
{{ $t('api_definition.view_case') }}
</el-link>
<el-link style="color: #6c327a" v-if="showScenario" @click="redirectPage('scenario', 'scenario', 'ref')">{{
$t('api_definition.view_scenario')
}}
</el-link>
<span slot="footer">
<el-button @click="close" size="mini">{{ $t('commons.cancel') }}</el-button>
<el-button v-prevent-re-click type="primary" @click="handleDelete" @keydown.enter.native.prevent size="mini">
{{ $t('commons.confirm') }}
</el-button>
</span>
</el-dialog>
</template>
<script>
import {getUUID} from "metersphere-frontend/src/utils";
export default {
name: "ApiDeleteConfirm",
components: {},
data() {
return {
deleteApiVisible: false,
title: null,
deleteCurrentVersion: true,
content: {},
apiCase: {},
selectIds: [],
};
},
props: {
hasRef: {
type: Boolean,
default: false
},
showCase: {
type: Boolean,
default: false
},
showScenario: {
type: Boolean,
default: false
}
},
methods: {
open(content, title, row, selectIds) {
this.content = content;
this.title = title;
this.deleteApiVisible = true;
this.apiCase = row;
this.selectIds = selectIds;
},
close() {
this.deleteApiVisible = false;
},
handleDelete() {
this.$emit('handleDeleteCase', this.apiCase);
},
showRef() {
this.$emit('showCaseRef', this.apiCase);
},
redirectPage(redirectPage, dataType, selectRange) {
//UUID
let uuid = getUUID();
let home;
switch (redirectPage) {
case "api":
home = this.$router.resolve({
name: 'ApiDefinitionWithQuery',
params: {redirectID: uuid, dataType: dataType, dataSelectRange: selectRange},
query: {ids: this.selectIds}
});
break;
case "scenario":
home = this.$router.resolve({
name: 'ApiAutomationWithQuery',
params: {redirectID: uuid, dataType: dataType, dataSelectRange: selectRange},
query: {ids: this.selectIds}
});
break;
}
if (home) {
window.open(home.href, '_blank');
}
}
}
};
</script>
<style scoped>
.delete-body :deep( .el-dialog__body , .el-dialog__footer) {
padding: 0px 20px;
}
</style>

View File

@ -650,7 +650,7 @@ export default {
this.condition.scenarioCoverage = null;
break;
case 'covered':
this.condition.apiCoverage = '"unCovered"';
this.condition.apiCoverage = '"covered"';
this.condition.scenarioCoverage = 'covered';
break;
case 'notCoveredTestCase':

View File

@ -9,13 +9,14 @@
{{ $t('api_test.create_performance_test') }}
</el-dropdown-item>
</el-dropdown-menu>
<ms-reference-view ref="viewRef"/>
<ms-show-reference ref="viewRef"/>
</el-dropdown>
</template>
<script>
import {genPerformanceTestXml} from "@/api/home";
import MsReferenceView from "./ReferenceView";
import MsShowReference from "./ShowReference";
import MsTestPlanList from "../../../automation/scenario/testplan/TestPlanList";
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
import {getBodyUploadFiles} from "@/business/definition/api-definition";
@ -27,7 +28,7 @@ import {usePerformanceStore} from "@/store";
const performanceStore = usePerformanceStore();
export default {
name: "MsApiExtendBtns",
components: {MsReferenceView, MsTestPlanList},
components: {MsShowReference, MsTestPlanList},
props: {
row: Object,
isCaseEdit: Boolean,
@ -43,7 +44,7 @@ export default {
if (this.row.id) {
switch (cmd) {
case "ref":
this.$refs.viewRef.open(this.row);
this.$refs.viewRef.open(this.row, 'API');
break;
case "create_performance":
this.createPerformance(this.row);

View File

@ -1,128 +0,0 @@
<template>
<el-dialog :close-on-click-modal="false" :title="$t('api_test.automation.case_ref')" :visible.sync="visible"
:modal="false" width="45%" :destroy-on-close="true">
<span>{{ $t('api_test.automation.scenario_ref') }}</span>
<div class="refs" v-loading="scenarioLoading">
<div v-for="(item, index) in scenarioRefs" :key="index" class="el-button--text">
<el-link @click="openScenario(item)">
{{ item.name }}
</el-link>
</div>
</div>
<span>{{ $t('api_test.automation.plan_ref') }}</span>
<div class="refs">
<div v-for="(item, index) in planRefs" :key="index" class="el-button--text">
<el-link @click="openTestPlan(item)">
{{ item.name }}
</el-link>
</div>
</div>
<template v-slot:footer>
<div class="dialog-footer">
<el-button type="primary" @click="visible = false" @keydown.enter.native.prevent>
{{ $t('commons.confirm') }}
</el-button>
</div>
</template>
</el-dialog>
</template>
<script>
import {getDefinitionReference} from "@/api/definition";
import {getCurrentProjectID, getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
import {getUUID} from "metersphere-frontend/src/utils";
import {getOwnerProjectIds, getProject} from "@/api/project";
export default {
name: "MsReferenceView",
components: {},
data() {
return {
visible: false,
scenarioLoading: false,
scenarioRefs: [],
planRefs: []
}
},
methods: {
getReferenceData(row) {
if (row.id === undefined) {
return;
}
this.scenarioLoading = true;
this.scenarioRefs = [];
getDefinitionReference(row).then(response => {
this.scenarioRefs = response.data.scenarioList;
this.planRefs = response.data.testPlanList;
this.scenarioLoading = false;
})
},
open(row) {
this.getReferenceData(row);
this.visible = true
},
openScenario(resource) {
let workspaceId = getCurrentWorkspaceId();
let isTurnSpace = true
if (resource.projectId !== getCurrentProjectID()) {
isTurnSpace = false;
getProject(resource.projectId).then(response => {
if (response.data) {
workspaceId = response.data.workspaceId;
isTurnSpace = true;
this.checkPermission(resource, workspaceId, isTurnSpace);
}
});
} else {
this.checkPermission(resource, workspaceId, isTurnSpace);
}
},
gotoTurn(resource, workspaceId, isTurnSpace) {
let automationData = this.$router.resolve({
name: 'ApiAutomationWithQuery',
params: {
redirectID: getUUID(),
dataType: "scenario",
dataSelectRange: 'edit:' + resource.id,
projectId: resource.projectId,
workspaceId: workspaceId
}
});
if (isTurnSpace) {
window.open(automationData.href, '_blank');
}
},
checkPermission(resource, workspaceId, isTurnSpace) {
getOwnerProjectIds().then(res => {
const project = res.data.find(p => p === resource.projectId);
if (!project) {
this.$warning(this.$t('commons.no_permission'));
} else {
this.gotoTurn(resource, workspaceId, isTurnSpace)
}
})
},
openTestPlan(item) {
let automationData = this.$router.resolve({
path: '/track/plan/view/' + item.id,
query: {workspaceId: item.workspaceId, projectId: item.projectId, charType: 'api'}
});
window.open(automationData.href, '_blank');
}
}
}
</script>
<style scoped>
.refs {
min-height: 50px;
max-height: 200px;
overflow-y: auto;
font-size: 12px;
padding-bottom: 10px;
}
</style>

View File

@ -0,0 +1,304 @@
<template>
<el-dialog
:visible.sync="isVisible"
class="advanced-item-value"
width="50%"
>
<el-tabs
tab-position="top"
style="width: 100%;"
v-model="activeName"
@tab-click="handleClick"
>
<el-tab-pane :label="$t('api_test.automation.scenario_ref')" name="scenario">
<ms-table
:data="scenarioData"
style="width: 100%"
:screen-height="screenHeight"
:total="total"
:page-size="pageSize"
:enable-selection="false"
@refresh="search"
:condition="condition"
>
<ms-table-column prop="num" label="ID" sortable width="80"/>
<ms-table-column prop="name" :label="$t('api_report.scenario_name')" width="200">
<template v-slot:default="{ row }">
<el-link @click="openScenario(row)" style="cursor: pointer">{{
row.name
}}
</el-link>
</template>
</ms-table-column>
<ms-table-column
prop="workspaceName"
:label="$t('group.belong_workspace')"
width="200"
column-key="workspaceId"
:filters="workspaceFilters"
>
</ms-table-column>
<ms-table-column
prop="projectName"
:label="$t('group.belong_project')"
:filters="projectFilters"
column-key="projectId"
width="200"
>
</ms-table-column>
</ms-table>
</el-tab-pane>
<el-tab-pane
:label="$t('api_test.automation.plan_ref')"
name="testPlan"
>
<ms-table
:data="planData"
style="width: 100%"
:screen-height="screenHeight"
:total="total"
:page-size="pageSize"
:enable-selection="false"
@refresh="search"
:condition="condition"
>
<ms-table-column prop="name" :label="$t('test_track.home.test_plan_name')" width="200" sortable>
<template v-slot:default="{ row }">
<el-link @click="openTestPlan(row)" style="cursor: pointer">{{
row.name
}}
</el-link>
</template>
</ms-table-column>
<ms-table-column
prop="workspaceName"
:label="$t('group.belong_workspace')"
width="200"
column-key="workspaceId"
>
</ms-table-column>
<ms-table-column
prop="projectName"
:label="$t('group.belong_project')"
:filters="projectFilters"
column-key="projectId"
width="200"
>
</ms-table-column>
</ms-table>
</el-tab-pane>
</el-tabs>
<ms-table-pagination
:change="search"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
:total="total"
/>
</el-dialog>
</template>
<script>
import MsTablePagination from "metersphere-frontend/src/components/pagination/TablePagination";
import {getOwnerProjectIds, getProject, getUserWorkspace, projectRelated} from "@/api/project";
import {getCurrentProjectID, getCurrentUserId, getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
import {getUUID} from "metersphere-frontend/src/utils";
import {getDefinitionReference, getPlanReference} from "@/api/definition";
import MsTable from "metersphere-frontend/src/components/table/MsTable";
import MsTableColumn from "metersphere-frontend/src/components/table/MsTableColumn";
export default {
name: "ShowReference",
data() {
return {
isVisible: false,
scenarioData: [],
planData: [],
currentPage: 1,
pageSize: 10,
total: 0,
activeName: "scenario",
scenarioId: "",
workspaceList: [],
workspaceFilters: [],
projectFilters: [],
projectList: [],
screenHeight: 'calc(100vh - 400px)',
condition: {},
type: ''
};
},
components: {
MsTablePagination, MsTable, MsTableColumn
},
watch: {
activeName(o) {
if (o) {
this.init();
this.search();
}
},
},
methods: {
getWorkSpaceList() {
getUserWorkspace().then(response => {
this.workspaceList = response.data;
});
},
getUserProjectList() {
projectRelated({
userId: getCurrentUserId(),
workspaceId: getCurrentWorkspaceId(),
}).then(res => {
let data = res.data ? res.data : [];
this.projectList = data.map((e) => {
return {text: e.name, value: e.id};
});
});
},
/**
* 操作方法
*/
init() {
this.currentPage = 1;
this.pageSize = 10;
this.total = 0;
this.condition = {};
this.scenarioData = [];
this.planData = []
},
open(row, type) {
this.activeName = "scenario";
this.init();
this.getUserProjectList();
this.getWorkSpaceList();
this.isVisible = true;
this.scenarioId = row.id;
this.type = type;
this.search(row);
},
close() {
this.isVisible = false;
},
search(row) {
this.condition.id = this.scenarioId;
if (row) {
this.condition.id = row.id;
this.condition.projectId = row.projectId;
this.condition.workspaceId = row.workspaceId;
}
this.condition.workspaceId = getCurrentWorkspaceId();
this.condition.scenarioType = this.type;
if (this.activeName === 'scenario') {
getDefinitionReference(this.currentPage, this.pageSize, this.condition).then(res => {
let data = res.data || [];
this.total = data.itemCount || 0;
if (this.workspaceList) {
this.workspaceFilters = this.workspaceList.filter(workspace => {
return data.listObject.find(i => i.workspaceId === workspace.id)
}).map((e) => {
return {text: e.name, value: e.id};
});
let workspaceIds = [];
this.workspaceFilters.map(item => {
workspaceIds.push(item.value);
})
projectRelated({
userId: getCurrentUserId(),
workspaceIds: workspaceIds,
}).then(res => {
this.projectFilters = res.data.filter(project => {
return data.listObject.find(i => i.projectId === project.id)
}).map((e) => {
return {text: e.name, value: e.id};
});
});
}
this.scenarioData = data.listObject || [];
});
} else {
getPlanReference(this.currentPage, this.pageSize, this.condition).then(res => {
let data = res.data || [];
this.total = data.itemCount || 0;
this.projectFilters = this.projectList.filter(project => {
return data.listObject.find(i => i.projectId === project.id)
}).map((e) => {
return {text: e.name, value: e.id};
});
this.planData = data.listObject || [];
});
}
},
handleClick(tab, event) {
//
},
openScenario(resource) {
if (this.type === 'API') {
let workspaceId = resource.workspaceId;
let isTurnSpace = true
if (resource.projectId !== getCurrentProjectID()) {
isTurnSpace = false;
getProject(resource.projectId).then(response => {
if (response.data) {
workspaceId = response.data.workspaceId;
isTurnSpace = true;
this.checkPermission(resource, workspaceId, isTurnSpace);
}
});
} else {
this.checkPermission(resource, workspaceId, isTurnSpace);
}
} else {
this.$emit('openScenario', resource);
this.isVisible = false;
}
},
gotoTurn(resource, workspaceId, isTurnSpace) {
let automationData = this.$router.resolve({
name: 'ApiAutomationWithQuery',
params: {
redirectID: getUUID(),
dataType: "scenario",
dataSelectRange: 'edit:' + resource.id,
projectId: resource.projectId,
workspaceId: workspaceId
}
});
if (isTurnSpace) {
window.open(automationData.href, '_blank');
}
},
checkPermission(resource, workspaceId, isTurnSpace) {
getOwnerProjectIds().then(res => {
const project = res.data.find(p => p === resource.projectId);
if (!project) {
this.$warning(this.$t('commons.no_permission'));
} else {
this.gotoTurn(resource, workspaceId, isTurnSpace)
}
})
},
openTestPlan(item) {
let automationData = this.$router.resolve({
path: '/track/plan/view/' + item.id,
query: {
workspaceId: item.workspaceId,
projectId: item.projectId,
charType: this.type === 'API' ? 'api' : 'scenario'
}
});
window.open(automationData.href, '_blank');
}
},
};
</script>
<style scoped>
:deep(.el-table__empty-block) {
padding-right: 0 !important;
}
:deep(.el-dialog__body) {
padding: 0 20px 30px 20px;
}
</style>

View File

@ -19,7 +19,15 @@ const message = {
json_format_error: "JSON format error"
},
case_name: "Case name",
case_no_permission: "No permission to edit case"
case_no_permission: "No permission to edit case",
view_case: "View case",
view_scenario: "View scenario",
case_is: "Case is",
scenario_is: "Scenario is",
scenario_count: "{0} [scenario]",
plan_count: "{0} [test plan]",
case_is_referenced: "{0} cases have reference relationships",
scenario_is_referenced: "{0} scenarios have reference relationships"
},
home: {
dashboard: {

View File

@ -20,6 +20,14 @@ const message = {
},
case_name: "用例名称",
case_no_permission: "无编辑用例的权限",
view_case: "查看用例",
view_scenario: "查看场景",
case_is: "用例被",
scenario_is: "场景被",
scenario_count: "{0}个[场景]",
plan_count: "{0}个[测试计划]",
case_is_referenced: "有{0}个用例存在引用关系",
scenario_is_referenced: "有{0}个场景存在引用关系",
},
home: {
dashboard: {

View File

@ -20,6 +20,14 @@ const message = {
},
case_name: "用例名稱",
case_no_permission: "無編輯用例的權限",
view_case: "查看用例",
view_scenario: "查看場景",
case_is: "用例被",
scenario_is: "場景被",
scenario_count: "{0}個[場景]",
plan_count: "{0}個[测试計劃]",
case_is_referenced: "有{0}個用例存在引用關係",
scenario_is_referenced: "有{0}個場景存在引用關係",
},
home: {
dashboard: {