# Conflicts:
#	backend/src/main/java/io/metersphere/xpack
This commit is contained in:
fit2-zhao 2021-01-05 09:34:02 +08:00
commit 4fb1a6319a
48 changed files with 352 additions and 109 deletions

View File

@ -85,15 +85,15 @@ public class ApiAutomationController {
} }
@PostMapping(value = "/run") @PostMapping(value = "/run")
public void run(@RequestBody RunScenarioRequest request) { public String run(@RequestBody RunScenarioRequest request) {
request.setExecuteType(ExecuteType.Completed.name()); request.setExecuteType(ExecuteType.Completed.name());
apiAutomationService.run(request); return apiAutomationService.run(request);
} }
@PostMapping(value = "/run/batch") @PostMapping(value = "/run/batch")
public void runBatch(@RequestBody RunScenarioRequest request) { public String runBatch(@RequestBody RunScenarioRequest request) {
request.setExecuteType(ExecuteType.Saved.name()); request.setExecuteType(ExecuteType.Saved.name());
apiAutomationService.run(request); return apiAutomationService.run(request);
} }

View File

@ -98,4 +98,9 @@ public class ApiTestCaseController {
public void testPlanRelevance(@RequestBody ApiCaseRelevanceRequest request) { public void testPlanRelevance(@RequestBody ApiCaseRelevanceRequest request) {
apiTestCaseService.relevanceByCase(request); apiTestCaseService.relevanceByCase(request);
} }
@PostMapping(value = "/jenkins/run")
public String jenkinsRun(@RequestBody RunCaseRequest request) {
return apiTestCaseService.run(request);
}
} }

View File

@ -0,0 +1,13 @@
package io.metersphere.api.dto.definition;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class RunCaseRequest {
private String caseId;
private String reportId;
}

View File

