Merge branch 'master' of https://github.com/metersphere/metersphere
This commit is contained in:
commit
0d8d12b17b
|
@ -1,16 +1,22 @@
|
||||||
package io.metersphere.api.controller;
|
package io.metersphere.api.controller;
|
||||||
|
|
||||||
|
import com.github.pagehelper.Page;
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
import io.metersphere.api.dto.APIReportResult;
|
import io.metersphere.api.dto.APIReportResult;
|
||||||
|
import io.metersphere.api.dto.DeleteAPIReportRequest;
|
||||||
|
import io.metersphere.api.dto.QueryAPIReportRequest;
|
||||||
|
import io.metersphere.api.dto.automation.APIScenarioReportResult;
|
||||||
import io.metersphere.api.service.ApiScenarioReportService;
|
import io.metersphere.api.service.ApiScenarioReportService;
|
||||||
import io.metersphere.commons.constants.RoleConstants;
|
import io.metersphere.commons.constants.RoleConstants;
|
||||||
|
import io.metersphere.commons.utils.PageUtils;
|
||||||
|
import io.metersphere.commons.utils.Pager;
|
||||||
|
import io.metersphere.commons.utils.SessionUtils;
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(value = "/api/scenario/report")
|
@RequestMapping(value = "/api/scenario/report")
|
||||||
|
@ -20,8 +26,41 @@ public class APIScenarioReportController {
|
||||||
@Resource
|
@Resource
|
||||||
private ApiScenarioReportService apiReportService;
|
private ApiScenarioReportService apiReportService;
|
||||||
|
|
||||||
@GetMapping("/get/{reportId}")
|
@GetMapping("/get/{reportId}/{infoDb}")
|
||||||
public APIReportResult get(@PathVariable String reportId) {
|
public APIReportResult get(@PathVariable String reportId,@PathVariable Boolean infoDb) {
|
||||||
|
if(infoDb){
|
||||||
|
return apiReportService.get(reportId);
|
||||||
|
}
|
||||||
return apiReportService.getCacheResult(reportId);
|
return apiReportService.getCacheResult(reportId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/list/{goPage}/{pageSize}")
|
||||||
|
public Pager<List<APIScenarioReportResult>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryAPIReportRequest request) {
|
||||||
|
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||||
|
request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
|
||||||
|
return PageUtils.setPageInfo(page, apiReportService.list(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/add")
|
||||||
|
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||||
|
public String add(@RequestBody APIScenarioReportResult node) {
|
||||||
|
return apiReportService.add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/update")
|
||||||
|
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||||
|
public String update(@RequestBody APIScenarioReportResult node) {
|
||||||
|
return apiReportService.update(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/delete")
|
||||||
|
public void delete(@RequestBody DeleteAPIReportRequest request) {
|
||||||
|
apiReportService.delete(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/batch/delete")
|
||||||
|
public void deleteAPIReportBatch(@RequestBody DeleteAPIReportRequest reportRequest) {
|
||||||
|
apiReportService.deleteAPIReportBatch(reportRequest);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.github.pagehelper.Page;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import io.metersphere.api.dto.automation.ApiScenarioDTO;
|
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.RunScenarioRequest;
|
||||||
import io.metersphere.api.dto.automation.SaveApiScenarioRequest;
|
import io.metersphere.api.dto.automation.SaveApiScenarioRequest;
|
||||||
import io.metersphere.api.dto.definition.RunDefinitionRequest;
|
import io.metersphere.api.dto.definition.RunDefinitionRequest;
|
||||||
import io.metersphere.api.service.ApiAutomationService;
|
import io.metersphere.api.service.ApiAutomationService;
|
||||||
|
@ -36,13 +37,13 @@ public class ApiAutomationController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/create")
|
@PostMapping(value = "/create")
|
||||||
public void create(@RequestBody SaveApiScenarioRequest request) {
|
public void create(@RequestPart("request") SaveApiScenarioRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||||
apiAutomationService.create(request);
|
apiAutomationService.create(request, bodyFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/update")
|
@PostMapping(value = "/update")
|
||||||
public void update(@RequestBody SaveApiScenarioRequest request) {
|
public void update(@RequestPart("request") SaveApiScenarioRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||||
apiAutomationService.update(request);
|
apiAutomationService.update(request, bodyFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/delete/{id}")
|
@GetMapping("/delete/{id}")
|
||||||
|
@ -70,9 +71,15 @@ public class ApiAutomationController {
|
||||||
return apiAutomationService.getApiScenarios(ids);
|
return apiAutomationService.getApiScenarios(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/run")
|
@PostMapping(value = "/run/debug")
|
||||||
public void runDebug(@RequestPart("request") RunDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
public void runDebug(@RequestPart("request") RunDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||||
apiAutomationService.run(request, bodyFiles);
|
apiAutomationService.run(request, bodyFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/run")
|
||||||
|
public void run(@RequestBody RunScenarioRequest request) {
|
||||||
|
apiAutomationService.run(request);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package io.metersphere.api.dto.automation;
|
||||||
|
|
||||||
|
import io.metersphere.base.domain.ApiScenarioReport;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class APIScenarioReportResult extends ApiScenarioReport {
|
||||||
|
|
||||||
|
private String testName;
|
||||||
|
|
||||||
|
private String projectName;
|
||||||
|
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
private String content;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package io.metersphere.api.dto.automation;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class RunScenarioRequest {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String reportId;
|
||||||
|
|
||||||
|
private String environmentId;
|
||||||
|
|
||||||
|
private List<String> scenarioIds;
|
||||||
|
}
|
|
@ -3,6 +3,8 @@ package io.metersphere.api.dto.automation;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
public class SaveApiScenarioRequest {
|
public class SaveApiScenarioRequest {
|
||||||
|
@ -35,4 +37,6 @@ public class SaveApiScenarioRequest {
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
private String scenarioDefinition;
|
private String scenarioDefinition;
|
||||||
|
|
||||||
|
List<String> bodyUploadIds;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@ import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
import com.alibaba.fastjson.annotation.JSONType;
|
import com.alibaba.fastjson.annotation.JSONType;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
||||||
import io.metersphere.api.service.ApiAutomationService;
|
import io.metersphere.api.service.ApiAutomationService;
|
||||||
import io.metersphere.api.service.ApiTestEnvironmentService;
|
import io.metersphere.api.service.ApiTestEnvironmentService;
|
||||||
|
@ -15,6 +18,7 @@ import lombok.EqualsAndHashCode;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.jorphan.collections.HashTree;
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@ -41,14 +45,21 @@ public class MsScenario extends MsTestElement {
|
||||||
if (this.getReferenced() != null && this.getReferenced().equals("Deleted")) {
|
if (this.getReferenced() != null && this.getReferenced().equals("Deleted")) {
|
||||||
return;
|
return;
|
||||||
} else if (this.getReferenced() != null && this.getReferenced().equals("REF")) {
|
} else if (this.getReferenced() != null && this.getReferenced().equals("REF")) {
|
||||||
ApiAutomationService apiAutomationService = CommonBeanFactory.getBean(ApiAutomationService.class);
|
try {
|
||||||
ApiScenario scenario = apiAutomationService.getApiScenario(this.getId());
|
ApiAutomationService apiAutomationService = CommonBeanFactory.getBean(ApiAutomationService.class);
|
||||||
JSONObject element = JSON.parseObject(scenario.getScenarioDefinition());
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
List<MsTestElement> dataArr = JSON.parseArray(element.getString("hashTree"), MsTestElement.class);
|
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
if (hashTree == null) {
|
ApiScenario scenario = apiAutomationService.getApiScenario(this.getId());
|
||||||
hashTree = dataArr;
|
JSONObject element = JSON.parseObject(scenario.getScenarioDefinition());
|
||||||
} else {
|
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"), new TypeReference<LinkedList<MsTestElement>>() {
|
||||||
hashTree.addAll(dataArr);
|
});
|
||||||
|
if (hashTree == null) {
|
||||||
|
hashTree = elements;
|
||||||
|
} else {
|
||||||
|
hashTree.addAll(elements);
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (CollectionUtils.isNotEmpty(hashTree)) {
|
if (CollectionUtils.isNotEmpty(hashTree)) {
|
||||||
|
|
|
@ -51,7 +51,7 @@ import java.util.List;
|
||||||
MsJSR223PreProcessor.class, MsTestPlan.class, MsThreadGroup.class, AuthManager.class, MsAssertions.class,
|
MsJSR223PreProcessor.class, MsTestPlan.class, MsThreadGroup.class, AuthManager.class, MsAssertions.class,
|
||||||
MsExtract.class, MsTCPSampler.class, MsDubboSampler.class, MsJDBCSampler.class, MsConstantTimer.class, MsIfController.class, MsScenario.class}, typeKey = "type")
|
MsExtract.class, MsTCPSampler.class, MsDubboSampler.class, MsJDBCSampler.class, MsConstantTimer.class, MsIfController.class, MsScenario.class}, typeKey = "type")
|
||||||
@Data
|
@Data
|
||||||
public abstract class MsTestElement {
|
public class MsTestElement {
|
||||||
private String type;
|
private String type;
|
||||||
@JSONField(ordinal = 1)
|
@JSONField(ordinal = 1)
|
||||||
private String id;
|
private String id;
|
||||||
|
|
|
@ -50,4 +50,5 @@ public class MsThreadGroup extends MsTestElement {
|
||||||
threadGroup.setSamplerController(loopController);
|
threadGroup.setSamplerController(loopController);
|
||||||
return threadGroup;
|
return threadGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
}
|
}
|
||||||
} else if (StringUtils.equals(this.runMode, ApiRunMode.SCENARIO.name())) {
|
} else if (StringUtils.equals(this.runMode, ApiRunMode.SCENARIO.name())) {
|
||||||
// 执行报告不需要存储,由用户确认后在存储
|
// 执行报告不需要存储,由用户确认后在存储
|
||||||
testResult.setTestId(debugReportId);
|
testResult.setTestId(testId);
|
||||||
apiScenarioReportService.complete(testResult);
|
apiScenarioReportService.complete(testResult);
|
||||||
} else {
|
} else {
|
||||||
apiTestService.changeStatus(testId, APITestStatus.Completed);
|
apiTestService.changeStatus(testId, APITestStatus.Completed);
|
||||||
|
|
|
@ -2,13 +2,16 @@ package io.metersphere.api.service;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import io.metersphere.api.dto.APIReportResult;
|
import io.metersphere.api.dto.APIReportResult;
|
||||||
import io.metersphere.api.dto.automation.ApiScenarioDTO;
|
import io.metersphere.api.dto.automation.*;
|
||||||
import io.metersphere.api.dto.automation.ApiScenarioRequest;
|
|
||||||
import io.metersphere.api.dto.automation.SaveApiScenarioRequest;
|
|
||||||
import io.metersphere.api.dto.automation.ScenarioStatus;
|
|
||||||
import io.metersphere.api.dto.definition.RunDefinitionRequest;
|
import io.metersphere.api.dto.definition.RunDefinitionRequest;
|
||||||
|
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.scenario.environment.EnvironmentConfig;
|
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
||||||
import io.metersphere.api.jmeter.JMeterService;
|
import io.metersphere.api.jmeter.JMeterService;
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
|
@ -24,6 +27,7 @@ import io.metersphere.i18n.Translator;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.jorphan.collections.HashTree;
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
import org.apache.jorphan.collections.ListedHashTree;
|
||||||
import org.aspectj.util.FileUtil;
|
import org.aspectj.util.FileUtil;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
@ -32,9 +36,9 @@ import org.springframework.web.multipart.MultipartFile;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@ -83,8 +87,9 @@ public class ApiAutomationService {
|
||||||
apiScenarioMapper.deleteByExample(example);
|
apiScenarioMapper.deleteByExample(example);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void create(SaveApiScenarioRequest request) {
|
public void create(SaveApiScenarioRequest request, List<MultipartFile> bodyFiles) {
|
||||||
checkNameExist(request);
|
checkNameExist(request);
|
||||||
|
|
||||||
final ApiScenario scenario = new ApiScenario();
|
final ApiScenario scenario = new ApiScenario();
|
||||||
scenario.setId(request.getId());
|
scenario.setId(request.getId());
|
||||||
scenario.setName(request.getName());
|
scenario.setName(request.getName());
|
||||||
|
@ -111,10 +116,16 @@ public class ApiAutomationService {
|
||||||
}
|
}
|
||||||
scenario.setDescription(request.getDescription());
|
scenario.setDescription(request.getDescription());
|
||||||
apiScenarioMapper.insert(scenario);
|
apiScenarioMapper.insert(scenario);
|
||||||
|
|
||||||
|
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
|
||||||
|
createBodyFiles(bodyUploadIds, bodyFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(SaveApiScenarioRequest request) {
|
public void update(SaveApiScenarioRequest request, List<MultipartFile> bodyFiles) {
|
||||||
checkNameExist(request);
|
checkNameExist(request);
|
||||||
|
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
|
||||||
|
createBodyFiles(bodyUploadIds, bodyFiles);
|
||||||
|
|
||||||
final ApiScenario scenario = new ApiScenario();
|
final ApiScenario scenario = new ApiScenario();
|
||||||
scenario.setId(request.getId());
|
scenario.setId(request.getId());
|
||||||
scenario.setName(request.getName());
|
scenario.setName(request.getName());
|
||||||
|
@ -176,7 +187,7 @@ public class ApiAutomationService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createBodyFiles(List<String> bodyUploadIds, List<MultipartFile> bodyFiles) {
|
private void createBodyFiles(List<String> bodyUploadIds, List<MultipartFile> bodyFiles) {
|
||||||
if (!bodyUploadIds.isEmpty()) {
|
if (!bodyUploadIds.isEmpty() && !bodyFiles.isEmpty()) {
|
||||||
File testDir = new File(BODY_FILE_DIR);
|
File testDir = new File(BODY_FILE_DIR);
|
||||||
if (!testDir.exists()) {
|
if (!testDir.exists()) {
|
||||||
testDir.mkdirs();
|
testDir.mkdirs();
|
||||||
|
@ -208,6 +219,63 @@ public class ApiAutomationService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createAPIReportResult(String id) {
|
||||||
|
APIReportResult report = new APIReportResult();
|
||||||
|
report.setId(id);
|
||||||
|
report.setTestId(id);
|
||||||
|
report.setName("");
|
||||||
|
report.setTriggerMode(null);
|
||||||
|
report.setCreateTime(System.currentTimeMillis());
|
||||||
|
report.setUpdateTime(System.currentTimeMillis());
|
||||||
|
report.setStatus(APITestStatus.Running.name());
|
||||||
|
report.setUserId(SessionUtils.getUserId());
|
||||||
|
apiReportService.addResult(report);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 场景测试执行
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String run(RunScenarioRequest request) {
|
||||||
|
List<ApiScenario> apiScenarios = extApiScenarioMapper.selectIds(request.getScenarioIds());
|
||||||
|
MsTestPlan testPlan = new MsTestPlan();
|
||||||
|
testPlan.setHashTree(new LinkedList<>());
|
||||||
|
HashTree jmeterTestPlanHashTree = new ListedHashTree();
|
||||||
|
EnvironmentConfig config = null;
|
||||||
|
for (ApiScenario item : apiScenarios) {
|
||||||
|
MsThreadGroup group = new MsThreadGroup();
|
||||||
|
group.setLabel(item.getName());
|
||||||
|
group.setName(item.getName());
|
||||||
|
try {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
|
JSONObject element = JSON.parseObject(item.getScenarioDefinition());
|
||||||
|
String environmentId = element.getString("environmentId");
|
||||||
|
if (environmentId != null) {
|
||||||
|
ApiTestEnvironmentWithBLOBs environment = environmentService.get(environmentId);
|
||||||
|
config = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"), new TypeReference<LinkedList<MsTestElement>>() {
|
||||||
|
});
|
||||||
|
group.setHashTree(elements);
|
||||||
|
testPlan.getHashTree().add(group);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testPlan.toHashTree(jmeterTestPlanHashTree, testPlan.getHashTree(), config);
|
||||||
|
|
||||||
|
// 调用执行方法
|
||||||
|
jMeterService.runDefinition(request.getId(), jmeterTestPlanHashTree, request.getReportId(), ApiRunMode.SCENARIO.name());
|
||||||
|
createAPIReportResult(request.getId());
|
||||||
|
return request.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 场景测试执行
|
* 场景测试执行
|
||||||
*
|
*
|
||||||
|
@ -228,17 +296,7 @@ public class ApiAutomationService {
|
||||||
|
|
||||||
// 调用执行方法
|
// 调用执行方法
|
||||||
jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), ApiRunMode.SCENARIO.name());
|
jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), ApiRunMode.SCENARIO.name());
|
||||||
APIReportResult report = new APIReportResult();
|
createAPIReportResult(request.getId());
|
||||||
report.setId(UUID.randomUUID().toString());
|
|
||||||
report.setTestId(request.getReportId());
|
|
||||||
report.setName("RUN");
|
|
||||||
report.setTriggerMode(null);
|
|
||||||
report.setCreateTime(System.currentTimeMillis());
|
|
||||||
report.setUpdateTime(System.currentTimeMillis());
|
|
||||||
report.setStatus(APITestStatus.Running.name());
|
|
||||||
report.setUserId(SessionUtils.getUserId());
|
|
||||||
apiReportService.addResult(report);
|
|
||||||
return request.getId();
|
return request.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,23 +2,39 @@ package io.metersphere.api.service;
|
||||||
|
|
||||||
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.DeleteAPIReportRequest;
|
||||||
|
import io.metersphere.api.dto.QueryAPIReportRequest;
|
||||||
|
import io.metersphere.api.dto.automation.APIScenarioReportResult;
|
||||||
import io.metersphere.api.jmeter.TestResult;
|
import io.metersphere.api.jmeter.TestResult;
|
||||||
import io.metersphere.base.domain.ApiTestReportDetail;
|
import io.metersphere.base.domain.*;
|
||||||
|
import io.metersphere.base.mapper.ApiScenarioReportDetailMapper;
|
||||||
|
import io.metersphere.base.mapper.ApiScenarioReportMapper;
|
||||||
|
import io.metersphere.base.mapper.ext.ExtApiScenarioReportMapper;
|
||||||
import io.metersphere.commons.constants.APITestStatus;
|
import io.metersphere.commons.constants.APITestStatus;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
|
import io.metersphere.commons.utils.ServiceUtils;
|
||||||
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;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import sun.security.util.Cache;
|
import sun.security.util.Cache;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public class ApiScenarioReportService {
|
public class ApiScenarioReportService {
|
||||||
|
|
||||||
private static Cache cache = Cache.newHardMemoryCache(0, 3600 * 24);
|
private static Cache cache = Cache.newHardMemoryCache(0, 3600 * 24);
|
||||||
|
@Resource
|
||||||
|
private ExtApiScenarioReportMapper extApiScenarioReportMapper;
|
||||||
|
@Resource
|
||||||
|
private ApiScenarioReportMapper apiScenarioReportMapper;
|
||||||
|
@Resource
|
||||||
|
private ApiScenarioReportDetailMapper apiScenarioReportDetailMapper;
|
||||||
|
|
||||||
public void complete(TestResult result) {
|
public void complete(TestResult result) {
|
||||||
Object obj = cache.get(result.getTestId());
|
Object obj = cache.get(result.getTestId());
|
||||||
|
@ -64,4 +80,103 @@ public class ApiScenarioReportService {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public APIReportResult get(String reportId) {
|
||||||
|
APIReportResult reportResult = extApiScenarioReportMapper.get(reportId);
|
||||||
|
ApiScenarioReportDetail detail = apiScenarioReportDetailMapper.selectByPrimaryKey(reportId);
|
||||||
|
if (detail != null) {
|
||||||
|
reportResult.setContent(new String(detail.getContent(), StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
return reportResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<APIScenarioReportResult> list(QueryAPIReportRequest request) {
|
||||||
|
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||||
|
return extApiScenarioReportMapper.list(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkNameExist(APIScenarioReportResult request) {
|
||||||
|
ApiScenarioReportExample example = new ApiScenarioReportExample();
|
||||||
|
example.createCriteria().andNameEqualTo(request.getName()).andProjectIdEqualTo(request.getProjectId()).andIdNotEqualTo(request.getId());
|
||||||
|
if (apiScenarioReportMapper.countByExample(example) > 0) {
|
||||||
|
MSException.throwException(Translator.get("load_test_already_exists"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApiScenarioReport createReport(APIScenarioReportResult test) {
|
||||||
|
checkNameExist(test);
|
||||||
|
ApiScenarioReport report = new ApiScenarioReport();
|
||||||
|
report.setId(UUID.randomUUID().toString());
|
||||||
|
report.setProjectId(test.getProjectId());
|
||||||
|
report.setName(test.getName());
|
||||||
|
report.setTriggerMode(test.getTriggerMode());
|
||||||
|
report.setDescription(test.getDescription());
|
||||||
|
report.setCreateTime(System.currentTimeMillis());
|
||||||
|
report.setUpdateTime(System.currentTimeMillis());
|
||||||
|
report.setStatus(test.getStatus());
|
||||||
|
report.setUserId(test.getUserId());
|
||||||
|
apiScenarioReportMapper.insert(report);
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApiScenarioReport updateReport(APIScenarioReportResult test) {
|
||||||
|
checkNameExist(test);
|
||||||
|
ApiScenarioReport report = new ApiScenarioReport();
|
||||||
|
report.setId(test.getId());
|
||||||
|
report.setProjectId(test.getProjectId());
|
||||||
|
report.setName(test.getName());
|
||||||
|
report.setTriggerMode(test.getTriggerMode());
|
||||||
|
report.setDescription(test.getDescription());
|
||||||
|
report.setCreateTime(System.currentTimeMillis());
|
||||||
|
report.setUpdateTime(System.currentTimeMillis());
|
||||||
|
report.setStatus(test.getStatus());
|
||||||
|
report.setUserId(test.getUserId());
|
||||||
|
apiScenarioReportMapper.updateByPrimaryKey(report);
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String add(APIScenarioReportResult test) {
|
||||||
|
ApiScenarioReport report = createReport(test);
|
||||||
|
ApiScenarioReportDetail detail = new ApiScenarioReportDetail();
|
||||||
|
detail.setContent(test.getContent().getBytes(StandardCharsets.UTF_8));
|
||||||
|
detail.setReportId(report.getId());
|
||||||
|
detail.setProjectId(test.getProjectId());
|
||||||
|
apiScenarioReportDetailMapper.insert(detail);
|
||||||
|
return report.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String update(APIScenarioReportResult test) {
|
||||||
|
ApiScenarioReport report = updateReport(test);
|
||||||
|
ApiScenarioReportDetail detail = apiScenarioReportDetailMapper.selectByPrimaryKey(test.getId());
|
||||||
|
if (detail == null) {
|
||||||
|
detail = new ApiScenarioReportDetail();
|
||||||
|
detail.setContent(test.getContent().getBytes(StandardCharsets.UTF_8));
|
||||||
|
detail.setReportId(report.getId());
|
||||||
|
detail.setProjectId(test.getProjectId());
|
||||||
|
apiScenarioReportDetailMapper.insert(detail);
|
||||||
|
} else {
|
||||||
|
detail.setContent(test.getContent().getBytes(StandardCharsets.UTF_8));
|
||||||
|
detail.setReportId(report.getId());
|
||||||
|
detail.setProjectId(test.getProjectId());
|
||||||
|
apiScenarioReportDetailMapper.updateByPrimaryKey(detail);
|
||||||
|
}
|
||||||
|
return report.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(DeleteAPIReportRequest request) {
|
||||||
|
apiScenarioReportDetailMapper.deleteByPrimaryKey(request.getId());
|
||||||
|
apiScenarioReportMapper.deleteByPrimaryKey(request.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteAPIReportBatch(DeleteAPIReportRequest reportRequest) {
|
||||||
|
ApiScenarioReportDetailExample detailExample = new ApiScenarioReportDetailExample();
|
||||||
|
detailExample.createCriteria().andReportIdIn(reportRequest.getIds());
|
||||||
|
apiScenarioReportDetailMapper.deleteByExample(detailExample);
|
||||||
|
|
||||||
|
ApiScenarioReportExample apiTestReportExample = new ApiScenarioReportExample();
|
||||||
|
apiTestReportExample.createCriteria().andIdIn(reportRequest.getIds());
|
||||||
|
apiScenarioReportMapper.deleteByExample(apiTestReportExample);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
package io.metersphere.base.domain;
|
package io.metersphere.base.domain;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class ApiScenarioReport implements Serializable {
|
public class ApiScenarioReport implements Serializable {
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
private String scenarioId;
|
private String projectId;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import lombok.Data;
|
||||||
public class ApiScenarioReportDetail implements Serializable {
|
public class ApiScenarioReportDetail implements Serializable {
|
||||||
private String reportId;
|
private String reportId;
|
||||||
|
|
||||||
private String scenarioId;
|
private String projectId;
|
||||||
|
|
||||||
private byte[] content;
|
private byte[] content;
|
||||||
|
|
||||||
|
|
|
@ -174,73 +174,73 @@ public class ApiScenarioReportDetailExample {
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdIsNull() {
|
public Criteria andProjectIdIsNull() {
|
||||||
addCriterion("scenario_id is null");
|
addCriterion("project_id is null");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdIsNotNull() {
|
public Criteria andProjectIdIsNotNull() {
|
||||||
addCriterion("scenario_id is not null");
|
addCriterion("project_id is not null");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdEqualTo(String value) {
|
public Criteria andProjectIdEqualTo(String value) {
|
||||||
addCriterion("scenario_id =", value, "scenarioId");
|
addCriterion("project_id =", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdNotEqualTo(String value) {
|
public Criteria andProjectIdNotEqualTo(String value) {
|
||||||
addCriterion("scenario_id <>", value, "scenarioId");
|
addCriterion("project_id <>", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdGreaterThan(String value) {
|
public Criteria andProjectIdGreaterThan(String value) {
|
||||||
addCriterion("scenario_id >", value, "scenarioId");
|
addCriterion("project_id >", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdGreaterThanOrEqualTo(String value) {
|
public Criteria andProjectIdGreaterThanOrEqualTo(String value) {
|
||||||
addCriterion("scenario_id >=", value, "scenarioId");
|
addCriterion("project_id >=", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdLessThan(String value) {
|
public Criteria andProjectIdLessThan(String value) {
|
||||||
addCriterion("scenario_id <", value, "scenarioId");
|
addCriterion("project_id <", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdLessThanOrEqualTo(String value) {
|
public Criteria andProjectIdLessThanOrEqualTo(String value) {
|
||||||
addCriterion("scenario_id <=", value, "scenarioId");
|
addCriterion("project_id <=", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdLike(String value) {
|
public Criteria andProjectIdLike(String value) {
|
||||||
addCriterion("scenario_id like", value, "scenarioId");
|
addCriterion("project_id like", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdNotLike(String value) {
|
public Criteria andProjectIdNotLike(String value) {
|
||||||
addCriterion("scenario_id not like", value, "scenarioId");
|
addCriterion("project_id not like", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdIn(List<String> values) {
|
public Criteria andProjectIdIn(List<String> values) {
|
||||||
addCriterion("scenario_id in", values, "scenarioId");
|
addCriterion("project_id in", values, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdNotIn(List<String> values) {
|
public Criteria andProjectIdNotIn(List<String> values) {
|
||||||
addCriterion("scenario_id not in", values, "scenarioId");
|
addCriterion("project_id not in", values, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdBetween(String value1, String value2) {
|
public Criteria andProjectIdBetween(String value1, String value2) {
|
||||||
addCriterion("scenario_id between", value1, value2, "scenarioId");
|
addCriterion("project_id between", value1, value2, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdNotBetween(String value1, String value2) {
|
public Criteria andProjectIdNotBetween(String value1, String value2) {
|
||||||
addCriterion("scenario_id not between", value1, value2, "scenarioId");
|
addCriterion("project_id not between", value1, value2, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,73 +174,73 @@ public class ApiScenarioReportExample {
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdIsNull() {
|
public Criteria andProjectIdIsNull() {
|
||||||
addCriterion("scenario_id is null");
|
addCriterion("project_id is null");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdIsNotNull() {
|
public Criteria andProjectIdIsNotNull() {
|
||||||
addCriterion("scenario_id is not null");
|
addCriterion("project_id is not null");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdEqualTo(String value) {
|
public Criteria andProjectIdEqualTo(String value) {
|
||||||
addCriterion("scenario_id =", value, "scenarioId");
|
addCriterion("project_id =", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdNotEqualTo(String value) {
|
public Criteria andProjectIdNotEqualTo(String value) {
|
||||||
addCriterion("scenario_id <>", value, "scenarioId");
|
addCriterion("project_id <>", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdGreaterThan(String value) {
|
public Criteria andProjectIdGreaterThan(String value) {
|
||||||
addCriterion("scenario_id >", value, "scenarioId");
|
addCriterion("project_id >", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdGreaterThanOrEqualTo(String value) {
|
public Criteria andProjectIdGreaterThanOrEqualTo(String value) {
|
||||||
addCriterion("scenario_id >=", value, "scenarioId");
|
addCriterion("project_id >=", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdLessThan(String value) {
|
public Criteria andProjectIdLessThan(String value) {
|
||||||
addCriterion("scenario_id <", value, "scenarioId");
|
addCriterion("project_id <", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdLessThanOrEqualTo(String value) {
|
public Criteria andProjectIdLessThanOrEqualTo(String value) {
|
||||||
addCriterion("scenario_id <=", value, "scenarioId");
|
addCriterion("project_id <=", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdLike(String value) {
|
public Criteria andProjectIdLike(String value) {
|
||||||
addCriterion("scenario_id like", value, "scenarioId");
|
addCriterion("project_id like", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdNotLike(String value) {
|
public Criteria andProjectIdNotLike(String value) {
|
||||||
addCriterion("scenario_id not like", value, "scenarioId");
|
addCriterion("project_id not like", value, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdIn(List<String> values) {
|
public Criteria andProjectIdIn(List<String> values) {
|
||||||
addCriterion("scenario_id in", values, "scenarioId");
|
addCriterion("project_id in", values, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdNotIn(List<String> values) {
|
public Criteria andProjectIdNotIn(List<String> values) {
|
||||||
addCriterion("scenario_id not in", values, "scenarioId");
|
addCriterion("project_id not in", values, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdBetween(String value1, String value2) {
|
public Criteria andProjectIdBetween(String value1, String value2) {
|
||||||
addCriterion("scenario_id between", value1, value2, "scenarioId");
|
addCriterion("project_id between", value1, value2, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andScenarioIdNotBetween(String value1, String value2) {
|
public Criteria andProjectIdNotBetween(String value1, String value2) {
|
||||||
addCriterion("scenario_id not between", value1, value2, "scenarioId");
|
addCriterion("project_id not between", value1, value2, "projectId");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<mapper namespace="io.metersphere.base.mapper.ApiScenarioReportDetailMapper">
|
<mapper namespace="io.metersphere.base.mapper.ApiScenarioReportDetailMapper">
|
||||||
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.ApiScenarioReportDetail">
|
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.ApiScenarioReportDetail">
|
||||||
<id column="report_id" jdbcType="VARCHAR" property="reportId" />
|
<id column="report_id" jdbcType="VARCHAR" property="reportId" />
|
||||||
<result column="scenario_id" jdbcType="VARCHAR" property="scenarioId" />
|
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiScenarioReportDetail">
|
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiScenarioReportDetail">
|
||||||
<result column="content" jdbcType="LONGVARBINARY" property="content" />
|
<result column="content" jdbcType="LONGVARBINARY" property="content" />
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
</where>
|
</where>
|
||||||
</sql>
|
</sql>
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
report_id, scenario_id
|
report_id, project_id
|
||||||
</sql>
|
</sql>
|
||||||
<sql id="Blob_Column_List">
|
<sql id="Blob_Column_List">
|
||||||
content
|
content
|
||||||
|
@ -121,9 +121,9 @@
|
||||||
</if>
|
</if>
|
||||||
</delete>
|
</delete>
|
||||||
<insert id="insert" parameterType="io.metersphere.base.domain.ApiScenarioReportDetail">
|
<insert id="insert" parameterType="io.metersphere.base.domain.ApiScenarioReportDetail">
|
||||||
insert into api_scenario_report_detail (report_id, scenario_id, content
|
insert into api_scenario_report_detail (report_id, project_id, content
|
||||||
)
|
)
|
||||||
values (#{reportId,jdbcType=VARCHAR}, #{scenarioId,jdbcType=VARCHAR}, #{content,jdbcType=LONGVARBINARY}
|
values (#{reportId,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{content,jdbcType=LONGVARBINARY}
|
||||||
)
|
)
|
||||||
</insert>
|
</insert>
|
||||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiScenarioReportDetail">
|
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiScenarioReportDetail">
|
||||||
|
@ -132,8 +132,8 @@
|
||||||
<if test="reportId != null">
|
<if test="reportId != null">
|
||||||
report_id,
|
report_id,
|
||||||
</if>
|
</if>
|
||||||
<if test="scenarioId != null">
|
<if test="projectId != null">
|
||||||
scenario_id,
|
project_id,
|
||||||
</if>
|
</if>
|
||||||
<if test="content != null">
|
<if test="content != null">
|
||||||
content,
|
content,
|
||||||
|
@ -143,8 +143,8 @@
|
||||||
<if test="reportId != null">
|
<if test="reportId != null">
|
||||||
#{reportId,jdbcType=VARCHAR},
|
#{reportId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="scenarioId != null">
|
<if test="projectId != null">
|
||||||
#{scenarioId,jdbcType=VARCHAR},
|
#{projectId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="content != null">
|
<if test="content != null">
|
||||||
#{content,jdbcType=LONGVARBINARY},
|
#{content,jdbcType=LONGVARBINARY},
|
||||||
|
@ -163,8 +163,8 @@
|
||||||
<if test="record.reportId != null">
|
<if test="record.reportId != null">
|
||||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="record.scenarioId != null">
|
<if test="record.projectId != null">
|
||||||
scenario_id = #{record.scenarioId,jdbcType=VARCHAR},
|
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="record.content != null">
|
<if test="record.content != null">
|
||||||
content = #{record.content,jdbcType=LONGVARBINARY},
|
content = #{record.content,jdbcType=LONGVARBINARY},
|
||||||
|
@ -177,7 +177,7 @@
|
||||||
<update id="updateByExampleWithBLOBs" parameterType="map">
|
<update id="updateByExampleWithBLOBs" parameterType="map">
|
||||||
update api_scenario_report_detail
|
update api_scenario_report_detail
|
||||||
set report_id = #{record.reportId,jdbcType=VARCHAR},
|
set report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||||
scenario_id = #{record.scenarioId,jdbcType=VARCHAR},
|
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||||
content = #{record.content,jdbcType=LONGVARBINARY}
|
content = #{record.content,jdbcType=LONGVARBINARY}
|
||||||
<if test="_parameter != null">
|
<if test="_parameter != null">
|
||||||
<include refid="Update_By_Example_Where_Clause" />
|
<include refid="Update_By_Example_Where_Clause" />
|
||||||
|
@ -186,7 +186,7 @@
|
||||||
<update id="updateByExample" parameterType="map">
|
<update id="updateByExample" parameterType="map">
|
||||||
update api_scenario_report_detail
|
update api_scenario_report_detail
|
||||||
set report_id = #{record.reportId,jdbcType=VARCHAR},
|
set report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||||
scenario_id = #{record.scenarioId,jdbcType=VARCHAR}
|
project_id = #{record.projectId,jdbcType=VARCHAR}
|
||||||
<if test="_parameter != null">
|
<if test="_parameter != null">
|
||||||
<include refid="Update_By_Example_Where_Clause" />
|
<include refid="Update_By_Example_Where_Clause" />
|
||||||
</if>
|
</if>
|
||||||
|
@ -194,8 +194,8 @@
|
||||||
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.ApiScenarioReportDetail">
|
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.ApiScenarioReportDetail">
|
||||||
update api_scenario_report_detail
|
update api_scenario_report_detail
|
||||||
<set>
|
<set>
|
||||||
<if test="scenarioId != null">
|
<if test="projectId != null">
|
||||||
scenario_id = #{scenarioId,jdbcType=VARCHAR},
|
project_id = #{projectId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="content != null">
|
<if test="content != null">
|
||||||
content = #{content,jdbcType=LONGVARBINARY},
|
content = #{content,jdbcType=LONGVARBINARY},
|
||||||
|
@ -205,13 +205,13 @@
|
||||||
</update>
|
</update>
|
||||||
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.ApiScenarioReportDetail">
|
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.ApiScenarioReportDetail">
|
||||||
update api_scenario_report_detail
|
update api_scenario_report_detail
|
||||||
set scenario_id = #{scenarioId,jdbcType=VARCHAR},
|
set project_id = #{projectId,jdbcType=VARCHAR},
|
||||||
content = #{content,jdbcType=LONGVARBINARY}
|
content = #{content,jdbcType=LONGVARBINARY}
|
||||||
where report_id = #{reportId,jdbcType=VARCHAR}
|
where report_id = #{reportId,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.ApiScenarioReportDetail">
|
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.ApiScenarioReportDetail">
|
||||||
update api_scenario_report_detail
|
update api_scenario_report_detail
|
||||||
set scenario_id = #{scenarioId,jdbcType=VARCHAR}
|
set project_id = #{projectId,jdbcType=VARCHAR}
|
||||||
where report_id = #{reportId,jdbcType=VARCHAR}
|
where report_id = #{reportId,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
</mapper>
|
</mapper>
|
|
@ -3,7 +3,7 @@
|
||||||
<mapper namespace="io.metersphere.base.mapper.ApiScenarioReportMapper">
|
<mapper namespace="io.metersphere.base.mapper.ApiScenarioReportMapper">
|
||||||
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.ApiScenarioReport">
|
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.ApiScenarioReport">
|
||||||
<id column="id" jdbcType="VARCHAR" property="id" />
|
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||||
<result column="scenario_id" jdbcType="VARCHAR" property="scenarioId" />
|
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
|
||||||
<result column="name" jdbcType="VARCHAR" property="name" />
|
<result column="name" jdbcType="VARCHAR" property="name" />
|
||||||
<result column="description" jdbcType="VARCHAR" property="description" />
|
<result column="description" jdbcType="VARCHAR" property="description" />
|
||||||
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
</where>
|
</where>
|
||||||
</sql>
|
</sql>
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
id, scenario_id, `name`, description, create_time, update_time, `status`, user_id,
|
id, project_id, `name`, description, create_time, update_time, `status`, user_id,
|
||||||
trigger_mode
|
trigger_mode
|
||||||
</sql>
|
</sql>
|
||||||
<select id="selectByExample" parameterType="io.metersphere.base.domain.ApiScenarioReportExample" resultMap="BaseResultMap">
|
<select id="selectByExample" parameterType="io.metersphere.base.domain.ApiScenarioReportExample" resultMap="BaseResultMap">
|
||||||
|
@ -105,11 +105,11 @@
|
||||||
</if>
|
</if>
|
||||||
</delete>
|
</delete>
|
||||||
<insert id="insert" parameterType="io.metersphere.base.domain.ApiScenarioReport">
|
<insert id="insert" parameterType="io.metersphere.base.domain.ApiScenarioReport">
|
||||||
insert into api_scenario_report (id, scenario_id, `name`,
|
insert into api_scenario_report (id, project_id, `name`,
|
||||||
description, create_time, update_time,
|
description, create_time, update_time,
|
||||||
`status`, user_id, trigger_mode
|
`status`, user_id, trigger_mode
|
||||||
)
|
)
|
||||||
values (#{id,jdbcType=VARCHAR}, #{scenarioId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
|
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
|
||||||
#{description,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
#{description,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
||||||
#{status,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR}, #{triggerMode,jdbcType=VARCHAR}
|
#{status,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR}, #{triggerMode,jdbcType=VARCHAR}
|
||||||
)
|
)
|
||||||
|
@ -120,8 +120,8 @@
|
||||||
<if test="id != null">
|
<if test="id != null">
|
||||||
id,
|
id,
|
||||||
</if>
|
</if>
|
||||||
<if test="scenarioId != null">
|
<if test="projectId != null">
|
||||||
scenario_id,
|
project_id,
|
||||||
</if>
|
</if>
|
||||||
<if test="name != null">
|
<if test="name != null">
|
||||||
`name`,
|
`name`,
|
||||||
|
@ -149,8 +149,8 @@
|
||||||
<if test="id != null">
|
<if test="id != null">
|
||||||
#{id,jdbcType=VARCHAR},
|
#{id,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="scenarioId != null">
|
<if test="projectId != null">
|
||||||
#{scenarioId,jdbcType=VARCHAR},
|
#{projectId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="name != null">
|
<if test="name != null">
|
||||||
#{name,jdbcType=VARCHAR},
|
#{name,jdbcType=VARCHAR},
|
||||||
|
@ -187,8 +187,8 @@
|
||||||
<if test="record.id != null">
|
<if test="record.id != null">
|
||||||
id = #{record.id,jdbcType=VARCHAR},
|
id = #{record.id,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="record.scenarioId != null">
|
<if test="record.projectId != null">
|
||||||
scenario_id = #{record.scenarioId,jdbcType=VARCHAR},
|
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="record.name != null">
|
<if test="record.name != null">
|
||||||
`name` = #{record.name,jdbcType=VARCHAR},
|
`name` = #{record.name,jdbcType=VARCHAR},
|
||||||
|
@ -219,7 +219,7 @@
|
||||||
<update id="updateByExample" parameterType="map">
|
<update id="updateByExample" parameterType="map">
|
||||||
update api_scenario_report
|
update api_scenario_report
|
||||||
set id = #{record.id,jdbcType=VARCHAR},
|
set id = #{record.id,jdbcType=VARCHAR},
|
||||||
scenario_id = #{record.scenarioId,jdbcType=VARCHAR},
|
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||||
`name` = #{record.name,jdbcType=VARCHAR},
|
`name` = #{record.name,jdbcType=VARCHAR},
|
||||||
description = #{record.description,jdbcType=VARCHAR},
|
description = #{record.description,jdbcType=VARCHAR},
|
||||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||||
|
@ -234,8 +234,8 @@
|
||||||
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.ApiScenarioReport">
|
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.ApiScenarioReport">
|
||||||
update api_scenario_report
|
update api_scenario_report
|
||||||
<set>
|
<set>
|
||||||
<if test="scenarioId != null">
|
<if test="projectId != null">
|
||||||
scenario_id = #{scenarioId,jdbcType=VARCHAR},
|
project_id = #{projectId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="name != null">
|
<if test="name != null">
|
||||||
`name` = #{name,jdbcType=VARCHAR},
|
`name` = #{name,jdbcType=VARCHAR},
|
||||||
|
@ -263,7 +263,7 @@
|
||||||
</update>
|
</update>
|
||||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.ApiScenarioReport">
|
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.ApiScenarioReport">
|
||||||
update api_scenario_report
|
update api_scenario_report
|
||||||
set scenario_id = #{scenarioId,jdbcType=VARCHAR},
|
set project_id = #{projectId,jdbcType=VARCHAR},
|
||||||
`name` = #{name,jdbcType=VARCHAR},
|
`name` = #{name,jdbcType=VARCHAR},
|
||||||
description = #{description,jdbcType=VARCHAR},
|
description = #{description,jdbcType=VARCHAR},
|
||||||
create_time = #{createTime,jdbcType=BIGINT},
|
create_time = #{createTime,jdbcType=BIGINT},
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package io.metersphere.base.mapper.ext;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.APIReportResult;
|
||||||
|
import io.metersphere.api.dto.QueryAPIReportRequest;
|
||||||
|
import io.metersphere.api.dto.automation.APIScenarioReportResult;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface ExtApiScenarioReportMapper {
|
||||||
|
List<APIScenarioReportResult> list(@Param("request") QueryAPIReportRequest request);
|
||||||
|
|
||||||
|
APIReportResult get(@Param("reportId") String reportId);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,169 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="io.metersphere.base.mapper.ext.ExtApiScenarioReportMapper">
|
||||||
|
|
||||||
|
<resultMap id="BaseResultMap" type="io.metersphere.api.dto.automation.APIScenarioReportResult"
|
||||||
|
extends="io.metersphere.base.mapper.ApiScenarioReportMapper.BaseResultMap">
|
||||||
|
<result column="test_name" property="testName"/>
|
||||||
|
<result column="project_name" property="projectName"/>
|
||||||
|
<result column="user_name" property="userName"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="condition">
|
||||||
|
<choose>
|
||||||
|
<when test='${object}.operator == "like"'>
|
||||||
|
like CONCAT('%', #{${object}.value},'%')
|
||||||
|
</when>
|
||||||
|
<when test='${object}.operator == "not like"'>
|
||||||
|
not like CONCAT('%', #{${object}.value},'%')
|
||||||
|
</when>
|
||||||
|
<when test='${object}.operator == "in"'>
|
||||||
|
in
|
||||||
|
<foreach collection="${object}.value" item="v" separator="," open="(" close=")">
|
||||||
|
#{v}
|
||||||
|
</foreach>
|
||||||
|
</when>
|
||||||
|
<when test='${object}.operator == "not in"'>
|
||||||
|
not in
|
||||||
|
<foreach collection="${object}.value" item="v" separator="," open="(" close=")">
|
||||||
|
#{v}
|
||||||
|
</foreach>
|
||||||
|
</when>
|
||||||
|
<when test='${object}.operator == "between"'>
|
||||||
|
between #{${object}.value[0]} and #{${object}.value[1]}
|
||||||
|
</when>
|
||||||
|
<when test='${object}.operator == "gt"'>
|
||||||
|
> #{${object}.value}
|
||||||
|
</when>
|
||||||
|
<when test='${object}.operator == "lt"'>
|
||||||
|
< #{${object}.value}
|
||||||
|
</when>
|
||||||
|
<when test='${object}.operator == "ge"'>
|
||||||
|
>= #{${object}.value}
|
||||||
|
</when>
|
||||||
|
<when test='${object}.operator == "le"'>
|
||||||
|
<= #{${object}.value}
|
||||||
|
</when>
|
||||||
|
<when test='${object}.operator == "current user"'>
|
||||||
|
= '${@io.metersphere.commons.utils.SessionUtils@getUserId()}'
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
= #{${object}.value}
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<sql id="combine">
|
||||||
|
<if test='${condition}.name != null and (${name} == null or ${name} == "")'>
|
||||||
|
and r.name
|
||||||
|
<include refid="condition">
|
||||||
|
<property name="object" value="${condition}.name"/>
|
||||||
|
</include>
|
||||||
|
</if>
|
||||||
|
<if test="${condition}.testName != null">
|
||||||
|
and t.name
|
||||||
|
<include refid="condition">
|
||||||
|
<property name="object" value="${condition}.testName"/>
|
||||||
|
</include>
|
||||||
|
</if>
|
||||||
|
<if test="${condition}.projectName != null">
|
||||||
|
and project.name
|
||||||
|
<include refid="condition">
|
||||||
|
<property name="object" value="${condition}.projectName"/>
|
||||||
|
</include>
|
||||||
|
</if>
|
||||||
|
<if test="${condition}.createTime != null">
|
||||||
|
and r.create_time
|
||||||
|
<include refid="condition">
|
||||||
|
<property name="object" value="${condition}.createTime"/>
|
||||||
|
</include>
|
||||||
|
</if>
|
||||||
|
<if test="${condition}.status != null">
|
||||||
|
and r.status
|
||||||
|
<include refid="condition">
|
||||||
|
<property name="object" value="${condition}.status"/>
|
||||||
|
</include>
|
||||||
|
</if>
|
||||||
|
<if test="${condition}.triggerMode != null">
|
||||||
|
and r.trigger_mode
|
||||||
|
<include refid="condition">
|
||||||
|
<property name="object" value="${condition}.triggerMode"/>
|
||||||
|
</include>
|
||||||
|
</if>
|
||||||
|
<if test="${condition}.creator != null">
|
||||||
|
and r.user_id
|
||||||
|
<include refid="condition">
|
||||||
|
<property name="object" value="${condition}.creator"/>
|
||||||
|
</include>
|
||||||
|
</if>
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="list" resultMap="BaseResultMap">
|
||||||
|
SELECT r.name AS test_name,
|
||||||
|
r.name, r.description, r.id, r.project_id, r.create_time, r.update_time, r.status, r.trigger_mode,
|
||||||
|
project.name AS project_name, user.name AS user_name
|
||||||
|
FROM api_scenario_report r
|
||||||
|
LEFT JOIN project ON project.id = r.project_id
|
||||||
|
LEFT JOIN user ON user.id = r.user_id
|
||||||
|
<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 r.name like CONCAT('%', #{request.name},'%')
|
||||||
|
</if>
|
||||||
|
<if test="request.userId != null">
|
||||||
|
AND r.user_id = #{request.userId,jdbcType=VARCHAR}
|
||||||
|
</if>
|
||||||
|
<if test="request.projectId != null">
|
||||||
|
AND project.id = #{request.projectId}
|
||||||
|
</if>
|
||||||
|
<if test="request.workspaceId != null">
|
||||||
|
AND project.workspace_id = #{request.workspaceId,jdbcType=VARCHAR}
|
||||||
|
</if>
|
||||||
|
<if test="request.filters != null and request.filters.size() > 0">
|
||||||
|
<foreach collection="request.filters.entrySet()" index="key" item="values">
|
||||||
|
<if test="values != null and values.size() > 0">
|
||||||
|
<choose>
|
||||||
|
<when test="key=='status'">
|
||||||
|
and r.status in
|
||||||
|
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||||
|
#{value}
|
||||||
|
</foreach>
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
and r.trigger_mode in
|
||||||
|
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||||
|
#{value}
|
||||||
|
</foreach>
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
</if>
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
AND r.status != 'Debug'
|
||||||
|
</where>
|
||||||
|
<if test="request.orders != null and request.orders.size() > 0">
|
||||||
|
order by
|
||||||
|
<foreach collection="request.orders" separator="," item="order">
|
||||||
|
r.${order.name} ${order.type}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="get" resultType="io.metersphere.api.dto.APIReportResult">
|
||||||
|
SELECT r.*,r.id As testId, r.name AS test_name, project.name AS project_name, user.name AS user_name
|
||||||
|
FROM api_scenario_report r
|
||||||
|
LEFT JOIN project ON project.id = r.project_id
|
||||||
|
LEFT JOIN user ON user.id = r.user_id
|
||||||
|
<where>
|
||||||
|
r.id = #{reportId}
|
||||||
|
</where>
|
||||||
|
ORDER BY r.update_time DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
|
@ -83,4 +83,10 @@ public class ProjectController {
|
||||||
public void updateProject(@RequestBody Project Project) {
|
public void updateProject(@RequestBody Project Project) {
|
||||||
projectService.updateProject(Project);
|
projectService.updateProject(Project);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/search")
|
||||||
|
public List<ProjectDTO> searchProject(@RequestBody ProjectRequest projectRequest) {
|
||||||
|
projectRequest.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
|
||||||
|
return projectService.getProjectList(projectRequest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,10 +64,8 @@
|
||||||
|
|
||||||
<!--要生成的数据库表 -->
|
<!--要生成的数据库表 -->
|
||||||
|
|
||||||
<table tableName="schedule"/>
|
<table tableName="api_scenario_report"/>
|
||||||
<table tableName="notice"/>
|
<table tableName="api_scenario_report_detail"/>
|
||||||
<table tableName="message_task"/>
|
|
||||||
<table tableName="test_plan"/>
|
|
||||||
|
|
||||||
</context>
|
</context>
|
||||||
</generatorConfiguration>
|
</generatorConfiguration>
|
|
@ -4,12 +4,12 @@
|
||||||
<el-card>
|
<el-card>
|
||||||
<section class="report-container" v-if="this.report.testId">
|
<section class="report-container" v-if="this.report.testId">
|
||||||
|
|
||||||
<ms-api-report-view-header :report="report" @reportExport="handleExport"/>
|
<ms-api-report-view-header :report="report" @reportExport="handleExport" @reportSave="handleSave"/>
|
||||||
|
|
||||||
<main v-if="this.isNotRunning">
|
<main v-if="this.isNotRunning">
|
||||||
<ms-metric-chart :content="content" :totalTime="totalTime"/>
|
<ms-metric-chart :content="content" :totalTime="totalTime"/>
|
||||||
<div @click="active">
|
<div>
|
||||||
<ms-scenario-results :scenarios="content.scenarios" v-on:requestResult="requestResult"/>
|
<ms-scenario-results :scenarios="content.scenarios" v-on:requestResult="requestResult"/>
|
||||||
</div>
|
</div>
|
||||||
<el-collapse-transition>
|
<el-collapse-transition>
|
||||||
<div v-show="isActive" style="width: 99%">
|
<div v-show="isActive" style="width: 99%">
|
||||||
|
@ -64,10 +64,14 @@
|
||||||
requestType: undefined,
|
requestType: undefined,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: ['reportId'],
|
|
||||||
activated() {
|
activated() {
|
||||||
this.isRequestResult = false;
|
this.isRequestResult = false;
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
reportId: String,
|
||||||
|
currentProjectId: String,
|
||||||
|
infoDb: Boolean,
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
reportId() {
|
reportId() {
|
||||||
this.getReport();
|
this.getReport();
|
||||||
|
@ -91,7 +95,7 @@
|
||||||
getReport() {
|
getReport() {
|
||||||
this.init();
|
this.init();
|
||||||
if (this.reportId) {
|
if (this.reportId) {
|
||||||
let url = "/api/scenario/report/get/" + this.reportId;
|
let url = "/api/scenario/report/get/" + this.reportId + "/" + this.infoDb;
|
||||||
this.$get(url, response => {
|
this.$get(url, response => {
|
||||||
this.report = response.data || {};
|
this.report = response.data || {};
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
|
@ -99,7 +103,6 @@
|
||||||
try {
|
try {
|
||||||
this.content = JSON.parse(this.report.content);
|
this.content = JSON.parse(this.report.content);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// console.log(this.report.content)
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
this.getFails();
|
this.getFails();
|
||||||
|
@ -136,6 +139,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
requestResult(requestResult) {
|
requestResult(requestResult) {
|
||||||
|
this.active();
|
||||||
this.isRequestResult = false;
|
this.isRequestResult = false;
|
||||||
this.requestType = undefined;
|
this.requestType = undefined;
|
||||||
if (requestResult.request.body.indexOf('[Callable Statement]') > -1) {
|
if (requestResult.request.body.indexOf('[Callable Statement]') > -1) {
|
||||||
|
@ -155,6 +159,27 @@
|
||||||
reset();
|
reset();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
handleSave() {
|
||||||
|
if (!this.report.name) {
|
||||||
|
this.$warning(this.$t('api_test.automation.report_name_info'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.currentProjectId) {
|
||||||
|
this.$warning(this.$t('api_test.select_project'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.loading = true;
|
||||||
|
this.report.projectId = this.currentProjectId;
|
||||||
|
let url = "/api/scenario/report/add";
|
||||||
|
if (this.infoDb === true) {
|
||||||
|
url = "/api/scenario/report/update";
|
||||||
|
}
|
||||||
|
this.result = this.$post(url, this.report, response => {
|
||||||
|
this.$success(this.$t('commons.save_success'));
|
||||||
|
this.loading = false;
|
||||||
|
this.$emit('refresh');
|
||||||
|
});
|
||||||
|
},
|
||||||
exportReportReset() {
|
exportReportReset() {
|
||||||
this.$router.go(0);
|
this.$router.go(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,228 @@
|
||||||
|
<template>
|
||||||
|
<ms-container>
|
||||||
|
<ms-main-container>
|
||||||
|
<el-card class="table-card" v-loading="result.loading">
|
||||||
|
<template v-slot:header>
|
||||||
|
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search"
|
||||||
|
:title="$t('api_report.title')"
|
||||||
|
:show-create="false"/>
|
||||||
|
</template>
|
||||||
|
<el-table border :data="tableData" class="adjust-table table-content" @sort-change="sort"
|
||||||
|
@select-all="handleSelectAll"
|
||||||
|
@select="handleSelect"
|
||||||
|
@filter-change="filter" @row-click="handleView">
|
||||||
|
<el-table-column
|
||||||
|
type="selection"/>
|
||||||
|
<el-table-column width="40" :resizable="false" align="center">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectRows.size"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('commons.name')" width="200" show-overflow-tooltip prop="name">
|
||||||
|
</el-table-column>
|
||||||
|
<!--
|
||||||
|
<el-table-column prop="testName" :label="$t('api_report.test_name')" width="200" show-overflow-tooltip/>
|
||||||
|
-->
|
||||||
|
<el-table-column prop="projectName" :label="$t('load_test.project_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="createTime" width="250" :label="$t('commons.create_time')" sortable>
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="triggerMode" width="150" :label="$t('commons.trigger_mode.name')"
|
||||||
|
column-key="triggerMode" :filters="triggerFilters">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<report-trigger-mode-item :trigger-mode="scope.row.triggerMode"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="status" :label="$t('commons.status')"
|
||||||
|
column-key="status"
|
||||||
|
:filters="statusFilters">
|
||||||
|
<template v-slot:default="{row}">
|
||||||
|
<ms-api-report-status :row="row"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column width="150" :label="$t('commons.operating')">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<ms-table-operator-button :tip="$t('api_report.detail')" icon="el-icon-s-data"
|
||||||
|
@exec="handleView(scope.row)" type="primary"/>
|
||||||
|
<ms-table-operator-button :is-tester-permission="true" :tip="$t('api_report.delete')"
|
||||||
|
icon="el-icon-delete" @exec="handleDelete(scope.row)" type="danger"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<ms-table-pagination :change="search" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||||
|
:total="total"/>
|
||||||
|
</el-card>
|
||||||
|
</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%">
|
||||||
|
<ms-api-report-detail :report-id="reportId" :currentProjectId="currentProjectId" :info-db="true" @refresh="search"/>
|
||||||
|
</el-drawer>
|
||||||
|
</ms-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsTablePagination from "../../../common/pagination/TablePagination";
|
||||||
|
import MsTableHeader from "../../../common/components/MsTableHeader";
|
||||||
|
import MsContainer from "../../../common/components/MsContainer";
|
||||||
|
import MsMainContainer from "../../../common/components/MsMainContainer";
|
||||||
|
import MsApiReportStatus from "./ApiReportStatus";
|
||||||
|
import {_filter, _sort} from "@/common/js/utils";
|
||||||
|
import MsTableOperatorButton from "../../../common/components/MsTableOperatorButton";
|
||||||
|
import ReportTriggerModeItem from "../../../common/tableItem/ReportTriggerModeItem";
|
||||||
|
import {REPORT_CONFIGS} from "../../../common/components/search/search-components";
|
||||||
|
import {ApiEvent, LIST_CHANGE} from "@/business/components/common/head/ListEvent";
|
||||||
|
import ShowMoreBtn from "../../../track/case/components/ShowMoreBtn";
|
||||||
|
import MsApiReportDetail from "./ApiReportDetail";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
ReportTriggerModeItem,
|
||||||
|
MsTableOperatorButton,
|
||||||
|
MsApiReportStatus, MsMainContainer, MsContainer, MsTableHeader, MsTablePagination, ShowMoreBtn, MsApiReportDetail
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
result: {},
|
||||||
|
reportId: "",
|
||||||
|
debugVisible: false,
|
||||||
|
condition: {
|
||||||
|
components: REPORT_CONFIGS
|
||||||
|
},
|
||||||
|
tableData: [],
|
||||||
|
multipleSelection: [],
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
total: 0,
|
||||||
|
loading: false,
|
||||||
|
currentProjectId: "",
|
||||||
|
statusFilters: [
|
||||||
|
{text: 'Saved', value: 'Saved'},
|
||||||
|
{text: 'Starting', value: 'Starting'},
|
||||||
|
{text: 'Running', value: 'Running'},
|
||||||
|
{text: 'Reporting', value: 'Reporting'},
|
||||||
|
{text: 'Completed', value: 'Completed'},
|
||||||
|
{text: 'Error', value: 'Error'},
|
||||||
|
{text: 'Success', value: 'Success'},
|
||||||
|
],
|
||||||
|
triggerFilters: [
|
||||||
|
{text: this.$t('commons.trigger_mode.manual'), value: 'MANUAL'},
|
||||||
|
{text: this.$t('commons.trigger_mode.schedule'), value: 'SCHEDULE'},
|
||||||
|
{text: this.$t('commons.trigger_mode.api'), value: 'API'}
|
||||||
|
],
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.table-content {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -2,13 +2,17 @@
|
||||||
<header class="report-header">
|
<header class="report-header">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col>
|
<el-col>
|
||||||
<span>{{ report.projectName === null || report.projectName ==='' ? "场景执行报告": report.projectName}} / </span>
|
<span><el-input size="mini" style="width: 200px" v-model="report.name"/> </span>
|
||||||
<router-link :to="path">{{ report.testName }}</router-link>
|
|
||||||
<span class="time"> {{ report.createTime | timestampFormatDate }}</span>
|
<span class="time"> {{ report.createTime | timestampFormatDate }}</span>
|
||||||
<el-button :disabled="isReadOnly" class="export-button" plain type="primary" size="mini" @click="handleExport(report.name)"
|
|
||||||
style="margin-left: 1200px">
|
<el-button :disabled="isReadOnly" class="export-button" plain type="primary" size="mini" @click="handleExport(report.name)" style="margin-right: 10px">
|
||||||
{{$t('test_track.plan_view.export_report')}}
|
{{$t('test_track.plan_view.export_report')}}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
|
<el-button :disabled="isReadOnly" class="export-button" plain type="primary" size="mini" @click="handleSave(report.name)" style="margin-right: 10px">
|
||||||
|
{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
|
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</header>
|
</header>
|
||||||
|
@ -38,6 +42,9 @@
|
||||||
methods: {
|
methods: {
|
||||||
handleExport(name) {
|
handleExport(name) {
|
||||||
this.$emit('reportExport', name);
|
this.$emit('reportExport', name);
|
||||||
|
},
|
||||||
|
handleSave(name) {
|
||||||
|
this.$emit('reportSave', name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,24 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="scenario-result">
|
<div class="scenario-result">
|
||||||
<div v-for="(request, index) in scenario.requestResults" :key="index">
|
|
||||||
<ms-request-result :key="index" :request="request" :indexNumber="index"
|
<div @click="active">
|
||||||
v-on:requestResult="requestResult"
|
<el-row :gutter="10" type="flex" align="middle" class="info">
|
||||||
:scenarioName="scenario.name"/>
|
<el-col :span="16">
|
||||||
|
<i class="icon el-icon-arrow-right" :class="{'is-active': isActive}"/>
|
||||||
|
{{scenario.name}}
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
|
<el-collapse-transition>
|
||||||
|
<div v-show="isActive">
|
||||||
|
<div v-for="(request, index) in scenario.requestResults" :key="index">
|
||||||
|
<ms-request-result :key="index" :request="request" :indexNumber="index"
|
||||||
|
v-on:requestResult="requestResult"
|
||||||
|
:scenarioName="scenario.name"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</el-collapse-transition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -1,62 +1,72 @@
|
||||||
<template>
|
<template>
|
||||||
<el-card class="table-card" v-loading="result.loading">
|
<div>
|
||||||
<template v-slot:header>
|
<el-card class="table-card" v-loading="result.loading">
|
||||||
<ms-table-header :condition.sync="condition" @search="search" title=""
|
<template v-slot:header>
|
||||||
:show-create="false"/>
|
<ms-table-header :condition.sync="condition" @search="search" title=""
|
||||||
</template>
|
:show-create="false"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
<el-table ref="scenarioTable" border :data="tableData" class="adjust-table" @select-all="select" @select="select">
|
<el-table ref="scenarioTable" border :data="tableData" class="adjust-table" @select-all="select" @select="select">
|
||||||
<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">
|
||||||
<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="selection.length"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="name" :label="$t('api_test.automation.scenario_name')"
|
<el-table-column prop="name" :label="$t('api_test.automation.scenario_name')"
|
||||||
show-overflow-tooltip/>
|
show-overflow-tooltip/>
|
||||||
<el-table-column prop="level" :label="$t('api_test.automation.case_level')"
|
<el-table-column prop="level" :label="$t('api_test.automation.case_level')"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<ms-tag v-if="scope.row.level == 'P0'" type="info" effect="plain" content="P0"/>
|
<ms-tag v-if="scope.row.level == 'P0'" type="info" effect="plain" content="P0"/>
|
||||||
<ms-tag v-if="scope.row.level == 'P1'" type="warning" effect="plain" content="P1"/>
|
<ms-tag v-if="scope.row.level == 'P1'" type="warning" effect="plain" content="P1"/>
|
||||||
<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="tagName" :label="$t('api_test.automation.tag')" show-overflow-tooltip>
|
<el-table-column prop="tagName" :label="$t('api_test.automation.tag')" show-overflow-tooltip>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<ms-tag type="success" effect="plain" v-if="scope.row.tagName!=undefined" :content="scope.row.tagName"/>
|
<ms-tag type="success" effect="plain" v-if="scope.row.tagName!=undefined" :content="scope.row.tagName"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="userId" :label="$t('api_test.automation.creator')" show-overflow-tooltip/>
|
<el-table-column prop="userId" :label="$t('api_test.automation.creator')" show-overflow-tooltip/>
|
||||||
<el-table-column prop="updateTime" :label="$t('api_test.automation.update_time')" width="180">
|
<el-table-column prop="updateTime" :label="$t('api_test.automation.update_time')" width="180">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<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="status" :label="$t('api_test.automation.last_result')">
|
<el-table-column prop="status" :label="$t('api_test.automation.last_result')">
|
||||||
<template v-slot:default="{row}">
|
<template v-slot:default="{row}">
|
||||||
<el-link type="success" v-if="row.status === 'Success'">{{ $t('api_test.automation.success') }}</el-link>
|
<el-link type="success" v-if="row.status === 'Success'">{{ $t('api_test.automation.success') }}</el-link>
|
||||||
<el-link type="danger" v-if="row.status === 'Fail'">{{ $t('api_test.automation.fail') }}</el-link>
|
<el-link type="danger" v-if="row.status === 'Fail'">{{ $t('api_test.automation.fail') }}</el-link>
|
||||||
<el-link type="warning" v-if="row.status === 'Trash'">{{ $t('api_test.automation.trash') }}</el-link>
|
<el-link type="warning" v-if="row.status === 'Trash'">{{ $t('api_test.automation.trash') }}</el-link>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="passingRate" :label="$t('api_test.automation.passing_rate')"
|
<el-table-column prop="passingRate" :label="$t('api_test.automation.passing_rate')"
|
||||||
show-overflow-tooltip/>
|
show-overflow-tooltip/>
|
||||||
<el-table-column :label="$t('commons.operating')" width="180">
|
<el-table-column :label="$t('commons.operating')" width="180">
|
||||||
<template v-slot:default="{row}">
|
<template v-slot:default="{row}">
|
||||||
<el-button type="text" @click="edit(row)">{{ $t('api_test.automation.edit') }}</el-button>
|
<el-button type="text" @click="edit(row)">{{ $t('api_test.automation.edit') }}</el-button>
|
||||||
<el-button type="text" @click="execute(row)">{{ $t('api_test.automation.execute') }}</el-button>
|
<el-button type="text" @click="execute(row)">{{ $t('api_test.automation.execute') }}</el-button>
|
||||||
<el-button type="text" @click="copy(row)">{{ $t('api_test.automation.copy') }}</el-button>
|
<el-button type="text" @click="copy(row)">{{ $t('api_test.automation.copy') }}</el-button>
|
||||||
<el-button type="text" @click="remove(row)">{{ $t('api_test.automation.remove') }}</el-button>
|
<el-button type="text" @click="remove(row)">{{ $t('api_test.automation.remove') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<ms-table-pagination :change="search" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
<ms-table-pagination :change="search" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||||
:total="total"/>
|
:total="total"/>
|
||||||
</el-card>
|
|
||||||
|
<div>
|
||||||
|
<!-- 调试结果 -->
|
||||||
|
<el-drawer :visible.sync="runVisible" :destroy-on-close="true" direction="ltr" :withHeader="false" :title="$t('test_track.plan_view.test_result')" :modal="false" size="90%">
|
||||||
|
<ms-api-report-detail :report-id="reportId" :currentProjectId="currentProject!=undefined ? currentProject.id:''"/>
|
||||||
|
</el-drawer>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -65,10 +75,11 @@
|
||||||
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} from "@/common/js/utils";
|
import {getUUID} from "@/common/js/utils";
|
||||||
|
import MsApiReportDetail from "../report/ApiReportDetail";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsApiScenarioList",
|
name: "MsApiScenarioList",
|
||||||
components: {ShowMoreBtn, MsTablePagination, MsTableHeader, MsTag},
|
components: {ShowMoreBtn, MsTablePagination, MsTableHeader, MsTag, MsApiReportDetail},
|
||||||
props: {
|
props: {
|
||||||
currentProject: Object,
|
currentProject: Object,
|
||||||
currentModule: Object,
|
currentModule: Object,
|
||||||
|
@ -83,6 +94,9 @@
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 0,
|
total: 0,
|
||||||
|
reportId: "",
|
||||||
|
runVisible: false,
|
||||||
|
runData: [],
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
name: this.$t('api_test.automation.batch_add_plan'), handleClick: this.handleBatchAddCase
|
name: this.$t('api_test.automation.batch_add_plan'), handleClick: this.handleBatchAddCase
|
||||||
|
@ -140,7 +154,16 @@
|
||||||
|
|
||||||
},
|
},
|
||||||
handleBatchExecute() {
|
handleBatchExecute() {
|
||||||
|
let url = "/api/automation/run";
|
||||||
|
let run = {};
|
||||||
|
let scenarioIds = this.selection;
|
||||||
|
run.id = getUUID();
|
||||||
|
run.scenarioIds = scenarioIds;
|
||||||
|
this.result = this.$post(url, run, response => {
|
||||||
|
let data = response.data;
|
||||||
|
this.runVisible = true;
|
||||||
|
this.reportId = run.id;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
selectAllChange() {
|
selectAllChange() {
|
||||||
this.handleCommand("table");
|
this.handleCommand("table");
|
||||||
|
@ -156,7 +179,17 @@
|
||||||
this.$emit('edit', row);
|
this.$emit('edit', row);
|
||||||
},
|
},
|
||||||
execute(row) {
|
execute(row) {
|
||||||
|
let url = "/api/automation/run";
|
||||||
|
let run = {};
|
||||||
|
let scenarioIds = [];
|
||||||
|
scenarioIds.push(row.id);
|
||||||
|
run.id = getUUID();
|
||||||
|
run.scenarioIds = scenarioIds;
|
||||||
|
this.result = this.$post(url, run, response => {
|
||||||
|
let data = response.data;
|
||||||
|
this.runVisible = true;
|
||||||
|
this.reportId = run.id;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
copy(row) {
|
copy(row) {
|
||||||
row.id = getUUID();
|
row.id = getUUID();
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
<template>
|
||||||
|
<div></div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import {getUUID} from "@/common/js/utils";
|
||||||
|
import {createComponent} from "../../definition/components/jmeter/components";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'MsDebugRun',
|
||||||
|
components: {},
|
||||||
|
props: {
|
||||||
|
environment: String,
|
||||||
|
debug: Boolean,
|
||||||
|
reportId: String,
|
||||||
|
runData: Object,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
result: {},
|
||||||
|
loading: false,
|
||||||
|
runId: "",
|
||||||
|
reqNumber: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
// 初始化
|
||||||
|
reportId() {
|
||||||
|
this.run()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setFiles(item, bodyUploadFiles, obj) {
|
||||||
|
if (item.body) {
|
||||||
|
item.body.kvs.forEach(param => {
|
||||||
|
if (param.files) {
|
||||||
|
param.files.forEach(item => {
|
||||||
|
if (item.file) {
|
||||||
|
if (!item.id) {
|
||||||
|
let fileId = getUUID().substring(0, 12);
|
||||||
|
item.name = item.file.name;
|
||||||
|
item.id = fileId;
|
||||||
|
}
|
||||||
|
obj.bodyUploadIds.push(item.id);
|
||||||
|
bodyUploadFiles.push(item.file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
item.body.binary.forEach(param => {
|
||||||
|
if (param.files) {
|
||||||
|
param.files.forEach(item => {
|
||||||
|
if (item.file) {
|
||||||
|
if (!item.id) {
|
||||||
|
let fileId = getUUID().substring(0, 12);
|
||||||
|
item.name = item.file.name;
|
||||||
|
item.id = fileId;
|
||||||
|
}
|
||||||
|
obj.bodyUploadIds.push(item.id);
|
||||||
|
bodyUploadFiles.push(item.file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
recursiveFile(arr, bodyUploadFiles, obj) {
|
||||||
|
arr.forEach(item => {
|
||||||
|
this.setFiles(item, bodyUploadFiles, obj);
|
||||||
|
if (item.hashTree != undefined && item.hashTree.length > 0) {
|
||||||
|
this.recursiveFile(item.hashTree, bodyUploadFiles, obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getBodyUploadFiles(obj) {
|
||||||
|
let bodyUploadFiles = [];
|
||||||
|
obj.bodyUploadIds = [];
|
||||||
|
let request = this.runData;
|
||||||
|
request.hashTree.forEach(item => {
|
||||||
|
this.setFiles(item, bodyUploadFiles, obj);
|
||||||
|
if (item.hashTree != undefined && item.hashTree.length > 0) {
|
||||||
|
this.recursiveFile(item.hashTree, bodyUploadFiles, obj);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return bodyUploadFiles;
|
||||||
|
},
|
||||||
|
run() {
|
||||||
|
let testPlan = createComponent('TestPlan');
|
||||||
|
let threadGroup = createComponent('ThreadGroup');
|
||||||
|
threadGroup.hashTree = [];
|
||||||
|
threadGroup.name = this.runData.name;
|
||||||
|
threadGroup.hashTree.push(this.runData);
|
||||||
|
testPlan.hashTree.push(threadGroup);
|
||||||
|
let reqObj = {id: this.reportId, reportId: this.reportId, environmentId: this.environment, testElement: testPlan};
|
||||||
|
let bodyFiles = this.getBodyUploadFiles(reqObj);
|
||||||
|
console.log(bodyFiles)
|
||||||
|
let url = "/api/automation/run/debug";
|
||||||
|
this.$fileUpload(url, null, bodyFiles, reqObj, response => {
|
||||||
|
this.runId = response.data;
|
||||||
|
this.$emit('runRefresh', {});
|
||||||
|
}, erro => {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -261,7 +261,7 @@
|
||||||
@runRefresh="runRefresh" ref="runTest"/>
|
@runRefresh="runRefresh" ref="runTest"/>
|
||||||
<!-- 调试结果 -->
|
<!-- 调试结果 -->
|
||||||
<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" :title="$t('test_track.plan_view.test_result')" :modal="false" size="90%">
|
||||||
<ms-api-report-detail :report-id="reportId"/>
|
<ms-api-report-detail :report-id="reportId" :currentProjectId="currentProject.id"/>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
@ -284,7 +284,7 @@
|
||||||
import {getUUID} from "@/common/js/utils";
|
import {getUUID} from "@/common/js/utils";
|
||||||
import ApiEnvironmentConfig from "../../definition/components/environment/ApiEnvironmentConfig";
|
import ApiEnvironmentConfig from "../../definition/components/environment/ApiEnvironmentConfig";
|
||||||
import MsAddTag from "./AddTag";
|
import MsAddTag from "./AddTag";
|
||||||
import MsRun from "./Run";
|
import MsRun from "./DebugRun";
|
||||||
import MsImportApiScenario from "./ImportApiScenario";
|
import MsImportApiScenario from "./ImportApiScenario";
|
||||||
import MsApiScenarioComponent from "./ApiScenarioComponent";
|
import MsApiScenarioComponent from "./ApiScenarioComponent";
|
||||||
import MsApiReportDetail from "../report/ApiReportDetail";
|
import MsApiReportDetail from "../report/ApiReportDetail";
|
||||||
|
@ -333,7 +333,7 @@
|
||||||
expandedNode: [],
|
expandedNode: [],
|
||||||
scenarioDefinition: [],
|
scenarioDefinition: [],
|
||||||
path: "/api/automation/create",
|
path: "/api/automation/create",
|
||||||
debugData: [],
|
debugData: {},
|
||||||
reportId: "",
|
reportId: "",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -539,9 +539,7 @@
|
||||||
this.$error(this.$t('api_test.environment.select_environment'));
|
this.$error(this.$t('api_test.environment.select_environment'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let scenario = {id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario", referenced: 'Created', environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition};
|
this.debugData = {id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario", referenced: 'Created', environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition};
|
||||||
this.debugData = [];
|
|
||||||
this.debugData.push(scenario);
|
|
||||||
this.reportId = getUUID().substring(0, 8);
|
this.reportId = getUUID().substring(0, 8);
|
||||||
},
|
},
|
||||||
getEnvironments() {
|
getEnvironments() {
|
||||||
|
@ -592,11 +590,68 @@
|
||||||
});
|
});
|
||||||
return path[0].path;
|
return path[0].path;
|
||||||
},
|
},
|
||||||
|
setFiles(item, bodyUploadFiles, obj) {
|
||||||
|
if (item.body) {
|
||||||
|
item.body.kvs.forEach(param => {
|
||||||
|
if (param.files) {
|
||||||
|
param.files.forEach(item => {
|
||||||
|
if (item.file) {
|
||||||
|
if (!item.id) {
|
||||||
|
let fileId = getUUID().substring(0, 12);
|
||||||
|
item.name = item.file.name;
|
||||||
|
item.id = fileId;
|
||||||
|
}
|
||||||
|
obj.bodyUploadIds.push(item.id);
|
||||||
|
bodyUploadFiles.push(item.file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
item.body.binary.forEach(param => {
|
||||||
|
if (param.files) {
|
||||||
|
param.files.forEach(item => {
|
||||||
|
if (item.file) {
|
||||||
|
if (!item.id) {
|
||||||
|
let fileId = getUUID().substring(0, 12);
|
||||||
|
item.name = item.file.name;
|
||||||
|
item.id = fileId;
|
||||||
|
}
|
||||||
|
obj.bodyUploadIds.push(item.id);
|
||||||
|
bodyUploadFiles.push(item.file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
recursiveFile(arr, bodyUploadFiles, obj) {
|
||||||
|
arr.forEach(item => {
|
||||||
|
this.setFiles(item, bodyUploadFiles, obj);
|
||||||
|
if (item.hashTree != undefined && item.hashTree.length > 0) {
|
||||||
|
this.recursiveFile(item.hashTree, bodyUploadFiles, obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getBodyUploadFiles(obj) {
|
||||||
|
let bodyUploadFiles = [];
|
||||||
|
obj.bodyUploadIds = [];
|
||||||
|
this.scenarioDefinition.forEach(item => {
|
||||||
|
this.setFiles(item, bodyUploadFiles, obj);
|
||||||
|
if (item.hashTree != undefined && item.hashTree.length > 0) {
|
||||||
|
this.recursiveFile(item.hashTree, bodyUploadFiles, obj);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return bodyUploadFiles;
|
||||||
|
},
|
||||||
editScenario() {
|
editScenario() {
|
||||||
this.$refs['currentScenario'].validate((valid) => {
|
this.$refs['currentScenario'].validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.setParameter();
|
this.setParameter();
|
||||||
this.result = this.$post(this.path, this.currentScenario, () => {
|
let bodyFiles = this.getBodyUploadFiles(this.currentScenario);
|
||||||
|
console.log(bodyFiles)
|
||||||
|
console.log(this.currentScenario.bodyUploadIds)
|
||||||
|
|
||||||
|
this.$fileUpload(this.path, null, bodyFiles, this.currentScenario, () => {
|
||||||
this.$success(this.$t('commons.save_success'));
|
this.$success(this.$t('commons.save_success'));
|
||||||
this.path = "/api/automation/update";
|
this.path = "/api/automation/update";
|
||||||
this.currentScenario.tagId = JSON.parse(this.currentScenario.tagId);
|
this.currentScenario.tagId = JSON.parse(this.currentScenario.tagId);
|
||||||
|
|
|
@ -1,118 +0,0 @@
|
||||||
<template>
|
|
||||||
<div></div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import {getUUID} from "@/common/js/utils";
|
|
||||||
import ThreadGroup from "../../definition/components/jmeter/components/thread-group";
|
|
||||||
import TestPlan from "../../definition/components/jmeter/components/test-plan";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'MsRun',
|
|
||||||
components: {},
|
|
||||||
props: {
|
|
||||||
environment: String,
|
|
||||||
debug: Boolean,
|
|
||||||
reportId: String,
|
|
||||||
runData: Array,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
result: {},
|
|
||||||
loading: false,
|
|
||||||
runId: "",
|
|
||||||
reqNumber: 0,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
|
||||||
// 初始化
|
|
||||||
reportId() {
|
|
||||||
this.run()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getResult() {
|
|
||||||
if (this.runId) {
|
|
||||||
let url = "";
|
|
||||||
if (this.debug) {
|
|
||||||
url = "/api/definition/report/get/" + this.runId + "/" + "debug";
|
|
||||||
} else {
|
|
||||||
url = "/api/definition/report/get/" + this.runId + "/" + "run";
|
|
||||||
}
|
|
||||||
this.$get(url, response => {
|
|
||||||
if (response.data) {
|
|
||||||
let data = JSON.parse(response.data.content);
|
|
||||||
this.$emit('runRefresh', data);
|
|
||||||
} else {
|
|
||||||
if (this.reqNumber < 60) {
|
|
||||||
this.reqNumber++;
|
|
||||||
setTimeout(this.getResult, 2000);
|
|
||||||
} else {
|
|
||||||
this.$error("获取报告超时");
|
|
||||||
this.$emit('runRefresh', {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getBodyUploadFiles(obj) {
|
|
||||||
let bodyUploadFiles = [];
|
|
||||||
obj.bodyUploadIds = [];
|
|
||||||
this.runData.forEach(request => {
|
|
||||||
if (request.body) {
|
|
||||||
request.body.kvs.forEach(param => {
|
|
||||||
if (param.files) {
|
|
||||||
param.files.forEach(item => {
|
|
||||||
if (item.file) {
|
|
||||||
if (!item.id) {
|
|
||||||
let fileId = getUUID().substring(0, 12);
|
|
||||||
item.name = item.file.name;
|
|
||||||
item.id = fileId;
|
|
||||||
}
|
|
||||||
obj.bodyUploadIds.push(item.id);
|
|
||||||
bodyUploadFiles.push(item.file);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
request.body.binary.forEach(param => {
|
|
||||||
if (param.files) {
|
|
||||||
param.files.forEach(item => {
|
|
||||||
if (item.file) {
|
|
||||||
if (!item.id) {
|
|
||||||
let fileId = getUUID().substring(0, 12);
|
|
||||||
item.name = item.file.name;
|
|
||||||
item.id = fileId;
|
|
||||||
}
|
|
||||||
obj.bodyUploadIds.push(item.id);
|
|
||||||
bodyUploadFiles.push(item.file);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return bodyUploadFiles;
|
|
||||||
},
|
|
||||||
run() {
|
|
||||||
let testPlan = new TestPlan();
|
|
||||||
this.runData.forEach(item => {
|
|
||||||
let threadGroup = new ThreadGroup();
|
|
||||||
threadGroup.hashTree = [];
|
|
||||||
threadGroup.name = item.name;
|
|
||||||
threadGroup.hashTree.push(item);
|
|
||||||
testPlan.hashTree.push(threadGroup);
|
|
||||||
})
|
|
||||||
console.log("====",testPlan)
|
|
||||||
let reqObj = {id: this.reportId, reportId: this.reportId, environmentId: this.environment, testElement: testPlan};
|
|
||||||
let bodyFiles = this.getBodyUploadFiles(reqObj);
|
|
||||||
let url = "/api/automation/run";
|
|
||||||
this.$fileUpload(url, null, bodyFiles, reqObj, response => {
|
|
||||||
this.runId = response.data;
|
|
||||||
this.$emit('runRefresh', {});
|
|
||||||
}, erro => {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -12,12 +12,7 @@ export const TYPE = "TestPlan";
|
||||||
export default class TestPlan extends HashTreeElement {
|
export default class TestPlan extends HashTreeElement {
|
||||||
constructor(options = DEFAULT_OPTIONS) {
|
constructor(options = DEFAULT_OPTIONS) {
|
||||||
super(options);
|
super(options);
|
||||||
this.$type = TYPE;
|
|
||||||
this.type = TYPE;
|
this.type = TYPE;
|
||||||
this.functionalMode = this.initBoolProp('TestPlan.functional_mode', false);
|
|
||||||
this.serializeThreadGroups = this.initBoolProp('TestPlan.serialize_threadgroups', false);
|
|
||||||
this.tearDownOnShutdown = this.initBoolProp('TestPlan.tearDown_on_shutdown', true);
|
|
||||||
this.userDefineClasspath = this.initStringProp('TestPlan.user_define_classpath');
|
|
||||||
this.hashTree = [];
|
this.hashTree = [];
|
||||||
this.userDefinedVariables = [];
|
this.userDefinedVariables = [];
|
||||||
|
|
||||||
|
|
|
@ -11,21 +11,7 @@ export const TYPE = "ThreadGroup";
|
||||||
export default class ThreadGroup extends HashTreeElement {
|
export default class ThreadGroup extends HashTreeElement {
|
||||||
constructor(options = DEFAULT_OPTIONS) {
|
constructor(options = DEFAULT_OPTIONS) {
|
||||||
super(options);
|
super(options);
|
||||||
this.$type = TYPE;
|
|
||||||
this.type = TYPE;
|
this.type = TYPE;
|
||||||
this.onSampleError = this.initStringProp('ThreadGroup.on_sample_error', 'continue');
|
|
||||||
this.numThreads = this.initStringProp('ThreadGroup.num_threads', 1);
|
|
||||||
this.rampTime = this.initStringProp('ThreadGroup.ramp_time', 1);
|
|
||||||
|
|
||||||
let loopController = this.initElementProp('ThreadGroup.main_controller', 'LoopController');
|
|
||||||
this.continueForever = loopController.initBoolProp('LoopController.continue_forever', false);
|
|
||||||
this.loops = loopController.initStringProp('LoopController.loops', 1);
|
|
||||||
|
|
||||||
this.sameUserOnNextIteration = this.initBoolProp('ThreadGroup.same_user_on_next_iteration', true);
|
|
||||||
this.delayedStart = this.initBoolProp('ThreadGroup.delayedStart');
|
|
||||||
this.scheduler = this.initBoolProp('ThreadGroup.scheduler', false);
|
|
||||||
this.delay = this.initStringProp('ThreadGroup.delay');
|
|
||||||
this.duration = this.initStringProp('ThreadGroup.duration');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,18 @@
|
||||||
<el-row type="flex">
|
<el-row type="flex">
|
||||||
<el-col :span="10">
|
<el-col :span="10">
|
||||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router :default-active='$route.path'>
|
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router :default-active='$route.path'>
|
||||||
|
|
||||||
|
<el-submenu :class="{'deactivation':!isProjectActivation}" v-permission="['test_manager','test_user','test_viewer']" index="3">
|
||||||
|
<template v-slot:title>{{ $t('commons.project') }}</template>
|
||||||
|
<search-list ref="projectRecent" :options="projectRecent"/>
|
||||||
|
<el-divider class="menu-divider"/>
|
||||||
|
<el-menu-item :index="'/performance/project/create'">
|
||||||
|
<font-awesome-icon :icon="['fa', 'plus']"/>
|
||||||
|
<span style="padding-left: 7px;">创建项目</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<ms-show-all :index="'/setting/project'"/>
|
||||||
|
</el-submenu>
|
||||||
|
|
||||||
<el-menu-item :index="'/api/home'">
|
<el-menu-item :index="'/api/home'">
|
||||||
{{ $t("i18n.home") }}
|
{{ $t("i18n.home") }}
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
@ -15,14 +27,9 @@
|
||||||
{{ $t("i18n.automation") }}
|
{{ $t("i18n.automation") }}
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
|
||||||
<el-submenu :class="{'deactivation':!isProjectActivation}" v-permission="['test_manager','test_user','test_viewer']" index="3">
|
<el-menu-item :index="'/api/automation/report'">
|
||||||
<template v-slot:title>{{ $t('commons.project') }}</template>
|
{{ $t("i18n.report") }}
|
||||||
<ms-recent-list ref="projectRecent" :options="projectRecent"/>
|
</el-menu-item>
|
||||||
<el-divider class="menu-divider"/>
|
|
||||||
<ms-show-all :index="'/api/project/all'"/>
|
|
||||||
<ms-create-button v-permission="['test_manager','test_user']" :index="'/api/project/create'"
|
|
||||||
:title="$t('project.create')"/>
|
|
||||||
</el-submenu>
|
|
||||||
|
|
||||||
<el-submenu v-permission="['test_manager','test_user','test_viewer']" index="4">
|
<el-submenu v-permission="['test_manager','test_user','test_viewer']" index="4">
|
||||||
<template v-slot:title>{{ $t('commons.test') }}</template>
|
<template v-slot:title>{{ $t('commons.test') }}</template>
|
||||||
|
@ -65,10 +72,11 @@ import MsShowAll from "../../common/head/ShowAll";
|
||||||
import MsCreateButton from "../../common/head/CreateButton";
|
import MsCreateButton from "../../common/head/CreateButton";
|
||||||
import MsCreateTest from "../../common/head/CreateTest";
|
import MsCreateTest from "../../common/head/CreateTest";
|
||||||
import {ApiEvent, LIST_CHANGE} from "@/business/components/common/head/ListEvent";
|
import {ApiEvent, LIST_CHANGE} from "@/business/components/common/head/ListEvent";
|
||||||
|
import SearchList from "@/business/components/common/head/SearchList";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsApiHeaderMenus",
|
name: "MsApiHeaderMenus",
|
||||||
components: {MsCreateTest, MsCreateButton, MsShowAll, MsRecentList},
|
components: {SearchList, MsCreateTest, MsCreateButton, MsShowAll, MsRecentList},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
projectRecent: {
|
projectRecent: {
|
||||||
|
|
|
@ -48,6 +48,11 @@ export default {
|
||||||
path: "automation",
|
path: "automation",
|
||||||
name: "ApiAutomation",
|
name: "ApiAutomation",
|
||||||
component: () => import('@/business/components/api/automation/ApiAutomation'),
|
component: () => import('@/business/components/api/automation/ApiAutomation'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "automation/report",
|
||||||
|
name: "ApiReportList",
|
||||||
|
component: () => import('@/business/components/api/automation/report/ApiReportList'),
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<el-row class="table-title" type="flex" justify="space-between" align="middle">
|
<el-row v-if="title" class="table-title" type="flex" justify="space-between" align="middle">
|
||||||
<slot name="title">
|
<slot name="title">
|
||||||
{{title}}
|
{{title}}
|
||||||
</slot>
|
</slot>
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
<template>
|
||||||
|
<span>
|
||||||
|
<el-submenu index="10">
|
||||||
|
<template v-slot:title>操作</template>
|
||||||
|
<el-input
|
||||||
|
placeholder="请输入内容"
|
||||||
|
prefix-icon="el-icon-search"
|
||||||
|
v-model="input2">
|
||||||
|
</el-input>
|
||||||
|
</el-submenu>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "ProjectMenu",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
input2: '1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,107 @@
|
||||||
|
<template>
|
||||||
|
<div v-loading="result.loading" class="search-list">
|
||||||
|
<el-input placeholder="搜索项目"
|
||||||
|
prefix-icon="el-icon-search"
|
||||||
|
v-model="search_text"
|
||||||
|
clearable
|
||||||
|
class="search-input"
|
||||||
|
size="small"/>
|
||||||
|
<div v-if="items.length === 0" style="text-align: center; margin: 15px 0">
|
||||||
|
<span style="font-size: 15px; color: #8a8b8d;">
|
||||||
|
无数据
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div v-else style="height: 120px;overflow: auto">
|
||||||
|
<el-menu-item :key="i.id" v-for="i in items" :index="getIndex(i)" :route="getRouter(i)">
|
||||||
|
<template slot="title">
|
||||||
|
<div class="title">{{ i.name }}</div>
|
||||||
|
</template>
|
||||||
|
</el-menu-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {hasRoles} from "@/common/js/utils";
|
||||||
|
import {ROLE_TEST_MANAGER, ROLE_TEST_USER, ROLE_TEST_VIEWER} from "@/common/js/constants";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "SearchList",
|
||||||
|
props: {
|
||||||
|
options: Object
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.recent();
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
result: {},
|
||||||
|
items: [],
|
||||||
|
search_text: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
search_text(val) {
|
||||||
|
if (!val) {
|
||||||
|
this.recent();
|
||||||
|
} else {
|
||||||
|
this.search();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
getIndex: function () {
|
||||||
|
return function (item) {
|
||||||
|
return this.options.index(item);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getRouter: function () {
|
||||||
|
return function (item) {
|
||||||
|
if (this.options.router) {
|
||||||
|
return this.options.router(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
recent: function () {
|
||||||
|
if (hasRoles(ROLE_TEST_VIEWER, ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
||||||
|
this.result = this.$get(this.options.url, (response) => {
|
||||||
|
this.items = response.data;
|
||||||
|
this.items = this.items.splice(0, 3);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
search() {
|
||||||
|
if (hasRoles(ROLE_TEST_VIEWER, ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
||||||
|
this.result = this.$post("/project/search", {name: this.search_text},response => {
|
||||||
|
this.items = response.data;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
padding: 0;
|
||||||
|
margin-top: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input >>> .el-input__inner {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: 20px;
|
||||||
|
max-width: 200px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<el-menu-item :index="this.index" @click="changeRoute">
|
<el-menu-item :index="this.index">
|
||||||
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
||||||
<span>{{ $t('commons.show_all') }}</span>
|
<span>{{ $t('commons.show_all') }}</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
@ -10,14 +10,6 @@ export default {
|
||||||
name: "MsShowAll",
|
name: "MsShowAll",
|
||||||
props: {
|
props: {
|
||||||
index: String
|
index: String
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
changeRoute() {
|
|
||||||
// 解决在列表页面点击 显示全部 无效的问题(点击显示全部后改变路由)
|
|
||||||
if (this.$route.path === this.index) {
|
|
||||||
this.$router.replace({path: this.index, query: {type: 'all'}});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -3,20 +3,23 @@
|
||||||
<el-row type="flex">
|
<el-row type="flex">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router :default-active='$route.path'>
|
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router :default-active='$route.path'>
|
||||||
<el-menu-item :index="'/performance/home'">
|
|
||||||
{{ $t("i18n.home") }}
|
|
||||||
</el-menu-item>
|
|
||||||
|
|
||||||
<el-submenu v-permission="['test_manager','test_user','test_viewer']"
|
<el-submenu v-permission="['test_manager','test_user','test_viewer']"
|
||||||
index="3" popper-class="submenu">
|
index="3" popper-class="submenu">
|
||||||
<template v-slot:title>{{ $t('commons.project') }}</template>
|
<template v-slot:title>{{ $t('commons.project') }}</template>
|
||||||
<ms-recent-list ref="projectRecent" :options="projectRecent"/>
|
<search-list ref="projectRecent" :options="projectRecent"/>
|
||||||
<el-divider/>
|
<el-divider/>
|
||||||
<ms-show-all :index="'/performance/project/all'"/>
|
<el-menu-item :index="'/performance/project/create'">
|
||||||
<ms-create-button v-permission="['test_manager','test_user']" :index="'/performance/project/create'"
|
<font-awesome-icon :icon="['fa', 'plus']"/>
|
||||||
:title="$t('project.create')"/>
|
<span style="padding-left: 7px;">创建项目</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<ms-show-all :index="'/setting/project'"/>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
|
||||||
|
<el-menu-item :index="'/performance/home'">
|
||||||
|
{{ $t("i18n.home") }}
|
||||||
|
</el-menu-item>
|
||||||
|
|
||||||
<el-submenu v-permission="['test_manager','test_user','test_viewer']"
|
<el-submenu v-permission="['test_manager','test_user','test_viewer']"
|
||||||
index="4" popper-class="submenu">
|
index="4" popper-class="submenu">
|
||||||
<template v-slot:title>{{ $t('commons.test') }}</template>
|
<template v-slot:title>{{ $t('commons.test') }}</template>
|
||||||
|
@ -53,10 +56,12 @@ import MsRecentList from "../../common/head/RecentList";
|
||||||
import MsCreateButton from "../../common/head/CreateButton";
|
import MsCreateButton from "../../common/head/CreateButton";
|
||||||
import MsShowAll from "../../common/head/ShowAll";
|
import MsShowAll from "../../common/head/ShowAll";
|
||||||
import {LIST_CHANGE, PerformanceEvent} from "@/business/components/common/head/ListEvent";
|
import {LIST_CHANGE, PerformanceEvent} from "@/business/components/common/head/ListEvent";
|
||||||
|
import SearchList from "@/business/components/common/head/SearchList";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "PerformanceHeaderMenus",
|
name: "PerformanceHeaderMenus",
|
||||||
components: {
|
components: {
|
||||||
|
SearchList,
|
||||||
MsCreateButton,
|
MsCreateButton,
|
||||||
MsShowAll,
|
MsShowAll,
|
||||||
MsRecentList,
|
MsRecentList,
|
||||||
|
@ -92,7 +97,8 @@ export default {
|
||||||
},
|
},
|
||||||
router(item) {
|
router(item) {
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
input2: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<el-card class="table-card" v-loading="result.loading">
|
<el-card class="table-card" v-loading="result.loading">
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search" @create="create"
|
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search" @create="create"
|
||||||
:create-tip="btnTips" :title="title"/>
|
:create-tip="btnTips" title=""/>
|
||||||
</template>
|
</template>
|
||||||
<el-table border class="adjust-table" @row-click="link" :data="items" style="width: 100%" @sort-change="sort">
|
<el-table border class="adjust-table" @row-click="link" :data="items" style="width: 100%" @sort-change="sort">
|
||||||
<el-table-column prop="name" :label="$t('commons.name')" width="250" show-overflow-tooltip/>
|
<el-table-column prop="name" :label="$t('commons.name')" width="250" show-overflow-tooltip/>
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<ms-table-operator :is-tester-permission="true" @editClick="edit(scope.row)"
|
<ms-table-operator :is-tester-permission="true" @editClick="edit(scope.row)"
|
||||||
@deleteClick="handleDelete(scope.row)">
|
@deleteClick="handleDelete(scope.row)">
|
||||||
<template v-if="baseUrl == 'api'" v-slot:behind>
|
<template v-slot:behind>
|
||||||
<ms-table-operator-button :is-tester-permission="true" :tip="$t('api_test.environment.environment_config')" icon="el-icon-setting"
|
<ms-table-operator-button :is-tester-permission="true" :tip="$t('api_test.environment.environment_config')" icon="el-icon-setting"
|
||||||
type="info" @exec="openEnvironmentConfig(scope.row)"/>
|
type="info" @exec="openEnvironmentConfig(scope.row)"/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -188,21 +188,19 @@ export default {
|
||||||
this.createVisible = true;
|
this.createVisible = true;
|
||||||
listenGoBack(this.handleClose);
|
listenGoBack(this.handleClose);
|
||||||
this.form = Object.assign({}, row);
|
this.form = Object.assign({}, row);
|
||||||
if (this.baseUrl === 'track') {
|
this.$get("/service/integration/all/" + getCurrentUser().lastOrganizationId, response => {
|
||||||
this.$get("/service/integration/all/" + getCurrentUser().lastOrganizationId, response => {
|
let data = response.data;
|
||||||
let data = response.data;
|
let platforms = data.map(d => d.platform);
|
||||||
let platforms = data.map(d => d.platform);
|
if (platforms.indexOf("Tapd") !== -1) {
|
||||||
if (platforms.indexOf("Tapd") !== -1) {
|
this.tapd = true;
|
||||||
this.tapd = true;
|
}
|
||||||
}
|
if (platforms.indexOf("Jira") !== -1) {
|
||||||
if (platforms.indexOf("Jira") !== -1) {
|
this.jira = true;
|
||||||
this.jira = true;
|
}
|
||||||
}
|
if (platforms.indexOf("Zentao") !== -1) {
|
||||||
if (platforms.indexOf("Zentao") !== -1) {
|
this.zentao = true;
|
||||||
this.zentao = true;
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
submit(formName) {
|
submit(formName) {
|
||||||
|
|
|
@ -41,6 +41,14 @@
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
|
||||||
|
<el-menu-item v-for="menu in project" :key="menu.index" :index="menu.index" class="setting-item"
|
||||||
|
v-permission="menu.roles">
|
||||||
|
<template v-slot:title>
|
||||||
|
<font-awesome-icon class="icon" :icon="['fa', 'bars']" size="lg"/>
|
||||||
|
<span>{{ $t(menu.title) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-menu-item>
|
||||||
|
|
||||||
</el-menu>
|
</el-menu>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -73,6 +81,7 @@
|
||||||
organizations: getMenus('organization'),
|
organizations: getMenus('organization'),
|
||||||
workspaces: getMenus('workspace'),
|
workspaces: getMenus('workspace'),
|
||||||
persons: getMenus('person'),
|
persons: getMenus('person'),
|
||||||
|
project: getMenus('project'),
|
||||||
isCurrentOrganizationAdmin: false,
|
isCurrentOrganizationAdmin: false,
|
||||||
isCurrentWorkspaceUser: false,
|
isCurrentWorkspaceUser: false,
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
<template>
|
||||||
|
<el-card>
|
||||||
|
<el-tabs class="system-setting" v-model="activeName">
|
||||||
|
<el-tab-pane label="项目管理" name="project">
|
||||||
|
<ms-project/>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsProject from "@/business/components/project/MsProject";
|
||||||
|
export default {
|
||||||
|
name: "Project",
|
||||||
|
components: {MsProject},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeName: 'project'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -79,6 +79,11 @@ export default {
|
||||||
roles: ['test_manager', 'test_user', 'test_viewer', 'org_admin', 'admin']
|
roles: ['test_manager', 'test_user', 'test_viewer', 'org_admin', 'admin']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'project',
|
||||||
|
component: () => import('@/business/components/settings/project/Project'),
|
||||||
|
meta: {project: true, title: '项目管理'}
|
||||||
|
},
|
||||||
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,19 +5,22 @@
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router
|
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router
|
||||||
:default-active='$route.path'>
|
:default-active='$route.path'>
|
||||||
<el-menu-item :index="'/track/home'">
|
|
||||||
{{ $t("i18n.home") }}
|
|
||||||
</el-menu-item>
|
|
||||||
<el-submenu :class="{'deactivation':!isProjectActivation}"
|
<el-submenu :class="{'deactivation':!isProjectActivation}"
|
||||||
v-permission="['test_manager','test_user','test_viewer']" index="3" popper-class="submenu">
|
v-permission="['test_manager','test_user','test_viewer']" index="3" popper-class="submenu">
|
||||||
<template v-slot:title>{{ $t('commons.project') }}</template>
|
<template v-slot:title>{{ $t('commons.project') }}</template>
|
||||||
<ms-recent-list ref="projectRecent" :options="projectRecent"/>
|
<search-list ref="projectRecent" :options="projectRecent"/>
|
||||||
<el-divider/>
|
<el-divider/>
|
||||||
<ms-show-all :index="'/track/project/all'"/>
|
<el-menu-item :index="'/performance/project/create'">
|
||||||
<ms-create-button v-permission="['test_manager','test_user']" :index="'/track/project/create'"
|
<font-awesome-icon :icon="['fa', 'plus']"/>
|
||||||
:title="$t('project.create')"/>
|
<span style="padding-left: 7px;">创建项目</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<ms-show-all :index="'/setting/project'"/>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
|
||||||
|
<el-menu-item :index="'/track/home'">
|
||||||
|
{{ $t("i18n.home") }}
|
||||||
|
</el-menu-item>
|
||||||
|
|
||||||
<el-submenu v-permission="['test_manager','test_user','test_viewer']"
|
<el-submenu v-permission="['test_manager','test_user','test_viewer']"
|
||||||
index="6" popper-class="submenu">
|
index="6" popper-class="submenu">
|
||||||
<template v-slot:title>{{ $t('test_track.case.test_case') }}</template>
|
<template v-slot:title>{{ $t('test_track.case.test_case') }}</template>
|
||||||
|
@ -62,10 +65,11 @@ import MsShowAll from "../../common/head/ShowAll";
|
||||||
import MsRecentList from "../../common/head/RecentList";
|
import MsRecentList from "../../common/head/RecentList";
|
||||||
import MsCreateButton from "../../common/head/CreateButton";
|
import MsCreateButton from "../../common/head/CreateButton";
|
||||||
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
|
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
|
||||||
|
import SearchList from "@/business/components/common/head/SearchList";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TrackHeaderMenus",
|
name: "TrackHeaderMenus",
|
||||||
components: {MsShowAll, MsRecentList, MsCreateButton},
|
components: {SearchList, MsShowAll, MsRecentList, MsCreateButton},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
testPlanViewPath: '',
|
testPlanViewPath: '',
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit a22a3005d9bd254793fcf634d72539cbdf31be3a
|
Subproject commit 8a972a198775b3783ed6e4cef27197e53d1ebdc8
|
|
@ -28,7 +28,7 @@ export const xpack = {
|
||||||
function checkLicense(el, binding, type) {
|
function checkLicense(el, binding, type) {
|
||||||
let v = hasLicense()
|
let v = hasLicense()
|
||||||
|
|
||||||
if (v) {
|
if (!v) {
|
||||||
el.parentNode && el.parentNode.removeChild(el)
|
el.parentNode && el.parentNode.removeChild(el)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,7 @@ export default {
|
||||||
current_user: "Current user"
|
current_user: "Current user"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
monitor:"monitor"
|
monitor: "monitor"
|
||||||
},
|
},
|
||||||
license: {
|
license: {
|
||||||
title: 'Authorization management',
|
title: 'Authorization management',
|
||||||
|
@ -543,6 +543,7 @@ export default {
|
||||||
customize_script: "Custom script",
|
customize_script: "Custom script",
|
||||||
customize_req: "Custom request",
|
customize_req: "Custom request",
|
||||||
reference_info: "Please select interface or use case",
|
reference_info: "Please select interface or use case",
|
||||||
|
report_name_info: 'Please enter the registration name',
|
||||||
},
|
},
|
||||||
environment: {
|
environment: {
|
||||||
name: "Environment Name",
|
name: "Environment Name",
|
||||||
|
@ -779,14 +780,14 @@ export default {
|
||||||
not_exist: "Test report does not exist",
|
not_exist: "Test report does not exist",
|
||||||
},
|
},
|
||||||
api_monitor: {
|
api_monitor: {
|
||||||
to:"to",
|
to: "to",
|
||||||
start_time:"Start Time",
|
start_time: "Start Time",
|
||||||
end_time:"End Time",
|
end_time: "End Time",
|
||||||
today:"Today",
|
today: "Today",
|
||||||
this_week:"This Week",
|
this_week: "This Week",
|
||||||
this_mouth:"This Mouth",
|
this_mouth: "This Mouth",
|
||||||
please_search:"Please Search",
|
please_search: "Please Search",
|
||||||
date:"Date"
|
date: "Date"
|
||||||
},
|
},
|
||||||
test_track: {
|
test_track: {
|
||||||
test_track: "Track",
|
test_track: "Track",
|
||||||
|
@ -1096,6 +1097,7 @@ export default {
|
||||||
home: 'Home',
|
home: 'Home',
|
||||||
definition: 'Api Definition',
|
definition: 'Api Definition',
|
||||||
automation: 'Api Automation',
|
automation: 'Api Automation',
|
||||||
|
report: 'Test report',
|
||||||
},
|
},
|
||||||
ldap: {
|
ldap: {
|
||||||
url: 'LDAP URL',
|
url: 'LDAP URL',
|
||||||
|
|
|
@ -570,7 +570,8 @@ export default {
|
||||||
follow_people: "关注人",
|
follow_people: "关注人",
|
||||||
select_table: "选择可见数据",
|
select_table: "选择可见数据",
|
||||||
select_all: "选择全部数据"
|
select_all: "选择全部数据"
|
||||||
}
|
},
|
||||||
|
report_name_info: '请输入报名名称',
|
||||||
},
|
},
|
||||||
environment: {
|
environment: {
|
||||||
name: "环境名称",
|
name: "环境名称",
|
||||||
|
@ -809,14 +810,14 @@ export default {
|
||||||
not_exist: "测试报告不存在",
|
not_exist: "测试报告不存在",
|
||||||
},
|
},
|
||||||
api_monitor: {
|
api_monitor: {
|
||||||
to:"至",
|
to: "至",
|
||||||
start_time:"开始日期",
|
start_time: "开始日期",
|
||||||
end_time:"结束日期",
|
end_time: "结束日期",
|
||||||
today:"今日",
|
today: "今日",
|
||||||
this_week:"本周",
|
this_week: "本周",
|
||||||
this_mouth:"本月",
|
this_mouth: "本月",
|
||||||
please_search:"请搜索",
|
please_search: "请搜索",
|
||||||
date:"日期"
|
date: "日期"
|
||||||
},
|
},
|
||||||
test_track: {
|
test_track: {
|
||||||
test_track: "测试跟踪",
|
test_track: "测试跟踪",
|
||||||
|
@ -1125,6 +1126,7 @@ export default {
|
||||||
home: '首页',
|
home: '首页',
|
||||||
definition: '接口定义',
|
definition: '接口定义',
|
||||||
automation: '接口自动化',
|
automation: '接口自动化',
|
||||||
|
report: '测试报告',
|
||||||
},
|
},
|
||||||
ldap: {
|
ldap: {
|
||||||
url: 'LDAP地址',
|
url: 'LDAP地址',
|
||||||
|
|
|
@ -543,8 +543,8 @@ export default {
|
||||||
scenario_import: "場景導入",
|
scenario_import: "場景導入",
|
||||||
customize_script: "自定義腳本",
|
customize_script: "自定義腳本",
|
||||||
customize_req: "自定義請求",
|
customize_req: "自定義請求",
|
||||||
reference_info: "請選擇接口或用例"
|
reference_info: "請選擇接口或用例",
|
||||||
|
report_name_info: '请输入报名名称',
|
||||||
},
|
},
|
||||||
environment: {
|
environment: {
|
||||||
name: "環境名稱",
|
name: "環境名稱",
|
||||||
|
@ -1098,6 +1098,7 @@ export default {
|
||||||
home: '首頁',
|
home: '首頁',
|
||||||
definition: '接口定義',
|
definition: '接口定義',
|
||||||
automation: '接口自動化',
|
automation: '接口自動化',
|
||||||
|
report: '測試報告',
|
||||||
},
|
},
|
||||||
ldap: {
|
ldap: {
|
||||||
url: 'LDAP地址',
|
url: 'LDAP地址',
|
||||||
|
|
Loading…
Reference in New Issue