Merge branch 'v1.6'

This commit is contained in:
Captain.B 2020-12-30 10:35:16 +08:00
commit 7ef0be2783
33 changed files with 1034 additions and 485 deletions

View File

@ -41,6 +41,13 @@ public class ApiDefinitionController {
return PageUtils.setPageInfo(page, apiDefinitionService.list(request)); return PageUtils.setPageInfo(page, apiDefinitionService.list(request));
} }
@PostMapping("/list/relevance/{goPage}/{pageSize}")
public Pager<List<ApiDefinitionResult>> listRelevance(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ApiDefinitionRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
return PageUtils.setPageInfo(page, apiDefinitionService.listRelevance(request));
}
@PostMapping("/list/all") @PostMapping("/list/all")
public List<ApiDefinitionResult> list(@RequestBody ApiDefinitionRequest request) { public List<ApiDefinitionResult> list(@RequestBody ApiDefinitionRequest request) {
return apiDefinitionService.list(request); return apiDefinitionService.list(request);
@ -72,12 +79,23 @@ public class ApiDefinitionController {
apiDefinitionService.deleteBatch(ids); apiDefinitionService.deleteBatch(ids);
} }
@PostMapping("/deleteBatchByParams")
public void deleteBatchByParams(@RequestBody ApiDefinitionBatchProcessingRequest request) {
apiDefinitionService.deleteByParams(request);
}
@PostMapping("/removeToGc") @PostMapping("/removeToGc")
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR) @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR)
public void removeToGc(@RequestBody List<String> ids) { public void removeToGc(@RequestBody List<String> ids) {
apiDefinitionService.removeToGc(ids); apiDefinitionService.removeToGc(ids);
} }
@PostMapping("/removeToGcByParams")
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR)
public void removeToGcByParams(@RequestBody ApiDefinitionBatchProcessingRequest request) {
apiDefinitionService.removeToGcByParams(request);
}
@PostMapping("/reduction") @PostMapping("/reduction")
public void reduction(@RequestBody List<SaveApiDefinitionRequest> requests) { public void reduction(@RequestBody List<SaveApiDefinitionRequest> requests) {
apiDefinitionService.reduction(requests); apiDefinitionService.reduction(requests);
@ -130,6 +148,12 @@ public class ApiDefinitionController {
apiDefinitionService.editApiBath(request); apiDefinitionService.editApiBath(request);
} }
@PostMapping("/batch/editByParams")
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
public void editByParams(@RequestBody ApiBatchRequest request) {
apiDefinitionService.editApiByParam(request);
}
@PostMapping("/relevance") @PostMapping("/relevance")
public void testPlanRelevance(@RequestBody ApiCaseRelevanceRequest request) { public void testPlanRelevance(@RequestBody ApiCaseRelevanceRequest request) {
apiDefinitionService.testPlanRelevance(request); apiDefinitionService.testPlanRelevance(request);

View File

@ -11,4 +11,24 @@ public class DeleteAPIReportRequest {
private String id; private String id;
private List<String> ids; private List<String> ids;
/**
* isSelectAllDate选择的数据是否是全部数据全部数据是不受分页影响的数据
* filters: 数据状态
* name如果是全部数据那么表格如果历经查询查询参数是什么
* moduleIds 哪些模块的数据
* unSelectIds是否在页面上有未勾选的数据有的话他们的ID是哪些
* filters/name/moduleIds/unSeelctIds 只在isSelectAllDate为true时需要为了让程序能明确批量的范围
*/
private boolean isSelectAllDate;
private List<String> filters;
private String name;
private String projectId;
private List<String> moduleIds;
private List<String> unSelectIds;
} }

View File

@ -28,4 +28,23 @@ public class RunScenarioRequest {
private String reportUserID; private String reportUserID;
private List<String> scenarioIds; private List<String> scenarioIds;
/**
* isSelectAllDate选择的数据是否是全部数据全部数据是不受分页影响的数据
* filters: 数据状态
* name如果是全部数据那么表格如果历经查询查询参数是什么
* moduleIds 哪些模块的数据
* unSelectIds是否在页面上有未勾选的数据有的话他们的ID是哪些
* filters/name/moduleIds/unSeelctIds 只在isSelectAllDate为true时需要为了让程序能明确批量的范围
*/
private boolean isSelectAllDate;
private List<String> filters;
private String name;
private List<String> moduleIds;
private List<String> unSelectIds;
} }

View File

@ -11,4 +11,26 @@ public class SaveApiPlanRequest {
private List<String> planIds; private List<String> planIds;
private List<String> apiIds; private List<String> apiIds;
private List<String> scenarioIds; private List<String> scenarioIds;
/**
* isSelectAllDate选择的数据是否是全部数据全部数据是不受分页影响的数据
* filters: 数据状态
* name如果是全部数据那么表格如果历经查询查询参数是什么
* moduleIds 哪些模块的数据
* unSelectIds是否在页面上有未勾选的数据有的话他们的ID是哪些
* filters/name/moduleIds/unSeelctIds 只在isSelectAllDate为true时需要为了让程序能明确批量的范围
*/
private boolean isSelectAllDate;
private List<String> filters;
private String name;
private List<String> moduleIds;
private List<String> unSelectIds;
private String projectId;
} }

View File

@ -13,4 +13,23 @@ public class ApiBatchRequest extends ApiDefinitionWithBLOBs {
private List<String> ids; private List<String> ids;
private List<OrderRequest> orders; private List<OrderRequest> orders;
private String projectId; private String projectId;
/**
* isSelectAllDate选择的数据是否是全部数据全部数据是不受分页影响的数据
* filters: 数据状态
* name如果是全部数据那么表格如果历经查询查询参数是什么
* moduleIds 哪些模块的数据
* unSelectIds是否在页面上有未勾选的数据有的话他们的ID是哪些
* filters/name/moduleIds/unSeelctIds 只在isSelectAllDate为true时需要为了让程序能明确批量的范围
*/
private boolean isSelectAllDate;
private List<String> filters;
private String name;
private List<String> moduleIds;
private List<String> unSelectIds;
} }

View File

@ -0,0 +1,39 @@
package io.metersphere.api.dto.definition;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* 接口定义模块-批量处理请求类
* @author song.tianyang
* @Date 2020/12/29 4:13 下午
* @Description
*/
@Getter
@Setter
public class ApiDefinitionBatchProcessingRequest {
/**
* isSelectAllDate选择的数据是否是全部数据全部数据是不受分页影响的数据
* filters: 数据状态
* name如果是全部数据那么表格如果历经查询查询参数是什么
* moduleIds 哪些模块的数据
* unSelectIds是否在页面上有未勾选的数据有的话他们的ID是哪些
* filters/name/moduleIds/unSeelctIds 只在isSelectAllDate为true时需要为了让程序能明确批量的范围
*/
private boolean isSelectAllDate;
private List<String> filters;
private String name;
private List<String> moduleIds;
private List<String> unSelectIds;
private String projectId;
private List<String> dataIds;
}

View File