@ -275,6 +275,11 @@ public class Swagger2Parser extends ApiImportAbstractParser {
} else if (value instanceof RefProperty) { } else if (value instanceof RefProperty) {
RefProperty refProperty = (RefProperty) value; RefProperty refProperty = (RefProperty) value;
String simpleRef = refProperty.getSimpleRef(); String simpleRef = refProperty.getSimpleRef();
if (refSet.contains(simpleRef)) {
//避免嵌套死循环
jsonObject.put(key, new JSONArray());
return;
}
refSet.add(simpleRef); refSet.add(simpleRef);
Model model = definitions.get(simpleRef); Model model = definitions.get(simpleRef);
jsonObject.put(key, getBodyParameters(model.getProperties(), refSet)); jsonObject.put(key, getBodyParameters(model.getProperties(), refSet));

View File

@ -1,11 +1,17 @@
package io.metersphere.api.service; package io.metersphere.api.service;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.automation.ApiScenarioDTO; import com.fasterxml.jackson.core.type.TypeReference;
import io.metersphere.api.dto.automation.ApiScenarioRequest; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.metersphere.api.dto.ApiCaseBatchRequest;
import io.metersphere.api.dto.datacount.ApiDataCountResult; import io.metersphere.api.dto.datacount.ApiDataCountResult;
import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.definition.*;
import io.metersphere.api.dto.ApiCaseBatchRequest; import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.dto.definition.request.MsTestPlan;
import io.metersphere.api.dto.definition.request.MsThreadGroup;
import io.metersphere.api.dto.definition.request.ParameterConfig;
import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiDefinitionMapper; import io.metersphere.base.mapper.ApiDefinitionMapper;
import io.metersphere.base.mapper.ApiTestCaseMapper; import io.metersphere.base.mapper.ApiTestCaseMapper;
@ -14,6 +20,7 @@ import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ext.ExtApiTestCaseMapper; import io.metersphere.base.mapper.ext.ExtApiTestCaseMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanApiCaseMapper; import io.metersphere.base.mapper.ext.ExtTestPlanApiCaseMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper; import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.*; import io.metersphere.commons.utils.*;
import io.metersphere.i18n.Translator; import io.metersphere.i18n.Translator;
@ -21,11 +28,13 @@ import io.metersphere.service.FileService;
import io.metersphere.service.QuotaService; import io.metersphere.service.QuotaService;
import io.metersphere.service.UserService; import io.metersphere.service.UserService;
import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest; import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.jorphan.collections.HashTree;
import org.apache.jorphan.collections.ListedHashTree;
import org.aspectj.util.FileUtil; import org.aspectj.util.FileUtil;
import org.python.antlr.ast.Str;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
@ -57,6 +66,8 @@ public class ApiTestCaseService {
private ExtApiDefinitionExecResultMapper extApiDefinitionExecResultMapper; private ExtApiDefinitionExecResultMapper extApiDefinitionExecResultMapper;
@Resource @Resource
private ApiDefinitionMapper apiDefinitionMapper; private ApiDefinitionMapper apiDefinitionMapper;
@Resource
private JMeterService jMeterService;
private static final String BODY_FILE_DIR = "/opt/metersphere/data/body"; private static final String BODY_FILE_DIR = "/opt/metersphere/data/body";
@ -271,7 +282,7 @@ public class ApiTestCaseService {
} }
public void deleteBatch(List<String> ids) { public void deleteBatch(List<String> ids) {
for (String testId:ids) { for (String testId : ids) {
extTestPlanTestCaseMapper.deleteByTestCaseID(testId); extTestPlanTestCaseMapper.deleteByTestCaseID(testId);
} }
ApiTestCaseExample example = new ApiTestCaseExample(); ApiTestCaseExample example = new ApiTestCaseExample();
@ -331,10 +342,10 @@ public class ApiTestCaseService {
Date firstTime = startAndEndDateInWeek.get("firstTime"); Date firstTime = startAndEndDateInWeek.get("firstTime");
Date lastTime = startAndEndDateInWeek.get("lastTime"); Date lastTime = startAndEndDateInWeek.get("lastTime");
if(firstTime==null || lastTime == null){ if (firstTime == null || lastTime == null) {
return 0; return 0;
}else { } else {
return extApiTestCaseMapper.countByProjectIDAndCreateInThisWeek(projectId,firstTime.getTime(),lastTime.getTime()); return extApiTestCaseMapper.countByProjectIDAndCreateInThisWeek(projectId, firstTime.getTime(), lastTime.getTime());
} }
} }
@ -351,16 +362,16 @@ public class ApiTestCaseService {
public void deleteBatchByParam(ApiTestBatchRequest request) { public void deleteBatchByParam(ApiTestBatchRequest request) {
List<String> ids = request.getIds(); List<String> ids = request.getIds();
if(request.isSelectAllDate()){ if (request.isSelectAllDate()) {
ids = this.getAllApiCaseIdsByFontedSelect(request.getFilters(),request.getModuleIds(),request.getName(),request.getProjectId(),request.getProtocol(),request.getUnSelectIds(),request.getStatus()); ids = this.getAllApiCaseIdsByFontedSelect(request.getFilters(), request.getModuleIds(), request.getName(), request.getProjectId(), request.getProtocol(), request.getUnSelectIds(), request.getStatus());
} }
this.deleteBatch(ids); this.deleteBatch(ids);
} }
public void editApiBathByParam(ApiTestBatchRequest request) { public void editApiBathByParam(ApiTestBatchRequest request) {
List<String> ids = request.getIds(); List<String> ids = request.getIds();
if(request.isSelectAllDate()){ if (request.isSelectAllDate()) {
ids = this.getAllApiCaseIdsByFontedSelect(request.getFilters(),request.getModuleIds(),request.getName(),request.getProjectId(),request.getProtocol(),request.getUnSelectIds(),request.getStatus()); ids = this.getAllApiCaseIdsByFontedSelect(request.getFilters(), request.getModuleIds(), request.getName(), request.getProjectId(), request.getProtocol(), request.getUnSelectIds(), request.getStatus());
} }
request.cleanSelectParam(); request.cleanSelectParam();
ApiTestCaseExample apiDefinitionExample = new ApiTestCaseExample(); ApiTestCaseExample apiDefinitionExample = new ApiTestCaseExample();
@ -371,7 +382,7 @@ public class ApiTestCaseService {
apiTestCaseMapper.updateByExampleSelective(apiDefinitionWithBLOBs, apiDefinitionExample); apiTestCaseMapper.updateByExampleSelective(apiDefinitionWithBLOBs, apiDefinitionExample);
} }
private List<String> getAllApiCaseIdsByFontedSelect(Map<String, List<String>> filters,List<String>moduleIds, String name, String projectId, String protocol,List<String> unSelectIds,String status) { private List<String> getAllApiCaseIdsByFontedSelect(Map<String, List<String>> filters, List<String> moduleIds, String name, String projectId, String protocol, List<String> unSelectIds, String status) {
ApiTestCaseRequest selectRequest = new ApiTestCaseRequest(); ApiTestCaseRequest selectRequest = new ApiTestCaseRequest();
selectRequest.setFilters(filters); selectRequest.setFilters(filters);
selectRequest.setModuleIds(moduleIds); selectRequest.setModuleIds(moduleIds);
@ -383,6 +394,44 @@ public class ApiTestCaseService {
List<ApiTestCaseResult> list = extApiTestCaseMapper.list(selectRequest); List<ApiTestCaseResult> list = extApiTestCaseMapper.list(selectRequest);
List<String> allIds = list.stream().map(ApiTestCaseResult::getId).collect(Collectors.toList()); List<String> allIds = list.stream().map(ApiTestCaseResult::getId).collect(Collectors.toList());
List<String> ids = allIds.stream().filter(id -> !unSelectIds.contains(id)).collect(Collectors.toList()); List<String> ids = allIds.stream().filter(id -> !unSelectIds.contains(id)).collect(Collectors.toList());
return ids; return ids;
} }
public String run(RunCaseRequest request) {
ApiTestCaseWithBLOBs testCaseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(request.getCaseId());
// 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取
if (testCaseWithBLOBs != null && StringUtils.isNotEmpty(testCaseWithBLOBs.getRequest())) {
try {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MsTestElement element = mapper.readValue(testCaseWithBLOBs.getRequest(), new TypeReference<MsTestElement>() {
});
// 测试计划
MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>());
HashTree jmeterHashTree = new ListedHashTree();
// 线程组
MsThreadGroup group = new MsThreadGroup();
group.setLabel(testCaseWithBLOBs.getName());
group.setName(testCaseWithBLOBs.getId());
LinkedList<MsTestElement> hashTrees = new LinkedList<>();
hashTrees.add(element);
group.setHashTree(hashTrees);
testPlan.getHashTree().add(group);
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), new ParameterConfig());
String runMode = ApiRunMode.DELIMIT.name();
// 调用执行方法
jMeterService.runDefinition(request.getReportId(), jmeterHashTree, request.getReportId(), runMode);
} catch (Exception ex) {
LogUtil.error(ex.getMessage());
}
}
return request.getReportId();
}
} }

