Merge branch 'master' of github.com:metersphere/metersphere

This commit is contained in:
chenjianxing 2021-03-23 15:49:35 +08:00
commit 41a1a5f38b
47 changed files with 416 additions and 205 deletions

View File

@ -80,8 +80,8 @@ public class ApiAutomationController {
}
@PostMapping("/reduction")
public void reduction(@RequestBody List<SaveApiScenarioRequest> requests) {
apiAutomationService.reduction(requests);
public void reduction(@RequestBody List<String> ids) {
apiAutomationService.reduction(ids);
}
@GetMapping("/getApiScenario/{id}")

View File

@ -63,6 +63,7 @@ public class ApiDefinitionController {
request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
return PageUtils.setPageInfo(page, apiDefinitionService.listRelevance(request));
}
@PostMapping("/list/relevance/review/{goPage}/{pageSize}")
public Pager<List<ApiDefinitionResult>> listRelevanceReview(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ApiDefinitionRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
@ -103,7 +104,7 @@ public class ApiDefinitionController {
@PostMapping(value = "/updateEsbRequest")
public SaveApiDefinitionRequest updateEsbRequest(@RequestBody SaveApiDefinitionRequest request) {
if(StringUtils.equals(request.getMethod(),"ESB")){
if (StringUtils.equals(request.getMethod(), "ESB")) {
//ESB的接口类型数据采用TCP方式去发送并将方法类型改为TCP 并修改发送数据
request = esbApiParamService.updateEsbRequest(request);
}
@ -128,8 +129,8 @@ public class ApiDefinitionController {
}
@PostMapping("/reduction")
public void reduction(@RequestBody List<SaveApiDefinitionRequest> requests) {
apiDefinitionService.reduction(requests);
public void reduction(@RequestBody ApiBatchRequest request) {
apiDefinitionService.reduction(request);
}
@GetMapping("/get/{id}")
@ -180,15 +181,18 @@ public class ApiDefinitionController {
public void createSchedule(@RequestBody ScheduleRequest request) throws MalformedURLException {
apiDefinitionService.createSchedule(request);
}
@PostMapping(value = "/schedule/update")
public void updateSchedule(@RequestBody Schedule request){
public void updateSchedule(@RequestBody Schedule request) {
apiDefinitionService.updateSchedule(request);
}
//查找定时任务资源Id
@PostMapping(value = "/getResourceId")
public String getResourceId(@RequestBody SwaggerUrlRequest swaggerUrlRequest){
public String getResourceId(@RequestBody SwaggerUrlRequest swaggerUrlRequest) {
return apiDefinitionService.getResourceId(swaggerUrlRequest);
}
//查找定时任务列表
@GetMapping("/scheduleTask/{projectId}")
public List<SwaggerTaskResult> getSwaggerScheduleList(@PathVariable String projectId) {
@ -198,12 +202,13 @@ public class ApiDefinitionController {
resultList) {
swaggerTaskResult.setIndex(dataIndex++);
Date nextExecutionTime = CronUtils.getNextTriggerTime(swaggerTaskResult.getRule());
if(nextExecutionTime!=null){
if (nextExecutionTime != null) {
swaggerTaskResult.setNextExecutionTime(nextExecutionTime.getTime());
}
}
return resultList;
return resultList;
}
//更新定时任务
@PostMapping(value = "/schedule/updateByPrimyKey")
public void updateScheduleEnableByPrimyKey(@RequestBody ScheduleInfoSwaggerUrlRequest request) {
@ -211,11 +216,13 @@ public class ApiDefinitionController {
schedule.setEnable(request.getTaskStatus());
apiDefinitionService.updateSchedule(schedule);
}
//删除定时任务和swaggereUrl
@PostMapping("/schedule/deleteByPrimyKey")
public void deleteSchedule(@RequestBody ScheduleInfoSwaggerUrlRequest request) {
apiDefinitionService.deleteSchedule(request);
}
@PostMapping("/getReference")
public ReferenceDTO getReference(@RequestBody ApiScenarioRequest request) {
return apiDefinitionService.getReference(request);
@ -237,8 +244,9 @@ public class ApiDefinitionController {
public void testPlanRelevance(@RequestBody ApiCaseRelevanceRequest request) {
apiDefinitionService.testPlanRelevance(request);
}
@PostMapping("/relevance/review")
public void testCaseReviewRelevance(@RequestBody ApiCaseRelevanceRequest request){
public void testCaseReviewRelevance(@RequestBody ApiCaseRelevanceRequest request) {
apiDefinitionService.testCaseReviewRelevance(request);
}

View File

@ -40,4 +40,7 @@ public class ApiTestBatchRequest extends ApiTestCaseWithBLOBs {
private String protocol;
private String status;
private String envId;
}

View File

@ -17,6 +17,8 @@ import org.apache.jmeter.control.LoopController;
import org.apache.jmeter.control.RunTime;
import org.apache.jmeter.control.WhileController;
import org.apache.jmeter.modifiers.CounterConfig;
import org.apache.jmeter.modifiers.JSR223PreProcessor;
import org.apache.jmeter.protocol.java.sampler.JSR223Sampler;
import org.apache.jmeter.reporters.ResultAction;
import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.testelement.TestElement;
@ -24,6 +26,7 @@ import org.apache.jmeter.timers.ConstantTimer;
import org.apache.jorphan.collections.HashTree;
import java.util.List;
import java.util.UUID;
@Data
@EqualsAndHashCode(callSuper = true)
@ -42,6 +45,9 @@ public class MsLoopController extends MsTestElement {
@JSONField(ordinal = 23)
private MsWhileController whileController;
private String ms_current_timer = UUID.randomUUID().toString();
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
// 非导出操作且不是启用状态则跳过执行
@ -122,7 +128,8 @@ public class MsLoopController extends MsTestElement {
operator = "";
value = "";
}
return "${__jexl3(" + variable + operator + value + ")}";
ms_current_timer = UUID.randomUUID().toString();
return "${__jexl3(" + variable + operator + value + " && \"${" + ms_current_timer + "}\" !=\"stop\")}";
}
private WhileController initWhileController() {
@ -151,6 +158,32 @@ public class MsLoopController extends MsTestElement {
return controller;
}
private String script() {
String script = "\n" +
"import java.util.*;\n" +
"import java.text.SimpleDateFormat;\n" +
"import org.apache.jmeter.threads.JMeterContextService;\n" +
"\n" +
"// 循环控制器超时后结束循环\n" +
"try{\n" +
"\tString ms_current_timer = vars.get(\"" + ms_current_timer + "\");\n" +
"\tlong _nowTime = System.currentTimeMillis(); \n" +
"\tif(ms_current_timer == null ){\n" +
"\t\tvars.put(\"" + ms_current_timer + "\",_nowTime.toString());\n" +
"\t}\n" +
"\tlong time = Long.parseLong(vars.get(\"" + ms_current_timer + "\"));\n" +
"\t if((_nowTime - time) > " + this.whileController.getTimeout() + " ){\n" +
"\t \tvars.put(\"" + ms_current_timer + "\", \"stop\");\n" +
"\t \tlog.info( \"结束循环\");\n" +
"\t }\n" +
"}catch (Exception e){\n" +
"\tlog.info( e.getMessage());\n" +
"\tvars.put(\"" + ms_current_timer + "\", \"stop\");\n" +
"}\n";
return script;
}
private HashTree controller(HashTree tree) {
if (StringUtils.equals(this.loopType, LoopConstants.WHILE.name()) && this.whileController != null) {
RunTime runTime = new RunTime();
@ -162,9 +195,17 @@ public class MsLoopController extends MsTestElement {
timeout = 1;
}
runTime.setRuntime(timeout);
HashTree hashTree = tree.add(initWhileController());
// 添加超时处理防止死循环
HashTree hashTree = tree.add(runTime);
return hashTree.add(initWhileController());
JSR223PreProcessor jsr223PreProcessor = new JSR223PreProcessor();
jsr223PreProcessor.setName("循环超时处理");
jsr223PreProcessor.setProperty(TestElement.TEST_CLASS, JSR223Sampler.class.getName());
jsr223PreProcessor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
jsr223PreProcessor.setProperty("cacheKey", "true");
jsr223PreProcessor.setProperty("scriptLanguage", "beanshell");
jsr223PreProcessor.setProperty("script", script());
hashTree.add(jsr223PreProcessor);
return hashTree;
}
if (StringUtils.equals(this.loopType, LoopConstants.FOREACH.name()) && this.forEachController != null) {
return tree.add(initForeachController());

View File

@ -34,10 +34,10 @@ public class MsExtract extends MsTestElement {
if (!config.isOperating() && !this.isEnable()) {
return;
}
addRequestExtractors(tree);
addRequestExtractors(tree, config);
}
private void addRequestExtractors(HashTree samplerHashTree) {
private void addRequestExtractors(HashTree samplerHashTree, ParameterConfig config) {
StringJoiner extract = new StringJoiner(";");
if (CollectionUtils.isNotEmpty(this.getRegex())) {
@ -55,7 +55,7 @@ public class MsExtract extends MsTestElement {
samplerHashTree.add(jsonPostProcessor(extractJSONPath, extract))
);
}
if (Optional.ofNullable(extract).orElse(extract).length() > 0) {
if (Optional.ofNullable(extract).orElse(extract).length() > 0 && !config.isOperating()) {
JSR223PostProcessor shell = new JSR223PostProcessor();
shell.setEnabled(true);
shell.setName(StringUtils.isEmpty(this.getName()) ? "JSR223PostProcessor" : this.getName());

View File

@ -316,13 +316,8 @@ public class ApiAutomationService {
}
}
public void reduction(List<SaveApiScenarioRequest> requests) {
List<String> apiIds = new ArrayList<>();
requests.forEach(item -> {
checkNameExist(item);
apiIds.add(item.getId());
});
extApiScenarioMapper.reduction(apiIds);
public void reduction(List<String> ids) {
extApiScenarioMapper.reduction(ids);
}
private void checkNameExist(SaveApiScenarioRequest request) {

View File

@ -136,10 +136,11 @@ public class ApiDefinitionService {
public ApiDefinitionWithBLOBs getBLOBs(String id) {
return apiDefinitionMapper.selectByPrimaryKey(id);
}
public List<ApiDefinitionWithBLOBs> getBLOBs(List<String> idList) {
if(idList == null || idList.isEmpty()){
return new ArrayList<>(0);
}else{
if (idList == null || idList.isEmpty()) {
return new ArrayList<>(0);
} else {
ApiDefinitionExample example = new ApiDefinitionExample();
example.createCriteria().andIdIn(idList);
example.setOrderByClause("create_time DESC ");
@ -189,13 +190,8 @@ public class ApiDefinitionService {
extApiDefinitionMapper.removeToGc(apiIds);
}
public void reduction(List<SaveApiDefinitionRequest> requests) {
List<String> apiIds = new ArrayList<>();
requests.forEach(item -> {
checkNameExist(item);
apiIds.add(item.getId());
});
extApiDefinitionMapper.reduction(apiIds);
public void reduction(ApiBatchRequest request) {
extApiDefinitionMapper.reduction(request.getIds());
}
public void deleteBodyFiles(String apiId) {
@ -243,7 +239,7 @@ public class ApiDefinitionService {
private ApiDefinition updateTest(SaveApiDefinitionRequest request) {
checkNameExist(request);
if(StringUtils.equals(request.getMethod(),"ESB")){
if (StringUtils.equals(request.getMethod(), "ESB")) {
//ESB的接口类型数据采用TCP方式去发送并将方法类型改为TCP 并修改发送数据
request = esbApiParamService.handleEsbRequest(request);
}
@ -272,7 +268,7 @@ public class ApiDefinitionService {
private ApiDefinition createTest(SaveApiDefinitionRequest request) {
checkNameExist(request);
if(StringUtils.equals(request.getMethod(),"ESB")){
if (StringUtils.equals(request.getMethod(), "ESB")) {
//ESB的接口类型数据采用TCP方式去发送并将方法类型改为TCP 并修改发送数据
request = esbApiParamService.handleEsbRequest(request);
}
@ -709,6 +705,7 @@ public class ApiDefinitionService {
calculateResult(resList);
return resList;
}
public List<ApiDefinitionResult> listRelevanceReview(ApiDefinitionRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
List<ApiDefinitionResult> resList = extApiDefinitionMapper.listRelevanceReview(request);
@ -740,7 +737,7 @@ public class ApiDefinitionService {
res.setCaseStatus("-");
}
if(StringUtils.equals("ESB",res.getMethod())){
if (StringUtils.equals("ESB", res.getMethod())) {
esbApiParamService.handleApiEsbParams(res);
}
}
@ -827,8 +824,7 @@ public class ApiDefinitionService {
((MsApiExportResult) apiExportResult).setProtocol(request.getProtocol());
((MsApiExportResult) apiExportResult).setProjectId(request.getProjectId());
((MsApiExportResult) apiExportResult).setVersion(System.getenv("MS_VERSION"));
}
else { // 导出为 Swagger 格式
} else { // 导出为 Swagger 格式
Swagger3Parser swagger3Parser = new Swagger3Parser();
System.out.println(apiDefinitionMapper.selectByExampleWithBLOBs(example));
apiExportResult = swagger3Parser.swagger3Export(apiDefinitionMapper.selectByExampleWithBLOBs(example));

View File

@ -50,7 +50,7 @@ public class ApiTestCaseService {
@Resource
TestPlanMapper testPlanMapper;
@Resource
TestCaseReviewMapper testCaseReviewMapper;
TestCaseReviewMapper testCaseReviewMapper;
@Resource
private ApiTestCaseMapper apiTestCaseMapper;
@Resource
@ -82,12 +82,12 @@ public class ApiTestCaseService {
public List<ApiTestCaseResult> list(ApiTestCaseRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
List<ApiTestCaseResult> returnList = extApiTestCaseMapper.list(request);
List<ApiTestCaseResult> returnList = extApiTestCaseMapper.list(request);
for (ApiTestCaseResult res : returnList) {
esbApiParamService.handleApiEsbParams(res);
}
return returnList;
return returnList;
}
public List<ApiTestCaseDTO> listSimple(ApiTestCaseRequest request) {
@ -230,7 +230,7 @@ public class ApiTestCaseService {
private ApiTestCase updateTest(SaveApiTestCaseRequest request) {
checkNameExist(request);
if(StringUtils.isNotEmpty(request.getEsbDataStruct())){
if (StringUtils.isNotEmpty(request.getEsbDataStruct())) {
request = esbApiParamService.handleEsbRequest(request);
}
@ -253,7 +253,7 @@ public class ApiTestCaseService {
request.setId(UUID.randomUUID().toString());
checkNameExist(request);
if(StringUtils.isNotEmpty(request.getEsbDataStruct())||StringUtils.isNotEmpty(request.getBackEsbDataStruct())){
if (StringUtils.isNotEmpty(request.getEsbDataStruct()) || StringUtils.isNotEmpty(request.getBackEsbDataStruct())) {
request = esbApiParamService.handleEsbRequest(request);
}
@ -332,7 +332,8 @@ public class ApiTestCaseService {
List<ApiTestCase> apiTestCases = apiTestCaseMapper.selectByExample(example);
relevance(apiTestCases, request);
}
public void relevanceByApiByReview(ApiCaseRelevanceRequest request){
public void relevanceByApiByReview(ApiCaseRelevanceRequest request) {
List<String> ids = request.getSelectIds();
if (CollectionUtils.isEmpty(ids)) {
return;
@ -342,6 +343,7 @@ public class ApiTestCaseService {
List<ApiTestCase> apiTestCases = apiTestCaseMapper.selectByExample(example);
relevanceByReview(apiTestCases, request);
}
public void relevanceByCase(ApiCaseRelevanceRequest request) {
List<String> ids = request.getSelectIds();
if (CollectionUtils.isEmpty(ids)) {
@ -391,7 +393,7 @@ public class ApiTestCaseService {
TestCaseReviewApiCase.setUpdateTime(System.currentTimeMillis());
batchMapper.insertIfNotExists(TestCaseReviewApiCase);
});
TestCaseReview testCaseReview=testCaseReviewMapper.selectByPrimaryKey(request.getReviewId());
TestCaseReview testCaseReview = testCaseReviewMapper.selectByPrimaryKey(request.getReviewId());
if (StringUtils.equals(testCaseReview.getStatus(), TestPlanStatus.Prepare.name())
|| StringUtils.equals(testCaseReview.getStatus(), TestPlanStatus.Completed.name())) {
testCaseReview.setStatus(TestPlanStatus.Underway.name());
@ -399,11 +401,13 @@ public class ApiTestCaseService {
}
sqlSession.flushStatements();
}
public List<String> selectIdsNotExistsInPlan(String projectId, String planId) {
return extApiTestCaseMapper.selectIdsNotExistsInPlan(projectId, planId);
}
public List<String> selectIdsNotExistsInReview(String projectId,String reviewId){
return extApiTestCaseMapper.selectIdsNotExistsInReview(projectId,reviewId);
public List<String> selectIdsNotExistsInReview(String projectId, String reviewId) {
return extApiTestCaseMapper.selectIdsNotExistsInReview(projectId, reviewId);
}
public List<ApiDataCountResult> countProtocolByProjectID(String projectId) {
@ -497,7 +501,22 @@ public class ApiTestCaseService {
sqlSession.flushStatements();
}
if (StringUtils.isNotEmpty(request.getEnvId())) {
List<ApiTestCaseWithBLOBs> bloBs = apiTestCaseMapper.selectByExampleWithBLOBs(apiDefinitionExample);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiTestCaseMapper batchMapper = sqlSession.getMapper(ApiTestCaseMapper.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
bloBs.forEach(apiTestCase -> {
JSONObject req = JSON.parseObject(apiTestCase.getRequest());
req.put("useEnvironment", request.getEnvId());
String requestStr = JSON.toJSONString(req);
apiTestCase.setRequest(requestStr);
batchMapper.updateByPrimaryKeySelective(apiTestCase);
});
sqlSession.flushStatements();
}
}
private List<String> getAllApiCaseIdsByFontedSelect(Map<String, List<String>> filters, List<String> moduleIds, String name, String projectId, String protocol, List<String> unSelectIds, String status) {

View File

@ -306,9 +306,12 @@
or test_case.num like CONCAT('%', #{request.name},'%')
or test_case.tags like CONCAT('%', #{request.name},'%'))
</if>
<if test="request.createTime >0">
<if test="request.relevanceCreateTime >0">
and test_case.id in (select test_case_id from test_case_test where test_case_test.create_time >= #{request.createTime})
</if>
<if test="request.createTime >0">
and test_case.create_time >= #{request.createTime}
</if>
<if test="request.nodeIds != null and request.nodeIds.size() > 0">
and test_case.node_id in
<foreach collection="request.nodeIds" item="nodeId" separator="," open="(" close=")">

View File

@ -52,6 +52,7 @@ public class ShiroUtils {
filterChainDefinitionMap.put("/", "apikey, authc"); // 跳转到 / 不用校验 csrf
filterChainDefinitionMap.put("/language", "apikey, authc");// 跳转到 /language 不用校验 csrf
filterChainDefinitionMap.put("/document", "apikey, authc"); // 跳转到 /document 不用校验 csrf
filterChainDefinitionMap.put("/test/case/file/preview/**", "apikey, authc"); // 预览测试用例附件 不用校验 csrf
}
public static Cookie getSessionIdCookie(){

View File

@ -42,7 +42,12 @@ public class CsrfFilter extends AnonymousFilter {
// 请求头取出的token value
String csrfToken = httpServletRequest.getHeader(TOKEN_NAME);
// 校验 token
validateToken(csrfToken);
try {
validateToken(csrfToken);
} catch (ExpiredCredentialsException e) {
((HttpServletResponse) response).setHeader("Authentication-Status", "invalid");
return true;
}
// 校验 referer
validateReferer(httpServletRequest);
return true;

View File

@ -23,7 +23,8 @@ public class ReportFailureAdvanceResultComponent extends ReportComponent {
@Override
public void readRecord(TestPlanCaseDTO testCase) {
if (StringUtils.equals(testCase.getStatus(), TestPlanTestCaseStatus.Failure.name())) {
if (StringUtils.equals(testCase.getStatus(), TestPlanTestCaseStatus.Failure.name()) ||
StringUtils.equals(testCase.getStatus(), TestPlanTestCaseStatus.Blocking.name())) {
this.functionalTestCases.add(testCase);
}
}

View File

@ -4,6 +4,8 @@ import io.metersphere.base.domain.TestCaseWithBLOBs;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class TestReviewCaseDTO extends TestCaseWithBLOBs {
@ -16,4 +18,5 @@ public class TestReviewCaseDTO extends TestCaseWithBLOBs {
private String issues;
private String model;
private String projectName;
private List<TestCaseTestDTO> list;
}

View File

@ -24,8 +24,10 @@ public class QueryTestCaseRequest extends BaseQueryRequest {
private String reviewId;
private boolean isSelectThisWeedData = false;
private boolean isSelectThisWeedRelevanceData = false;
private String caseCoverage;
private long createTime = 0;
private long relevanceCreateTime = 0;
}

View File

@ -6,7 +6,7 @@ public class TrackCount {
public static final String P2 = "P2";
public static final String P3 = "P3";
public static final String API = "api";
public static final String TESTCASE = "testcase";
public static final String PERFORMANCE = "performance";
public static final String AUTOMATION = "automation";
}

View File

@ -145,7 +145,7 @@ public class TrackStatisticsDTO {
public void countRelevance(List<TrackCountResult> relevanceResults) {
for (TrackCountResult countResult : relevanceResults) {
switch (countResult.getGroupField()){
case TrackCount.API:
case TrackCount.TESTCASE:
this.apiCaseCount += countResult.getCountNumber();
this.allRelevanceCaseCount += countResult.getCountNumber();
break;

View File

@ -210,13 +210,19 @@ public class TestCaseService {
*/
private void initRequest(QueryTestCaseRequest request, boolean checkThisWeekData) {
if (checkThisWeekData) {
Map<String, Date> weekFirstTimeAndLastTime = DateUtils.getWeedFirstTimeAndLastTime(new Date());
Date weekFirstTime = weekFirstTimeAndLastTime.get("firstTime");
if (request.isSelectThisWeedData()) {
Map<String, Date> weekFirstTimeAndLastTime = DateUtils.getWeedFirstTimeAndLastTime(new Date());
Date weekFirstTime = weekFirstTimeAndLastTime.get("firstTime");
if (weekFirstTime != null) {
request.setCreateTime(weekFirstTime.getTime());
}
}
if (request.isSelectThisWeedRelevanceData()) {
if (weekFirstTime != null) {
request.setRelevanceCreateTime(weekFirstTime.getTime());
}
}
}
}

View File

@ -1,16 +1,16 @@
package io.metersphere.track.service;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.TestCaseMapper;
import io.metersphere.base.mapper.TestCaseReviewMapper;
import io.metersphere.base.mapper.TestCaseReviewTestCaseMapper;
import io.metersphere.base.mapper.TestCaseReviewUsersMapper;
import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
import io.metersphere.base.mapper.ext.ExtTestReviewCaseMapper;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.controller.request.member.QueryMemberRequest;
import io.metersphere.service.UserService;
import io.metersphere.track.dto.TestCaseTestDTO;
import io.metersphere.track.dto.TestPlanCaseDTO;
import io.metersphere.track.dto.TestReviewCaseDTO;
import io.metersphere.track.request.testplancase.TestReviewCaseBatchRequest;
import io.metersphere.track.request.testreview.DeleteRelevanceRequest;
@ -29,7 +29,14 @@ import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class TestReviewTestCaseService {
@Resource
private TestCaseTestMapper testCaseTestMapper;
@Resource
private LoadTestMapper loadTestMapper;
@Resource
private ApiTestCaseMapper apiTestCaseMapper;
@Resource
private ApiScenarioMapper apiScenarioMapper;
@Resource
ExtTestReviewCaseMapper extTestReviewCaseMapper;
@Resource
@ -44,6 +51,8 @@ public class TestReviewTestCaseService {
TestCaseReviewService testCaseReviewService;
@Resource
TestCaseMapper testCaseMapper;
@Resource
ExtTestPlanTestCaseMapper extTestPlanTestCaseMapper;
public List<TestReviewCaseDTO> list(QueryCaseReviewRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
@ -128,7 +137,40 @@ public class TestReviewTestCaseService {
}
public TestReviewCaseDTO get(String reviewId) {
return extTestReviewCaseMapper.get(reviewId);
TestReviewCaseDTO testReviewCaseDTO=extTestReviewCaseMapper.get(reviewId);
List<TestCaseTestDTO> testCaseTestDTOS = extTestPlanTestCaseMapper.listTestCaseTest(testReviewCaseDTO.getCaseId());
testCaseTestDTOS.forEach(dto -> {
setTestName(dto);
});
testReviewCaseDTO.setList(testCaseTestDTOS);
return testReviewCaseDTO;
}
private void setTestName(TestCaseTestDTO dto) {
String type = dto.getTestType();
String id = dto.getTestId();
switch (type) {
case "performance":
LoadTest loadTest = loadTestMapper.selectByPrimaryKey(id);
if (loadTest != null) {
dto.setTestName(loadTest.getName());
}
break;
case "testcase":
ApiTestCaseWithBLOBs apiTestCaseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(id);
if (apiTestCaseWithBLOBs != null) {
dto.setTestName(apiTestCaseWithBLOBs.getName());
}
break;
case "automation":
ApiScenarioWithBLOBs apiScenarioWithBLOBs = apiScenarioMapper.selectByPrimaryKey(id);
if (apiScenarioWithBLOBs != null) {
dto.setTestName(apiScenarioWithBLOBs.getName());
}
break;
default:
break;
}
}
public void editTestCaseBatchStatus(TestReviewCaseBatchRequest request) {

View File

@ -24,7 +24,7 @@
<el-table-column v-if="!referenced" width="30" min-width="30" :resizable="false" align="center">
<template v-slot:default="scope">
<show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectDataCounts" v-tester/>
<show-more-btn :is-show="scope.row.showMore" :buttons="trashEnable ? trashButtons: buttons" :size="selectDataCounts" v-tester/>
</template>
</el-table-column>
<template v-for="(item, index) in tableLabel">
@ -69,7 +69,7 @@
<el-table-column v-if="item.id == 'tags'" prop="tags" min-width="120px"
:label="$t('api_test.automation.tag')" :key="index">
<template v-slot:default="scope">
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :content="itemName" :show-tooltip="true" tooltip style="margin-left: 5px"/>
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :content="itemName" :show-tooltip="true" tooltip style="margin-left: 0px; margin-right: 2px"/>
</template>
</el-table-column>
<el-table-column v-if="item.id == 'userId'" prop="userId" min-width="120px"
@ -244,7 +244,7 @@
return {
type: API_SCENARIO_LIST,
headerItems: Api_Scenario_List,
tableLabel: [],
tableLabel: Api_Scenario_List,
loading: false,
screenHeight: document.documentElement.clientHeight - 280,//,
condition: {
@ -286,6 +286,12 @@
{name: this.$t('api_test.definition.request.batch_delete'), handleClick: this.handleDeleteBatch},
],
trashButtons: [
{name: this.$t('api_test.definition.request.batch_delete'), handleClick: this.handleDeleteBatch},
{
name: "批量恢复", handleClick: this.handleBatchRestore
},
],
isSelectAllDate: false,
selectRows: new Set(),
selectDataCounts: 0,
@ -419,6 +425,9 @@
});
this.loading = false;
this.unSelection = data.listObject.map(s => s.id);
if (this.$refs.scenarioTable) {
this.$refs.scenarioTable.doLayout()
}
});
}
getLabel(this, API_SCENARIO_LIST);
@ -589,10 +598,14 @@
this.$emit('edit', data);
},
reductionApi(row) {
row.scenarioDefinition = null;
row.tags = null;
let rows = [row];
this.$post("/api/automation/reduction", rows, response => {
this.$post("/api/automation/reduction", [row.id], response => {
this.$success(this.$t('commons.save_success'));
this.search();
})
},
handleBatchRestore() {
let ids = Array.from(this.selectRows).map(row => row.id);
this.$post("/api/automation/reduction", ids, response => {
this.$success(this.$t('commons.save_success'));
this.search();
})

View File

@ -135,7 +135,6 @@
}
//
this.getApiInfo();
console.log(JSON.stringify(this.request));
if (this.request.protocol === 'HTTP') {
this.setUrl(this.request.url);
this.setUrl(this.request.path);

View File

@ -23,7 +23,7 @@
<el-button :disabled="scenarioDefinition.length < 1" size="mini" type="primary" v-prevent-re-click @click="runDebug">{{$t('api_test.request.debug')}}</el-button>
<font-awesome-icon class="alt-ico" :icon="['fa', 'compress-alt']" size="lg" @click="unFullScreen"/>
<font-awesome-icon class="ms-alt-ico" :icon="['fa', 'compress-alt']" size="lg" @click="unFullScreen"/>
<i class="el-icon-close alt-ico-close" @click="close"/>
</div>
@ -124,14 +124,12 @@
.ms-header-right {
float: right;
width: 420px;
margin-top: 2px;
position: fixed;
right: 20px;
z-index: 1;
}
.alt-ico {
.ms-alt-ico {
font-size: 16px;
margin: 10px 10px 0px;
}
@ -146,7 +144,7 @@
cursor: pointer;
}
.alt-ico:hover {
.ms-alt-ico:hover {
color: black;
cursor: pointer;
}

View File

@ -230,7 +230,8 @@
}
data.message = true;
data.request.useEnvironment = this.environment;
this.saveTestCase(data);
//this.saveTestCase(data);
this.$emit('singleRun', data);
},
copyCase(data) {

View File

@ -181,7 +181,7 @@
this.visible = false;
},
runRefresh(data) {
runRefresh() {
this.batchLoadingIds = [];
this.singleLoading = false;
this.singleRunId = "";
@ -192,12 +192,9 @@
this.$set(item, 'selected', false);
})
}
//
let cases = this.apiCaseList[0];
cases.request.useEnvironment = this.environment;
cases.message = true;
this.$refs.apiCaseItem[0].saveCase(cases);
this.refresh();
//
let obj = {envId: this.environment, show: true};
this.batchEdit(obj);
this.$success(this.$t('organization.integration.successful_operation'));
},
@ -222,7 +219,7 @@
}
this.result = this.$post("/api/testcase/list", this.condition, response => {
if(response.data){
if (response.data) {
this.apiCaseList = response.data;
}
this.apiCaseList.forEach(apiCase => {
@ -260,7 +257,7 @@
if (!request.hashTree) {
request.hashTree = [];
}
if(request.backScript != null){
if (request.backScript != null) {
request.hashTree.push(request.backScript);
}
let uuid = getUUID();
@ -286,18 +283,17 @@
this.$warning(this.$t('api_test.environment.select_environment'));
return;
}
this.selectdCases = [];
this.selectdCases.push(row.id);
this.runData = [];
this.singleLoading = true;
this.singleRunId = row.id;
row.request.name = row.id;
this.$get('/api/definition/get/' + row.request.id, response => {
row.request.path = response.data.path; // pathpath
row.request.useEnvironment = this.environment;
row.request.projectId = getCurrentProjectID();
this.runData.push(row.request);
/*触发执行操作*/
this.reportId = getUUID().substring(0, 8);
});
row.request.useEnvironment = this.environment;
row.request.projectId = getCurrentProjectID();
this.runData.push(row.request);
/*触发执行操作*/
this.reportId = getUUID().substring(0, 8);
},
batchRun() {
@ -307,6 +303,7 @@
}
this.runData = [];
this.batchLoadingIds = [];
this.selectdCases = [];
if (this.apiCaseList.length > 0) {
this.apiCaseList.forEach(item => {
if (item.selected && item.id) {
@ -314,6 +311,7 @@
item.request.useEnvironment = this.environment;
this.runData.push(item.request);
this.batchLoadingIds.push(item.id);
this.selectdCases.push(item.id);
}
})
if (this.runData.length > 0) {
@ -353,17 +351,22 @@
},
batchEdit(form) {
let param = {};
param[form.type] = form.value;
param.ids = this.selectdCases;
param.projectId = getCurrentProjectID();
if (this.api) {
param.protocol = this.api.protocol;
if (form) {
param[form.type] = form.value;
param.ids = this.selectdCases;
param.projectId = getCurrentProjectID();
param.envId = form.envId;
if (this.api) {
param.protocol = this.api.protocol;
}
param.selectAllDate = this.isSelectAllDate;
param.unSelectIds = this.unSelection;
param = Object.assign(param, this.condition);
}
param.selectAllDate = this.isSelectAllDate;
param.unSelectIds = this.unSelection;
param = Object.assign(param, this.condition);
this.$post('/api/testcase/batch/editByParam', param, () => {
this.$success(this.$t('commons.save_success'));
if (!form.show) {
this.$success(this.$t('commons.save_success'));
}
this.selectdCases = [];
this.getApiTest();
});

View File

@ -71,7 +71,7 @@
<el-table-column v-if="item.id=='tags'" prop="tags" min-width="120px" :label="$t('commons.tag')"
:key="index">
<template v-slot:default="scope">
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :content="itemName" style="margin-left: 5px"/>
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :content="itemName" style="margin-left: 0px; margin-right: 2px"/>
</template>
</el-table-column>
@ -186,7 +186,7 @@ export default {
return {
type: API_CASE_LIST,
headerItems: Api_Case_List,
tableLabel: [],
tableLabel: Api_Case_List,
condition: {
components: API_CASE_CONFIGS
},
@ -260,6 +260,10 @@ export default {
},
created: function () {
this.initTable();
this.$nextTick(() => {
this.$refs.caseTable.bodyWrapper.scrollTop = 5
})
},
watch: {
selectNodeIds() {
@ -277,24 +281,24 @@ export default {
this.initTable();
}
},
computed: {
computed: {
//
isApiModel() {
return this.model === 'api'
},
//
isApiModel() {
return this.model === 'api'
},
methods: {
customHeader() {
getLabel(this, API_CASE_LIST);
this.$refs.headerCustom.open(this.tableLabel)
},
initTable() {
},
methods: {
customHeader() {
getLabel(this, API_CASE_LIST);
this.$refs.headerCustom.open(this.tableLabel)
},
initTable() {
this.selectRows = new Set();
this.condition.status = "";
this.condition.moduleIds = this.selectNodeIds;
if (this.trashEnable) {
this.selectRows = new Set();
this.condition.status = "";
this.condition.moduleIds = this.selectNodeIds;
if (this.trashEnable) {
this.condition.status = "Trash";
this.condition.moduleIds = [];
}
@ -331,9 +335,13 @@ export default {
item.tags = JSON.parse(item.tags);
}
})
if (this.$refs.caseTable) {
this.$refs.caseTable.doLayout()
}
});
}
getLabel(this, API_CASE_LIST);
},
open() {
this.$refs.searchBar.open();
@ -636,4 +644,7 @@ export default {
top: -2px;
}
/deep/ .el-table__fixed {
height: 100% !important;
}
</style>

View File

@ -28,7 +28,7 @@
<el-table-column width="30" :resizable="false" align="center">
<template v-slot:default="scope">
<!-- 选中记录后浮现的按钮提供对记录的批量操作 -->
<show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectDataCounts" v-tester/>
<show-more-btn :is-show="scope.row.showMore" :buttons="trashEnable ? trashButtons : buttons" :size="selectDataCounts" v-tester/>
</template>
</el-table-column>
<template v-for="(item, index) in tableLabel">
@ -116,7 +116,7 @@
min-width="120px"
:key="index">
<template v-slot:default="scope">
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :show-tooltip="true" :content="itemName" style="margin-left: 5px"/>
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :show-tooltip="true" :content="itemName" style="margin-left: 0px; margin-right: 2px"/>
</template>
</el-table-column>
@ -272,7 +272,7 @@
return {
type: API_LIST,
headerItems: Api_List,
tableLabel: [],
tableLabel: Api_List,
condition: {
components: API_DEFINITION_CONFIGS
},
@ -289,6 +289,12 @@
name: this.$t('api_test.definition.request.batch_move'), handleClick: this.handleBatchMove
}
],
trashButtons: [
{name: this.$t('api_test.definition.request.batch_delete'), handleClick: this.handleDeleteBatch},
{
name: "批量恢复", handleClick: this.handleBatchRestore
},
],
typeArr: [
{id: 'status', name: this.$t('api_test.definition.api_status')},
{id: 'method', name: this.$t('api_test.definition.api_type')},
@ -442,6 +448,10 @@
item.tags = JSON.parse(item.tags);
}
})
if (this.$refs.apiDefinitionTable) {
this.$refs.apiDefinitionTable.doLayout()
}
});
}
getLabel(this, API_LIST);
@ -560,17 +570,18 @@
},
reductionApi(row) {
let tmp = JSON.parse(JSON.stringify(row));
tmp.request = null;
tmp.response = null;
if (tmp.tags instanceof Array) {
tmp.tags = JSON.stringify(tmp.tags);
}
let rows = [tmp];
let rows = {ids: [tmp.id]};
this.$post('/api/definition/reduction/', rows, () => {
this.$success(this.$t('commons.save_success'));
this.search();
});
},
handleBatchRestore() {
this.$post('/api/definition/reduction/', buildBatchParam(this), () => {
this.$success(this.$t('commons.save_success'));
this.search();
});
},
handleDeleteBatch() {
if (this.trashEnable) {
this.$alert(this.$t('api_test.definition.request.delete_confirm') + "", '', {

View File

@ -47,19 +47,12 @@ export default {
},
open(items) {
this.defaultCheckedKeys = []
this.dialogTableVisible = true
this.fieldSelected = items
if (items.size <= 0) {
this.optionalField = this.optionalFields
} else {
items.forEach(i => {
this.defaultCheckedKeys.push(i.id)
}
)
}
console.log(this.defaultCheckedKeys)
items.forEach(i => {
this.defaultCheckedKeys.push(i.id)
}
)
this.fieldSelected = items;
},
saveHeader() {
let param = {
@ -71,8 +64,8 @@ export default {
console.log(this.optionalFields)
console.log(this.fieldSelected)
this.$success(this.$t("commons.save_success"));
this.dialogTableVisible = false
this.initTableData()
this.close();
})
},
removeAt(idx) {
@ -83,7 +76,6 @@ export default {
},
// 穿transfer addressList
// changeMode() {
// if (this.mode == "transfer") {

View File

@ -22,7 +22,7 @@
:label="$t('api_test.automation.tag')">
<template v-slot:default="scope">
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :content="itemName"
style="margin-left: 5px"/>
style="margin-left: 0px; margin-right: 2px"/>
</template>
</el-table-column>
<el-table-column

View File

@ -26,6 +26,11 @@
row: Object,
size: Number
},
created() {
if (this.trashEnable) {
this.buttons.splice(1, 1);
}
},
methods: {
click(btn) {
if (btn.handleClick instanceof Function) {

View File

@ -105,13 +105,12 @@ export default {
this.testCaseForm.projectId = getCurrentProjectID();
this.testCaseForm.type = "";
this.testCaseForm.priority = "P0";
this.testCaseForm.method = "manual";
if(this.currentModule!==undefined){
if (this.currentModule !== undefined || this.currentModule !== null || this.currentModule !== 0 || this.currentModule !== "") {
this.testCaseForm.nodePath = this.currentModule.path;
this.testCaseForm.nodeId = this.currentModule.id;
}else{
this.testCaseForm.nodePath="/全部用例"
this.testCaseForm.nodeId="root"
} else {
this.testCaseForm.nodePath = "/全部用例"
this.testCaseForm.nodeId = "root"
}
this.result = this.$post(path, this.testCaseForm, response => {
this.testCaseForm.id=response.data.id

View File

@ -97,17 +97,12 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item :label="$t('test_track.case.relate_test')" :label-width="formLabelWidth" prop="testId">
<el-cascader show-all-levels v-model="form.selected" :props="props" ></el-cascader>
</el-form-item>
</el-col>
<!-- <el-col :span="7" v-if="form.testId=='other'">
<el-form-item :label="$t('test_track.case.test_name')" :label-width="formLabelWidth" prop="testId">
<el-input v-model="form.otherTestName" :placeholder="$t('test_track.case.input_test_case')"></el-input>
<el-col :span="14">
<el-form-item :label="$t('test_track.case.relate_test')" :label-width="formLabelWidth">
<el-cascader filterable placeholder="请选择要关联的测试" show-all-levels v-model="form.selected" :props="props"
class="ms-case"></el-cascader>
</el-form-item>
</el-col>-->
</el-col>
</el-row>
<el-row>
@ -125,8 +120,9 @@
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="需求名称" :label-width="formLabelWidth" prop="demandName" v-if="form.demandId=='other'">
<el-col :span="10" :offset="1">
<el-form-item label="需求ID/名称" :label-width="formLabelWidth" prop="demandName"
v-if="form.demandId=='other'">
<el-input v-model="form.demandName"></el-input>
</el-form-item>
</el-col>
@ -340,7 +336,6 @@ export default {
}
if (this.projectId && this.form.type != '' && this.form.type != 'undefined') {
this.$get(url, response => {
response.data.unshift({id: 'other', name: this.$t('test_track.case.other')})
const nodes = response.data
.map(item => ({
value: item.id,
@ -444,6 +439,14 @@ export default {
if (this.type === 'edit' || this.type === 'copy') {
this.open(this.currentTestCaseInfo)
}
// Cascader : input
setInterval(function () {
document.querySelectorAll('.el-cascader-node__label').forEach(el => {
el.onclick = function () {
if (this.previousElementSibling) this.previousElementSibling.click();
};
});
}, 1000);
},
watch: {
treeNodes() {
@ -581,8 +584,10 @@ export default {
}
Object.assign(this.form, tmp);
this.form.module = testCase.nodeId;
this.form.testId=testCase.selected
console.log(this.form.testId)
/*
this.form.testId=testCase.selected
*/
console.log(this.form.selected)
this.getFileMetaData(testCase);
},
setTestCaseExtInfo(testCase) {
@ -677,8 +682,6 @@ export default {
}
this.dialogFormVisible = false;
this.$emit("refresh");
// 广 head
TrackEvent.$emit(LIST_CHANGE);
});
}
} else {
@ -778,7 +781,6 @@ export default {
});
},
getTestOptions(val) {
console.log(val)
this.projectId = getCurrentProjectID()
this.testOptions = [];
let url = '';
@ -998,6 +1000,10 @@ export default {
width: 100%;
}
.ms-case {
width: 100%;
}
/deep/ .el-button-group > .el-button:first-child {
border-top-right-radius: 0;
border-bottom-right-radius: 0;

View File

@ -29,6 +29,7 @@ export default {
},
methods: {
open(file) {
console.log(file)
this.file = file;
this.dialogVisible = true;
},

View File

@ -131,7 +131,7 @@
<el-table-column v-if="item.id=='tags'" prop="tags" :label="$t('commons.tag')" :key="index">
<template v-slot:default="scope">
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain"
:content="itemName" style="margin-left: 5px"/>
:content="itemName" style="margin-left: 0px; margin-right: 2px"/>
</template>
</el-table-column>
@ -259,7 +259,7 @@ export default {
return {
type: TEST_CASE_LIST,
headerItems: Track_Test_Case,
tableLabel: [],
tableLabel: Track_Test_Case,
result: {},
deletePath: "/test/case/delete",
condition: {
@ -409,11 +409,15 @@ export default {
getData() {
this.getSelectDataRange();
this.condition.selectThisWeedData = false;
this.condition.selectThisWeedRelevanceData = false;
this.condition.caseCoverage = null;
switch (this.selectDataRange) {
case 'thisWeekCount':
this.condition.selectThisWeedData = true;
break;
case 'thisWeekRelevanceCount':
this.condition.selectThisWeedRelevanceData = true;
break;
case 'uncoverage':
this.condition.caseCoverage = 'uncoverage';
break;
@ -443,6 +447,10 @@ export default {
item.tags = JSON.parse(item.tags);
}
})
if (this.$refs.table) {
this.$refs.table.doLayout()
}
});
}
},

View File

@ -9,18 +9,22 @@
<el-menu-item :index="'/track/home'">
{{ $t("i18n.home") }}
</el-menu-item>
<el-submenu v-permission="['test_manager','test_user','test_viewer']"
index="6" popper-class="submenu">
<template v-slot:title>{{ $t('test_track.case.test_case') }}</template>
<ms-recent-list ref="caseRecent" :options="caseRecent"/>
<el-divider/>
<ms-show-all :index="'/track/case/all'"/>
<el-menu-item :index="testCaseEditPath" class="blank_item"></el-menu-item>
<el-menu-item :index="testCaseProjectPath" class="blank_item"></el-menu-item>
<ms-create-button v-permission="['test_manager','test_user']" :index="'/track/case/create'"
:title="$t('test_track.case.create_case')"/>
</el-submenu>
<el-menu-item :index="'/track/case/all'">
{{ $t("test_track.case.test_case") }}
</el-menu-item>
<!--
<el-submenu v-permission="['test_manager','test_user','test_viewer']"
index="6" popper-class="submenu">
<template v-slot:title>{{ $t('test_track.case.test_case') }}</template>
<ms-recent-list ref="caseRecent" :options="caseRecent"/>
<el-divider/>
<ms-show-all :index="'/track/case/all'"/>
<el-menu-item :index="testCaseEditPath" class="blank_item"></el-menu-item>
<el-menu-item :index="testCaseProjectPath" class="blank_item"></el-menu-item>
<ms-create-button v-permission="['test_manager','test_user']" :index="'/track/case/create'"
:title="$t('test_track.case.create_case')"/>
</el-submenu>
-->
<el-submenu v-permission="['test_manager','test_user','test_viewer']"
index="8" popper-class="submenu">

View File

@ -40,7 +40,7 @@
<el-row>
<el-col>
{{$t('api_test.home_page.api_details_card.this_week_add')}}
<el-link type="info" @click="redirectPage('thisWeekCount')" target="_blank" style="color: #000000">{{relevanceCountData.thisWeekAddedCount}}
<el-link type="info" @click="redirectPage('thisWeekRelevanceCount')" target="_blank" style="color: #000000">{{relevanceCountData.thisWeekAddedCount}}
</el-link>
{{$t('api_test.home_page.unit_of_measurement')}}
</el-col>

View File

@ -96,7 +96,7 @@
:label="$t('api_test.automation.tag')" :key="index">
<template v-slot:default="scope">
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain"
:content="itemName" style="margin-left: 5px"></ms-tag>
:content="itemName" style="margin-left: 0px; margin-right: 2px"></ms-tag>
</template>
</el-table-column>
<el-table-column
@ -248,7 +248,7 @@ export default {
return {
type: TEST_PLAN_LIST,
headerItems: Test_Plan_List,
tableLabel: [],
tableLabel: Test_Plan_List,
result: {},
enableDeleteTip: false,
queryPath: "/test/plan/list",

View File

@ -31,7 +31,7 @@
</el-table-column>
<el-table-column prop="tagNames" :label="$t('api_test.automation.tag')" min-width="120">
<template v-slot:default="scope">
<ms-tag v-for="itemName in scope.row.tags" :key="itemName" type="success" effect="plain" :content="itemName" style="margin-left: 5px"/>
<ms-tag v-for="itemName in scope.row.tags" :key="itemName" type="success" effect="plain" :content="itemName" style="margin-left: 0px; margin-right: 2px"/>
</template>
</el-table-column>
<el-table-column prop="userId" :label="$t('api_test.automation.creator')" show-overflow-tooltip/>

View File

@ -80,7 +80,7 @@
:label="$t('commons.tag')"
:key="index">
<template v-slot:default="scope">
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :content="itemName" style="margin-left: 5px"/>
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :content="itemName" style="margin-left: 0px; margin-right: 2px"/>
</template>
</el-table-column>
@ -192,7 +192,7 @@ export default {
return {
type: TEST_PLAN_API_CASE,
headerItems: Test_Plan_Api_Case,
tableLabel: [],
tableLabel: Test_Plan_Api_Case,
condition: {},
selectCase: {},
result: {},
@ -453,15 +453,12 @@ export default {
this.initTable();
},
singleRun(row) {
if (!row.environmentId) {
this.$warning(this.$t('api_test.environment.select_environment'));
return;
}
this.runData = [];
this.rowLoading = row.id;
this.$get('/api/testcase/get/' + row.caseId, (response) => {
console.log(response.data)
let apiCase = response.data;
let request = JSON.parse(apiCase.request);
request.name = row.id;

View File

@ -38,7 +38,7 @@
width="200px" :key="index">
<template v-slot:default="scope">
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain"
:content="itemName" style="margin-left: 5px"/>
:content="itemName" style="margin-left: 0px; margin-right: 2px"/>
</template>
</el-table-column>
<el-table-column v-if="item.id == 'userId'" prop="userId" :label="$t('api_test.automation.creator')"
@ -148,7 +148,7 @@ export default {
return {
type: TEST_PLAN_SCENARIO_CASE,
headerItems: Test_Plan_Scenario_Case,
tableLabel: [],
tableLabel: Test_Plan_Scenario_Case,
loading: false,
condition: {},
currentScenario: {},

View File

@ -33,6 +33,7 @@
:select-ids="new Set(Array.from(this.selectRows).map(row => row.id))" @refresh="initTableData"/>
<el-table
ref="table"
class="adjust-table"
border
@select-all="handleSelectAll"
@ -328,7 +329,7 @@ export default {
return {
type: TEST_PLAN_FUNCTION_TEST_CASE,
headerItems: Test_Plan_Function_Test_Case,
tableLabel: [],
tableLabel: Test_Plan_Function_Test_Case,
result: {},
deletePath: "/test/case/delete",
condition: {
@ -479,6 +480,9 @@ export default {
}
}
this.selectRows.clear();
if (this.$refs.table) {
this.$refs.table.doLayout()
}
});
}
getLabel(this, TEST_PLAN_FUNCTION_TEST_CASE);

View File

@ -154,7 +154,7 @@ export default {
return {
type: TEST_PLAN_LOAD_CASE,
headerItems: Test_Plan_Load_Case,
tableLabel: [],
tableLabel: Test_Plan_Load_Case,
condition: {},
result: {},
tableData: [],

View File

@ -20,7 +20,7 @@
<el-table-column prop="tags" :label="$t('api_test.automation.tag')" width="200px">
<template v-slot:default="scope">
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :content="itemName" style="margin-left: 5px"/>
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :content="itemName" style="margin-left: 0px; margin-right: 2px"/>
</template>
</el-table-column>

View File

@ -62,7 +62,7 @@
:label="$t('api_test.automation.tag')" :key="index">
<template v-slot:default="scope">
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain"
:content="itemName" style="margin-left: 5px"></ms-tag>
:content="itemName" style="margin-left: 0px; margin-right: 2px"></ms-tag>
</template>
</el-table-column>
<el-table-column

View File

@ -74,8 +74,12 @@
</el-row>
<el-row>
<el-col :offset="1">
<span class="cast_label">{{ $t('test_track.plan_view.relevance_test_case') }}</span>
<span class="cast_item">{{ testCase.prerequisite }}</span>
<span class="cast_label">关联测试</span>
<span v-for="(item,index) in testCase.list" :key="index">
<el-button @click="openTest(item)" type="text" style="margin-left: 7px;">{{
item.testName
}}</el-button>
</span>
</el-col>
</el-row>
<el-row>
@ -241,7 +245,7 @@ import PerformanceTestDetail from "../../../plan/view/comonents/test/Performance
import ApiTestResult from "../../../plan/view/comonents/test/ApiTestResult";
import ApiTestDetail from "../../../plan/view/comonents/test/ApiTestDetail";
import TestPlanTestCaseStatusButton from "../../../plan/common/TestPlanTestCaseStatusButton";
import {getCurrentProjectID, listenGoBack, removeGoBackListener} from "@/common/js/utils";
import {getCurrentProjectID, getUUID, listenGoBack, removeGoBackListener} from "@/common/js/utils";
import ReviewComment from "../../commom/ReviewComment";
import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment";
import ApiCaseItem from "@/business/components/api/definition/components/case/ApiCaseItem";
@ -295,6 +299,35 @@ export default {
}
},
methods: {
openTest(item) {
const type = item.testType;
const id = item.testId;
switch (type) {
case "performance": {
let performanceData = this.$router.resolve({
path: '/performance/test/edit/' + id,
})
window.open(performanceData.href, '_blank');
break;
}
case "testcase": {
let caseData = this.$router.resolve({
name: 'ApiDefinition',
params: {redirectID: getUUID(), dataType: "apiTestCase", dataSelectRange: 'single:' + id}
});
window.open(caseData.href, '_blank');
break;
}
case "automation": {
let automationData = this.$router.resolve({
name: 'ApiAutomation',
params: {redirectID: getUUID(), dataType: "scenario", dataSelectRange: 'edit:' + id}
});
window.open(automationData.href, '_blank');
break;
}
}
},
handleClose() {
removeGoBackListener(this.handleClose);
this.showDialog = false;
@ -354,6 +387,7 @@ export default {
item.steptResults.push(item.steps[i]);
}
this.testCase = item;
console.log(this.testCase)
this.getRelatedTest();
this.getComments(item);
/* this.initTest();*/

@ -1 +1 @@
Subproject commit 3571feccf7c2bc68e4b619f6c367ac47d37c6723
Subproject commit bc5735a2eb796640bde400ae6cafca6229672905

View File

@ -945,9 +945,9 @@ export default {
export_tip: "Export Tip",
ms_tip: "Support for MeterSphere JSON format",
ms_export_tip: "Export jSON-formatted files via MeterSphere website or browser plug-ins",
har_export_tip: "Export Har files by browser dev-tool",
har_export_tip: "Export HAR files by browser dev-tool",
swagger_tip: "Swagger 2.0 and 3.0 json files are supported",
har_tip: "Only Har files are supported",
har_tip: "Only HAR files are supported",
postman_tip: "Only Postman Collection V2.1 json files are supported",
postman_export_tip: "Export the test collection by Postman",
swagger_export_tip: "Export jSON-formatted files via Swagger website",

View File

@ -948,10 +948,10 @@ export default {
export_tip: "导出方法",
ms_tip: "支持 MeterSphere json 格式",
ms_export_tip: "通过 MeterSphere 接口测试页面或者浏览器插件导出 json 格式文件",
har_export_tip: "通过 浏览器的开发者工具 导出 Har 格式文件",
har_export_tip: "通过 浏览器的开发者工具 导出 HAR 格式文件",
postman_tip: "只支持 Postman Collection v2.1 格式的 json 文件",
swagger_tip: "支持 Swagger 2.0 与 3.0 版本的 json 文件",
har_tip: "只支持 Har 文件",
har_tip: "只支持 HAR 文件",
post_export_tip: "通过 Postman 导出测试集合",
swagger_export_tip: "通过 Swagger 页面导出",
jmeter_export_tip: "通过 JMeter 生成JMX文件",

View File

@ -947,10 +947,10 @@ export default {
export_tip: "導出方法",
ms_tip: "支持 MeterSphere json 格式",
ms_export_tip: "通過 MeterSphere 接口測試頁面或者瀏覽器插件導出 json 格式文件",
har_export_tip: "通过 瀏覽器到開發者工具 导出 Har 格式文件",
har_export_tip: "通过 瀏覽器到開發者工具 导出 HAR 格式文件",
postman_tip: "只支持 Postman Collection v2.1 格式的 json 文件",
swagger_tip: "支持 Swagger 2.0 與 3.0 版本的 json 文件",
har_tip: "只支持 Har 文件",
har_tip: "只支持 HAR 文件",
post_export_tip: "通過 Postman 導出測試集合",
swagger_export_tip: "通過 Swagger 頁面導出",
jmeter_export_tip: "通過 JMeter 生成JMX文件",