feat(缺陷管理): 补充关联接口场景用例功能
This commit is contained in:
parent
439742a2c5
commit
1598b5facb
|
@ -0,0 +1,29 @@
|
|||
package io.metersphere.context;
|
||||
|
||||
import io.metersphere.provider.BaseAssociateCaseProvider;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 关联用例接口Bean实例上下文
|
||||
*/
|
||||
@Component
|
||||
public class AssociateCaseFactory implements ApplicationContextAware {
|
||||
|
||||
public static final Map<String, BaseAssociateCaseProvider> PROVIDER_MAP = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
Map<String, BaseAssociateCaseProvider> beanMap = applicationContext.getBeansOfType(BaseAssociateCaseProvider.class);
|
||||
PROVIDER_MAP.putAll(beanMap);
|
||||
}
|
||||
|
||||
public static BaseAssociateCaseProvider getInstance(String serviceType) {
|
||||
return PROVIDER_MAP.get(serviceType);
|
||||
}
|
||||
}
|
|
@ -6,6 +6,9 @@ import io.metersphere.request.TestCasePageProviderRequest;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 多个实现(关联用例基础接口)
|
||||
*/
|
||||
public interface BaseAssociateCaseProvider {
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package io.metersphere.sdk.constants;
|
||||
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
@ -10,41 +9,41 @@ public enum CaseType {
|
|||
/**
|
||||
* 功能用例
|
||||
*/
|
||||
FUNCTIONAL_CASE("FUNCTIONAL", "test_case"),
|
||||
FUNCTIONAL_CASE("FUNCTIONAL", "test_case", PermissionConstants.FUNCTIONAL_CASE_READ, "functional_case", "functional_case_module", "functional_case.module.default.name"),
|
||||
/**
|
||||
* 接口用例
|
||||
*/
|
||||
API_CASE("API", "api_case"),
|
||||
API_CASE("API", "api_case", PermissionConstants.PROJECT_API_DEFINITION_CASE_READ, "api_test_case", "api_definition_module", "api_unplanned_request"),
|
||||
/**
|
||||
* 性能用例
|
||||
* 场景用例
|
||||
*/
|
||||
SCENARIO_CASE("SCENARIO", "scenario_case"),
|
||||
/**
|
||||
* UI用例
|
||||
*/
|
||||
UI_CASE("UI", "ui_case"),
|
||||
/**
|
||||
* 性能用例
|
||||
*/
|
||||
PERFORMANCE_CASE("PERFORMANCE", "performance_case");
|
||||
SCENARIO_CASE("SCENARIO", "scenario_case", PermissionConstants.PROJECT_API_SCENARIO_READ, "api_scenario", "api_scenario_module", "api_unplanned_scenario");
|
||||
|
||||
private final String key;
|
||||
|
||||
private final String value;
|
||||
private final String type;
|
||||
|
||||
CaseType(String key, String value) {
|
||||
private final String usePermission;
|
||||
|
||||
private final String caseTable;
|
||||
|
||||
private final String moduleTable;
|
||||
|
||||
private final String unPlanName;
|
||||
|
||||
CaseType(String key, String type, String usePermission, String caseTable, String moduleTable, String unPlanName) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
this.usePermission = usePermission;
|
||||
this.caseTable = caseTable;
|
||||
this.moduleTable = moduleTable;
|
||||
this.unPlanName = unPlanName;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return Translator.get(value);
|
||||
}
|
||||
|
||||
public static String getValue(String key) {
|
||||
public static CaseType getType(String key) {
|
||||
for (CaseType caseType : CaseType.values()) {
|
||||
if (StringUtils.equals(caseType.getKey(), key)) {
|
||||
return caseType.getValue();
|
||||
return caseType;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -94,6 +94,7 @@ bug_comment_not_exist=缺陷评论不存在
|
|||
bug_comment_not_owner=非当前评论创建人, 无法操作!
|
||||
bug_relate_case_not_found=未查询到关联的用例
|
||||
bug_relate_case_type_unknown=关联的用例类型未知, 无法查看
|
||||
unknown_case_type_of_relate_case=参数错误, 未知的用例类型
|
||||
bug_relate_case_permission_error=无用例查看权限, 请联系管理员
|
||||
bug_status_can_not_be_empty=缺陷状态不能为空
|
||||
handle_user_can_not_be_empty=缺陷处理人不能为空
|
||||
|
|
|
@ -94,6 +94,7 @@ bug_comment_not_exist=Bug comment does not exist
|
|||
bug_comment_not_owner=Not owner of the bug comment!
|
||||
bug_relate_case_not_found=Bug related case not found
|
||||
bug_relate_case_type_unknown=Bug related case type unknown
|
||||
unknown_case_type_of_relate_case=Parameter error, unknown case type
|
||||
bug_relate_case_permission_error=No permission to show the case
|
||||
bug_status_can_not_be_empty=Status cannot be empty
|
||||
handle_user_can_not_be_empty=Handle user cannot be empty
|
||||
|
|
|
@ -94,6 +94,7 @@ bug_comment_not_exist=缺陷评论不存在
|
|||
bug_comment_not_owner=非当前评论创建人, 无法操作!
|
||||
bug_relate_case_not_found=未查询到关联的用例
|
||||
bug_relate_case_type_unknown=关联的用例类型未知, 无法查看
|
||||
unknown_case_type_of_relate_case=参数错误, 未知的用例类型
|
||||
bug_relate_case_permission_error=无用例查看权限, 请联系管理员
|
||||
bug_status_can_not_be_empty=缺陷状态不能为空
|
||||
handle_user_can_not_be_empty=缺陷处理人不能为空
|
||||
|
|
|
@ -94,6 +94,7 @@ bug_comment_not_exist=缺陷評論不存在
|
|||
bug_comment_not_owner=非當前評論創建人, 無法操作!
|
||||
bug_relate_case_not_found=未查詢到關聯的用例
|
||||
bug_relate_case_type_unknown=關聯的用例類型未知, 無法查看
|
||||
unknown_case_type_of_relate_case=參數錯誤, 未知的用例類型
|
||||
bug_relate_case_permission_error=無權限查看, 請聯繫管理員
|
||||
bug_status_can_not_be_empty=缺陷狀態不能為空
|
||||
handle_user_can_not_be_empty=缺陷處理人不能為空
|
||||
|
|
|
@ -59,4 +59,21 @@ public interface ExtApiScenarioMapper {
|
|||
List<ApiScenario> getScenarioExecuteInfoByIds(@Param("ids") List<String> ids);
|
||||
|
||||
List<ModuleCountDTO> countModuleIdByRequest(@Param("request") ApiScenarioModuleRequest request, @Param("deleted") boolean deleted);
|
||||
|
||||
/**
|
||||
* 获取缺陷未关联的场景用例列表
|
||||
* @param request provider参数
|
||||
* @param deleted 是否删除状态
|
||||
* @param sort 排序
|
||||
* @return 通用的列表Case集合
|
||||
*/
|
||||
List<TestCaseProviderDTO> listUnRelatedCaseWithBug(@Param("request") TestCasePageProviderRequest request, @Param("deleted") boolean deleted, @Param("sort") String sort);
|
||||
|
||||
/**
|
||||
* 根据关联条件获取关联的用例ID
|
||||
* @param request 关联参数
|
||||
* @param deleted 是否删除状态
|
||||
* @return 关联的用例ID集合
|
||||
*/
|
||||
List<String> getSelectIdsByAssociateParam(@Param("request")AssociateOtherCaseRequest request, @Param("deleted") boolean deleted);
|
||||
}
|
||||
|
|
|
@ -555,6 +555,49 @@
|
|||
GROUP BY api_scenario.module_id
|
||||
</select>
|
||||
|
||||
<select id="listUnRelatedCaseWithBug" resultMap="TestCaseProviderDTO">
|
||||
select
|
||||
ao.id,
|
||||
ao.num,
|
||||
ao.name,
|
||||
ao.priority,
|
||||
ao.project_id,
|
||||
ao.tags,
|
||||
pv.name as versionName,
|
||||
ao.create_user,
|
||||
u.name as createUserName,
|
||||
ao.create_time
|
||||
from api_scenario ao
|
||||
left join project_version pv ON ao.version_id = pv.id
|
||||
left join user u ON ao.create_user = u.id
|
||||
where ao.deleted = #{deleted}
|
||||
and ao.project_id = #{request.projectId}
|
||||
and ao.id not in
|
||||
(
|
||||
select brc.case_id from bug_relation_case brc where brc.bug_id = #{request.sourceId} and brc.case_type = #{request.sourceType}
|
||||
)
|
||||
<include refid="queryByTestCaseProviderParam"/>
|
||||
order by
|
||||
<if test="sort != null and sort != ''">
|
||||
ao.${sort}
|
||||
</if>
|
||||
<if test="sort == null or sort == ''">
|
||||
ao.create_time desc
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="getSelectIdsByAssociateParam" resultType="java.lang.String">
|
||||
select ac.id
|
||||
from api_test_case ac
|
||||
where ac.deleted = #{deleted}
|
||||
and ac.project_id = #{request.projectId}
|
||||
and ac.id not in
|
||||
(
|
||||
select brc.case_id from bug_relation_case brc where brc.bug_id = #{request.sourceId} and brc.case_type = #{request.sourceType}
|
||||
)
|
||||
<include refid="queryByAssociateParam"/>
|
||||
</select>
|
||||
|
||||
<sql id="report_filters">
|
||||
<if test="${filter} != null and ${filter}.size() > 0">
|
||||
<foreach collection="${filter}.entrySet()" index="key" item="values">
|
||||
|
@ -577,4 +620,38 @@
|
|||
</foreach>
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<sql id="queryByTestCaseProviderParam">
|
||||
<!-- 待补充关联Case弹窗中的高级搜索条件filter, combine -->
|
||||
<if test="request.keyword != null and request.keyword != ''">
|
||||
and (
|
||||
ao.num like concat('%', #{request.keyword}, '%')
|
||||
or ao.name like concat('%', #{request.keyword}, '%')
|
||||
or ao.tags like concat('%', #{request.keyword}, '%')
|
||||
)
|
||||
</if>
|
||||
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
|
||||
and ao.module_id in
|
||||
<foreach collection="request.moduleIds" item="moduleId" open="(" separator="," close=")">
|
||||
#{moduleId}
|
||||
</foreach>
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<sql id="queryByAssociateParam">
|
||||
<!-- 待补充关联Case弹窗中的高级搜索条件filter, combine -->
|
||||
<if test="request.condition.keyword != null and request.condition.keyword != ''">
|
||||
and (
|
||||
ao.num like concat('%', #{request.keyword}, '%')
|
||||
or ao.name like concat('%', #{request.keyword}, '%')
|
||||
or ao.tags like concat('%', #{request.keyword}, '%')
|
||||
)
|
||||
</if>
|
||||
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
|
||||
and ao.module_id in
|
||||
<foreach collection="request.moduleIds" item="moduleId" open="(" separator="," close=")">
|
||||
#{moduleId}
|
||||
</foreach>
|
||||
</if>
|
||||
</sql>
|
||||
</mapper>
|
||||
|
|
|
@ -76,4 +76,21 @@ public interface ExtApiTestCaseMapper {
|
|||
DropNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam);
|
||||
|
||||
List<ApiTestCase> getApiCaseExecuteInfoByIds(@Param("ids")List<String> ids);
|
||||
|
||||
/**
|
||||
* 获取缺陷未关联的接口用例列表
|
||||
* @param request provider参数
|
||||
* @param deleted 是否删除状态
|
||||
* @param sort 排序
|
||||
* @return 通用的列表Case集合
|
||||
*/
|
||||
List<TestCaseProviderDTO> listUnRelatedCaseWithBug(@Param("request") TestCasePageProviderRequest request, @Param("deleted") boolean deleted, @Param("sort") String sort);
|
||||
|
||||
/**
|
||||
* 根据关联条件获取关联的用例ID
|
||||
* @param request 关联参数
|
||||
* @param deleted 是否删除状态
|
||||
* @return 关联的用例ID集合
|
||||
*/
|
||||
List<String> getSelectIdsByAssociateParam(@Param("request")AssociateOtherCaseRequest request, @Param("deleted") boolean deleted);
|
||||
}
|
|
@ -336,6 +336,52 @@
|
|||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<select id="listUnRelatedCaseWithBug" resultMap="TestCaseProviderDTO">
|
||||
select
|
||||
ac.id,
|
||||
ac.num,
|
||||
ac.name,
|
||||
ac.priority,
|
||||
ac.project_id,
|
||||
ac.tags,
|
||||
pv.name as versionName,
|
||||
ac.create_user,
|
||||
u.name as createUserName,
|
||||
ac.create_time
|
||||
from api_test_case ac
|
||||
inner join api_definition ad on ac.api_definition_id = ad.id
|
||||
left join project_version pv ON ac.version_id = pv.id
|
||||
left join user u ON ac.create_user = u.id
|
||||
where ac.deleted = #{deleted}
|
||||
and ac.project_id = #{request.projectId}
|
||||
and ac.id not in
|
||||
(
|
||||
select brc.case_id from bug_relation_case brc where brc.bug_id = #{request.sourceId} and brc.case_type = #{request.sourceType}
|
||||
)
|
||||
<include refid="queryByTestCaseProviderParam"/>
|
||||
order by
|
||||
<if test="sort != null and sort != ''">
|
||||
ac.${sort}
|
||||
</if>
|
||||
<if test="sort == null or sort == ''">
|
||||
ac.create_time desc
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="getSelectIdsByAssociateParam" resultType="java.lang.String">
|
||||
select ac.id
|
||||
from api_test_case ac
|
||||
inner join api_definition ad on ac.api_definition_id = ad.id
|
||||
where ac.deleted = #{deleted}
|
||||
and ac.project_id = #{request.projectId}
|
||||
and ac.id not in
|
||||
(
|
||||
select brc.case_id from bug_relation_case brc where brc.bug_id = #{request.sourceId} and brc.case_type = #{request.sourceType}
|
||||
)
|
||||
<include refid="queryByAssociateParam"/>
|
||||
</select>
|
||||
|
||||
<sql id="report_filters">
|
||||
<if test="${filter} != null and ${filter}.size() > 0">
|
||||
<foreach collection="${filter}.entrySet()" index="key" item="values">
|
||||
|
@ -484,4 +530,50 @@
|
|||
AND a.latest = 1
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<sql id="queryByTestCaseProviderParam">
|
||||
<!-- 待补充关联Case弹窗中的高级搜索条件filter, combine -->
|
||||
<if test="request.keyword != null and request.keyword != ''">
|
||||
and (
|
||||
ac.num like concat('%', #{request.keyword}, '%')
|
||||
or ac.name like concat('%', #{request.keyword}, '%')
|
||||
or ac.tags like concat('%', #{request.keyword}, '%')
|
||||
)
|
||||
</if>
|
||||
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
|
||||
and ac.module_id in
|
||||
<foreach collection="request.moduleIds" item="moduleId" open="(" separator="," close=")">
|
||||
#{moduleId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="request.protocol != null and request.protocol!=''">
|
||||
and ad.protocol = #{request.protocol}
|
||||
</if>
|
||||
<if test="request.apiDefinitionId != null and request.apiDefinitionId!=''">
|
||||
and ac.api_definition_id = #{request.apiDefinitionId}
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<sql id="queryByAssociateParam">
|
||||
<!-- 待补充关联Case弹窗中的高级搜索条件filter, combine -->
|
||||
<if test="request.condition.keyword != null and request.condition.keyword != ''">
|
||||
and (
|
||||
ac.num like concat('%', #{request.keyword}, '%')
|
||||
or ac.name like concat('%', #{request.keyword}, '%')
|
||||
or ac.tags like concat('%', #{request.keyword}, '%')
|
||||
)
|
||||
</if>
|
||||
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
|
||||
and ac.module_id in
|
||||
<foreach collection="request.moduleIds" item="moduleId" open="(" separator="," close=")">
|
||||
#{moduleId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="request.protocol != null and request.protocol!=''">
|
||||
and ad.protocol = #{request.protocol}
|
||||
</if>
|
||||
<if test="request.apiDefinitionId != null and request.apiDefinitionId!=''">
|
||||
and ac.api_definition_id = #{request.apiDefinitionId}
|
||||
</if>
|
||||
</sql>
|
||||
</mapper>
|
|
@ -8,6 +8,7 @@ import io.metersphere.api.service.definition.ApiDefinitionModuleService;
|
|||
import io.metersphere.dto.TestCaseProviderDTO;
|
||||
import io.metersphere.project.dto.ModuleCountDTO;
|
||||
import io.metersphere.provider.BaseAssociateApiProvider;
|
||||
import io.metersphere.provider.BaseAssociateCaseProvider;
|
||||
import io.metersphere.request.AssociateOtherCaseRequest;
|
||||
import io.metersphere.request.TestCasePageProviderRequest;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
|
@ -16,12 +17,13 @@ import jakarta.annotation.Resource;
|
|||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Service
|
||||
public class AssociateApiProvider implements BaseAssociateApiProvider {
|
||||
@Service("API")
|
||||
public class AssociateApiProvider implements BaseAssociateApiProvider, BaseAssociateCaseProvider {
|
||||
@Resource
|
||||
private ExtApiTestCaseMapper extApiTestCaseMapper;
|
||||
|
||||
|
@ -88,4 +90,26 @@ public class AssociateApiProvider implements BaseAssociateApiProvider {
|
|||
return moduleTreeService.buildTreeAndCountResource(fileModuleList, moduleCountDTOList, true, Translator.get(UNPLANNED_API));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<TestCaseProviderDTO> listUnRelatedTestCaseList(TestCasePageProviderRequest request) {
|
||||
List<TestCaseProviderDTO> apiCases = extApiTestCaseMapper.listUnRelatedCaseWithBug(request, false, request.getSortString());
|
||||
if (CollectionUtils.isEmpty(apiCases)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return apiCases;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRelatedIdsByParam(AssociateOtherCaseRequest request, boolean deleted) {
|
||||
if (request.isSelectAll()) {
|
||||
List<String> relatedIds = extApiTestCaseMapper.getSelectIdsByAssociateParam(request, deleted);
|
||||
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
||||
relatedIds = relatedIds.stream().filter(id -> !request.getExcludeIds().contains(id)).toList();
|
||||
}
|
||||
return relatedIds;
|
||||
} else {
|
||||
return request.getSelectIds();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import io.metersphere.api.mapper.ExtApiScenarioMapper;
|
|||
import io.metersphere.api.service.scenario.ApiScenarioModuleService;
|
||||
import io.metersphere.dto.TestCaseProviderDTO;
|
||||
import io.metersphere.project.dto.ModuleCountDTO;
|
||||
import io.metersphere.provider.BaseAssociateCaseProvider;
|
||||
import io.metersphere.provider.BaseAssociateScenarioProvider;
|
||||
import io.metersphere.request.AssociateOtherCaseRequest;
|
||||
import io.metersphere.request.TestCasePageProviderRequest;
|
||||
|
@ -16,11 +17,12 @@ import jakarta.annotation.Resource;
|
|||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class AssociateScenarioProvider implements BaseAssociateScenarioProvider {
|
||||
@Service("SCENARIO")
|
||||
public class AssociateScenarioProvider implements BaseAssociateScenarioProvider, BaseAssociateCaseProvider {
|
||||
|
||||
@Resource
|
||||
private ExtApiScenarioMapper extApiScenarioMapper;
|
||||
|
@ -87,4 +89,26 @@ public class AssociateScenarioProvider implements BaseAssociateScenarioProvider
|
|||
List<BaseTreeNode> fileModuleList = extApiScenarioMapper.selectIdAndParentIdByProjectId(request.getProjectId());
|
||||
return apiScenarioModuleService.buildTreeAndCountResource(fileModuleList, moduleCountDTOList, true, Translator.get(UNPLANNED_SCENARIO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TestCaseProviderDTO> listUnRelatedTestCaseList(TestCasePageProviderRequest request) {
|
||||
List<TestCaseProviderDTO> apiScenarios = extApiScenarioMapper.listUnRelatedCaseWithBug(request, false, request.getSortString());
|
||||
if (CollectionUtils.isEmpty(apiScenarios)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return apiScenarios;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRelatedIdsByParam(AssociateOtherCaseRequest request, boolean deleted) {
|
||||
if (request.isSelectAll()) {
|
||||
List<String> relatedIds = extApiScenarioMapper.getSelectIdsByAssociateParam(request, deleted);
|
||||
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
||||
relatedIds = relatedIds.stream().filter(id -> !request.getExcludeIds().contains(id)).toList();
|
||||
}
|
||||
return relatedIds;
|
||||
} else {
|
||||
return request.getSelectIds();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
package io.metersphere.api.service;
|
||||
|
||||
import io.metersphere.api.provider.AssociateApiProvider;
|
||||
import io.metersphere.api.provider.AssociateScenarioProvider;
|
||||
import io.metersphere.request.AssociateOtherCaseRequest;
|
||||
import io.metersphere.request.TestCasePageProviderRequest;
|
||||
import io.metersphere.system.base.BaseTest;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.jdbc.SqlConfig;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@AutoConfigureMockMvc
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class AssociateCaseProviderTests extends BaseTest {
|
||||
|
||||
@Resource
|
||||
AssociateApiProvider apiProvider;
|
||||
@Resource
|
||||
AssociateScenarioProvider scenarioProvider;
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
@Sql(scripts = {"/dml/init_associate_provider_test.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED))
|
||||
void coverApiProvider() {
|
||||
TestCasePageProviderRequest request = new TestCasePageProviderRequest();
|
||||
request.setProjectId("test-associate-pro");
|
||||
request.setSourceId("test-source-id");
|
||||
request.setSourceType("test-source-type");
|
||||
apiProvider.listUnRelatedTestCaseList(request);
|
||||
request.setKeyword("api-case-associate-2");
|
||||
apiProvider.listUnRelatedTestCaseList(request);
|
||||
AssociateOtherCaseRequest associateRequest = new AssociateOtherCaseRequest();
|
||||
associateRequest.setSelectAll(true);
|
||||
associateRequest.setProjectId("test-associate-pro");
|
||||
associateRequest.setSourceId("test-source-id");
|
||||
associateRequest.setSourceType("test-source-type");
|
||||
apiProvider.getRelatedIdsByParam(associateRequest, false);
|
||||
associateRequest.setExcludeIds(List.of("api-case-associate-1"));
|
||||
apiProvider.getRelatedIdsByParam(associateRequest, false);
|
||||
associateRequest.setSelectAll(false);
|
||||
associateRequest.setSelectIds(List.of("api-case-associate-1"));
|
||||
apiProvider.getRelatedIdsByParam(associateRequest, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
void coverScenarioProvider() {
|
||||
TestCasePageProviderRequest request = new TestCasePageProviderRequest();
|
||||
request.setProjectId("test-associate-pro");
|
||||
request.setSourceId("test-source-id");
|
||||
request.setSourceType("test-source-type");
|
||||
scenarioProvider.listUnRelatedTestCaseList(request);
|
||||
request.setKeyword("api-scenario-associate-2");
|
||||
scenarioProvider.listUnRelatedTestCaseList(request);
|
||||
AssociateOtherCaseRequest associateRequest = new AssociateOtherCaseRequest();
|
||||
associateRequest.setSelectAll(true);
|
||||
associateRequest.setProjectId("test-associate-pro");
|
||||
associateRequest.setSourceId("test-source-id");
|
||||
associateRequest.setSourceType("test-source-type");
|
||||
scenarioProvider.getRelatedIdsByParam(associateRequest, false);
|
||||
associateRequest.setExcludeIds(List.of("api-case-scenario-1"));
|
||||
scenarioProvider.getRelatedIdsByParam(associateRequest, false);
|
||||
associateRequest.setSelectAll(false);
|
||||
associateRequest.setSelectIds(List.of("api-case-scenario-1"));
|
||||
scenarioProvider.getRelatedIdsByParam(associateRequest, false);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
INSERT INTO `api_definition` (`id`, `name`, `protocol`, `method`, `path`, `status`, `num`, `tags`, `pos`, `project_id`, `module_id`, `latest`, `version_id`, `ref_id`, `description`, `create_time`, `create_user`, `update_time`, `update_user`, `delete_user`, `delete_time`, `deleted`)
|
||||
VALUES ('api-definition-tmp', 'test31931', 'HTTP', 'POST', '/api/test', 'PROCESSING', 1000001, '[\"test3\",\"te\"]', 1, 'test-associate-pro', 'root', b'1', '100570499574136985', '1001', NULL, UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'admin', NULL, NULL, false);
|
||||
|
||||
INSERT INTO `api_definition` (`id`, `name`, `protocol`, `method`, `path`, `status`, `num`, `tags`, `pos`, `project_id`, `module_id`, `latest`, `version_id`, `ref_id`, `description`, `create_time`, `create_user`, `update_time`, `update_user`, `delete_user`, `delete_time`, `deleted`)
|
||||
VALUES ('api-definition-associate-1', 'test31931313', 'HTTP', 'POST', '/api/test', 'PROCESSING', 1000001, '[\"test3\",\"te\"]', 1, 'test-associate-pro', 'root', b'1', '100570499574136985', '1001', NULL, UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'admin', NULL, NULL, false);
|
||||
|
||||
INSERT INTO api_test_case(id, name, priority, num, tags, status, last_report_status, last_report_id, pos, project_id, api_definition_id, version_id, environment_id, create_time, create_user, update_time, update_user, delete_time, delete_user, deleted)
|
||||
VALUES ('api-case-associate-1','test4938131', 'P0', 10000023131, null, 'Underway', 'PENDING', null, 1, 'test-associate-pro', 'api-definition-associate-1', '100570499574136985', 'test_associate_env_id', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'admin', null, null, false);
|
||||
|
||||
INSERT INTO api_scenario(id, name, priority, status, last_report_status, last_report_id, num, pos, version_id, ref_id, project_id, module_id, description, tags, create_user, create_time, delete_time, delete_user, update_user, update_time, deleted)
|
||||
VALUES ('api-scenario-associate-1', 'test323131', 'p1', 'test-api-status', 'PENDING', null, 1000001, 1, 'v1.10', 'api-scenario-associate-rid', 'test-associate-pro', 'root', null, null, 'admin', UNIX_TIMESTAMP() * 1000, null, null, 'admin', UNIX_TIMESTAMP() * 1000, false);
|
|
@ -7,6 +7,7 @@ import io.metersphere.bug.dto.request.BugRelatedCasePageRequest;
|
|||
import io.metersphere.bug.dto.response.BugRelateCaseDTO;
|
||||
import io.metersphere.bug.service.BugRelateCaseCommonService;
|
||||
import io.metersphere.bug.service.BugRelateCaseLogService;
|
||||
import io.metersphere.context.AssociateCaseFactory;
|
||||
import io.metersphere.dto.TestCaseProviderDTO;
|
||||
import io.metersphere.provider.BaseAssociateCaseProvider;
|
||||
import io.metersphere.request.AssociateCaseModuleRequest;
|
||||
|
@ -37,23 +38,22 @@ public class BugRelateCaseController {
|
|||
|
||||
@Resource
|
||||
private BugRelateCaseCommonService bugRelateCaseCommonService;
|
||||
@Resource
|
||||
private BaseAssociateCaseProvider functionalCaseProvider;
|
||||
|
||||
@PostMapping("/un-relate/page")
|
||||
@Operation(description = "缺陷管理-关联用例-未关联用例-列表分页")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
||||
public Pager<List<TestCaseProviderDTO>> unRelatedPage(@Validated @RequestBody TestCasePageProviderRequest request) {
|
||||
// 目前只保留功能用例的Provider接口, 后续其他用例根据RelateCaseType扩展
|
||||
bugRelateCaseCommonService.checkCaseTypeParamIllegal(request.getSourceType());
|
||||
BaseAssociateCaseProvider associateCaseProvider = AssociateCaseFactory.getInstance(request.getSourceType());
|
||||
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize());
|
||||
return PageUtils.setPageInfo(page, functionalCaseProvider.listUnRelatedTestCaseList(request));
|
||||
return PageUtils.setPageInfo(page, associateCaseProvider.listUnRelatedTestCaseList(request));
|
||||
}
|
||||
|
||||
@PostMapping("/un-relate/module/count")
|
||||
@Operation(summary = "缺陷管理-关联用例-未关联用例-模块树数量")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
||||
@CheckOwner(resourceId = "#request.projectId", resourceType = "project")
|
||||
public Map<String, Long> countTree(@RequestBody @Validated TestCasePageProviderRequest request) {
|
||||
public Map<String, Long> countTree(@RequestBody @Validated AssociateCaseModuleRequest request) {
|
||||
return bugRelateCaseCommonService.countTree(request);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import io.metersphere.dto.BugProviderDTO;
|
|||
import io.metersphere.project.dto.ModuleCountDTO;
|
||||
import io.metersphere.request.AssociateBugPageRequest;
|
||||
import io.metersphere.request.AssociateCaseModuleRequest;
|
||||
import io.metersphere.request.TestCasePageProviderRequest;
|
||||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
|
@ -21,17 +20,20 @@ public interface ExtBugRelateCaseMapper {
|
|||
/**
|
||||
* 获取缺陷关联的用例模块树
|
||||
* @param request 请求参数
|
||||
* @param caseTable 关联用例表
|
||||
* @param moduleTable 关联用例模块表
|
||||
* @return 模块树集合
|
||||
*/
|
||||
List<BaseTreeNode> getRelateCaseModule(@Param("request") AssociateCaseModuleRequest request);
|
||||
List<BaseTreeNode> getRelateCaseModule(@Param("request") AssociateCaseModuleRequest request, @Param("caseTable") String caseTable, @Param("moduleTable") String moduleTable);
|
||||
|
||||
/**
|
||||
* 获取缺陷关联的用例模块树数量
|
||||
* @param request 请求参数
|
||||
* @param deleted 是否删除状态
|
||||
* @param caseTable 关联用例表
|
||||
* @return 模块树数量
|
||||
*/
|
||||
List<ModuleCountDTO> countRelateCaseModuleTree(@Param("request") TestCasePageProviderRequest request, @Param("deleted") boolean deleted);
|
||||
List<ModuleCountDTO> countRelateCaseModuleTree(@Param("request") AssociateCaseModuleRequest request, @Param("deleted") boolean deleted, @Param("caseTable") String caseTable);
|
||||
|
||||
/**
|
||||
* 统计缺陷关联的用例数量
|
||||
|
|
|
@ -3,34 +3,55 @@
|
|||
<mapper namespace="io.metersphere.bug.mapper.ExtBugRelateCaseMapper">
|
||||
<select id="getRelateCaseModule" resultType="io.metersphere.system.dto.sdk.BaseTreeNode">
|
||||
select
|
||||
distinct fcm.id,
|
||||
fcm.parent_id as parentId,
|
||||
fcm.name,
|
||||
fcm.pos,
|
||||
fcm.project_id
|
||||
from functional_case_module fcm left join functional_case fc on fc.module_id = fcm.id
|
||||
where fcm.project_id = #{request.projectId}
|
||||
and fc.id not in
|
||||
distinct mt.id,
|
||||
mt.parent_id as parentId,
|
||||
mt.name,
|
||||
mt.pos,
|
||||
mt.project_id
|
||||
from ${moduleTable} mt
|
||||
<if test="caseTable != null and caseTable != '' and caseTable != 'api_test_case'">
|
||||
left join ${caseTable} ct on ct.module_id = mt.id
|
||||
</if>
|
||||
<if test="caseTable != null and caseTable != '' and caseTable == 'api_test_case'">
|
||||
left join api_definition ad on ad.module_id = mt.id
|
||||
left join api_test_case ct on ct.api_definition_id = ad.id
|
||||
</if>
|
||||
where mt.project_id = #{request.projectId}
|
||||
and ct.id not in
|
||||
(
|
||||
select brc.case_id from bug_relation_case brc where brc.bug_id = #{request.sourceId} and brc.case_type = #{request.sourceType}
|
||||
)
|
||||
<include refid="queryModuleWhereCondition"/>
|
||||
order by pos
|
||||
order by mt.pos
|
||||
</select>
|
||||
|
||||
<select id="countRelateCaseModuleTree" resultType="io.metersphere.project.dto.ModuleCountDTO">
|
||||
select
|
||||
fc.module_id AS moduleId,
|
||||
count(fc.id) as dataCount
|
||||
from functional_case fc
|
||||
where fc.deleted = #{deleted}
|
||||
and fc.project_id = #{request.projectId}
|
||||
and fc.id not in
|
||||
<if test="caseTable != null and caseTable != '' and caseTable == 'api_test_case'">
|
||||
ad.module_id as moduleId,
|
||||
count(ad.id) as dataCount
|
||||
</if>
|
||||
<if test="caseTable != null and caseTable != '' and caseTable != 'api_test_case'">
|
||||
ct.module_id as moduleId,
|
||||
count(ct.id) as dataCount
|
||||
</if>
|
||||
from ${caseTable} ct
|
||||
<if test="caseTable != null and caseTable != '' and caseTable == 'api_test_case'">
|
||||
join api_definition ad on ct.api_definition_id = ad.id
|
||||
</if>
|
||||
where ct.deleted = #{deleted}
|
||||
and ct.project_id = #{request.projectId}
|
||||
and ct.id not in
|
||||
(
|
||||
select brc.case_id from bug_relation_case brc where brc.bug_id = #{request.sourceId} and brc.case_type = #{request.sourceType}
|
||||
)
|
||||
<include refid="queryModuleWhereCondition"/>
|
||||
group by fc.module_id
|
||||
<if test="caseTable != null and caseTable != '' and caseTable == 'api_test_case'">
|
||||
group by ad.module_id
|
||||
</if>
|
||||
<if test="caseTable != null and caseTable != '' and caseTable != 'api_test_case'">
|
||||
group by ct.module_id
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="countRelationCases" resultType="io.metersphere.bug.dto.response.BugRelateCaseCountDTO">
|
||||
|
@ -45,15 +66,22 @@
|
|||
<select id="list" resultType="io.metersphere.bug.dto.response.BugRelateCaseDTO">
|
||||
select brc.id relateId, fc.id relateCaseId, fc.num relateCaseNum, fc.name relateCaseName, fc.project_id projectId, fc.version_id versionId, brc.case_type relateCaseType,
|
||||
brc.test_plan_id is not null relatePlanCase, brc.case_id is not null relateCase
|
||||
from bug_relation_case brc join functional_case fc on (brc.case_id = fc.id or brc.test_plan_case_id = fc.id)
|
||||
where brc.bug_id = #{request.bugId} and fc.deleted = false
|
||||
from bug_relation_case brc
|
||||
left join functional_case fc on ((brc.case_id = fc.id or brc.test_plan_case_id = fc.id) and fc.deleted = false)
|
||||
left join api_test_case atc on ((brc.case_id = atc.id or brc.test_plan_case_id = atc.id) and atc.deleted = false)
|
||||
left join api_scenario ao on ((brc.case_id = ao.id or brc.test_plan_case_id = ao.id) and ao.deleted = false)
|
||||
where brc.bug_id = #{request.bugId}
|
||||
<if test="request.keyword != null and request.keyword != ''">
|
||||
and (
|
||||
fc.name like concat('%', #{request.keyword}, '%')
|
||||
or fc.num like concat('%', #{request.keyword}, '%')
|
||||
or atc.name like concat('%', #{request.keyword}, '%')
|
||||
or atc.num like concat('%', #{request.keyword}, '%')
|
||||
or ao.name like concat('%', #{request.keyword}, '%')
|
||||
or ao.num like concat('%', #{request.keyword}, '%')
|
||||
)
|
||||
</if>
|
||||
order by brc.id desc
|
||||
order by brc.create_time desc
|
||||
</select>
|
||||
|
||||
<select id="getRelateCase" resultType="io.metersphere.bug.dto.response.BugRelateCaseDTO">
|
||||
|
@ -171,17 +199,27 @@
|
|||
</sql>
|
||||
|
||||
<sql id="queryModuleWhereCondition">
|
||||
<!-- 待补充关联Case弹窗中的高级搜索条件 -->
|
||||
<!-- 待补充关联Case弹窗中的高级搜索条件filter, combine -->
|
||||
<if test="request.keyword != null and request.keyword != ''">
|
||||
and (
|
||||
fc.num like concat('%', #{request.keyword}, '%') or fc.name like concat('%', #{request.keyword}, '%')
|
||||
ct.num like concat('%', #{request.keyword}, '%')
|
||||
or ct.name like concat('%', #{request.keyword}, '%')
|
||||
or ct.tags like concat('%', #{request.keyword}, '%')
|
||||
)
|
||||
</if>
|
||||
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
|
||||
and fc.module_id in
|
||||
<if test="caseTable != null and caseTable != '' and caseTable == 'api_test_case'">
|
||||
and ad.module_id in
|
||||
<foreach collection="request.moduleIds" item="moduleId" open="(" separator="," close=")">
|
||||
#{moduleId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="caseTable != null and caseTable != '' and caseTable != 'api_test_case'">
|
||||
and ct.module_id in
|
||||
<foreach collection="request.moduleIds" item="moduleId" open="(" separator="," close=")">
|
||||
#{moduleId}
|
||||
</foreach>
|
||||
</if>
|
||||
</if>
|
||||
</sql>
|
||||
</mapper>
|
|
@ -7,6 +7,7 @@ import io.metersphere.bug.dto.request.BugRelatedCasePageRequest;
|
|||
import io.metersphere.bug.dto.response.BugRelateCaseDTO;
|
||||
import io.metersphere.bug.mapper.BugRelationCaseMapper;
|
||||
import io.metersphere.bug.mapper.ExtBugRelateCaseMapper;
|
||||
import io.metersphere.context.AssociateCaseFactory;
|
||||
import io.metersphere.project.domain.Project;
|
||||
import io.metersphere.project.domain.ProjectExample;
|
||||
import io.metersphere.project.domain.ProjectVersion;
|
||||
|
@ -19,11 +20,8 @@ import io.metersphere.project.service.PermissionCheckService;
|
|||
import io.metersphere.provider.BaseAssociateCaseProvider;
|
||||
import io.metersphere.request.AssociateCaseModuleRequest;
|
||||
import io.metersphere.request.AssociateOtherCaseRequest;
|
||||
import io.metersphere.request.TestCasePageProviderRequest;
|
||||
import io.metersphere.sdk.constants.CaseType;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.BeanUtils;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
|
@ -40,6 +38,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
|
@ -58,8 +57,27 @@ public class BugRelateCaseCommonService extends ModuleTreeService {
|
|||
private ExtBugRelateCaseMapper extBugRelateCaseMapper;
|
||||
@Resource
|
||||
private PermissionCheckService permissionCheckService;
|
||||
@Resource
|
||||
private BaseAssociateCaseProvider functionalCaseProvider;
|
||||
|
||||
/**
|
||||
* 获取关联用例模块树数量
|
||||
* @param request 请求参数
|
||||
* @return 模块树集合
|
||||
*/
|
||||
public Map<String, Long> countTree(AssociateCaseModuleRequest request) {
|
||||
// 用例类型参数非法校验
|
||||
this.checkCaseTypeParamIllegal(request.getSourceType());
|
||||
// 统计模块数量不用传模块ID
|
||||
request.setModuleIds(null);
|
||||
List<ModuleCountDTO> moduleCounts = extBugRelateCaseMapper.countRelateCaseModuleTree(request, false, Objects.requireNonNull(CaseType.getType(request.getSourceType())).getCaseTable());
|
||||
List<BaseTreeNode> relateCaseModules = extBugRelateCaseMapper.getRelateCaseModule(request,
|
||||
Objects.requireNonNull(CaseType.getType(request.getSourceType())).getCaseTable(), Objects.requireNonNull(CaseType.getType(request.getSourceType())).getModuleTable());
|
||||
List<BaseTreeNode> relateCaseModuleWithCount = buildTreeAndCountResource(relateCaseModules, moduleCounts, true,
|
||||
Translator.get(Objects.requireNonNull(CaseType.getType(request.getSourceType())).getUnPlanName()));
|
||||
Map<String, Long> moduleCountMap = getIdCountMapByBreadth(relateCaseModuleWithCount);
|
||||
long total = getAllCount(moduleCounts);
|
||||
moduleCountMap.put("total", total);
|
||||
return moduleCountMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取关联用例模块树(不包括数量)
|
||||
|
@ -67,30 +85,12 @@ public class BugRelateCaseCommonService extends ModuleTreeService {
|
|||
* @return 模块树集合
|
||||
*/
|
||||
public List<BaseTreeNode> getRelateCaseTree(AssociateCaseModuleRequest request) {
|
||||
// 目前只保留功能用例的左侧模块树方法调用, 后续其他用例根据RelateCaseType扩展
|
||||
List<BaseTreeNode> relateCaseModules = extBugRelateCaseMapper.getRelateCaseModule(request);
|
||||
// 用例类型参数非法校验
|
||||
this.checkCaseTypeParamIllegal(request.getSourceType());
|
||||
List<BaseTreeNode> relateCaseModules = extBugRelateCaseMapper.getRelateCaseModule(request,
|
||||
Objects.requireNonNull(CaseType.getType(request.getSourceType())).getCaseTable(), Objects.requireNonNull(CaseType.getType(request.getSourceType())).getModuleTable());
|
||||
// 构建模块树层级数量为通用逻辑
|
||||
return super.buildTreeAndCountResource(relateCaseModules, true, Translator.get("api_unplanned_request"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取关联用例模块树数量
|
||||
* @param request 请求参数
|
||||
* @return 模块树集合
|
||||
*/
|
||||
public Map<String, Long> countTree(TestCasePageProviderRequest request) {
|
||||
// 统计模块数量不用传模块ID
|
||||
request.setModuleIds(null);
|
||||
// 目前只保留功能用例的左侧模块树方法调用, 后续其他用例根据RelateCaseType扩展
|
||||
List<ModuleCountDTO> moduleCounts = extBugRelateCaseMapper.countRelateCaseModuleTree(request, false);
|
||||
AssociateCaseModuleRequest moduleRequest = new AssociateCaseModuleRequest();
|
||||
BeanUtils.copyBean(moduleRequest, request);
|
||||
List<BaseTreeNode> relateCaseModules = extBugRelateCaseMapper.getRelateCaseModule(moduleRequest);
|
||||
List<BaseTreeNode> relateCaseModuleWithCount = buildTreeAndCountResource(relateCaseModules, moduleCounts, true, Translator.get("api_unplanned_request"));
|
||||
Map<String, Long> moduleCountMap = getIdCountMapByBreadth(relateCaseModuleWithCount);
|
||||
long total = getAllCount(moduleCounts);
|
||||
moduleCountMap.put("total", total);
|
||||
return moduleCountMap;
|
||||
return super.buildTreeAndCountResource(relateCaseModules, true, Translator.get(Objects.requireNonNull(CaseType.getType(request.getSourceType())).getUnPlanName()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,8 +100,11 @@ public class BugRelateCaseCommonService extends ModuleTreeService {
|
|||
* @param currentUser 当前用户
|
||||
*/
|
||||
public void relateCase(AssociateOtherCaseRequest request, boolean deleted, String currentUser) {
|
||||
// 用例类型参数非法校验
|
||||
this.checkCaseTypeParamIllegal(request.getSourceType());
|
||||
// 目前只需根据关联条件获取功能用例ID, 后续扩展
|
||||
List<String> relatedIds = functionalCaseProvider.getRelatedIdsByParam(request, deleted);
|
||||
BaseAssociateCaseProvider caseProvider = AssociateCaseFactory.getInstance(request.getSourceType());
|
||||
List<String> relatedIds = caseProvider.getRelatedIdsByParam(request, deleted);
|
||||
// 缺陷关联用例通用逻辑
|
||||
if (CollectionUtils.isEmpty(relatedIds)) {
|
||||
return;
|
||||
|
@ -114,6 +117,7 @@ public class BugRelateCaseCommonService extends ModuleTreeService {
|
|||
List<BugRelationCase> planRelatedCases = bugRelationCaseMapper.selectByExample(bugRelationCaseExample);
|
||||
Map<String, String> planRelatedMap = planRelatedCases.stream().collect(Collectors.toMap(BugRelationCase::getTestPlanCaseId, BugRelationCase::getId));
|
||||
bugRelationCaseExample.clear();
|
||||
// 根据用例ID筛选出已直接关联缺陷的用例(防止重复关联)
|
||||
bugRelationCaseExample.createCriteria().andBugIdEqualTo(request.getSourceId()).andCaseIdIn(relatedIds);
|
||||
List<BugRelationCase> bugRelationCases = bugRelationCaseMapper.selectByExample(bugRelationCaseExample);
|
||||
Map<String, String> bugRelatedMap = bugRelationCases.stream().collect(Collectors.toMap(BugRelationCase::getCaseId, BugRelationCase::getId));
|
||||
|
@ -124,7 +128,7 @@ public class BugRelateCaseCommonService extends ModuleTreeService {
|
|||
continue;
|
||||
}
|
||||
if (planRelatedMap.containsKey(relatedId)) {
|
||||
// 计划已关联, 补全用例ID
|
||||
// 计划已关联, 补充用例ID
|
||||
record.setId(planRelatedMap.get(relatedId));
|
||||
record.setCaseId(relatedId);
|
||||
record.setUpdateTime(System.currentTimeMillis());
|
||||
|
@ -150,7 +154,6 @@ public class BugRelateCaseCommonService extends ModuleTreeService {
|
|||
* @param request 请求参数
|
||||
*/
|
||||
public List<BugRelateCaseDTO> page(BugRelatedCasePageRequest request) {
|
||||
// 目前只查关联的功能用例类型, 后续多个用例类型SQL扩展
|
||||
List<BugRelateCaseDTO> relateCases = extBugRelateCaseMapper.list(request);
|
||||
if (CollectionUtils.isEmpty(relateCases)) {
|
||||
return new ArrayList<>();
|
||||
|
@ -160,7 +163,7 @@ public class BugRelateCaseCommonService extends ModuleTreeService {
|
|||
relateCases.forEach(relateCase -> {
|
||||
relateCase.setProjectName(projectMap.get(relateCase.getProjectId()));
|
||||
relateCase.setVersionName(versionMap.get(relateCase.getVersionId()));
|
||||
relateCase.setRelateCaseTypeName(CaseType.getValue(relateCase.getRelateCaseType()));
|
||||
relateCase.setRelateCaseTypeName(Translator.get(Objects.requireNonNull(CaseType.getType(relateCase.getRelateCaseType())).getType()));
|
||||
});
|
||||
return relateCases;
|
||||
}
|
||||
|
@ -189,12 +192,9 @@ public class BugRelateCaseCommonService extends ModuleTreeService {
|
|||
* @param caseType 用例类型
|
||||
*/
|
||||
public BugCaseCheckResult checkPermission(String projectId, String currentUser, String caseType) {
|
||||
// 校验关联用例的查看权限, 目前只支持功能用例的查看权限, 后续支持除功能用例外的其他类型用例
|
||||
if (!CaseType.FUNCTIONAL_CASE.getKey().equals(caseType)) {
|
||||
// 关联的用例类型未知
|
||||
return BugCaseCheckResult.builder().pass(false).msg(Translator.get("bug_relate_case_type_unknown")).build();
|
||||
}
|
||||
boolean hasPermission = permissionCheckService.userHasProjectPermission(currentUser, projectId, PermissionConstants.FUNCTIONAL_CASE_READ);
|
||||
// 校验用例类型是否合法
|
||||
this.checkCaseTypeParamIllegal(caseType);
|
||||
boolean hasPermission = permissionCheckService.userHasProjectPermission(currentUser, projectId, Objects.requireNonNull(CaseType.getType(caseType)).getUsePermission());
|
||||
if (!hasPermission) {
|
||||
// 没有该用例的访问权限
|
||||
return BugCaseCheckResult.builder().pass(false).msg(Translator.get("bug_relate_case_permission_error")).build();
|
||||
|
@ -248,4 +248,14 @@ public class BugRelateCaseCommonService extends ModuleTreeService {
|
|||
public void refreshPos(String parentId) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验用例类型字段是否合法
|
||||
* @param caseType 用例类型
|
||||
*/
|
||||
public void checkCaseTypeParamIllegal(String caseType) {
|
||||
if (CaseType.getType(caseType) == null) {
|
||||
throw new MSException(Translator.get("unknown_case_type_of_relate_case"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import io.metersphere.bug.dto.BugCaseCheckResult;
|
|||
import io.metersphere.bug.dto.request.BugRelatedCasePageRequest;
|
||||
import io.metersphere.bug.dto.response.BugRelateCaseDTO;
|
||||
import io.metersphere.bug.service.BugRelateCaseCommonService;
|
||||
import io.metersphere.context.AssociateCaseFactory;
|
||||
import io.metersphere.provider.BaseAssociateCaseProvider;
|
||||
import io.metersphere.request.AssociateOtherCaseRequest;
|
||||
import io.metersphere.request.TestCasePageProviderRequest;
|
||||
|
@ -36,6 +37,7 @@ public class BugRelateCaseControllerTests extends BaseTest {
|
|||
|
||||
@Resource
|
||||
BaseAssociateCaseProvider functionalCaseProvider;
|
||||
|
||||
@Resource
|
||||
BugRelateCaseCommonService bugRelateCaseCommonService;
|
||||
|
||||
|
@ -85,6 +87,7 @@ public class BugRelateCaseControllerTests extends BaseTest {
|
|||
request.setVersionId("default_bug_version");
|
||||
request.setSourceId("default-relate-bug-id");
|
||||
request.setSourceType("FUNCTIONAL");
|
||||
AssociateCaseFactory.PROVIDER_MAP.put("FUNCTIONAL", functionalCaseProvider);
|
||||
Mockito.when(functionalCaseProvider.getRelatedIdsByParam(request, false)).thenReturn(Collections.emptyList());
|
||||
this.requestPostWithOk(BUG_CASE_RELATE, request);
|
||||
request.setExcludeIds(null);
|
||||
|
@ -173,10 +176,7 @@ public class BugRelateCaseControllerTests extends BaseTest {
|
|||
@Order(8)
|
||||
void testBugRelateCheckPermissionError() throws Exception {
|
||||
// 非功能用例类型参数
|
||||
MvcResult mvcResult = this.requestGetAndReturn(BUG_CASE_CHECK + "/100001100001/API");
|
||||
BugCaseCheckResult resultData = getResultData(mvcResult, BugCaseCheckResult.class);
|
||||
Assertions.assertFalse(resultData.getPass());
|
||||
Assertions.assertEquals(resultData.getMsg(), Translator.get("bug_relate_case_type_unknown"));
|
||||
this.requestGet(BUG_CASE_CHECK + "/100001100001/UI", status().is5xxServerError());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -17,8 +17,8 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class AssociateCaseProvider implements BaseAssociateCaseProvider {
|
||||
@Service("FUNCTIONAL")
|
||||
public class AssociateFunctionalProvider implements BaseAssociateCaseProvider {
|
||||
|
||||
@Resource
|
||||
private FunctionalCaseService functionalCaseService;
|
||||
|
@ -35,13 +35,13 @@ public class AssociateCaseProvider implements BaseAssociateCaseProvider {
|
|||
Map<String, List<FunctionalCaseCustomFieldDTO>> caseCustomFiledMap = functionalCaseService.getCaseCustomFiledMap(ids, testCasePageProviderRequest.getProjectId());
|
||||
functionalCases.forEach(functionalCase -> {
|
||||
List<FunctionalCaseCustomFieldDTO> customFields = caseCustomFiledMap.get(functionalCase.getId());
|
||||
List<BaseCaseCustomFieldDTO> baseCaseCustomFieldDTOS = new ArrayList<>();
|
||||
List<BaseCaseCustomFieldDTO> customs = new ArrayList<>();
|
||||
for (FunctionalCaseCustomFieldDTO customField : customFields) {
|
||||
BaseCaseCustomFieldDTO baseCaseCustomFieldDTO = new BaseCaseCustomFieldDTO();
|
||||
BeanUtils.copyBean(baseCaseCustomFieldDTO, customField);
|
||||
baseCaseCustomFieldDTOS.add(baseCaseCustomFieldDTO);
|
||||
customs.add(baseCaseCustomFieldDTO);
|
||||
}
|
||||
functionalCase.setCustomFields(baseCaseCustomFieldDTOS);
|
||||
functionalCase.setCustomFields(customs);
|
||||
});
|
||||
return functionalCases;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package io.metersphere.functional.controller;
|
||||
|
||||
import io.metersphere.functional.provider.AssociateCaseProvider;
|
||||
import io.metersphere.functional.provider.AssociateFunctionalProvider;
|
||||
import io.metersphere.request.AssociateOtherCaseRequest;
|
||||
import io.metersphere.request.TestCasePageProviderRequest;
|
||||
import io.metersphere.system.base.BaseTest;
|
||||
|
@ -22,7 +22,7 @@ import java.util.List;
|
|||
public class AssociateCaseProviderTests extends BaseTest {
|
||||
|
||||
@Resource
|
||||
AssociateCaseProvider associateCaseProvider;
|
||||
AssociateFunctionalProvider functionalProvider;
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
|
@ -33,17 +33,18 @@ public class AssociateCaseProviderTests extends BaseTest {
|
|||
request.setVersionId("test-ver");
|
||||
request.setSourceId("test-source-id");
|
||||
request.setSourceType("test-source-type");
|
||||
associateCaseProvider.listUnRelatedTestCaseList(request);
|
||||
functionalProvider.listUnRelatedTestCaseList(request);
|
||||
AssociateOtherCaseRequest associateRequest = new AssociateOtherCaseRequest();
|
||||
associateRequest.setSelectAll(true);
|
||||
associateRequest.setProjectId("select-case-pro");
|
||||
associateRequest.setVersionId("v1.0.0");
|
||||
associateRequest.setSourceId("test-source-id");
|
||||
associateRequest.setSourceType("test-source-type");
|
||||
associateCaseProvider.getRelatedIdsByParam(associateRequest, false);
|
||||
functionalProvider.getRelatedIdsByParam(associateRequest, false);
|
||||
associateRequest.setExcludeIds(List.of("select-case"));
|
||||
associateCaseProvider.getRelatedIdsByParam(associateRequest, false);
|
||||
functionalProvider.getRelatedIdsByParam(associateRequest, false);
|
||||
associateRequest.setSelectAll(false);
|
||||
associateRequest.setSelectIds(List.of("select-case"));
|
||||
functionalProvider.getRelatedIdsByParam(associateRequest, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@
|
|||
<if test="request.keyword != null">
|
||||
and (
|
||||
o.name like concat('%', #{request.keyword},'%')
|
||||
or o.id like concat('%', #{request.keyword},'%')
|
||||
or o.num like concat('%', #{request.keyword},'%')
|
||||
)
|
||||
</if>
|
||||
<include refid="filter"/>
|
||||
|
|
Loading…
Reference in New Issue