View File

@ -297,20 +297,9 @@
</select> </select>
<select id="listRelevance" resultType="io.metersphere.api.dto.definition.ApiDefinitionResult"> <select id="listRelevance" resultType="io.metersphere.api.dto.definition.ApiDefinitionResult">
select api_definition.id, api_definition.project_id, api_definition.num, select
api_definition.name,api_definition.protocol,api_definition.path,api_definition.module_id,api_definition.module_path,api_definition.method, <include refid="io.metersphere.base.mapper.ApiDefinitionMapper.Base_Column_List"/>
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 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> <where>
<if test="request.combine != null"> <if test="request.combine != null">
<include refid="combine"> <include refid="combine">
@ -346,6 +335,17 @@
#{value} #{value}
</foreach> </foreach>
</if> </if>
and exists (
select id
from api_test_case c
where 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> </where>
<if test="request.orders != null and request.orders.size() > 0"> <if test="request.orders != null and request.orders.size() > 0">
order by order by

View File

@ -333,6 +333,13 @@
and project_id= #{request.projectId} and project_id= #{request.projectId}
</if> </if>
</where> </where>
UNION ALL
select id,name,status,project_id,"scenario" as type from api_scenario
<where>
<if test="request.projectId!=null">
and project_id= #{request.projectId}
</if>
</where>
</select> </select>
<select id="listByTestCaseIds" resultType="io.metersphere.track.dto.TestCaseDTO"> <select id="listByTestCaseIds" resultType="io.metersphere.track.dto.TestCaseDTO">
select test_case.*,api_test.name as apiName,load_test.name AS performName from test_case left join api_test on select test_case.*,api_test.name as apiName,load_test.name AS performName from test_case left join api_test on

View File

@ -15,4 +15,6 @@ public interface ExtTestPlanApiCaseMapper {
List<String> getExecResultByPlanId(String planId); List<String> getExecResultByPlanId(String planId);
List<String> getIdsByPlanId(String planId); List<String> getIdsByPlanId(String planId);
List<String> getNotRelevanceCaseIds(@Param("planId")String planId, @Param("relevanceProjectIds")List<String> relevanceProjectIds);
} }

View File

@ -90,17 +90,31 @@
</foreach> </foreach>
</if> </if>
</select> </select>
<select id="getExecResultByPlanId" resultType="java.lang.String"> <select id="getExecResultByPlanId" resultType="java.lang.String">
select status select status
from from
test_plan_api_case test_plan_api_case
where test_plan_id = #{planId} where test_plan_id = #{planId}
</select> </select>
<select id="getIdsByPlanId" resultType="java.lang.String"> <select id="getIdsByPlanId" resultType="java.lang.String">
select id from select id
from test_plan_api_case from test_plan_api_case
where id = #{planId} where id = #{planId}
</select> </select>
<select id="getNotRelevanceCaseIds" resultType="java.lang.String">
select t.id
from test_plan_api_case t
inner join api_test_case c
on c.id = t.api_case_id
<if test="relevanceProjectIds != null and relevanceProjectIds.size() > 0">
and c.project_id not in
<foreach collection="relevanceProjectIds" item="projectId" separator="," open="(" close=")">
#{projectId}
</foreach>
</if>
where t.test_plan_id = #{planId}
</select>
</mapper> </mapper>

View File

@ -21,4 +21,6 @@ public interface ExtTestPlanScenarioCaseMapper {
List<String> getExecResultByPlanId(String planId); List<String> getExecResultByPlanId(String planId);
List<String> getIdsByPlanId(String planId); List<String> getIdsByPlanId(String planId);
List<String> getNotRelevanceCaseIds(String planId, List<String> relevanceProjectIds);
} }

View File