@ -20,6 +20,7 @@ public class ApiDefinitionRequest {
private String name; private String name;
private String workspaceId; private String workspaceId;
private String userId; private String userId;
private String planId;
private boolean recent = false; private boolean recent = false;
private List<OrderRequest> orders; private List<OrderRequest> orders;
private List<String> filters; private List<String> filters;

View File

@ -24,7 +24,6 @@ import io.metersphere.base.mapper.ext.ExtTestPlanScenarioCaseMapper;
import io.metersphere.commons.constants.*; import io.metersphere.commons.constants.*;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.DateUtils; import io.metersphere.commons.utils.DateUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.ServiceUtils; import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.commons.utils.SessionUtils; import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.i18n.Translator; import io.metersphere.i18n.Translator;
@ -303,13 +302,23 @@ public class ApiAutomationService {
* @return * @return
*/ */
public String run(RunScenarioRequest request) { public String run(RunScenarioRequest request) {
List<ApiScenarioWithBLOBs> apiScenarios = extApiScenarioMapper.selectIds(request.getScenarioIds()); List<ApiScenarioWithBLOBs> apiScenarios = null;
List<String> ids = request.getScenarioIds();
if (request.isSelectAllDate()) {
ids = this.getAllScenarioIdsByFontedSelect(
request.getModuleIds(), request.getName(), request.getProjectId(), request.getFilters(), request.getUnSelectIds());
}
apiScenarios = extApiScenarioMapper.selectIds(ids);
MsTestPlan testPlan = new MsTestPlan(); MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>()); testPlan.setHashTree(new LinkedList<>());
HashTree jmeterHashTree = new ListedHashTree(); HashTree jmeterHashTree = new ListedHashTree();
try { try {
boolean isFirst = true; boolean isFirst = true;
for (ApiScenarioWithBLOBs item : apiScenarios) { for (ApiScenarioWithBLOBs item : apiScenarios) {
if (item.getStepTotal() == 0) {
MSException.throwException(item.getName() + "" + Translator.get("automation_exec_info"));
break;
}
MsThreadGroup group = new MsThreadGroup(); MsThreadGroup group = new MsThreadGroup();
group.setLabel(item.getName()); group.setLabel(item.getName());
group.setName(UUID.randomUUID().toString()); group.setName(UUID.randomUUID().toString());
@ -347,7 +356,7 @@ public class ApiAutomationService {
} }
} catch (Exception ex) { } catch (Exception ex) {
LogUtil.error(ex.getMessage()); MSException.throwException(ex.getMessage());
} }
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), new ParameterConfig()); testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), new ParameterConfig());
@ -360,6 +369,27 @@ public class ApiAutomationService {
return request.getId(); return request.getId();
} }
/**
* 获取前台查询条件查询的所有(未经分页筛选)数据ID
*
* @param moduleIds 模块ID_前台查询时所选择的
* @param name 搜索条件_名称_前台查询时所输入的
* @param projectId 所属项目_前台查询时所在项目
* @param filters 过滤集合__前台查询时的过滤条件
* @param unSelectIds 未勾选ID_前台没有勾选的ID
* @return
*/
private List<String> getAllScenarioIdsByFontedSelect(List<String> moduleIds, String name, String projectId, List<String> filters, List<String> unSelectIds) {
ApiScenarioRequest selectRequest = new ApiScenarioRequest();
selectRequest.setModuleIds(moduleIds);
selectRequest.setName(name);
selectRequest.setProjectId(projectId);
selectRequest.setFilters(filters);
List<ApiScenarioDTO> list = extApiScenarioMapper.list(selectRequest);
List<String> allIds = list.stream().map(ApiScenarioDTO::getId).collect(Collectors.toList());
List<String> ids = allIds.stream().filter(id -> !unSelectIds.contains(id)).collect(Collectors.toList());
return ids;
}
/** /**
* 场景测试执行 * 场景测试执行
@ -401,6 +431,11 @@ public class ApiAutomationService {
if (CollectionUtils.isEmpty(request.getPlanIds())) { if (CollectionUtils.isEmpty(request.getPlanIds())) {
MSException.throwException(Translator.get("plan id is null ")); MSException.throwException(Translator.get("plan id is null "));
} }
List<String> scenarioIds = request.getScenarioIds();
if (request.isSelectAllDate()) {
scenarioIds = this.getAllScenarioIdsByFontedSelect(
request.getModuleIds(), request.getName(), request.getProjectId(), request.getFilters(), request.getUnSelectIds());
}
List<TestPlanDTO> list = extTestPlanMapper.selectByIds(request.getPlanIds()); List<TestPlanDTO> list = extTestPlanMapper.selectByIds(request.getPlanIds());
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ExtTestPlanMapper mapper = sqlSession.getMapper(ExtTestPlanMapper.class); ExtTestPlanMapper mapper = sqlSession.getMapper(ExtTestPlanMapper.class);
@ -408,8 +443,8 @@ public class ApiAutomationService {
ExtTestPlanApiCaseMapper apiCaseBatchMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class); ExtTestPlanApiCaseMapper apiCaseBatchMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class);
for (TestPlanDTO testPlan : list) { for (TestPlanDTO testPlan : list) {
if (request.getScenarioIds() != null) { if (scenarioIds != null) {
for (String scenarioId : request.getScenarioIds()) { for (String scenarioId : scenarioIds) {
TestPlanApiScenario testPlanApiScenario = new TestPlanApiScenario(); TestPlanApiScenario testPlanApiScenario = new TestPlanApiScenario();
testPlanApiScenario.setId(UUID.randomUUID().toString()); testPlanApiScenario.setId(UUID.randomUUID().toString());
testPlanApiScenario.setApiScenarioId(scenarioId); testPlanApiScenario.setApiScenarioId(scenarioId);

View File

@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.APIReportResult; import io.metersphere.api.dto.APIReportResult;
import io.metersphere.api.dto.ApiTestImportRequest; import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.automation.ApiScenarioDTO;
import io.metersphere.api.dto.automation.ApiScenarioRequest; import io.metersphere.api.dto.automation.ApiScenarioRequest;
import io.metersphere.api.dto.automation.ReferenceDTO; import io.metersphere.api.dto.automation.ReferenceDTO;
import io.metersphere.api.dto.datacount.ApiDataCountResult; import io.metersphere.api.dto.datacount.ApiDataCountResult;
@ -78,23 +79,7 @@ public class ApiDefinitionService {
public List<ApiDefinitionResult> list(ApiDefinitionRequest request) { public List<ApiDefinitionResult> list(ApiDefinitionRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders())); request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
List<ApiDefinitionResult> resList = extApiDefinitionMapper.list(request); List<ApiDefinitionResult> resList = extApiDefinitionMapper.list(request);
if (!resList.isEmpty()) { calculateResult(resList);
List<String> ids = resList.stream().map(ApiDefinitionResult::getId).collect(Collectors.toList());
List<ApiComputeResult> results = extApiDefinitionMapper.selectByIds(ids);
Map<String, ApiComputeResult> resultMap = results.stream().collect(Collectors.toMap(ApiComputeResult::getApiDefinitionId, Function.identity()));
for (ApiDefinitionResult res : resList) {
ApiComputeResult compRes = resultMap.get(res.getId());
if (compRes != null) {
res.setCaseTotal(compRes.getCaseTotal());
res.setCasePassingRate(compRes.getPassRate());
res.setCaseStatus(compRes.getStatus());
} else {
res.setCaseTotal("-");
res.setCasePassingRate("-");
res.setCaseStatus("-");
}
}
}
return resList; return resList;
} }
@ -420,6 +405,23 @@ public class ApiDefinitionService {
apiDefinitionMapper.updateByExampleSelective(definitionWithBLOBs, definitionExample); apiDefinitionMapper.updateByExampleSelective(definitionWithBLOBs, definitionExample);
} }
public void editApiByParam(ApiBatchRequest request) {
List<String> ids = request.getIds();
if(request.isSelectAllDate()){
ids = this.getAllApiIdsByFontedSelect(request.getFilters(),request.getName(),request.getModuleIds(),request.getProjectId(),request.getUnSelectIds());
}
//name在这里只是查询参数
request.setName(null);
ApiDefinitionExample definitionExample = new ApiDefinitionExample();
definitionExample.createCriteria().andIdIn(ids);
ApiDefinitionWithBLOBs definitionWithBLOBs = new ApiDefinitionWithBLOBs();
BeanUtils.copyBean(definitionWithBLOBs, request);
definitionWithBLOBs.setUpdateTime(System.currentTimeMillis());
apiDefinitionMapper.updateByExampleSelective(definitionWithBLOBs, definitionExample);
}
public void testPlanRelevance(ApiCaseRelevanceRequest request) { public void testPlanRelevance(ApiCaseRelevanceRequest request) {
apiTestCaseService.relevanceByApi(request); apiTestCaseService.relevanceByApi(request);
} }
@ -466,4 +468,64 @@ public class ApiDefinitionService {
example.createCriteria().andIdIn(ids); example.createCriteria().andIdIn(ids);
return apiDefinitionMapper.selectByExample(example); return apiDefinitionMapper.selectByExample(example);
} }
public void deleteByParams(ApiDefinitionBatchProcessingRequest request) {
List<String> apiIds = request.getDataIds();
if(request.isSelectAllDate()){
apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(),request.getName(),request.getModuleIds(),request.getProjectId(),request.getUnSelectIds());
}
ApiDefinitionExample example = new ApiDefinitionExample();
example.createCriteria().andIdIn(apiIds);
apiDefinitionMapper.deleteByExample(example);
}
private List<String> getAllApiIdsByFontedSelect(List<String> filter,String name,List<String> moduleIds,String projectId,List<String>unSelectIds) {
ApiDefinitionRequest request = new ApiDefinitionRequest();
request.setFilters(filter);
request.setName(name);
request.setModuleIds(moduleIds);
request.setProjectId(projectId);
List<ApiDefinitionResult> resList = extApiDefinitionMapper.list(request);
List<String> ids = new ArrayList<>(0);
if (!resList.isEmpty()) {
List<String> allIds = resList.stream().map(ApiDefinitionResult::getId).collect(Collectors.toList());
ids = allIds.stream().filter(id -> !unSelectIds.contains(id)).collect(Collectors.toList());
}
return ids;
}
public void removeToGcByParams(ApiDefinitionBatchProcessingRequest request) {
List<String> apiIds = request.getDataIds();
if(request.isSelectAllDate()){
apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(),request.getName(),request.getModuleIds(),request.getProjectId(),request.getUnSelectIds());
}
extApiDefinitionMapper.removeToGc(apiIds);
}
public List<ApiDefinitionResult> listRelevance(ApiDefinitionRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
List<ApiDefinitionResult> resList = extApiDefinitionMapper.listRelevance(request);
calculateResult(resList);
return resList;
}
public void calculateResult(List<ApiDefinitionResult> resList) {
if (!resList.isEmpty()) {
List<String> ids = resList.stream().map(ApiDefinitionResult::getId).collect(Collectors.toList());
List<ApiComputeResult> results = extApiDefinitionMapper.selectByIds(ids);
Map<String, ApiComputeResult> resultMap = results.stream().collect(Collectors.toMap(ApiComputeResult::getApiDefinitionId, Function.identity()));
for (ApiDefinitionResult res : resList) {
ApiComputeResult compRes = resultMap.get(res.getId());
if (compRes != null) {
res.setCaseTotal(compRes.getCaseTotal());
res.setCasePassingRate(compRes.getPassRate());
res.setCaseStatus(compRes.getStatus());
} else {
res.setCaseTotal("-");
res.setCasePassingRate("-");
res.setCaseStatus("-");
}
}
}
}
} }

View File

@ -3,9 +3,7 @@ package io.metersphere.api.service;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import io.metersphere.api.dto.DeleteAPIReportRequest; import io.metersphere.api.dto.DeleteAPIReportRequest;
import io.metersphere.api.dto.QueryAPIReportRequest; import io.metersphere.api.dto.QueryAPIReportRequest;
import io.metersphere.api.dto.automation.APIScenarioReportResult; import io.metersphere.api.dto.automation.*;
import io.metersphere.api.dto.automation.ExecuteType;
import io.metersphere.api.dto.automation.ScenarioStatus;
import io.metersphere.api.dto.datacount.ApiDataCountResult; import io.metersphere.api.dto.datacount.ApiDataCountResult;
import io.metersphere.api.jmeter.ScenarioResult; import io.metersphere.api.jmeter.ScenarioResult;
import io.metersphere.api.jmeter.TestResult; import io.metersphere.api.jmeter.TestResult;
@ -19,6 +17,7 @@ import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.DateUtils; import io.metersphere.commons.utils.DateUtils;
import io.metersphere.commons.utils.ServiceUtils; import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.i18n.Translator; import io.metersphere.i18n.Translator;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -31,6 +30,7 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
@Service @Service
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@ -208,12 +208,23 @@ public class ApiScenarioReportService {
} }
public void deleteAPIReportBatch(DeleteAPIReportRequest reportRequest) { public void deleteAPIReportBatch(DeleteAPIReportRequest reportRequest) {
List<String> ids = reportRequest.getIds();
if (reportRequest.isSelectAllDate()) {
QueryAPIReportRequest selectRequest = new QueryAPIReportRequest();
selectRequest.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
selectRequest.setName(reportRequest.getName());
selectRequest.setProjectId(reportRequest.getProjectId());
List<APIScenarioReportResult> list = extApiScenarioReportMapper.list(selectRequest);
List<String> allIds = list.stream().map(APIScenarioReportResult::getId).collect(Collectors.toList());
ids = allIds.stream().filter(id -> !reportRequest.getUnSelectIds().contains(id)).collect(Collectors.toList());
}
ApiScenarioReportDetailExample detailExample = new ApiScenarioReportDetailExample(); ApiScenarioReportDetailExample detailExample = new ApiScenarioReportDetailExample();
detailExample.createCriteria().andReportIdIn(reportRequest.getIds()); detailExample.createCriteria().andReportIdIn(ids);
apiScenarioReportDetailMapper.deleteByExample(detailExample); apiScenarioReportDetailMapper.deleteByExample(detailExample);
ApiScenarioReportExample apiTestReportExample = new ApiScenarioReportExample(); ApiScenarioReportExample apiTestReportExample = new ApiScenarioReportExample();
apiTestReportExample.createCriteria().andIdIn(reportRequest.getIds()); apiTestReportExample.createCriteria().andIdIn(ids);
apiScenarioReportMapper.deleteByExample(apiTestReportExample); apiScenarioReportMapper.deleteByExample(apiTestReportExample);
} }

View File

@ -28,4 +28,6 @@ public interface ExtApiDefinitionMapper {
List<ApiDataCountResult> countApiCoverageByProjectID(String projectId); List<ApiDataCountResult> countApiCoverageByProjectID(String projectId);
ApiDefinition getNextNum(@Param("projectId") String projectId); ApiDefinition getNextNum(@Param("projectId") String projectId);
List<ApiDefinitionResult> listRelevance(@Param("request")ApiDefinitionRequest request);
} }

View File

@ -295,4 +295,63 @@
<select id="getNextNum" resultType="io.metersphere.base.domain.ApiDefinition"> <select id="getNextNum" resultType="io.metersphere.base.domain.ApiDefinition">
SELECT * FROM api_definition WHERE api_definition.project_id = #{projectId} ORDER BY num DESC LIMIT 1; SELECT * FROM api_definition WHERE api_definition.project_id = #{projectId} ORDER BY num DESC LIMIT 1;
</select> </select>
<select id="listRelevance" resultType="io.metersphere.api.dto.definition.ApiDefinitionResult">
select api_definition.id, api_definition.project_id, api_definition.num,
api_definition.name,api_definition.protocol,api_definition.path,api_definition.module_id,api_definition.module_path,api_definition.method,
api_definition.description,api_definition.request,api_definition.response,api_definition.environment_id,
api_definition.status, api_definition.user_id, api_definition.create_time, api_definition.update_time
from api_definition
inner join
api_test_case c
on c.api_definition_id = api_definition.id
and not exists (
select id
from test_plan_api_case t
where t.api_case_id = c.id
and t.test_plan_id = #{request.planId}
)
<where>
<if test="request.combine != null">
<include refid="combine">
<property name="condition" value="request.combine"/>
<property name="name" value="request.name"/>
</include>
</if>
<if test="request.name != null">
and api_definition.name like CONCAT('%', #{request.name},'%')
</if>
<if test="request.protocol != null">
AND api_definition.protocol = #{request.protocol}
</if>
<if test="request.id != null">
AND api_definition.id = #{request.id}
</if>
<if test="request.moduleId != null">
AND api_definition.module_id = #{request.moduleId}
</if>
<if test="request.projectId != null">
AND api_definition.project_id = #{request.projectId}
</if>
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
AND api_definition.module_id in
<foreach collection="request.moduleIds" item="nodeId" separator="," open="(" close=")">
#{nodeId}
</foreach>
</if>
<if test="request.filters != null and request.filters.size() > 0">
and api_definition.status in
<foreach collection="request.filters" item="value" separator="," open="(" close=")">
#{value}
</foreach>
</if>
</where>
<if test="request.orders != null and request.orders.size() > 0">
order by
<foreach collection="request.orders" separator="," item="order">
api_definition.${order.name} ${order.type}
</foreach>
</if>
</select>
</mapper> </mapper>

View File

@ -19,7 +19,7 @@
select select
t.id, t.environment_id, t.create_time, t.update_time, t.id, t.environment_id, t.create_time, t.update_time,
c.id as case_id, c.project_id, c.name, c.api_definition_id, c.priority, c.description, c.create_user_id, c.update_user_id, c.id as case_id, c.project_id, c.name, c.api_definition_id, c.priority, c.description, c.create_user_id, c.update_user_id,
a.module_id, a.path, a.protocol, ader.status execResult a.module_id, a.path, a.protocol, t.status execResult
from from
test_plan_api_case t test_plan_api_case t
inner join inner join
@ -32,24 +32,6 @@
api_definition a api_definition a
on on
c.api_definition_id = a.id c.api_definition_id = a.id
left join (
select
e.status, e.id, e.resource_id
from
api_definition_exec_result e
left join (
select
max(start_time) start_time , resource_id
from
api_definition_exec_result
group by
resource_id
) as b
on e.resource_id = b.resource_id
where
e.start_time = b.start_time and e.type = 'API_PLAN'
) as ader
on t.id = ader.resource_id
<if test="request.protocol != null and request.protocol!=''"> <if test="request.protocol != null and request.protocol!=''">
and a.protocol = #{request.protocol} and a.protocol = #{request.protocol}
</if> </if>

View File

@ -100,7 +100,7 @@
parameterType="io.metersphere.track.request.testcase.QueryTestPlanRequest"> parameterType="io.metersphere.track.request.testcase.QueryTestPlanRequest">
select DISTINCT test_plan.*, user.name as user_name from test_plan select DISTINCT test_plan.*, user.name as user_name from test_plan
LEFT JOIN user ON user.id = test_plan.principal LEFT JOIN user ON user.id = test_plan.principal
JOIN test_plan_project on test_plan.id = test_plan_id JOIN project on project.id = project_id JOIN test_plan_project on test_plan.id = test_plan_project.test_plan_id JOIN project on project.id = test_plan_project.project_id
<where> <where>
<if test="request.combine != null"> <if test="request.combine != null">
<include refid="combine"> <include refid="combine">

@ -1 +1 @@
Subproject commit f27d1609d77f7d6c988d37d709466e844d350e17 Subproject commit 6f082f93de680139816f95349fc95cf538784c20

View File

@ -177,6 +177,6 @@ task_notification=Result notification
message_task_already_exists=Task recipient already exists message_task_already_exists=Task recipient already exists
#automation #automation
automation_name_already_exists=the scenario already exists in the project and the module automation_name_already_exists=the scenario already exists in the project and the module
automation_exec_info=There are no test steps to execute

View File

@ -177,4 +177,5 @@ task_notification_jenkins=jenkins任务通知
task_notification=任务通知 task_notification=任务通知
message_task_already_exists=任务接收人已经存在 message_task_already_exists=任务接收人已经存在
#automation #automation
automation_name_already_exists=同一个项目和模块下,场景名称不能重复 automation_name_already_exists=同一个项目和模块下,场景名称不能重复
automation_exec_info=没有测试步骤,无法执行

View File

@ -179,3 +179,4 @@ api_definition_url_not_repeating=接口請求地址已經存在
message_task_already_exists=任務接收人已經存在 message_task_already_exists=任務接收人已經存在
#automation #automation
automation_name_already_exists=同一個項目和模塊下,場景名稱不能重複 automation_name_already_exists=同一個項目和模塊下,場景名稱不能重複
automation_exec_info=沒有測試步驟,無法執行

View File

@ -7,21 +7,35 @@
:title="$t('api_report.title')" :title="$t('api_report.title')"
:show-create="false"/> :show-create="false"/>
</template> </template>
<el-table border :data="tableData" class="adjust-table table-content" @sort-change="sort" <el-table ref="reportListTable" border :data="tableData" class="adjust-table table-content" @sort-change="sort"
@select-all="handleSelectAll" @select-all="handleSelectAll"
@select="handleSelect" @select="handleSelect"
@filter-change="filter" @row-click="handleView"> @filter-change="filter" @row-click="handleView">
<el-table-column <el-table-column
type="selection"/> type="selection"/>
<el-table-column width="40" :resizable="false" align="center"> <el-table-column width="40" :resizable="false" align="center">
<el-dropdown slot="header" style="width: 14px">
<span class="el-dropdown-link" style="width: 14px">
<i class="el-icon-arrow-down el-icon--right" style="margin-left: 0px"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native.stop="isSelectDataAll(true)">
{{ $t('api_test.batch_menus.select_all_data', [total]) }}
</el-dropdown-item>
<el-dropdown-item @click.native.stop="isSelectDataAll(false)">
{{ $t('api_test.batch_menus.select_show_data', [tableData.length]) }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<template v-slot:default="scope"> <template v-slot:default="scope">
<show-more-btn v-tester :is-show="scope.row.showMore" :buttons="buttons" :size="selectRows.size"/> <show-more-btn v-tester :is-show="scope.row.showMore" :buttons="buttons" :size="selectDataCounts"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('commons.name')" width="200" show-overflow-tooltip prop="name"> <el-table-column :label="$t('commons.name')" width="200" show-overflow-tooltip prop="name">
</el-table-column> </el-table-column>
<el-table-column prop="scenarioName" :label="$t('api_test.automation.scenario_name')" width="150" show-overflow-tooltip/> <el-table-column prop="scenarioName" :label="$t('api_test.automation.scenario_name')" width="150"
show-overflow-tooltip/>
<el-table-column prop="userName" :label="$t('api_test.creator')" width="150" show-overflow-tooltip/> <el-table-column prop="userName" :label="$t('api_test.creator')" width="150" show-overflow-tooltip/>
<el-table-column prop="createTime" width="250" :label="$t('commons.create_time')" sortable> <el-table-column prop="createTime" width="250" :label="$t('commons.create_time')" sortable>
<template v-slot:default="scope"> <template v-slot:default="scope">
@ -55,8 +69,10 @@
</el-card> </el-card>
</ms-main-container> </ms-main-container>
<el-drawer :visible.sync="debugVisible" :destroy-on-close="true" direction="ltr" :withHeader="false" :title="$t('test_track.plan_view.test_result')" :modal="false" size="90%"> <el-drawer :visible.sync="debugVisible" :destroy-on-close="true" direction="ltr" :withHeader="false"
<ms-api-report-detail :report-id="reportId" :currentProjectId="currentProjectId" :info-db="true" @refresh="search"/> :title="$t('test_track.plan_view.test_result')" :modal="false" size="90%">
<ms-api-report-detail :report-id="reportId" :currentProjectId="currentProjectId" :info-db="true"
@refresh="search"/>
</el-drawer> </el-drawer>
</ms-container> </ms-container>
</template> </template>
@ -76,152 +92,190 @@ import ShowMoreBtn from "../../../track/case/components/ShowMoreBtn";
import MsApiReportDetail from "./ApiReportDetail"; import MsApiReportDetail from "./ApiReportDetail";
export default { export default {
components: { components: {
ReportTriggerModeItem, ReportTriggerModeItem,
MsTableOperatorButton, MsTableOperatorButton,
MsApiReportStatus, MsMainContainer, MsContainer, MsTableHeader, MsTablePagination, ShowMoreBtn, MsApiReportDetail MsApiReportStatus, MsMainContainer, MsContainer, MsTableHeader, MsTablePagination, ShowMoreBtn, MsApiReportDetail
}, },
data() { data() {
return { return {
result: {}, result: {},
reportId: "", reportId: "",
debugVisible: false, debugVisible: false,
condition: { condition: {
components: REPORT_CONFIGS components: REPORT_CONFIGS
}, },
tableData: [], tableData: [],
multipleSelection: [], multipleSelection: [],
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 5,
total: 0, total: 0,
loading: false, loading: false,
currentProjectId: "", currentProjectId: "",
statusFilters: [ statusFilters: [
{text: 'Saved', value: 'Saved'}, {text: 'Saved', value: 'Saved'},
{text: 'Starting', value: 'Starting'}, {text: 'Starting', value: 'Starting'},
{text: 'Running', value: 'Running'}, {text: 'Running', value: 'Running'},
{text: 'Reporting', value: 'Reporting'}, {text: 'Reporting', value: 'Reporting'},
{text: 'Completed', value: 'Completed'}, {text: 'Completed', value: 'Completed'},
{text: 'Error', value: 'Error'}, {text: 'Error', value: 'Error'},
{text: 'Success', value: 'Success'}, {text: 'Success', value: 'Success'},
], ],
triggerFilters: [ triggerFilters: [
{text: this.$t('commons.trigger_mode.manual'), value: 'MANUAL'}, {text: this.$t('commons.trigger_mode.manual'), value: 'MANUAL'},
{text: this.$t('commons.trigger_mode.schedule'), value: 'SCHEDULE'}, {text: this.$t('commons.trigger_mode.schedule'), value: 'SCHEDULE'},
{text: this.$t('commons.trigger_mode.api'), value: 'API'} {text: this.$t('commons.trigger_mode.api'), value: 'API'}
], ],
buttons: [ buttons: [
{ {
name: this.$t('api_report.batch_delete'), handleClick: this.handleBatchDelete name: this.$t('api_report.batch_delete'), handleClick: this.handleBatchDelete
}
],
selectRows: new Set(),
}
},
watch: {
'$route': 'init',
},
methods: {
search() {
if (this.testId !== 'all') {
this.condition.testId = this.testId;
} }
this.condition.projectId = getCurrentProjectID(); ],
let url = "/api/scenario/report/list/" + this.currentPage + "/" + this.pageSize; selectRows: new Set(),
this.result = this.$post(url, this.condition, response => { selectAll: false,
let data = response.data; unSelection: [],
this.total = data.itemCount; selectDataCounts: 0,
this.tableData = data.listObject;
this.selectRows.clear();
});
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
handleView(report) {
this.reportId = report.id;
this.currentProjectId = report.projectId;
this.debugVisible = true;
},
handleDelete(report) {
this.$alert(this.$t('api_report.delete_confirm') + report.name + "", '', {
confirmButtonText: this.$t('commons.confirm'),
callback: (action) => {
if (action === 'confirm') {
this.result = this.$post("/api/scenario/report/delete", {id: report.id}, () => {
this.$success(this.$t('commons.delete_success'));
this.search();
// 广 head
ApiEvent.$emit(LIST_CHANGE);
});
}
}
});
},
init() {
this.testId = this.$route.params.testId;
this.search();
},
sort(column) {
_sort(column, this.condition);
this.init();
},
filter(filters) {
_filter(filters, this.condition);
this.init();
},
handleSelect(selection, row) {
if (this.selectRows.has(row)) {
this.$set(row, "showMore", false);
this.selectRows.delete(row);
} else {
this.$set(row, "showMore", true);
this.selectRows.add(row);
}
},
handleSelectAll(selection) {
if (selection.length > 0) {
this.tableData.forEach(item => {
this.$set(item, "showMore", true);
this.selectRows.add(item);
});
} else {
this.selectRows.clear();
this.tableData.forEach(row => {
this.$set(row, "showMore", false);
})
}
},
handleBatchDelete() {
this.$alert(this.$t('api_report.delete_batch_confirm') + "", '', {
confirmButtonText: this.$t('commons.confirm'),
callback: (action) => {
if (action === 'confirm') {
let ids = Array.from(this.selectRows).map(row => row.id);
this.$post('/api/scenario/report/batch/delete', {ids: ids}, () => {
this.selectRows.clear();
this.$success(this.$t('commons.delete_success'));
this.search();
// 广 head
ApiEvent.$emit(LIST_CHANGE);
});
}
}
});
}
},
created() {
this.init();
} }
},
watch: {
'$route': 'init',
},
methods: {
search() {
if (this.testId !== 'all') {
this.condition.testId = this.testId;
}
this.condition.projectId = getCurrentProjectID();
this.selectAll = false;
this.unSelection = [];
this.selectDataCounts = 0;
let url = "/api/scenario/report/list/" + this.currentPage + "/" + this.pageSize;
this.result = this.$post(url, this.condition, response => {
let data = response.data;
this.total = data.itemCount;
this.tableData = data.listObject;
this.selectRows.clear();
this.unSelection = data.listObject.map(s => s.id);
});
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
handleView(report) {
this.reportId = report.id;
this.currentProjectId = report.projectId;
this.debugVisible = true;
},
handleDelete(report) {
this.$alert(this.$t('api_report.delete_confirm') + report.name + "", '', {
confirmButtonText: this.$t('commons.confirm'),
callback: (action) => {
if (action === 'confirm') {
this.result = this.$post("/api/scenario/report/delete", {id: report.id}, () => {
this.$success(this.$t('commons.delete_success'));
this.search();
// 广 head
ApiEvent.$emit(LIST_CHANGE);
});
}
}
});
},
init() {
this.testId = this.$route.params.testId;
this.search();
},
sort(column) {
_sort(column, this.condition);
this.init();
},
filter(filters) {
_filter(filters, this.condition);
this.init();
},
handleSelect(selection, row) {
if (this.selectRows.has(row)) {
this.$set(row, "showMore", false);
this.selectRows.delete(row);
} else {
this.$set(row, "showMore", true);
this.selectRows.add(row);
}
this.selectRowsCount(this.selectRows)
},
handleSelectAll(selection) {
if (selection.length > 0) {
this.tableData.forEach(item => {
this.$set(item, "showMore", true);
this.selectRows.add(item);
});
} else {
this.selectRows.clear();
this.tableData.forEach(row => {
this.$set(row, "showMore", false);
})
}
this.selectRowsCount(this.selectRows)
},
handleBatchDelete() {
this.$alert(this.$t('api_report.delete_batch_confirm') + "", '', {
confirmButtonText: this.$t('commons.confirm'),
callback: (action) => {
if (action === 'confirm') {
let ids = Array.from(this.selectRows).map(row => row.id);
let sendParam = {};
sendParam.ids = ids;
sendParam.selectAllDate = this.isSelectAllDate;
sendParam.unSelectIds = this.unSelection;
sendParam = Object.assign(sendParam, this.condition);
this.$post('/api/scenario/report/batch/delete', sendParam, () => {
this.selectRows.clear();
this.$success(this.$t('commons.delete_success'));
this.search();
// 广 head
ApiEvent.$emit(LIST_CHANGE);
});
}
}
});
},
selectRowsCount(selection) {
let selectedIDs = this.getIds(selection);
let allIDs = this.tableData.map(s => s.id);
this.unSelection = allIDs.filter(function (val) {
return selectedIDs.indexOf(val) === -1
});
if (this.isSelectAllDate) {
this.selectDataCounts = this.total - this.unSelection.length;
} else {
this.selectDataCounts = selection.size;
}
},
isSelectDataAll(dataType) {
this.isSelectAllDate = dataType;
this.selectRowsCount(this.selectRows)
//
if (this.selectRows.size != this.tableData.length) {
this.$refs.reportListTable.toggleAllSelection(true);
}
},
getIds(rowSets) {
let rowArray = Array.from(rowSets)
let ids = rowArray.map(s => s.id);
return ids;
}
},
created() {
this.init();
} }
}
</script> </script>
<style scoped> <style scoped>
.table-content { .table-content {
width: 100%; width: 100%;
} }
</style> </style>

View File

@ -6,11 +6,26 @@
:show-create="false"/> :show-create="false"/>
</template> </template>
<el-table ref="scenarioTable" border :data="tableData" class="adjust-table" @select-all="select" @select="select" v-loading="loading"> <el-table ref="scenarioTable" border :data="tableData" class="adjust-table" @select-all="select" @select="select"
<el-table-column type="selection"/> v-loading="loading">
<el-table-column type="selection" width="38"/>
<el-table-column v-if="!referenced" width="40" :resizable="false" align="center"> <el-table-column v-if="!referenced" width="40" :resizable="false" align="center">
<el-dropdown slot="header" style="width: 14px">
<span class="el-dropdown-link" style="width: 14px">
<i class="el-icon-arrow-down el-icon--right" style="margin-left: 0px"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native.stop="isSelectDataAll(true)">
{{$t('api_test.batch_menus.select_all_data',[total])}}
</el-dropdown-item>
<el-dropdown-item @click.native.stop="isSelectDataAll(false)">
{{$t('api_test.batch_menus.select_show_data',[tableData.length])}}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<template v-slot:default="{row}"> <template v-slot:default="{row}">
<show-more-btn :is-show="isSelect(row)" :buttons="buttons" :size="selection.length"/> <show-more-btn :is-show="isSelect(row)" :buttons="buttons" :size="selectDataCounts"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="num" label="ID" <el-table-column prop="num" label="ID"
@ -25,7 +40,6 @@
<ms-tag v-if="scope.row.level == 'P2'" type="success" effect="plain" content="P2"/> <ms-tag v-if="scope.row.level == 'P2'" type="success" effect="plain" content="P2"/>
<ms-tag v-if="scope.row.level == 'P3'" type="danger" effect="plain" content="P3"/> <ms-tag v-if="scope.row.level == 'P3'" type="danger" effect="plain" content="P3"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="tags" :label="$t('api_test.automation.tag')" width="200px"> <el-table-column prop="tags" :label="$t('api_test.automation.tag')" width="200px">
<template v-slot:default="scope"> <template v-slot:default="scope">
@ -43,8 +57,12 @@
<el-table-column prop="stepTotal" :label="$t('api_test.automation.step')" show-overflow-tooltip/> <el-table-column prop="stepTotal" :label="$t('api_test.automation.step')" show-overflow-tooltip/>
<el-table-column prop="lastResult" :label="$t('api_test.automation.last_result')"> <el-table-column prop="lastResult" :label="$t('api_test.automation.last_result')">
<template v-slot:default="{row}"> <template v-slot:default="{row}">
<el-link type="success" @click="showReport(row)" v-if="row.lastResult === 'Success'">{{ $t('api_test.automation.success') }}</el-link> <el-link type="success" @click="showReport(row)" v-if="row.lastResult === 'Success'">
<el-link type="danger" @click="showReport(row)" v-if="row.lastResult === 'Fail'">{{ $t('api_test.automation.fail') }}</el-link> {{ $t('api_test.automation.success') }}
</el-link>
<el-link type="danger" @click="showReport(row)" v-if="row.lastResult === 'Fail'">
{{ $t('api_test.automation.fail') }}
</el-link>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="passRate" :label="$t('api_test.automation.passing_rate')" <el-table-column prop="passRate" :label="$t('api_test.automation.passing_rate')"
@ -52,7 +70,7 @@
<el-table-column :label="$t('commons.operating')" width="200px" v-if="!referenced"> <el-table-column :label="$t('commons.operating')" width="200px" v-if="!referenced">
<template v-slot:default="{row}"> <template v-slot:default="{row}">
<div v-if="trashEnable"> <div v-if="trashEnable">
<el-button type="text" @click="reductionApi(row)" v-tester>{{$t('commons.reduction')}}</el-button> <el-button type="text" @click="reductionApi(row)" v-tester>{{ $t('commons.reduction') }}</el-button>
<el-button type="text" @click="remove(row)" v-tester>{{ $t('api_test.automation.remove') }}</el-button> <el-button type="text" @click="remove(row)" v-tester>{{ $t('api_test.automation.remove') }}</el-button>
</div> </div>
<div v-else> <div v-else>
@ -69,257 +87,313 @@
:total="total"/> :total="total"/>
<div> <div>
<!-- 执行结果 --> <!-- 执行结果 -->
<el-drawer :visible.sync="runVisible" :destroy-on-close="true" direction="ltr" :withHeader="true" :modal="false" size="90%"> <el-drawer :visible.sync="runVisible" :destroy-on-close="true" direction="ltr" :withHeader="true" :modal="false"
size="90%">
<ms-api-report-detail @refresh="search" :infoDb="infoDb" :report-id="reportId" :currentProjectId="projectId"/> <ms-api-report-detail @refresh="search" :infoDb="infoDb" :report-id="reportId" :currentProjectId="projectId"/>
</el-drawer> </el-drawer>
<!--测试计划--> <!--测试计划-->
<el-drawer :visible.sync="planVisible" :destroy-on-close="true" direction="ltr" :withHeader="false" :title="$t('test_track.plan_view.test_result')" :modal="false" size="90%"> <el-drawer :visible.sync="planVisible" :destroy-on-close="true" direction="ltr" :withHeader="false"
:title="$t('test_track.plan_view.test_result')" :modal="false" size="90%">
<ms-test-plan-list @addTestPlan="addTestPlan"/> <ms-test-plan-list @addTestPlan="addTestPlan"/>
</el-drawer> </el-drawer>
</div> </div>
</el-card> </el-card>
</div> </div>
</template> </template>
<script> <script>
import MsTableHeader from "@/business/components/common/components/MsTableHeader"; import MsTableHeader from "@/business/components/common/components/MsTableHeader";
import MsTablePagination from "@/business/components/common/pagination/TablePagination"; import MsTablePagination from "@/business/components/common/pagination/TablePagination";
import ShowMoreBtn from "@/business/components/track/case/components/ShowMoreBtn"; import ShowMoreBtn from "@/business/components/track/case/components/ShowMoreBtn";
import MsTag from "../../../common/components/MsTag"; import MsTag from "../../../common/components/MsTag";
import {getUUID, getCurrentProjectID} from "@/common/js/utils"; import {getUUID, getCurrentProjectID} from "@/common/js/utils";
import MsApiReportDetail from "../report/ApiReportDetail"; import MsApiReportDetail from "../report/ApiReportDetail";
import MsTableMoreBtn from "./TableMoreBtn"; import MsTableMoreBtn from "./TableMoreBtn";
import MsScenarioExtendButtons from "@/business/components/api/automation/scenario/ScenarioExtendBtns"; import MsScenarioExtendButtons from "@/business/components/api/automation/scenario/ScenarioExtendBtns";
import MsTestPlanList from "./testplan/TestPlanList"; import MsTestPlanList from "./testplan/TestPlanList";
export default { export default {
name: "MsApiScenarioList", name: "MsApiScenarioList",
components: {MsTablePagination, MsTableMoreBtn, ShowMoreBtn, MsTableHeader, MsTag, MsApiReportDetail, MsScenarioExtendButtons, MsTestPlanList}, components: {
props: { MsTablePagination,
referenced: { MsTableMoreBtn,
type: Boolean, ShowMoreBtn,
default: false, MsTableHeader,
}, MsTag,
selectNodeIds: Array, MsApiReportDetail,
trashEnable: { MsScenarioExtendButtons,
type: Boolean, MsTestPlanList
default: false, },
} props: {
referenced: {
type: Boolean,
default: false,
}, },
data() { selectNodeIds: Array,
return { trashEnable: {
loading: false, type: Boolean,
condition: {}, default: false,
currentScenario: {}, }
schedule: {}, },
selection: [], data() {
tableData: [], return {
currentPage: 1, loading: false,
pageSize: 10, condition: {},
total: 0, currentScenario: {},
reportId: "", schedule: {},
batchReportId: "", selection: [],
content: {}, tableData: [],
selectAll: false, currentPage: 1,
infoDb: false, pageSize: 10,
runVisible: false, total: 0,
planVisible: false, reportId: "",
projectId: "", batchReportId: "",
runData: [], content: {},
report: {}, infoDb: false,
buttons: [ runVisible: false,
{ planVisible: false,
name: this.$t('api_test.automation.batch_add_plan'), handleClick: this.handleBatchAddCase projectId: "",
}, { runData: [],
name: this.$t('api_test.automation.batch_execute'), handleClick: this.handleBatchExecute report: {},
} selectDataSize: 0,
], selectAll: false,
} buttons: [
}, {
created() { name: this.$t('api_test.automation.batch_add_plan'), handleClick: this.handleBatchAddCase
this.projectId = getCurrentProjectID(); }, {
name: this.$t('api_test.automation.batch_execute'), handleClick: this.handleBatchExecute
}
],
isSelectAllDate: false,
unSelection: [],
selectDataCounts: 0,
}
},
created() {
this.projectId = getCurrentProjectID();
this.search();
},
watch: {
selectNodeIds() {
this.search(); this.search();
}, },
watch: { trashEnable() {
selectNodeIds() { if (this.trashEnable) {
this.search(); this.search();
}, }
trashEnable() { },
if (this.trashEnable) { batchReportId() {
this.search(); this.loading = true;
} this.getReport();
}, }
batchReportId() { },
computed: {
isNotRunning() {
return "Running" !== this.report.status;
}
},
methods: {
search() {
this.condition.filters = ["Prepare", "Underway", "Completed"];
this.condition.moduleIds = this.selectNodeIds;
if (this.trashEnable) {
this.condition.filters = ["Trash"];
this.condition.moduleIds = [];
}
if (this.projectId != null) {
this.condition.projectId = this.projectId;
}
this.selection = [];
this.selectAll = false;
this.unSelection = [];
this.selectDataCounts = 0;
let url = "/api/automation/list/" + this.currentPage + "/" + this.pageSize;
if (this.condition.projectId) {
this.loading = true; this.loading = true;
this.getReport(); this.$post(url, this.condition, response => {
} let data = response.data;
}, this.total = data.itemCount;
computed: { this.tableData = data.listObject;
isNotRunning() { this.tableData.forEach(item => {
return "Running" !== this.report.status; if (item.tags && item.tags.length > 0) {
} item.tags = JSON.parse(item.tags);
}, }
methods: {
search() {
this.condition.filters = ["Prepare", "Underway", "Completed"];
this.condition.moduleIds = this.selectNodeIds;
if (this.trashEnable) {
this.condition.filters = ["Trash"];
this.condition.moduleIds = [];
}
if (this.projectId != null) {
this.condition.projectId = this.projectId;
}
this.selection = [];
let url = "/api/automation/list/" + this.currentPage + "/" + this.pageSize;
if (this.condition.projectId) {
this.loading = true;
this.$post(url, this.condition, response => {
let data = response.data;
this.total = data.itemCount;
this.tableData = data.listObject;
this.tableData.forEach(item => {
if (item.tags && item.tags.length > 0) {
item.tags = JSON.parse(item.tags);
}
});
this.loading = false;
}); });
} this.loading = false;
}, this.unSelection = data.listObject.map(s => s.id);
handleCommand(cmd) {
let table = this.$refs.scenarioTable;
switch (cmd) {
case "table":
this.selectAll = false;
table.toggleAllSelection();
break;
case "all":
this.selectAll = true;
break
}
},
handleBatchAddCase() {
this.planVisible = true;
},
addTestPlan(plans) {
let obj = {planIds: plans, scenarioIds: this.selection};
this.planVisible = false;
this.$post("/api/automation/scenario/plan", obj, response => {
this.$success(this.$t("commons.save_success"));
}); });
}, }
getReport() { },
if (this.batchReportId) { handleCommand(cmd) {
let url = "/api/scenario/report/get/" + this.batchReportId; let table = this.$refs.scenarioTable;
this.$get(url, response => { switch (cmd) {
this.report = response.data || {}; case "table":
if (response.data) { this.selectAll = false;
if (this.isNotRunning) { table.toggleAllSelection();
try { break;
this.content = JSON.parse(this.report.content); case "all":
} catch (e) { this.selectAll = true;
throw e; break
} }
this.loading = false; },
this.$success("批量执行成功,请到报告页面查看详情!"); handleBatchAddCase() {
} else { this.planVisible = true;
setTimeout(this.getReport, 2000) },
addTestPlan(plans) {
let obj = {planIds: plans, scenarioIds: this.selection};
obj.projectId = getCurrentProjectID();
obj.selectAllDate = this.isSelectAllDate;
obj.unSelectIds = this.unSelection;
obj = Object.assign(obj, this.condition);
this.planVisible = false;
this.$post("/api/automation/scenario/plan", obj, response => {
this.$success(this.$t("commons.save_success"));
});
},
getReport() {
if (this.batchReportId) {
let url = "/api/scenario/report/get/" + this.batchReportId;
this.$get(url, response => {
this.report = response.data || {};
if (response.data) {
if (this.isNotRunning) {
try {
this.content = JSON.parse(this.report.content);
} catch (e) {
throw e;
} }
} else {
this.loading = false; this.loading = false;
this.$error(this.$t('api_report.not_exist')); this.$success("批量执行成功,请到报告页面查看详情!");
} } else {
}); setTimeout(this.getReport, 2000)
}
},
handleBatchExecute() {
this.infoDb = false;
let url = "/api/automation/run/batch";
let run = {};
let scenarioIds = this.selection;
run.id = getUUID();
run.scenarioIds = scenarioIds;
run.projectId = getCurrentProjectID();
this.$post(url, run, response => {
let data = response.data;
this.runVisible = false;
this.batchReportId = run.id;
});
},
select(selection) {
this.selection = selection.map(s => s.id);
this.$emit('selection', selection);
},
isSelect(row) {
return this.selection.includes(row.id)
},
edit(row) {
this.$emit('edit', row);
},
reductionApi(row) {
row.scenarioDefinition = null;
row.tags = null;
let rows = [row];
this.$post("/api/automation/reduction", rows, response => {
this.$success(this.$t('commons.save_success'));
this.search();
})
},
execute(row) {
this.infoDb = false;
let url = "/api/automation/run";
let run = {};
let scenarioIds = [];
scenarioIds.push(row.id);
run.id = getUUID();
run.projectId = getCurrentProjectID();
run.scenarioIds = scenarioIds;
this.$post(url, run, response => {
let data = response.data;
this.runVisible = true;
this.reportId = run.id;
});
},
copy(row) {
row.copy = true;
this.$emit('edit', row);
},
showReport(row) {
this.runVisible = true;
this.infoDb = true;
this.reportId = row.reportId;
},
remove(row) {
if (this.trashEnable) {
this.$get('/api/automation/delete/' + row.id, () => {
this.$success(this.$t('commons.delete_success'));
this.search();
});
return;
}
this.$alert(this.$t('api_test.definition.request.delete_confirm') + ' ' + row.name + " ", '', {
confirmButtonText: this.$t('commons.confirm'),
callback: (action) => {
if (action === 'confirm') {
let ids = [row.id];
this.$post('/api/automation/removeToGc/', ids, () => {
this.$success(this.$t('commons.delete_success'));
this.search();
});
} }
} else {
this.loading = false;
this.$error(this.$t('api_report.not_exist'));
} }
}); });
}, }
} },
handleBatchExecute() {
this.infoDb = false;
let url = "/api/automation/run/batch";
let run = {};
let scenarioIds = this.selection;
run.id = getUUID();
run.scenarioIds = scenarioIds;
run.projectId = getCurrentProjectID();
run.selectAllDate = this.isSelectAllDate;
run.unSelectIds = this.unSelection;
run = Object.assign(run, this.condition);
this.$post(url, run, response => {
let data = response.data;
this.runVisible = false;
this.batchReportId = run.id;
});
},
select(selection) {
this.selection = selection.map(s => s.id);
//
this.selectRowsCount(this.selection)
this.$emit('selection', selection);
},
isSelect(row) {
return this.selection.includes(row.id)
},
edit(row) {
this.$emit('edit', row);
},
reductionApi(row) {
row.scenarioDefinition = null;
row.tags = null;
let rows = [row];
this.$post("/api/automation/reduction", rows, response => {
this.$success(this.$t('commons.save_success'));
this.search();
})
},
execute(row) {
this.infoDb = false;
let url = "/api/automation/run";
let run = {};
let scenarioIds = [];
scenarioIds.push(row.id);
run.id = getUUID();
run.projectId = getCurrentProjectID();
run.scenarioIds = scenarioIds;
this.$post(url, run, response => {
let data = response.data;
this.runVisible = true;
this.reportId = run.id;
});
},
copy(row) {
row.copy = true;
this.$emit('edit', row);
},
showReport(row) {
this.runVisible = true;
this.infoDb = true;
this.reportId = row.reportId;
},
//
isSelectDataAll(dataType) {
this.isSelectAllDate = dataType;
this.selectRowsCount(this.selection);
//
if (this.selection.length != this.tableData.length) {
this.$refs.scenarioTable.toggleAllSelection(true);
}
},
//
selectRowsCount(selection) {
let selectedIDs = selection;
let allIDs = this.tableData.map(s => s.id);
this.unSelection = allIDs.filter(function (val) {
return selectedIDs.indexOf(val) === -1
});
if (this.isSelectAllDate) {
this.selectDataCounts = this.total - this.unSelection.length;
} else {
this.selectDataCounts = this.selection.length;
}
},
remove(row) {
if (this.trashEnable) {
this.$get('/api/automation/delete/' + row.id, () => {
this.$success(this.$t('commons.delete_success'));
this.search();
});
return;
}
this.$alert(this.$t('api_test.definition.request.delete_confirm') + ' ' + row.name + " ", '', {
confirmButtonText: this.$t('commons.confirm'),
callback: (action) => {
if (action === 'confirm') {
let ids = [row.id];
this.$post('/api/automation/removeToGc/', ids, () => {
this.$success(this.$t('commons.delete_success'));
this.search();
});
}
}
});
},
} }
}
</script> </script>
<style scoped> <style scoped>
/deep/ .el-drawer__header { /deep/ .el-drawer__header {
margin-bottom: 0px; margin-bottom: 0px;
} }
</style> </style>

View File

@ -45,11 +45,6 @@
:label="$t('api_test.definition.api_path')" :label="$t('api_test.definition.api_path')"
show-overflow-tooltip/> show-overflow-tooltip/>
<el-table-column
prop="userName"
:label="$t('api_test.definition.api_principal')"
show-overflow-tooltip/>
<el-table-column width="160" :label="$t('api_test.definition.api_last_time')" prop="updateTime"> <el-table-column width="160" :label="$t('api_test.definition.api_last_time')" prop="updateTime">
<template v-slot:default="scope"> <template v-slot:default="scope">
<span>{{ scope.row.updateTime | timestampFormatDate }}</span> <span>{{ scope.row.updateTime | timestampFormatDate }}</span>
@ -156,6 +151,7 @@
default: false, default: false,
}, },
projectId: String, projectId: String,
planId: String,
isTestPlan: Boolean isTestPlan: Boolean
}, },
created: function () { created: function () {
@ -194,7 +190,12 @@
if (this.currentProtocol != null) { if (this.currentProtocol != null) {
this.condition.protocol = this.currentProtocol; this.condition.protocol = this.currentProtocol;
} }
this.result = this.$post("/api/definition/list/" + this.currentPage + "/" + this.pageSize, this.condition, response => { let url = '/api/definition/list/';
if (this.isTestPlan) {
url = '/api/definition/list/relevance/';
this.condition.planId = this.planId;
}
this.result = this.$post(url + this.currentPage + "/" + this.pageSize, this.condition, response => {
this.total = response.data.itemCount; this.total = response.data.itemCount;
this.tableData = response.data.listObject; this.tableData = response.data.listObject;
}); });

View File

@ -138,6 +138,7 @@
default: false, default: false,
}, },
projectId: String, projectId: String,
planId: String,
isTestPlan: Boolean isTestPlan: Boolean
}, },
created: function () { created: function () {
@ -174,7 +175,13 @@
if (this.currentProtocol != null) { if (this.currentProtocol != null) {
this.condition.protocol = this.currentProtocol; this.condition.protocol = this.currentProtocol;
} }
this.result = this.$post("/api/testcase/list/" + this.currentPage + "/" + this.pageSize, this.condition, response => { let url = '/api/testcase/list/';
if (this.isTestPlan) {
url = '/test/plan/api/case/relevance/list/';
this.condition.planId = this.planId;
}
this.result = this.$post(url + this.currentPage + "/" + this.pageSize, this.condition, response => {
this.total = response.data.itemCount; this.total = response.data.itemCount;
this.tableData = response.data.listObject; this.tableData = response.data.listObject;
}); });

View File

@ -20,11 +20,20 @@
<div> <div>
<el-select size="small" :placeholder="$t('api_test.definition.request.grade_info')" v-model="condition.priority" <el-select size="small" :placeholder="$t('api_test.definition.request.grade_info')" v-model="condition.priority"
:disabled="isCaseEdit" :disabled="isCaseEdit"
class="ms-api-header-select" @change="getApiTest" clearable style="margin-right: 20px"> class="ms-api-header-select" @change="getApiTest" clearable>
<el-option v-for="grd in priorities" :key="grd.id" :label="grd.name" :value="grd.id"/> <el-option v-for="grd in priorities" :key="grd.id" :label="grd.name" :value="grd.id"/>
</el-select> </el-select>
</div> </div>
</el-col> </el-col>
<el-col :span="3">
<div class="ms-api-header-select" style="margin-right: 20px">
<el-input size="small" :placeholder="$t('api_test.definition.request.select_case')"
:disabled="isCaseEdit"
v-model="condition.name" @blur="getApiTest" @keyup.enter.native="getApiTest" />
</div>
</el-col>
<el-col :span="4"> <el-col :span="4">
<div> <div>
<ms-environment-select <ms-environment-select
@ -33,13 +42,7 @@
@setEnvironment="setEnvironment"/> @setEnvironment="setEnvironment"/>
</div> </div>
</el-col> </el-col>
<el-col :span="3">
<div class="ms-api-header-select">
<el-input size="small" :placeholder="$t('api_test.definition.request.select_case')"
:disabled="isCaseEdit"
v-model="condition.name" @blur="getApiTest" @keyup.enter.native="getApiTest"/>
</div>
</el-col>
<el-col :span="2" v-if="!(isReadOnly || isCaseEdit)"> <el-col :span="2" v-if="!(isReadOnly || isCaseEdit)">
<el-dropdown size="small" split-button type="primary" class="ms-api-header-select" @click="addCase" <el-dropdown size="small" split-button type="primary" class="ms-api-header-select" @click="addCase"
@command="handleCommand" v-tester> @command="handleCommand" v-tester>
@ -56,17 +59,17 @@
<script> <script>
import ApiEnvironmentConfig from "../../../test/components/ApiEnvironmentConfig"; import ApiEnvironmentConfig from "../../../test/components/ApiEnvironmentConfig";
import {parseEnvironment} from "../../../test/model/EnvironmentModel"; import {parseEnvironment} from "../../../test/model/EnvironmentModel";
import MsTag from "../../../../common/components/MsTag"; import MsTag from "../../../../common/components/MsTag";
import MsEnvironmentSelect from "./MsEnvironmentSelect"; import MsEnvironmentSelect from "./MsEnvironmentSelect";
import {API_METHOD_COLOUR} from "../../model/JsonData"; import {API_METHOD_COLOUR} from "../../model/JsonData";
export default { export default {
name: "ApiCaseHeader", name: "ApiCaseHeader",
components: {MsEnvironmentSelect, MsTag, ApiEnvironmentConfig}, components: {MsEnvironmentSelect, MsTag, ApiEnvironmentConfig},
data() { data() {
return { return {
environments: [], environments: [],
environment: {}, environment: {},
methodColorMap: new Map(API_METHOD_COLOUR), methodColorMap: new Map(API_METHOD_COLOUR),
@ -171,7 +174,6 @@
font-size: 10px; font-size: 10px;
} }
.el-col { .el-col {
height: 32px; height: 32px;
line-height: 32px; line-height: 32px;

View File

@ -7,14 +7,28 @@
<el-input placeholder="搜索" @blur="search" class="search-input" size="small" @keyup.enter.native="search" v-model="condition.name"/> <el-input placeholder="搜索" @blur="search" class="search-input" size="small" @keyup.enter.native="search" v-model="condition.name"/>
<el-table v-loading="result.loading" <el-table v-loading="result.loading"
ref="apiDefinitionTable"
border border
:data="tableData" row-key="id" class="test-content adjust-table" :data="tableData" row-key="id" class="test-content adjust-table"
@select-all="handleSelectAll" @select-all="handleSelectAll"
@select="handleSelect" :height="screenHeight"> @select="handleSelect" :height="screenHeight">
<el-table-column type="selection"/> <el-table-column type="selection"/>
<el-table-column width="40" :resizable="false" align="center"> <el-table-column width="40" :resizable="false" align="center">
<el-dropdown slot="header" style="width: 14px">
<span class="el-dropdown-link" style="width: 14px">
<i class="el-icon-arrow-down el-icon--right" style="margin-left: 0px"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native.stop="isSelectDataAll(true)">
{{$t('api_test.batch_menus.select_all_data',[total])}}
</el-dropdown-item>
<el-dropdown-item @click.native.stop="isSelectDataAll(false)">
{{$t('api_test.batch_menus.select_show_data',[tableData.length])}}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<template v-slot:default="scope"> <template v-slot:default="scope">
<show-more-btn :is-show="scope.row.showMore && !isReadOnly" :buttons="buttons" :size="selectRows.size"/> <show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectDataCounts"/>
</template> </template>
</el-table-column> </el-table-column>
@ -157,7 +171,10 @@
pageSize: 10, pageSize: 10,
total: 0, total: 0,
screenHeight: document.documentElement.clientHeight - 330,//, screenHeight: document.documentElement.clientHeight - 330,//,
environmentId: undefined environmentId: undefined,
selectAll: false,
unSelection:[],
selectDataCounts:0,
} }
}, },
props: { props: {
@ -204,6 +221,11 @@
}, },
initTable() { initTable() {
this.selectRows = new Set(); this.selectRows = new Set();
this.selectAll = false;
this.unSelection = [];
this.selectDataCounts = 0;
this.condition.filters = ["Prepare", "Underway", "Completed"]; this.condition.filters = ["Prepare", "Underway", "Completed"];
this.condition.moduleIds = this.selectNodeIds; this.condition.moduleIds = this.selectNodeIds;
@ -220,6 +242,7 @@
this.result = this.$post("/api/definition/list/" + this.currentPage + "/" + this.pageSize, this.condition, response => { this.result = this.$post("/api/definition/list/" + this.currentPage + "/" + this.pageSize, this.condition, response => {
this.total = response.data.itemCount; this.total = response.data.itemCount;
this.tableData = response.data.listObject; this.tableData = response.data.listObject;
this.unSelection = response.data.listObject.map(s=>s.id);
}); });
} }
}, },
@ -247,6 +270,7 @@
this.$set(row, "showMore", true); this.$set(row, "showMore", true);
}) })
} }
this.selectRowsCount(this.selectRows)
}, },
handleSelectAll(selection) { handleSelectAll(selection) {
if (selection.length > 0) { if (selection.length > 0) {
@ -266,6 +290,7 @@
this.$set(row, "showMore", false); this.$set(row, "showMore", false);
}) })
} }
this.selectRowsCount(this.selectRows)
}, },
search() { search() {
this.initTable(); this.initTable();
@ -292,8 +317,14 @@
confirmButtonText: this.$t('commons.confirm'), confirmButtonText: this.$t('commons.confirm'),
callback: (action) => { callback: (action) => {
if (action === 'confirm') { if (action === 'confirm') {
let deleteParam = {};
let ids = Array.from(this.selectRows).map(row => row.id); let ids = Array.from(this.selectRows).map(row => row.id);
this.$post('/api/definition/deleteBatch/', ids, () => { deleteParam.dataIds = ids;
deleteParam.projectId = getCurrentProjectID();
deleteParam.selectAllDate = this.isSelectAllDate;
deleteParam.unSelectIds = this.unSelection;
deleteParam = Object.assign(deleteParam, this.condition);
this.$post('/api/definition/deleteBatchByParams/', deleteParam, () => {
this.selectRows.clear(); this.selectRows.clear();
this.initTable(); this.initTable();
this.$success(this.$t('commons.delete_success')); this.$success(this.$t('commons.delete_success'));
@ -307,7 +338,13 @@
callback: (action) => { callback: (action) => {
if (action === 'confirm') { if (action === 'confirm') {
let ids = Array.from(this.selectRows).map(row => row.id); let ids = Array.from(this.selectRows).map(row => row.id);
this.$post('/api/definition/removeToGc/', ids, () => { let deleteParam = {};
deleteParam.dataIds = ids;
deleteParam.projectId = getCurrentProjectID();
deleteParam.selectAllDate = this.isSelectAllDate;
deleteParam.unSelectIds = this.unSelection;
deleteParam = Object.assign(deleteParam, this.condition);
this.$post('/api/definition/removeToGcByParams/', deleteParam, () => {
this.selectRows.clear(); this.selectRows.clear();
this.initTable(); this.initTable();
this.$success(this.$t('commons.delete_success')); this.$success(this.$t('commons.delete_success'));
@ -327,7 +364,13 @@
let param = {}; let param = {};
param[form.type] = form.value; param[form.type] = form.value;
param.ids = ids; param.ids = ids;
this.$post('/api/definition/batch/edit', param, () => {
param.projectId = getCurrentProjectID();
param.selectAllDate = this.isSelectAllDate;
param.unSelectIds = this.unSelection;
param = Object.assign(param, this.condition);
this.$post('/api/definition/batch/editByParams', param, () => {
this.$success(this.$t('commons.save_success')); this.$success(this.$t('commons.save_success'));
this.initTable(); this.initTable();
}); });
@ -376,6 +419,31 @@
showExecResult(row) { showExecResult(row) {
this.$emit('showExecResult', row); this.$emit('showExecResult', row);
}, },
selectRowsCount(selection){
let selectedIDs = this.getIds(selection);
let allIDs = this.tableData.map(s=>s.id);
this.unSelection = allIDs.filter(function (val) {
return selectedIDs.indexOf(val) === -1
});
if(this.isSelectAllDate){
this.selectDataCounts =this.total - this.unSelection.length;
}else {
this.selectDataCounts =selection.size;
}
},
isSelectDataAll(dataType) {
this.isSelectAllDate = dataType;
this.selectRowsCount(this.selectRows)
//
if (this.selectRows.size != this.tableData.length) {
this.$refs.apiDefinitionTable.toggleAllSelection(true);
}
},
getIds(rowSets){
let rowArray = Array.from(rowSets)
let ids = rowArray.map(s=>s.id);
return ids;
}
}, },
} }
</script> </script>

View File

@ -66,7 +66,7 @@
</el-form-item> </el-form-item>
<el-form-item :label="$t('test_resource_pool.type')" prop="type"> <el-form-item :label="$t('test_resource_pool.type')" prop="type">
<el-select v-model="form.type" :placeholder="$t('test_resource_pool.select_pool_type')" <el-select v-model="form.type" :placeholder="$t('test_resource_pool.select_pool_type')"
@change="changeResourceType()"> @change="changeResourceType(form.type)">
<el-option key="NODE" value="NODE" label="Node">Node</el-option> <el-option key="NODE" value="NODE" label="Node">Node</el-option>
<el-option key="K8S" value="K8S" label="Kubernetes" v-xpack>Kubernetes</el-option> <el-option key="K8S" value="K8S" label="Kubernetes" v-xpack>Kubernetes</el-option>
</el-select> </el-select>
@ -89,6 +89,14 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row>
<el-col>
<el-form-item label="Namespace"
:rules="requiredRules">
<el-input v-model="item.namespace" type="text"/>
</el-form-item>
</el-col>
</el-row>
<el-row> <el-row>
<el-col> <el-col>
<el-form-item :label="$t('test_resource_pool.max_threads')" <el-form-item :label="$t('test_resource_pool.max_threads')"
@ -205,9 +213,20 @@ export default {
this.total = data.itemCount; this.total = data.itemCount;
}) })
}, },
changeResourceType() { changeResourceType(type) {
this.infoList = []; this.infoList = [];
this.infoList.push({}) let info = {};
if (type === 'NODE') {
info.ip = '';
info.port = '8082';
}
if (type === 'K8S') {
info.masterUrl = '';
info.token = '';
info.namespace = '';
}
info.maxConcurrency = 100;
this.infoList.push(info);
}, },
addResourceInfo() { addResourceInfo() {

View File

@ -23,6 +23,7 @@
:is-api-list-enable="isApiListEnable" :is-api-list-enable="isApiListEnable"
:project-id="projectId" :project-id="projectId"
:is-test-plan="true" :is-test-plan="true"
:plan-id="planId"
@isApiListEnableChange="isApiListEnableChange" @isApiListEnableChange="isApiListEnableChange"
ref="apiList"/> ref="apiList"/>
@ -33,6 +34,7 @@
:is-api-list-enable="isApiListEnable" :is-api-list-enable="isApiListEnable"
:project-id="projectId" :project-id="projectId"
:is-test-plan="true" :is-test-plan="true"
:plan-id="planId"
@isApiListEnableChange="isApiListEnableChange" @isApiListEnableChange="isApiListEnableChange"
ref="apiCaseList"/> ref="apiCaseList"/>
@ -81,8 +83,20 @@
}, },
methods: { methods: {
open() { open() {
this.init();
this.$refs.baseRelevance.open(); this.$refs.baseRelevance.open();
}, },
init() {
if (this.$refs.apiList) {
this.$refs.apiList.initTable();
}
if (this.$refs.apiCaseList) {
this.$refs.apiCaseList.initTable();
}
if (this.$refs.nodeTree) {
this.$refs.nodeTree.list();
}
},
setProject(projectId) { setProject(projectId) {
this.projectId = projectId; this.projectId = projectId;
}, },

View File

@ -162,18 +162,6 @@
this.moduleOptions = data; this.moduleOptions = data;
}, },
saveCaseRelevance() {
let url = '';
let selectIds = [];
let param = {};
param.planId = this.planId;
param.selectIds = selectIds;
this.result = this.$post(url, param, () => {
this.$success(this.$t('commons.save_success'));
this.refresh();
this.$refs.baseRelevance.close();
});
},
openTestCaseRelevanceDialog(model) { openTestCaseRelevanceDialog(model) {
if (model === 'scenario') { if (model === 'scenario') {
this.$refs.scenarioCaseRelevance.open(); this.$refs.scenarioCaseRelevance.open();
@ -194,4 +182,9 @@
margin: 5px 10px; margin: 5px 10px;
} }
/deep/ .run-button {
background-color: #409EFF;
border-color: #409EFF;
}
</style> </style>

View File

@ -81,8 +81,10 @@
<el-table-column v-if="!isReadOnly" :label="$t('commons.operating')" align="center"> <el-table-column v-if="!isReadOnly" :label="$t('commons.operating')" align="center">
<template v-slot:default="scope"> <template v-slot:default="scope">
<el-button type="text" @click="singleRun(scope.row)">{{$t('api_test.run')}}</el-button> <ms-table-operator-button class="run-button" :is-tester-permission="true" :tip="$t('api_test.run')" icon="el-icon-video-play"
<el-button type="text" @click="handleDelete(scope.row)" style="color: #F56C6C">{{$t('commons.delete')}}</el-button> @exec="singleRun(scope.row)" v-tester/>
<ms-table-operator-button :is-tester-permission="true" :tip="$t('test_track.plan_view.cancel_relevance')"
icon="el-icon-unlock" type="danger" @exec="handleDelete(scope.row)" v-tester/>
</template> </template>
</el-table-column> </el-table-column>
@ -334,7 +336,7 @@
this.selectRows.clear(); this.selectRows.clear();
this.initTable(); this.initTable();
this.$emit('refresh'); this.$emit('refresh');
this.$success(this.$t('commons.delete_success')); this.$success(this.$t('test_track.cancel_relevance_success'));
}); });
} }
} }
@ -414,7 +416,7 @@
}, },
handleDelete(apiCase) { handleDelete(apiCase) {
this.$get('/test/plan/api/case/delete/' + this.planId + '/' + apiCase.id, () => { this.$get('/test/plan/api/case/delete/' + this.planId + '/' + apiCase.id, () => {
this.$success(this.$t('commons.delete_success')); this.$success(this.$t('test_track.cancel_relevance_success'));
this.$emit('refresh'); this.$emit('refresh');
this.initTable(); this.initTable();
}); });

View File

@ -51,8 +51,10 @@
show-overflow-tooltip/> show-overflow-tooltip/>
<el-table-column :label="$t('commons.operating')" width="200px" v-if="!referenced"> <el-table-column :label="$t('commons.operating')" width="200px" v-if="!referenced">
<template v-slot:default="{row}"> <template v-slot:default="{row}">
<el-button type="text" @click="execute(row)">{{ $t('api_test.automation.execute') }}</el-button> <ms-table-operator-button class="run-button" :is-tester-permission="true" :tip="$t('api_test.run')" icon="el-icon-video-play"
<el-button type="text" @click="remove(row)">{{ $t('api_test.automation.remove') }}</el-button> @exec="execute(row)" v-tester/>
<ms-table-operator-button :is-tester-permission="true" :tip="$t('test_track.plan_view.cancel_relevance')"
icon="el-icon-unlock" type="danger" @exec="remove(row)" v-tester/>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -81,10 +83,12 @@
import MsTestPlanList from "../../../../../api/automation/scenario/testplan/TestPlanList"; import MsTestPlanList from "../../../../../api/automation/scenario/testplan/TestPlanList";
import TestPlanScenarioListHeader from "./TestPlanScenarioListHeader"; import TestPlanScenarioListHeader from "./TestPlanScenarioListHeader";
import {_handleSelect, _handleSelectAll} from "../../../../../../../common/js/tableUtils"; import {_handleSelect, _handleSelectAll} from "../../../../../../../common/js/tableUtils";
import MsTableOperatorButton from "../../../../../common/components/MsTableOperatorButton";
export default { export default {
name: "MsTestPlanApiScenarioList", name: "MsTestPlanApiScenarioList",
components: { components: {
MsTableOperatorButton,
TestPlanScenarioListHeader, TestPlanScenarioListHeader,
MsTablePagination, MsTableMoreBtn, ShowMoreBtn, MsTableHeader, MsTag, MsApiReportDetail, MsScenarioExtendButtons, MsTestPlanList}, MsTablePagination, MsTableMoreBtn, ShowMoreBtn, MsTableHeader, MsTag, MsApiReportDetail, MsScenarioExtendButtons, MsTestPlanList},
props: { props: {
@ -189,7 +193,7 @@
}, },
remove(row) { remove(row) {
this.$get('/test/plan/scenario/case/delete/' + this.planId + '/' + row.id, () => { this.$get('/test/plan/scenario/case/delete/' + this.planId + '/' + row.id, () => {
this.$success(this.$t('commons.delete_success')); this.$success(this.$t('test_track.cancel_relevance_success'));
this.$emit('refresh'); this.$emit('refresh');
this.search(); this.search();
}); });
@ -215,7 +219,7 @@
this.$post('/test/plan/scenario/case/batch/delete', param, () => { this.$post('/test/plan/scenario/case/batch/delete', param, () => {
this.selectRows.clear(); this.selectRows.clear();
this.search(); this.search();
this.$success(this.$t('commons.delete_success')); this.$success(this.$t('test_track.cancel_relevance_success'));
this.$emit('refresh'); this.$emit('refresh');
}); });
} }

View File

@ -364,12 +364,14 @@ export default {
for (let i = 0; i < this.tableData.length; i++) { for (let i = 0; i < this.tableData.length; i++) {
if (this.tableData[i]) { if (this.tableData[i]) {
this.$set(this.tableData[i], "issuesSize", 0); this.$set(this.tableData[i], "issuesSize", 0);
this.$get("/issues/get/" + this.tableData[i].caseId, response => { this.$get("/issues/get/" + this.tableData[i].caseId).then(response => {
let issues = response.data; let issues = response.data.data;
if (this.tableData[i]) { if (this.tableData[i]) {
this.$set(this.tableData[i], "issuesSize", issues.length); this.$set(this.tableData[i], "issuesSize", issues.length);
this.$set(this.tableData[i], "issuesContent", issues); this.$set(this.tableData[i], "issuesContent", issues);
} }
}).catch(() => {
this.$set(this.tableData[i], "issuesContent", [{title: '获取缺陷失败',description: '获取缺陷失败',platform: '获取缺陷失败' }]);
}) })
} }
} }

View File

@ -489,6 +489,10 @@ export default {
file_exist: "The name already exists in the project", file_exist: "The name already exists in the project",
upload_limit_size: "Upload file size cannot exceed 30MB!", upload_limit_size: "Upload file size cannot exceed 30MB!",
}, },
batch_menus:{
select_all_data: "Select all datas({0})",
select_show_data: "Select show datas({0})",
},
definition: { definition: {
api_title: "Api test", api_title: "Api test",
api_name: "Api name", api_name: "Api name",

View File

@ -487,6 +487,10 @@ export default {
file_exist: "该项目下已存在该jar包", file_exist: "该项目下已存在该jar包",
upload_limit_size: "上传文件大小不能超过 30MB!", upload_limit_size: "上传文件大小不能超过 30MB!",
}, },
batch_menus:{
select_all_data: "选择所有数据(共{0}条)",
select_show_data: "选择可见数据(共{0}条)",
},
definition: { definition: {
api_title: "接口列表", api_title: "接口列表",
api_name: "接口名称", api_name: "接口名称",

View File

@ -487,6 +487,10 @@ export default {
file_exist: "該項目下已存在該jar包", file_exist: "該項目下已存在該jar包",
upload_limit_size: "上傳文件大小不能超過 30MB!", upload_limit_size: "上傳文件大小不能超過 30MB!",
}, },
batch_menus:{
select_all_data: "選擇所有數據(共{0}條)",
select_show_data: "選擇可見數據(共{0}條)",
},
definition: { definition: {
api_title: "接口列表", api_title: "接口列表",
api_name: "接口名稱", api_name: "接口名稱",