@ -92,4 +92,18 @@
where test_plan_id = #{planId} where test_plan_id = #{planId}
</select> </select>
<select id="getNotRelevanceCaseIds" resultType="java.lang.String">
select t.id
from test_plan_api_scenario t
inner join api_scenario c
on c.id = t.api_scenario_id
<if test="relevanceProjectIds != null and relevanceProjectIds.size() > 0">
and c.project_id not in
<foreach collection="relevanceProjectIds" item="projectId" separator="," open="(" close=")">
#{projectId}
</foreach>
</if>
where t.test_plan_id = #{planId}
</select>
</mapper> </mapper>

View File

@ -15,6 +15,8 @@ public interface ExtTestPlanTestCaseMapper {
List<TestPlanCaseDTO> list(@Param("request") QueryTestPlanCaseRequest request); List<TestPlanCaseDTO> list(@Param("request") QueryTestPlanCaseRequest request);
List<TestPlanCaseDTO> listByPlanId(@Param("request") QueryTestPlanCaseRequest request);
List<TestPlanCaseDTO> listByNode(@Param("request") QueryTestPlanCaseRequest request); List<TestPlanCaseDTO> listByNode(@Param("request") QueryTestPlanCaseRequest request);
List<TestPlanCaseDTO> listByNodes(@Param("request") QueryTestPlanCaseRequest request); List<TestPlanCaseDTO> listByNodes(@Param("request") QueryTestPlanCaseRequest request);

View File

@ -334,6 +334,34 @@
test_plan_test_case test_plan_test_case
where plan_id = #{planId} where plan_id = #{planId}
</select> </select>
<select id="listByPlanId" resultType="io.metersphere.track.dto.TestPlanCaseDTO">
SELECT test_plan_api_case.api_case_id as id,"definition" as type,api_test_case.name,test_plan_api_case.status
from test_plan_api_case left join api_test_case on test_plan_api_case.api_case_id=api_test_case.id
<where>
<if test="request.planId != null">
and test_plan_api_case.test_plan_id = #{request.planId}
</if>
</where>
UNION ALL
SELECT test_plan_api_scenario.api_scenario_id as id,"scenario" as type,api_scenario.name,test_plan_api_scenario.status
from test_plan_api_scenario left join api_scenario on test_plan_api_scenario.api_scenario_id=api_scenario.id
<where>
<if test="request.planId != null">
and test_plan_api_scenario.test_plan_id = #{request.planId}
</if>
</where>
UNION ALL
SELECT test_case.test_id as id,test_case.type as type,test_case.name,test_plan_test_case.status
from test_plan_test_case left join test_case on test_plan_test_case.case_id =test_case.id
<where>
<if test="request.planId != null">
and test_plan_test_case.plan_id = #{request.planId}
</if>
<if test="request.method != null">
and test_case.method = #{request.method}
</if>
</where>
</select>
<update id="updateTestCaseStates" parameterType="java.lang.String"> <update id="updateTestCaseStates" parameterType="java.lang.String">
update test_plan_test_case update test_plan_test_case

View File

@ -1,5 +1,5 @@
package io.metersphere.commons.constants; package io.metersphere.commons.constants;
public enum ApiRunMode { public enum ApiRunMode {
RUN, DEBUG,DELIMIT,SCENARIO, API_PLAN, SCENARIO_PLAN RUN, DEBUG,DELIMIT,SCENARIO, API_PLAN, SCENARIO_PLAN,API
} }

View File

@ -57,7 +57,7 @@ public class TestCaseController {
return testCaseService.listTestCase(request); return testCaseService.listTestCase(request);
} }
/*jenkins项目下所有接口和性能测试用例*/
@GetMapping("/list/method/{projectId}") @GetMapping("/list/method/{projectId}")
public List<TestCaseDTO> listByMethod(@PathVariable String projectId) { public List<TestCaseDTO> listByMethod(@PathVariable String projectId) {
QueryTestCaseRequest request = new QueryTestCaseRequest(); QueryTestCaseRequest request = new QueryTestCaseRequest();

View File

@ -30,13 +30,13 @@ public class TestPlanTestCaseController {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true); Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, testPlanTestCaseService.list(request)); return PageUtils.setPageInfo(page, testPlanTestCaseService.list(request));
} }
/*jenkins测试计划下全部用例*/
@GetMapping("/list/{planId}") @GetMapping("/list/{planId}")
public List<TestPlanCaseDTO> getTestPlanCaseByPlanId(@PathVariable String planId) { public List<TestPlanCaseDTO> getTestPlanCaseByPlanId(@PathVariable String planId) {
QueryTestPlanCaseRequest request = new QueryTestPlanCaseRequest(); QueryTestPlanCaseRequest request = new QueryTestPlanCaseRequest();
request.setPlanId(planId); request.setPlanId(planId);
request.setMethod("auto"); request.setMethod("auto");
return testPlanTestCaseService.list(request); return testPlanTestCaseService.listByPlanId(request);
} }
@GetMapping("/list/node/{planId}/{nodePaths}") @GetMapping("/list/node/{planId}/{nodePaths}")

View File

@ -77,6 +77,9 @@ public class TestPlanApiCaseService {
} }
public void deleteApiCaseBath(TestPlanApiCaseBatchRequest request) { public void deleteApiCaseBath(TestPlanApiCaseBatchRequest request) {
if (CollectionUtils.isEmpty(request.getIds())) {
return;
}
apiDefinitionExecResultService.deleteByResourceIds(request.getIds()); apiDefinitionExecResultService.deleteByResourceIds(request.getIds());
TestPlanApiCaseExample example = new TestPlanApiCaseExample(); TestPlanApiCaseExample example = new TestPlanApiCaseExample();
example.createCriteria() example.createCriteria()
@ -97,4 +100,11 @@ public class TestPlanApiCaseService {
apiCase.setStatus(status); apiCase.setStatus(status);
testPlanApiCaseMapper.updateByPrimaryKeySelective(apiCase); testPlanApiCaseMapper.updateByPrimaryKeySelective(apiCase);
} }
public void deleteByRelevanceProjectIds(String planId, List<String> relevanceProjectIds) {
TestPlanApiCaseBatchRequest request = new TestPlanApiCaseBatchRequest();
request.setPlanId(planId);
request.setIds(extTestPlanApiCaseMapper.getNotRelevanceCaseIds(planId, relevanceProjectIds));
deleteApiCaseBath(request);
}
} }

View File

@ -73,6 +73,9 @@ public class TestPlanScenarioCaseService {
} }
public void deleteApiCaseBath(TestPlanApiCaseBatchRequest request) { public void deleteApiCaseBath(TestPlanApiCaseBatchRequest request) {
if (CollectionUtils.isEmpty(request.getIds())) {
return;
}
TestPlanApiScenarioExample example = new TestPlanApiScenarioExample(); TestPlanApiScenarioExample example = new TestPlanApiScenarioExample();
example.createCriteria() example.createCriteria()
.andIdIn(request.getIds()); .andIdIn(request.getIds());
@ -110,4 +113,11 @@ public class TestPlanScenarioCaseService {
request.setIds(ids); request.setIds(ids);
deleteApiCaseBath(request); deleteApiCaseBath(request);
} }
public void deleteByRelevanceProjectIds(String planId, List<String> relevanceProjectIds) {
TestPlanApiCaseBatchRequest request = new TestPlanApiCaseBatchRequest();
request.setIds(extTestPlanScenarioCaseMapper.getNotRelevanceCaseIds(planId, relevanceProjectIds));
request.setPlanId(planId);
deleteApiCaseBath(request);
}
} }

View File

@ -10,7 +10,6 @@ import io.metersphere.api.dto.definition.ApiTestCaseRequest;
import io.metersphere.api.dto.definition.TestPlanApiCaseDTO; import io.metersphere.api.dto.definition.TestPlanApiCaseDTO;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*; import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.ExtProjectMapper;
import io.metersphere.base.mapper.ext.ExtTestCaseMapper; import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanMapper; import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper; import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
@ -27,7 +26,6 @@ import io.metersphere.notice.service.NoticeSendService;
import io.metersphere.service.SystemParameterService; import io.metersphere.service.SystemParameterService;
import io.metersphere.track.Factory.ReportComponentFactory; import io.metersphere.track.Factory.ReportComponentFactory;
import io.metersphere.track.domain.ReportComponent; import io.metersphere.track.domain.ReportComponent;
import io.metersphere.track.dto.TestCaseReportMetricDTO; import io.metersphere.track.dto.TestCaseReportMetricDTO;
import io.metersphere.track.dto.TestPlanCaseDTO; import io.metersphere.track.dto.TestPlanCaseDTO;
import io.metersphere.track.dto.TestPlanDTO; import io.metersphere.track.dto.TestPlanDTO;
@ -69,8 +67,6 @@ public class TestPlanService {
@Resource @Resource
TestPlanTestCaseService testPlanTestCaseService; TestPlanTestCaseService testPlanTestCaseService;
@Resource @Resource
ExtProjectMapper extProjectMapper;
@Resource
TestCaseReportMapper testCaseReportMapper; TestCaseReportMapper testCaseReportMapper;
@Resource @Resource
TestPlanProjectMapper testPlanProjectMapper; TestPlanProjectMapper testPlanProjectMapper;
@ -229,6 +225,14 @@ public class TestPlanService {
criteria.andCaseIdNotIn(caseIds); criteria.andCaseIdNotIn(caseIds);
} }
testPlanTestCaseMapper.deleteByExample(testPlanTestCaseExample); testPlanTestCaseMapper.deleteByExample(testPlanTestCaseExample);
List<String> relevanceProjectIds = new ArrayList<>();
relevanceProjectIds.add(testPlan.getProjectId());
if (!CollectionUtils.isEmpty(testPlan.getProjectIds())) {
relevanceProjectIds.addAll(testPlan.getProjectIds());
}
testPlanApiCaseService.deleteByRelevanceProjectIds(testPlan.getId(), relevanceProjectIds);
testPlanScenarioCaseService.deleteByRelevanceProjectIds(testPlan.getId(), relevanceProjectIds);
} }
} }

View File

@ -55,6 +55,11 @@ public class TestPlanTestCaseService {
}); });
return list; return list;
} }
public List<TestPlanCaseDTO> listByPlanId(QueryTestPlanCaseRequest request) {
List<TestPlanCaseDTO> list = extTestPlanTestCaseMapper.listByPlanId(request);
return list;
}
public List<TestPlanCaseDTO> listByNode(QueryTestPlanCaseRequest request) { public List<TestPlanCaseDTO> listByNode(QueryTestPlanCaseRequest request) {
List<TestPlanCaseDTO> list = extTestPlanTestCaseMapper.listByNode(request); List<TestPlanCaseDTO> list = extTestPlanTestCaseMapper.listByNode(request);

View File

@ -108,7 +108,7 @@ export default {
tableData: [], tableData: [],
multipleSelection: [], multipleSelection: [],
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
loading: false, loading: false,
currentProjectId: "", currentProjectId: "",

View File

@ -56,10 +56,10 @@
</el-input> </el-input>
</div> </div>
<p class="tip">{{$t('api_test.definition.request.req_param')}} </p> <p class="tip">{{$t('api_test.definition.request.req_param')}} </p>
<ms-api-request-form :referenced="true" :headers="request.headers " :request="request" v-if="request.protocol==='HTTP'"/> <ms-api-request-form :referenced="true" :headers="request.headers " :request="request" v-if="request.protocol==='HTTP' || request.type==='HTTPSamplerProxy'"/>
<ms-tcp-basis-parameters :request="request" v-if="request.protocol==='TCP'"/> <ms-tcp-basis-parameters :request="request" v-if="request.protocol==='TCP'|| request.type==='TCPSampler'"/>
<ms-sql-basis-parameters :request="request" v-if="request.protocol==='SQL'"/> <ms-sql-basis-parameters :request="request" v-if="request.protocol==='SQL'|| request.type==='JDBCSampler'"/>
<ms-dubbo-basis-parameters :request="request" v-if="request.protocol==='DUBBO' || request.protocol==='dubbo://'"/> <ms-dubbo-basis-parameters :request="request" v-if="request.protocol==='DUBBO' || request.protocol==='dubbo://'|| request.type==='DubboSampler'"/>
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p> <p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
<ms-request-result-tail :response="request.requestResult" ref="runResult"/> <ms-request-result-tail :response="request.requestResult" ref="runResult"/>

View File

@ -623,12 +623,19 @@
this.$refs.tag.open(); this.$refs.tag.open();
}, },
remove(row, node) { remove(row, node) {
const parent = node.parent this.$alert(this.$t('api_test.definition.request.delete_confirm') + ' ' + row.name + " ", '', {
const hashTree = parent.data.hashTree || parent.data; confirmButtonText: this.$t('commons.confirm'),
const index = hashTree.findIndex(d => d.resourceId != undefined && row.resourceId != undefined && d.resourceId === row.resourceId) callback: (action) => {
hashTree.splice(index, 1); if (action === 'confirm') {
this.sort(); const parent = node.parent
this.reload(); const hashTree = parent.data.hashTree || parent.data;
const index = hashTree.findIndex(d => d.resourceId != undefined && row.resourceId != undefined && d.resourceId === row.resourceId)
hashTree.splice(index, 1);
this.sort();
this.reload();
}
}
});
} }
, ,
copyRow(row, node) { copyRow(row, node) {

View File

@ -78,7 +78,7 @@
}, },
open() { open() {
this.dialogVisible = true; this.dialogVisible = true;
this.size = this.$parent.selectRows.size; this.size = this.$parent.selectDataCounts;
listenGoBack(this.handleClose); listenGoBack(this.handleClose);
}, },
handleClose() { handleClose() {

View File

@ -140,10 +140,18 @@
methods: { methods: {
deleteCase(index, row) { deleteCase(index, row) {
this.$get('/api/testcase/delete/' + row.id, () => { this.$alert(this.$t('api_test.definition.request.delete_confirm') + ' ' + row.name + " ", '', {
this.$success(this.$t('commons.delete_success')); confirmButtonText: this.$t('commons.confirm'),
this.$emit('refresh'); callback: (action) => {
if (action === 'confirm') {
this.$get('/api/testcase/delete/' + row.id, () => {
this.$success(this.$t('commons.delete_success'));
this.$emit('refresh');
});
}
}
}); });
}, },
singleRun(data) { singleRun(data) {
this.$emit('singleRun', data); this.$emit('singleRun', data);

View File

@ -9,24 +9,18 @@
<el-table v-loading="result.loading" <el-table v-loading="result.loading"
ref="apiDefinitionTable" ref="apiDefinitionTable"
border border
:data="tableData" row-key="id" class="test-content adjust-table" :data="tableData" row-key="id" class="test-content adjust-table ms-select-all"
@select-all="handleSelectAll" @select-all="handleSelectAll"
@select="handleSelect" :height="screenHeight"> @select="handleSelect" :height="screenHeight">
<el-table-column type="selection"/> <el-table-column width="50" type="selection"/>
<el-table-column width="40" :resizable="false" align="center">
<el-dropdown slot="header" style="width: 14px"> <ms-table-select-all
<span class="el-dropdown-link" style="width: 14px"> :page-size="pageSize"
<i class="el-icon-arrow-down el-icon--right" style="margin-left: 0px"></i> :total="total"
</span> @selectPageAll="isSelectDataAll(false)"
<el-dropdown-menu slot="dropdown"> @selectAll="isSelectDataAll(true)"/>
<el-dropdown-item @click.native.stop="isSelectDataAll(true)">
{{$t('api_test.batch_menus.select_all_data',[total])}} <el-table-column width="30" :resizable="false" align="center">
</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" :buttons="buttons" :size="selectDataCounts"/> <show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectDataCounts"/>
</template> </template>
@ -126,10 +120,12 @@
import {getCurrentProjectID} from "@/common/js/utils"; import {getCurrentProjectID} from "@/common/js/utils";
import {WORKSPACE_ID} from '../../../../../../common/js/constants'; import {WORKSPACE_ID} from '../../../../../../common/js/constants';
import ApiListContainer from "./ApiListContainer"; import ApiListContainer from "./ApiListContainer";
import MsTableSelectAll from "../../../../common/components/table/MsTableSelectAll";
export default { export default {
name: "ApiList", name: "ApiList",
components: { components: {
MsTableSelectAll,
ApiListContainer, ApiListContainer,
MsTableButton, MsTableButton,
MsTableOperatorButton, MsTableOperatorButton,
@ -466,7 +462,6 @@
.search-input { .search-input {
float: right; float: right;
width: 300px; width: 300px;
/*margin-bottom: 20px;*/
margin-right: 20px; margin-right: 20px;
} }

View File

@ -97,7 +97,6 @@ export default {
methods: { methods: {
registerEvents() { registerEvents() {
ApiEvent.$on(LIST_CHANGE, () => { ApiEvent.$on(LIST_CHANGE, () => {
// // todo refs
this.$refs.testRecent.recent(); this.$refs.testRecent.recent();
this.$refs.reportRecent.recent(); this.$refs.reportRecent.recent();
}); });
@ -111,6 +110,9 @@ export default {
}, },
mounted() { mounted() {
this.registerEvents(); this.registerEvents();
},
beforeDestroy() {
ApiEvent.$off(LIST_CHANGE);
} }
} }

View File

@ -85,7 +85,7 @@ export default {
tableData: [], tableData: [],
multipleSelection: [], multipleSelection: [],
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
loading: false, loading: false,
statusFilters: [ statusFilters: [

View File

@ -45,7 +45,7 @@ export default {
tableData: [], tableData: [],
loading: false, loading: false,
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
} }
}, },

View File

@ -90,7 +90,7 @@
tableData: [], tableData: [],
multipleSelection: [], multipleSelection: [],
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
loading: false, loading: false,
selectIds: new Set(), selectIds: new Set(),

View File

@ -63,7 +63,7 @@ export default {
}, },
tableData: [], tableData: [],
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
selection: false, selection: false,
environmentMap: new Map() environmentMap: new Map()

View File

@ -0,0 +1,28 @@
<template>
<el-table-column width="1" :resizable="false" align="center">
<el-dropdown slot="header">
<span class="el-dropdown-link">
<i class="el-icon-arrow-down"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native.stop="$emit('selectAll')">
{{$t('api_test.batch_menus.select_all_data',[total])}}
</el-dropdown-item>
<el-dropdown-item @click.native.stop="$emit('selectPageAll')">
{{$t('api_test.batch_menus.select_show_data',[pageSize])}}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-table-column>
</template>
<script>
export default {
name: "MsTableSelectAll",
props: ['total', 'pageSize']
}
</script>
<style scoped>
</style>

View File

@ -84,7 +84,6 @@ export default {
methods: { methods: {
registerEvents() { registerEvents() {
PerformanceEvent.$on(LIST_CHANGE, () => { PerformanceEvent.$on(LIST_CHANGE, () => {
// // todo refs
this.$refs.testRecent.recent(); this.$refs.testRecent.recent();
this.$refs.reportRecent.recent(); this.$refs.reportRecent.recent();
}); });
@ -92,6 +91,9 @@ export default {
}, },
mounted() { mounted() {
this.registerEvents(); this.registerEvents();
},
beforeDestroy() {
PerformanceEvent.$off(LIST_CHANGE);
} }
} }

View File

@ -128,7 +128,7 @@ export default {
tableData: [], tableData: [],
multipleSelection: [], multipleSelection: [],
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
loading: false, loading: false,
testId: null, testId: null,

View File

@ -108,7 +108,7 @@ export default {
tableData: [], tableData: [],
multipleSelection: [], multipleSelection: [],
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
loading: false, loading: false,
testId: null, testId: null,

View File

@ -143,7 +143,7 @@
}, },
multipleSelection: [], multipleSelection: [],
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
options: [], options: [],
loading: false, loading: false,

View File

@ -458,10 +458,10 @@
items: [], items: [],
userList: [], userList: [],
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
dialogCurrentPage: 1, dialogCurrentPage: 1,
dialogPageSize: 5, dialogPageSize: 10,
dialogTotal: 0, dialogTotal: 0,
memberLineData: [], memberLineData: [],
memberForm: {}, memberForm: {},

View File

@ -120,7 +120,7 @@ export default {
zentao: false, zentao: false,
form: {}, form: {},
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
rules: { rules: {
name: [ name: [

View File

@ -218,10 +218,10 @@ export default {
dialogOrgMemberUpdateVisible: false, dialogOrgMemberUpdateVisible: false,
multipleSelection: [], multipleSelection: [],
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
dialogCurrentPage: 1, dialogCurrentPage: 1,
dialogPageSize: 5, dialogPageSize: 10,
dialogTotal: 0, dialogTotal: 0,
currentRow: {}, currentRow: {},
condition: {}, condition: {},

View File

@ -487,10 +487,10 @@
dialogCondition: {}, dialogCondition: {},
items: [], items: [],
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
dialogCurrentPage: 1, dialogCurrentPage: 1,
dialogPageSize: 5, dialogPageSize: 10,
dialogTotal: 0, dialogTotal: 0,
memberLineData: [], memberLineData: [],
memberForm: {}, memberForm: {},

View File

@ -177,7 +177,7 @@ export default {
condition: {}, condition: {},
items: [], items: [],
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
form: {}, form: {},
requiredRules: [{required: true, message: this.$t('test_resource_pool.fill_the_data'), trigger: 'blur'}], requiredRules: [{required: true, message: this.$t('test_resource_pool.fill_the_data'), trigger: 'blur'}],

View File

@ -367,7 +367,7 @@ export default {
multipleSelection: [], multipleSelection: [],
userRole: [], userRole: [],
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
condition: {}, condition: {},
tableData: [], tableData: [],

View File

@ -133,7 +133,7 @@
}, },
multipleSelection: [], multipleSelection: [],
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
} }
}, },

View File

@ -66,9 +66,6 @@ export default {
data() { data() {
return { return {
result: {}, result: {},
currentPage: 1,
pageSize: 5,
total: 0,
projects: [], projects: [],
treeNodes: [], treeNodes: [],
selectNodeIds: [], selectNodeIds: [],

View File

@ -62,7 +62,7 @@ export default {
id: '', id: '',
condition: {}, condition: {},
currentPage: 1, currentPage: 1,
pageSize: 5, pageSize: 10,
total: 0, total: 0,
url: '', url: '',
type: '' type: ''

View File

@ -131,11 +131,13 @@ export default {
}, },
registerEvents() { registerEvents() {
TrackEvent.$on(LIST_CHANGE, () => { TrackEvent.$on(LIST_CHANGE, () => {
// // todo refs
this.$refs.planRecent.recent(); this.$refs.planRecent.recent();
this.$refs.caseRecent.recent(); this.$refs.caseRecent.recent();
}); });
} }
},
beforeDestroy() {
TrackEvent.$off(LIST_CHANGE);
} }
} }

@ -1 +1 @@
Subproject commit 7d43154a7c19732407a8e9ace8a7d1ea13c91f36 Subproject commit 010ad7a5f072a5e9d368c756a2473bbd20781433

View File

@ -120,7 +120,6 @@ html,body {
padding-right: 60px; padding-right: 60px;
} }
/* 滚动条样式 */ /* 滚动条样式 */
::-webkit-scrollbar{ ::-webkit-scrollbar{
width: 5px; width: 5px;
@ -137,3 +136,36 @@ html,body {
background-color: transparent; background-color: transparent;
position: fixed; position: fixed;
} }
/* <-- 表格全选样式 */
.ms-select-all th:first-child {
border: 1px solid #DCDFE6;
border-radius:5px;
padding: 0px;
margin-top: 5px;
display: inline-block;
margin-top: 25px;
width: 50px;
}
.ms-select-all th:nth-child(2) {
overflow: visible;
}
.ms-select-all th:first-child>.cell {
padding: 5px;
width: 35px;
}
.ms-select-all th:nth-child(2)>.cell {
overflow: visible;
}
.ms-select-all .el-icon-arrow-down {
position: absolute;
display: inline-block;
top: -3px;
left: -40px;
width: 30px;
}
/* 表格全选样式 --> */