merge: 合并dev最新修改
This commit is contained in:
commit
77bfdd1a37
|
@ -9,6 +9,7 @@ import io.metersphere.base.mapper.ApiScenarioReportMapper;
|
||||||
import io.metersphere.commons.constants.TestPlanApiExecuteStatus;
|
import io.metersphere.commons.constants.TestPlanApiExecuteStatus;
|
||||||
import io.metersphere.commons.constants.TestPlanResourceType;
|
import io.metersphere.commons.constants.TestPlanResourceType;
|
||||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
|
import io.metersphere.track.dto.TestPlanReportExecuteCheckResultDTO;
|
||||||
import io.metersphere.utils.LoggerUtil;
|
import io.metersphere.utils.LoggerUtil;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
@ -20,6 +21,7 @@ import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author song.tianyang
|
* @author song.tianyang
|
||||||
|
@ -30,17 +32,16 @@ import java.util.Map;
|
||||||
public class TestPlanExecuteInfo {
|
public class TestPlanExecuteInfo {
|
||||||
private String reportId;
|
private String reportId;
|
||||||
private String creator;
|
private String creator;
|
||||||
private Map<String, String> apiCaseExecInfo = new HashMap<>();
|
private Map<String, String> apiCaseExecInfo = new ConcurrentHashMap<>();
|
||||||
private Map<String, String> apiScenarioCaseExecInfo = new HashMap<>();
|
private Map<String, String> apiScenarioCaseExecInfo = new ConcurrentHashMap<>();
|
||||||
private Map<String, String> loadCaseExecInfo = new HashMap<>();
|
private Map<String, String> loadCaseExecInfo = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private Map<String, String> apiCaseExecuteThreadMap = new HashMap<>();
|
private Map<String, String> apiCaseExecuteThreadMap = new ConcurrentHashMap<>();
|
||||||
private Map<String, String> apiScenarioThreadMap = new HashMap<>();
|
private Map<String, String> apiScenarioThreadMap = new ConcurrentHashMap<>();
|
||||||
private Map<String, String> loadCaseReportIdMap = new HashMap<>();
|
private Map<String, String> loadCaseReportIdMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private Map<String, String> apiCaseReportMap = new HashMap<>();
|
|
||||||
private Map<String, String> apiScenarioReportMap = new HashMap<>();
|
|
||||||
|
|
||||||
|
private Map<String, String> apiCaseReportMap = new ConcurrentHashMap<>();
|
||||||
|
private Map<String, String> apiScenarioReportMap = new ConcurrentHashMap<>();
|
||||||
private boolean reportDataInDataBase;
|
private boolean reportDataInDataBase;
|
||||||
|
|
||||||
int lastUnFinishedNumCount = 0;
|
int lastUnFinishedNumCount = 0;
|
||||||
|
@ -83,7 +84,8 @@ public class TestPlanExecuteInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int countUnFinishedNum() {
|
public synchronized TestPlanReportExecuteCheckResultDTO countUnFinishedNum() {
|
||||||
|
TestPlanReportExecuteCheckResultDTO executeCheck = new TestPlanReportExecuteCheckResultDTO();
|
||||||
int unFinishedCount = 0;
|
int unFinishedCount = 0;
|
||||||
|
|
||||||
this.isApiCaseAllExecuted = true;
|
this.isApiCaseAllExecuted = true;
|
||||||
|
@ -129,8 +131,22 @@ public class TestPlanExecuteInfo {
|
||||||
LoggerUtil.info("执行的报告还在队列中,重置超时时间");
|
LoggerUtil.info("执行的报告还在队列中,重置超时时间");
|
||||||
lastUnFinishedNumCount = unFinishedCount;
|
lastUnFinishedNumCount = unFinishedCount;
|
||||||
lastFinishedNumCountTime = System.currentTimeMillis();
|
lastFinishedNumCountTime = System.currentTimeMillis();
|
||||||
|
executeCheck.setFinishedCaseChanged(true);
|
||||||
|
} else if (unFinishedCount == 0) {
|
||||||
|
executeCheck.setFinishedCaseChanged(true);
|
||||||
|
} else {
|
||||||
|
executeCheck.setFinishedCaseChanged(false);
|
||||||
}
|
}
|
||||||
return unFinishedCount;
|
|
||||||
|
executeCheck.setTimeOut(false);
|
||||||
|
if (unFinishedCount > 0) {
|
||||||
|
//20分钟没有案例执行结果更新,则定位超时
|
||||||
|
long nowTime = System.currentTimeMillis();
|
||||||
|
if (nowTime - lastFinishedNumCountTime > 1200000) {
|
||||||
|
executeCheck.setTimeOut(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return executeCheck;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Map<String, String>> getExecutedResult() {
|
public Map<String, Map<String, String>> getExecutedResult() {
|
||||||
|
@ -228,7 +244,7 @@ public class TestPlanExecuteInfo {
|
||||||
this.countUnFinishedNum();
|
this.countUnFinishedNum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateReport(Map<String, String> apiCaseExecResultInfo, Map<String, String> apiScenarioCaseExecResultInfo) {
|
public synchronized void updateReport(Map<String, String> apiCaseExecResultInfo, Map<String, String> apiScenarioCaseExecResultInfo) {
|
||||||
if (MapUtils.isNotEmpty(apiCaseExecResultInfo)) {
|
if (MapUtils.isNotEmpty(apiCaseExecResultInfo)) {
|
||||||
this.apiCaseReportMap.putAll(apiCaseExecResultInfo);
|
this.apiCaseReportMap.putAll(apiCaseExecResultInfo);
|
||||||
}
|
}
|
||||||
|
@ -236,6 +252,35 @@ public class TestPlanExecuteInfo {
|
||||||
if (MapUtils.isNotEmpty(apiScenarioCaseExecResultInfo)) {
|
if (MapUtils.isNotEmpty(apiScenarioCaseExecResultInfo)) {
|
||||||
this.apiScenarioReportMap.putAll(apiScenarioCaseExecResultInfo);
|
this.apiScenarioReportMap.putAll(apiScenarioCaseExecResultInfo);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getRunningApiCaseReportMap() {
|
||||||
|
//key: reportId, value: testPlanApiCaseId
|
||||||
|
Map<String, String> returnMap = new HashMap<>();
|
||||||
|
for (Map.Entry<String, String> entry : apiCaseExecInfo.entrySet()) {
|
||||||
|
String planCaseId = entry.getKey();
|
||||||
|
String status = entry.getValue();
|
||||||
|
if (StringUtils.equalsIgnoreCase(status, TestPlanApiExecuteStatus.RUNNING.name())) {
|
||||||
|
if (apiCaseExecuteThreadMap.containsKey(planCaseId)) {
|
||||||
|
returnMap.put(apiCaseExecuteThreadMap.get(planCaseId), planCaseId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getRunningScenarioReportMap() {
|
||||||
|
//key: reportId, value: testPlanApiScenarioId
|
||||||
|
Map<String, String> returnMap = new HashMap<>();
|
||||||
|
for (Map.Entry<String, String> entry : apiScenarioCaseExecInfo.entrySet()) {
|
||||||
|
String planScenarioId = entry.getKey();
|
||||||
|
String status = entry.getValue();
|
||||||
|
if (StringUtils.equalsIgnoreCase(status, TestPlanApiExecuteStatus.RUNNING.name())) {
|
||||||
|
if (apiScenarioThreadMap.containsKey(planScenarioId)) {
|
||||||
|
returnMap.put(apiScenarioThreadMap.get(planScenarioId), planScenarioId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnMap;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.api.cache;
|
package io.metersphere.api.cache;
|
||||||
|
|
||||||
import io.metersphere.commons.constants.TestPlanApiExecuteStatus;
|
import io.metersphere.commons.constants.TestPlanApiExecuteStatus;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -50,7 +51,11 @@ public class TestPlanReportExecuteCatch {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized static boolean containsReport(String reportId) {
|
public synchronized static boolean containsReport(String reportId) {
|
||||||
return testPlanReportMap != null && testPlanReportMap.containsKey(reportId);
|
if(StringUtils.isEmpty(reportId)){
|
||||||
|
return false;
|
||||||
|
}else {
|
||||||
|
return testPlanReportMap != null && testPlanReportMap.containsKey(reportId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized static void updateApiTestPlanExecuteInfo(String reportId,
|
public synchronized static void updateApiTestPlanExecuteInfo(String reportId,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package io.metersphere.api.dto.automation;
|
package io.metersphere.api.dto.automation;
|
||||||
|
|
||||||
|
import org.junit.internal.runners.statements.Fail;
|
||||||
|
|
||||||
public enum ScenarioStatus {
|
public enum ScenarioStatus {
|
||||||
Saved, Success, Fail, Trash,Underway
|
Saved, Success, Error, Timeout, Fail, Trash, Underway
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ public class ApiDefinitionImportUtil {
|
||||||
if (parentModule != null) {
|
if (parentModule != null) {
|
||||||
module = apiModuleService.getNewModule(name, projectId, parentModule.getLevel() + 1);
|
module = apiModuleService.getNewModule(name, projectId, parentModule.getLevel() + 1);
|
||||||
module.setParentId(parentModule.getId());
|
module.setParentId(parentModule.getId());
|
||||||
|
module.setProtocol(parentModule.getProtocol());
|
||||||
} else {
|
} else {
|
||||||
module = apiModuleService.getNewModule(name, projectId, 1);
|
module = apiModuleService.getNewModule(name, projectId, 1);
|
||||||
}
|
}
|
||||||
|
@ -121,6 +122,7 @@ public class ApiDefinitionImportUtil {
|
||||||
if (parentModule != null) {
|
if (parentModule != null) {
|
||||||
module = apiModuleService.getNewModule(name, projectId, parentModule.getLevel() + 1);
|
module = apiModuleService.getNewModule(name, projectId, parentModule.getLevel() + 1);
|
||||||
module.setParentId(parentModule.getId());
|
module.setParentId(parentModule.getId());
|
||||||
|
module.setProtocol(parentModule.getProtocol());
|
||||||
} else {
|
} else {
|
||||||
module = apiModuleService.getNewModule(name, projectId, 1);
|
module = apiModuleService.getNewModule(name, projectId, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,8 +84,8 @@ public class JMeterScriptUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addItemHashTree(MsTestElement element, HashTree samplerHashTree, ParameterConfig config, String enviromentId) {
|
private static void addItemHashTree(MsTestElement element, HashTree samplerHashTree, ParameterConfig config, String enviromentId) {
|
||||||
if (element != null && element.getEnvironmentId() == null) {
|
if (element != null) {
|
||||||
element.setEnvironmentId(enviromentId);
|
element.setEnvironmentId(element.getEnvironmentId() == null ? enviromentId : element.getEnvironmentId());
|
||||||
element.toHashTree(samplerHashTree, element.getHashTree(), config);
|
element.toHashTree(samplerHashTree, element.getHashTree(), config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,8 +246,8 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
||||||
msResponse.setType(RequestType.HTTP);
|
msResponse.setType(RequestType.HTTP);
|
||||||
// todo 状态码要调整?
|
// todo 状态码要调整?
|
||||||
msResponse.setStatusCode(new ArrayList<>());
|
msResponse.setStatusCode(new ArrayList<>());
|
||||||
ApiResponse apiResponse = responses.get("200");
|
|
||||||
if (responses != null) {
|
if (responses != null) {
|
||||||
|
ApiResponse apiResponse = responses.get("200");
|
||||||
if (apiResponse == null) {
|
if (apiResponse == null) {
|
||||||
responses.forEach((responseCode, response) -> {
|
responses.forEach((responseCode, response) -> {
|
||||||
parseResponseHeader(response, msResponse.getHeaders());
|
parseResponseHeader(response, msResponse.getHeaders());
|
||||||
|
@ -257,10 +257,10 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
||||||
parseResponseHeader(apiResponse, msResponse.getHeaders());
|
parseResponseHeader(apiResponse, msResponse.getHeaders());
|
||||||
parseResponseBody(apiResponse, msResponse.getBody());
|
parseResponseBody(apiResponse, msResponse.getBody());
|
||||||
}
|
}
|
||||||
|
responses.forEach((responseCode, response) -> {
|
||||||
|
parseResponseCode(msResponse.getStatusCode(), responseCode, response);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
responses.forEach((responseCode, response) -> {
|
|
||||||
parseResponseCode(msResponse.getStatusCode(), responseCode, response);
|
|
||||||
});
|
|
||||||
return msResponse;
|
return msResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,7 @@ public class MsTCPSampler extends MsTestElement {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//根据配置将脚本放置在私有脚本之后
|
//根据配置将脚本放置在私有脚本之后
|
||||||
JMeterScriptUtil.setScript(envConfig, samplerHashTree, GlobalScriptFilterRequest.TCP.name(), enviromentId, config, false);
|
JMeterScriptUtil.setScript(envConfig, samplerHashTree, GlobalScriptFilterRequest.TCP.name(), enviromentId, config, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addItemHashTree(MsTestElement element, HashTree samplerHashTree, ParameterConfig config) {
|
private void addItemHashTree(MsTestElement element, HashTree samplerHashTree, ParameterConfig config) {
|
||||||
|
|
|
@ -136,8 +136,13 @@ public class TestPlanApiExecuteService {
|
||||||
JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(testPlanApiCase.getId(), reportId, request.getTriggerMode(), hashTree);
|
JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(testPlanApiCase.getId(), reportId, request.getTriggerMode(), hashTree);
|
||||||
if (request.getConfig() != null) {
|
if (request.getConfig() != null) {
|
||||||
runRequest.setPool(GenerateHashTreeUtil.isResourcePool(request.getConfig().getResourcePoolId()));
|
runRequest.setPool(GenerateHashTreeUtil.isResourcePool(request.getConfig().getResourcePoolId()));
|
||||||
|
runRequest.setPoolId(request.getConfig().getResourcePoolId());
|
||||||
}
|
}
|
||||||
runRequest.setTestPlanReportId(request.getPlanReportId());
|
runRequest.setTestPlanReportId(request.getPlanReportId());
|
||||||
|
runRequest.setReportType(executionQueue.getReportType());
|
||||||
|
runRequest.setTestPlanReportId(request.getPlanReportId());
|
||||||
|
runRequest.setRunType(RunModeConstants.PARALLEL.toString());
|
||||||
|
runRequest.setQueueId(executionQueue.getId());
|
||||||
jMeterService.run(runRequest);
|
jMeterService.run(runRequest);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
executeErrorList.add(testPlanApiCase.getId());
|
executeErrorList.add(testPlanApiCase.getId());
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.api.exec.queue;
|
package io.metersphere.api.exec.queue;
|
||||||
|
|
||||||
import io.metersphere.api.jmeter.JMeterService;
|
import io.metersphere.api.jmeter.JMeterService;
|
||||||
|
import io.metersphere.api.jmeter.JmeterThreadUtils;
|
||||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
import io.metersphere.dto.JmeterRunRequestDTO;
|
import io.metersphere.dto.JmeterRunRequestDTO;
|
||||||
import io.metersphere.utils.LoggerUtil;
|
import io.metersphere.utils.LoggerUtil;
|
||||||
|
@ -23,7 +24,7 @@ public class ExecTask implements Runnable {
|
||||||
jMeterService.addQueue(request);
|
jMeterService.addQueue(request);
|
||||||
if (request.getPool() == null || !request.getPool().isPool()) {
|
if (request.getPool() == null || !request.getPool().isPool()) {
|
||||||
Object res = PoolExecBlockingQueueUtil.take(request.getReportId());
|
Object res = PoolExecBlockingQueueUtil.take(request.getReportId());
|
||||||
if (res == null) {
|
if (res == null && !JmeterThreadUtils.isRunning(request.getReportId(), request.getTestId())) {
|
||||||
LoggerUtil.info("执行报告:【 " + request.getReportId() + " 】,资源ID【 " + request.getTestId() + " 】执行超时");
|
LoggerUtil.info("执行报告:【 " + request.getReportId() + " 】,资源ID【 " + request.getTestId() + " 】执行超时");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class PoolExecBlockingQueueUtil {
|
||||||
if (StringUtils.isNotEmpty(key) && !queue.containsKey(key)) {
|
if (StringUtils.isNotEmpty(key) && !queue.containsKey(key)) {
|
||||||
BlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(QUEUE_SIZE);
|
BlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(QUEUE_SIZE);
|
||||||
queue.put(key, blockingQueue);
|
queue.put(key, blockingQueue);
|
||||||
return blockingQueue.poll(5, TimeUnit.MINUTES);
|
return blockingQueue.poll(10, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtil.error("初始化队列失败:" + e.getMessage());
|
LogUtil.error("初始化队列失败:" + e.getMessage());
|
||||||
|
|
|
@ -91,7 +91,6 @@ public class ApiDefinitionExecResultUtil {
|
||||||
apiResult.setStartTime(System.currentTimeMillis());
|
apiResult.setStartTime(System.currentTimeMillis());
|
||||||
apiResult.setType(ApiRunMode.DEFINITION.name());
|
apiResult.setType(ApiRunMode.DEFINITION.name());
|
||||||
apiResult.setStatus(status);
|
apiResult.setStatus(status);
|
||||||
|
|
||||||
return apiResult;
|
return apiResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,9 +31,12 @@ import java.util.Map;
|
||||||
public class GenerateHashTreeUtil {
|
public class GenerateHashTreeUtil {
|
||||||
|
|
||||||
public static MsScenario parseScenarioDefinition(String scenarioDefinition) {
|
public static MsScenario parseScenarioDefinition(String scenarioDefinition) {
|
||||||
MsScenario scenario = JSONObject.parseObject(scenarioDefinition, MsScenario.class);
|
if(StringUtils.isNotEmpty(scenarioDefinition)) {
|
||||||
parse(scenarioDefinition, scenario, scenario.getId(), null);
|
MsScenario scenario = JSONObject.parseObject(scenarioDefinition, MsScenario.class);
|
||||||
return scenario;
|
parse(scenarioDefinition, scenario, scenario.getId(), null);
|
||||||
|
return scenario;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void parse(String scenarioDefinition, MsScenario scenario, String id, String reportType) {
|
public static void parse(String scenarioDefinition, MsScenario scenario, String id, String reportType) {
|
||||||
|
|
|
@ -5,10 +5,12 @@ import io.metersphere.api.exec.queue.PoolExecBlockingQueueUtil;
|
||||||
import io.metersphere.api.service.ApiExecutionQueueService;
|
import io.metersphere.api.service.ApiExecutionQueueService;
|
||||||
import io.metersphere.api.service.MsResultService;
|
import io.metersphere.api.service.MsResultService;
|
||||||
import io.metersphere.api.service.TestResultService;
|
import io.metersphere.api.service.TestResultService;
|
||||||
|
import io.metersphere.commons.constants.ApiRunMode;
|
||||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
import io.metersphere.dto.ResultDTO;
|
import io.metersphere.dto.ResultDTO;
|
||||||
import io.metersphere.jmeter.MsExecListener;
|
import io.metersphere.jmeter.MsExecListener;
|
||||||
import io.metersphere.utils.LoggerUtil;
|
import io.metersphere.utils.LoggerUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -18,13 +20,19 @@ public class APISingleResultListener extends MsExecListener {
|
||||||
LoggerUtil.info("处理单条执行结果报告【" + dto.getReportId() + " 】,资源【 " + dto.getTestId() + " 】");
|
LoggerUtil.info("处理单条执行结果报告【" + dto.getReportId() + " 】,资源【 " + dto.getTestId() + " 】");
|
||||||
dto.setConsole(CommonBeanFactory.getBean(MsResultService.class).getJmeterLogger(dto.getReportId()));
|
dto.setConsole(CommonBeanFactory.getBean(MsResultService.class).getJmeterLogger(dto.getReportId()));
|
||||||
CommonBeanFactory.getBean(TestResultService.class).saveResults(dto);
|
CommonBeanFactory.getBean(TestResultService.class).saveResults(dto);
|
||||||
|
|
||||||
|
// 更新报告最后接收到请求的时间
|
||||||
|
if (StringUtils.equalsAny(dto.getRunMode(), ApiRunMode.SCENARIO.name(),
|
||||||
|
ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(),
|
||||||
|
ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
|
||||||
|
CommonBeanFactory.getBean(TestResultService.class).editReportTime(dto);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testEnded(ResultDTO dto, Map<String, Object> kafkaConfig) {
|
public void testEnded(ResultDTO dto, Map<String, Object> kafkaConfig) {
|
||||||
try {
|
try {
|
||||||
LoggerUtil.info("进入TEST-END处理报告【" + dto.getReportId() + " 】整体执行完成;" + dto.getRunMode());
|
LoggerUtil.info("进入TEST-END处理报告【" + dto.getReportId() + " 】整体执行完成;" + dto.getRunMode());
|
||||||
|
|
||||||
// 全局并发队列
|
// 全局并发队列
|
||||||
PoolExecBlockingQueueUtil.offer(dto.getReportId());
|
PoolExecBlockingQueueUtil.offer(dto.getReportId());
|
||||||
dto.setConsole(CommonBeanFactory.getBean(MsResultService.class).getJmeterLogger(dto.getReportId()));
|
dto.setConsole(CommonBeanFactory.getBean(MsResultService.class).getJmeterLogger(dto.getReportId()));
|
||||||
|
|
|
@ -68,9 +68,9 @@ public class JMeterService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addDebugListener(String testId, HashTree testPlan) {
|
private void addDebugListener(String testId, HashTree testPlan) {
|
||||||
MsDebugListener resultCollector = new MsDebugListener();
|
MsResultCollector resultCollector = new MsResultCollector();
|
||||||
resultCollector.setName(testId);
|
resultCollector.setName(testId);
|
||||||
resultCollector.setProperty(TestElement.TEST_CLASS, MsDebugListener.class.getName());
|
resultCollector.setProperty(TestElement.TEST_CLASS, MsResultCollector.class.getName());
|
||||||
resultCollector.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ViewResultsFullVisualizer"));
|
resultCollector.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ViewResultsFullVisualizer"));
|
||||||
resultCollector.setEnabled(true);
|
resultCollector.setEnabled(true);
|
||||||
testPlan.add(testPlan.getArray()[0], resultCollector);
|
testPlan.add(testPlan.getArray()[0], resultCollector);
|
||||||
|
@ -139,8 +139,8 @@ public class JMeterService {
|
||||||
JvmInfoDTO jvmInfoDTO = resources.get(index);
|
JvmInfoDTO jvmInfoDTO = resources.get(index);
|
||||||
TestResourceDTO testResource = jvmInfoDTO.getTestResource();
|
TestResourceDTO testResource = jvmInfoDTO.getTestResource();
|
||||||
String configuration = testResource.getConfiguration();
|
String configuration = testResource.getConfiguration();
|
||||||
request.setCorePoolSize(MessageCache.corePoolSize);
|
|
||||||
NodeDTO node = JSON.parseObject(configuration, NodeDTO.class);
|
NodeDTO node = JSON.parseObject(configuration, NodeDTO.class);
|
||||||
|
request.setCorePoolSize(node.getMaxConcurrency());
|
||||||
String nodeIp = node.getIp();
|
String nodeIp = node.getIp();
|
||||||
Integer port = node.getPort();
|
Integer port = node.getPort();
|
||||||
String uri = String.format(BASE_URL + "/jmeter/api/start", nodeIp, port);
|
String uri = String.format(BASE_URL + "/jmeter/api/start", nodeIp, port);
|
||||||
|
|
|
@ -7,9 +7,7 @@ public class JmeterThreadUtils {
|
||||||
private final static String THREAD_SPLIT = " ";
|
private final static String THREAD_SPLIT = " ";
|
||||||
|
|
||||||
public static String stop(String name) {
|
public static String stop(String name) {
|
||||||
|
|
||||||
ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
|
ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
|
||||||
|
|
||||||
int noThreads = currentGroup.activeCount();
|
int noThreads = currentGroup.activeCount();
|
||||||
Thread[] lstThreads = new Thread[noThreads];
|
Thread[] lstThreads = new Thread[noThreads];
|
||||||
currentGroup.enumerate(lstThreads);
|
currentGroup.enumerate(lstThreads);
|
||||||
|
@ -24,4 +22,19 @@ public class JmeterThreadUtils {
|
||||||
}
|
}
|
||||||
return threadNames.toString();
|
return threadNames.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isRunning(String reportId, String testId) {
|
||||||
|
ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
|
||||||
|
int noThreads = currentGroup.activeCount();
|
||||||
|
Thread[] lstThreads = new Thread[noThreads];
|
||||||
|
currentGroup.enumerate(lstThreads);
|
||||||
|
for (int i = 0; i < noThreads; i++) {
|
||||||
|
if (StringUtils.isNotEmpty(reportId) && StringUtils.isNotEmpty(lstThreads[i].getName()) && lstThreads[i].getName().startsWith(reportId)) {
|
||||||
|
return true;
|
||||||
|
} else if (StringUtils.isNotEmpty(testId) && StringUtils.isNotEmpty(lstThreads[i].getName()) && lstThreads[i].getName().startsWith(testId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import io.metersphere.api.exec.queue.PoolExecBlockingQueueUtil;
|
||||||
import io.metersphere.api.service.ApiEnvironmentRunningParamService;
|
import io.metersphere.api.service.ApiEnvironmentRunningParamService;
|
||||||
import io.metersphere.api.service.ApiExecutionQueueService;
|
import io.metersphere.api.service.ApiExecutionQueueService;
|
||||||
import io.metersphere.api.service.TestResultService;
|
import io.metersphere.api.service.TestResultService;
|
||||||
|
import io.metersphere.commons.constants.ApiRunMode;
|
||||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
import io.metersphere.config.KafkaConfig;
|
import io.metersphere.config.KafkaConfig;
|
||||||
import io.metersphere.dto.ResultDTO;
|
import io.metersphere.dto.ResultDTO;
|
||||||
|
@ -34,6 +35,13 @@ public class MsKafkaListener {
|
||||||
// 全局并发队列
|
// 全局并发队列
|
||||||
PoolExecBlockingQueueUtil.offer(testResult.getReportId());
|
PoolExecBlockingQueueUtil.offer(testResult.getReportId());
|
||||||
} else {
|
} else {
|
||||||
|
// 更新报告最后接收到请求的时间
|
||||||
|
if (StringUtils.equalsAny(testResult.getRunMode(), ApiRunMode.SCENARIO.name(),
|
||||||
|
ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(),
|
||||||
|
ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
|
||||||
|
CommonBeanFactory.getBean(TestResultService.class).editReportTime(testResult);
|
||||||
|
}
|
||||||
|
|
||||||
testResultService.saveResults(testResult);
|
testResultService.saveResults(testResult);
|
||||||
}
|
}
|
||||||
LoggerUtil.info("执行内容存储结束");
|
LoggerUtil.info("执行内容存储结束");
|
||||||
|
|
|
@ -23,11 +23,10 @@ import io.metersphere.api.service.MsResultService;
|
||||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
import io.metersphere.commons.utils.LogUtil;
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
import io.metersphere.dto.RequestResult;
|
import io.metersphere.dto.RequestResult;
|
||||||
import io.metersphere.dto.ResultDTO;
|
|
||||||
import io.metersphere.jmeter.JMeterBase;
|
import io.metersphere.jmeter.JMeterBase;
|
||||||
import io.metersphere.utils.JMeterVars;
|
import io.metersphere.utils.JMeterVars;
|
||||||
import io.metersphere.utils.LoggerUtil;
|
import io.metersphere.utils.LoggerUtil;
|
||||||
import io.metersphere.websocket.c.to.c.MsWebSocketClient;
|
import io.metersphere.websocket.c.to.c.WebSocketUtils;
|
||||||
import io.metersphere.websocket.c.to.c.util.MsgDto;
|
import io.metersphere.websocket.c.to.c.util.MsgDto;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -44,7 +43,7 @@ import java.util.Map;
|
||||||
/**
|
/**
|
||||||
* 实时结果监听
|
* 实时结果监听
|
||||||
*/
|
*/
|
||||||
public class MsDebugListener extends AbstractListenerElement implements SampleListener, Clearable, Serializable,
|
public class MsResultCollector extends AbstractListenerElement implements SampleListener, Clearable, Serializable,
|
||||||
TestStateListener, Remoteable, NoThreadClone {
|
TestStateListener, Remoteable, NoThreadClone {
|
||||||
|
|
||||||
private static final String ERROR_LOGGING = "MsResultCollector.error_logging"; // $NON-NLS-1$
|
private static final String ERROR_LOGGING = "MsResultCollector.error_logging"; // $NON-NLS-1$
|
||||||
|
@ -55,11 +54,9 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
|
||||||
|
|
||||||
public static final String TEST_END = "MS_TEST_END";
|
public static final String TEST_END = "MS_TEST_END";
|
||||||
|
|
||||||
private MsWebSocketClient client;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object clone() {
|
public Object clone() {
|
||||||
MsDebugListener clone = (MsDebugListener) super.clone();
|
MsResultCollector clone = (MsResultCollector) super.clone();
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,28 +97,20 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
|
||||||
@Override
|
@Override
|
||||||
public void testEnded(String host) {
|
public void testEnded(String host) {
|
||||||
LoggerUtil.debug("TestEnded " + this.getName());
|
LoggerUtil.debug("TestEnded " + this.getName());
|
||||||
SampleResult result = new SampleResult();
|
MsgDto dto = new MsgDto();
|
||||||
result.setResponseCode(TEST_END);
|
dto.setExecEnd(false);
|
||||||
ResultDTO dto = new ResultDTO();
|
dto.setContent(TEST_END);
|
||||||
dto.setReportId(this.getName());
|
dto.setReportId("send." + this.getName());
|
||||||
try {
|
dto.setToReport(this.getName());
|
||||||
if (client != null) {
|
LoggerUtil.debug("send. " + this.getName());
|
||||||
client.close();
|
WebSocketUtils.sendMessageSingle(dto);
|
||||||
}
|
WebSocketUtils.onClose(this.getName());
|
||||||
} catch (Exception e) {
|
|
||||||
LogUtil.error(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testStarted(String host) {
|
public void testStarted(String host) {
|
||||||
LogUtil.debug("TestStarted " + this.getName());
|
LogUtil.debug("TestStarted " + this.getName());
|
||||||
try {
|
|
||||||
client = new MsWebSocketClient("ws://127.0.0.1:8081/ws/" + "send." + this.getName());
|
|
||||||
client.connect();
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogUtil.error(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -142,10 +131,9 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
|
||||||
dto.setReportId("send." + this.getName());
|
dto.setReportId("send." + this.getName());
|
||||||
dto.setToReport(this.getName());
|
dto.setToReport(this.getName());
|
||||||
LoggerUtil.debug("send. " + this.getName());
|
LoggerUtil.debug("send. " + this.getName());
|
||||||
if (client != null) {
|
WebSocketUtils.sendMessageSingle(dto);
|
||||||
client.send(JSON.toJSONString(dto));
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
LoggerUtil.error("消息推送失败:" + ex.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,9 +167,7 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
|
||||||
dto.setReportId("send." + this.getName());
|
dto.setReportId("send." + this.getName());
|
||||||
dto.setToReport(this.getName());
|
dto.setToReport(this.getName());
|
||||||
LoggerUtil.debug("send. " + this.getName());
|
LoggerUtil.debug("send. " + this.getName());
|
||||||
if (client != null) {
|
WebSocketUtils.sendMessageSingle(dto);
|
||||||
client.send(JSON.toJSONString(dto));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -116,8 +116,8 @@ public class ApiDefinitionExecResultService {
|
||||||
.operator(SessionUtils.getUserId())
|
.operator(SessionUtils.getUserId())
|
||||||
.context(context)
|
.context(context)
|
||||||
.subject("接口用例通知")
|
.subject("接口用例通知")
|
||||||
.successMailTemplate("api/CaseResult")
|
.successMailTemplate("api/CaseResultSuccess")
|
||||||
.failedMailTemplate("api/CaseResult")
|
.failedMailTemplate("api/CaseResultFailed")
|
||||||
.paramMap(paramMap)
|
.paramMap(paramMap)
|
||||||
.event(event)
|
.event(event)
|
||||||
.build();
|
.build();
|
||||||
|
@ -187,8 +187,6 @@ public class ApiDefinitionExecResultService {
|
||||||
* 定时任务时,userID要改为定时任务中的用户
|
* 定时任务时,userID要改为定时任务中的用户
|
||||||
*/
|
*/
|
||||||
public void saveApiResultByScheduleTask(List<RequestResult> requestResults, ResultDTO dto) {
|
public void saveApiResultByScheduleTask(List<RequestResult> requestResults, ResultDTO dto) {
|
||||||
Map<String, String> apiIdResultMap = new HashMap<>();
|
|
||||||
Map<String, String> caseReportMap = new HashMap<>();
|
|
||||||
boolean isFirst = true;
|
boolean isFirst = true;
|
||||||
int countExpectProcessResultCount = 0;
|
int countExpectProcessResultCount = 0;
|
||||||
if (CollectionUtils.isNotEmpty(requestResults)) {
|
if (CollectionUtils.isNotEmpty(requestResults)) {
|
||||||
|
@ -201,7 +199,7 @@ public class ApiDefinitionExecResultService {
|
||||||
|
|
||||||
for (RequestResult item : requestResults) {
|
for (RequestResult item : requestResults) {
|
||||||
if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) {
|
if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) {
|
||||||
ApiDefinitionExecResult saveResult = this.save(item, dto.getReportId(), dto.getConsole(), countExpectProcessResultCount, dto.getRunMode(), dto.getTestId(), isFirst);
|
this.save(item, dto.getReportId(), dto.getConsole(), countExpectProcessResultCount, dto.getRunMode(), dto.getTestId(), isFirst);
|
||||||
String status = item.isSuccess() ? "success" : "error";
|
String status = item.isSuccess() ? "success" : "error";
|
||||||
if (StringUtils.equalsAny(dto.getRunMode(), ApiRunMode.SCHEDULE_API_PLAN.name(), ApiRunMode.JENKINS_API_PLAN.name())) {
|
if (StringUtils.equalsAny(dto.getRunMode(), ApiRunMode.SCHEDULE_API_PLAN.name(), ApiRunMode.JENKINS_API_PLAN.name())) {
|
||||||
TestPlanApiCase apiCase = testPlanApiCaseService.getById(dto.getTestId());
|
TestPlanApiCase apiCase = testPlanApiCaseService.getById(dto.getTestId());
|
||||||
|
@ -214,19 +212,19 @@ public class ApiDefinitionExecResultService {
|
||||||
testPlanApiCaseService.setExecResult(dto.getTestId(), status, item.getStartTime());
|
testPlanApiCaseService.setExecResult(dto.getTestId(), status, item.getStartTime());
|
||||||
testCaseReviewApiCaseService.setExecResult(dto.getTestId(), status, item.getStartTime());
|
testCaseReviewApiCaseService.setExecResult(dto.getTestId(), status, item.getStartTime());
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotEmpty(dto.getTestId())) {
|
|
||||||
apiIdResultMap.put(dto.getTestId(), item.isSuccess() ? TestPlanApiExecuteStatus.SUCCESS.name() : TestPlanApiExecuteStatus.FAILD.name());
|
|
||||||
}
|
|
||||||
//更新报告ID
|
|
||||||
caseReportMap.put(dto.getTestId(), saveResult.getId());
|
|
||||||
isFirst = false;
|
isFirst = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateTestCaseStates(dto.getTestId());
|
updateTestCaseStates(dto.getTestId());
|
||||||
|
Map<String, String> apiIdResultMap = new HashMap<>();
|
||||||
|
long errorSize = requestResults.stream().filter(requestResult -> requestResult.getError() > 0).count();
|
||||||
|
String status = errorSize > 0 || requestResults.isEmpty() ? TestPlanApiExecuteStatus.FAILD.name() : TestPlanApiExecuteStatus.SUCCESS.name();
|
||||||
|
if (StringUtils.isNotEmpty(dto.getReportId())) {
|
||||||
|
apiIdResultMap.put(dto.getReportId(), status);
|
||||||
|
}
|
||||||
testPlanLog.info("TestPlanReportId[" + dto.getTestPlanReportId() + "] APICASE OVER. API CASE STATUS:" + JSONObject.toJSONString(apiIdResultMap));
|
testPlanLog.info("TestPlanReportId[" + dto.getTestPlanReportId() + "] APICASE OVER. API CASE STATUS:" + JSONObject.toJSONString(apiIdResultMap));
|
||||||
TestPlanReportExecuteCatch.updateApiTestPlanExecuteInfo(dto.getTestPlanReportId(), apiIdResultMap, null, null);
|
TestPlanReportExecuteCatch.updateApiTestPlanExecuteInfo(dto.getTestPlanReportId(), apiIdResultMap, null, null);
|
||||||
TestPlanReportExecuteCatch.updateTestPlanReport(dto.getTestPlanReportId(), caseReportMap, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -348,13 +346,13 @@ public class ApiDefinitionExecResultService {
|
||||||
ApiDefinitionExecResult prevResult = extApiDefinitionExecResultMapper.selectMaxResultByResourceIdAndType(item.getName(), type);
|
ApiDefinitionExecResult prevResult = extApiDefinitionExecResultMapper.selectMaxResultByResourceIdAndType(item.getName(), type);
|
||||||
if (prevResult != null) {
|
if (prevResult != null) {
|
||||||
prevResult.setContent(null);
|
prevResult.setContent(null);
|
||||||
apiDefinitionExecResultMapper.updateByPrimaryKeyWithBLOBs(prevResult);
|
apiDefinitionExecResultMapper.updateByPrimaryKeySelective(prevResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotEmpty(saveResult.getTriggerMode()) && saveResult.getTriggerMode().equals("CASE")) {
|
if (StringUtils.isNotEmpty(saveResult.getTriggerMode()) && saveResult.getTriggerMode().equals("CASE")) {
|
||||||
saveResult.setTriggerMode(TriggerMode.MANUAL.name());
|
saveResult.setTriggerMode(TriggerMode.MANUAL.name());
|
||||||
}
|
}
|
||||||
apiDefinitionExecResultMapper.updateByPrimaryKeyWithBLOBs(saveResult);
|
apiDefinitionExecResultMapper.updateByPrimaryKeySelective(saveResult);
|
||||||
return saveResult;
|
return saveResult;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -22,6 +22,7 @@ import io.metersphere.api.dto.scenario.request.RequestType;
|
||||||
import io.metersphere.api.dto.swaggerurl.SwaggerTaskResult;
|
import io.metersphere.api.dto.swaggerurl.SwaggerTaskResult;
|
||||||
import io.metersphere.api.dto.swaggerurl.SwaggerUrlRequest;
|
import io.metersphere.api.dto.swaggerurl.SwaggerUrlRequest;
|
||||||
import io.metersphere.api.exec.api.ApiExecuteService;
|
import io.metersphere.api.exec.api.ApiExecuteService;
|
||||||
|
import io.metersphere.api.exec.utils.ApiDefinitionExecResultUtil;
|
||||||
import io.metersphere.api.parse.ApiImportParser;
|
import io.metersphere.api.parse.ApiImportParser;
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
import io.metersphere.base.mapper.*;
|
import io.metersphere.base.mapper.*;
|
||||||
|
@ -102,16 +103,12 @@ public class ApiDefinitionService {
|
||||||
@Resource
|
@Resource
|
||||||
private ApiTestCaseMapper apiTestCaseMapper;
|
private ApiTestCaseMapper apiTestCaseMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private ApiTestEnvironmentService environmentService;
|
|
||||||
@Resource
|
|
||||||
private EsbApiParamService esbApiParamService;
|
private EsbApiParamService esbApiParamService;
|
||||||
@Resource
|
@Resource
|
||||||
private TcpApiParamService tcpApiParamService;
|
private TcpApiParamService tcpApiParamService;
|
||||||
@Resource
|
@Resource
|
||||||
private ApiModuleMapper apiModuleMapper;
|
private ApiModuleMapper apiModuleMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private SystemParameterService systemParameterService;
|
|
||||||
@Resource
|
|
||||||
private TestPlanMapper testPlanMapper;
|
private TestPlanMapper testPlanMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private NoticeSendService noticeSendService;
|
private NoticeSendService noticeSendService;
|
||||||
|
@ -855,6 +852,15 @@ public class ApiDefinitionService {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public MsExecResponseDTO run(RunDefinitionRequest request, List<MultipartFile> bodyFiles) {
|
public MsExecResponseDTO run(RunDefinitionRequest request, List<MultipartFile> bodyFiles) {
|
||||||
|
if (!request.isDebug()) {
|
||||||
|
String testId = request.getTestElement() != null &&
|
||||||
|
CollectionUtils.isNotEmpty(request.getTestElement().getHashTree()) &&
|
||||||
|
CollectionUtils.isNotEmpty(request.getTestElement().getHashTree().get(0).getHashTree()) ?
|
||||||
|
request.getTestElement().getHashTree().get(0).getHashTree().get(0).getName() : request.getId();
|
||||||
|
ApiDefinitionExecResult result = ApiDefinitionExecResultUtil.add(testId, APITestStatus.Running.name(), request.getId());
|
||||||
|
result.setTriggerMode(TriggerMode.MANUAL.name());
|
||||||
|
apiDefinitionExecResultMapper.insert(result);
|
||||||
|
}
|
||||||
return apiExecuteService.debug(request, bodyFiles);
|
return apiExecuteService.debug(request, bodyFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.api.service;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import io.metersphere.api.dto.RunModeDataDTO;
|
import io.metersphere.api.dto.RunModeDataDTO;
|
||||||
|
import io.metersphere.api.dto.automation.ScenarioStatus;
|
||||||
import io.metersphere.api.exec.queue.DBTestQueue;
|
import io.metersphere.api.exec.queue.DBTestQueue;
|
||||||
import io.metersphere.api.exec.scenario.ApiScenarioSerialService;
|
import io.metersphere.api.exec.scenario.ApiScenarioSerialService;
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
|
@ -179,9 +180,8 @@ public class ApiExecutionQueueService {
|
||||||
public void timeOut() {
|
public void timeOut() {
|
||||||
final int SECOND_MILLIS = 1000;
|
final int SECOND_MILLIS = 1000;
|
||||||
final int MINUTE_MILLIS = 60 * SECOND_MILLIS;
|
final int MINUTE_MILLIS = 60 * SECOND_MILLIS;
|
||||||
long now = System.currentTimeMillis();
|
// 二十分钟前的超时报告
|
||||||
// 八分钟前的数据
|
final long now = System.currentTimeMillis() - (20 * MINUTE_MILLIS);
|
||||||
now = now - 8 * MINUTE_MILLIS;
|
|
||||||
ApiExecutionQueueDetailExample example = new ApiExecutionQueueDetailExample();
|
ApiExecutionQueueDetailExample example = new ApiExecutionQueueDetailExample();
|
||||||
example.createCriteria().andCreateTimeLessThan(now);
|
example.createCriteria().andCreateTimeLessThan(now);
|
||||||
List<ApiExecutionQueueDetail> queueDetails = executionQueueDetailMapper.selectByExample(example);
|
List<ApiExecutionQueueDetail> queueDetails = executionQueueDetailMapper.selectByExample(example);
|
||||||
|
@ -190,14 +190,14 @@ public class ApiExecutionQueueService {
|
||||||
queueDetails.forEach(item -> {
|
queueDetails.forEach(item -> {
|
||||||
if (StringUtils.equalsAny(item.getType(), ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
|
if (StringUtils.equalsAny(item.getType(), ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
|
||||||
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(item.getReportId());
|
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(item.getReportId());
|
||||||
if (report != null && StringUtils.equalsAny(report.getStatus(), TestPlanReportStatus.RUNNING.name())) {
|
if (report != null && StringUtils.equalsAny(report.getStatus(), TestPlanReportStatus.RUNNING.name()) && report.getUpdateTime() < now) {
|
||||||
report.setStatus("timeout");
|
report.setStatus(ScenarioStatus.Timeout.name());
|
||||||
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
|
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ApiDefinitionExecResult result = apiDefinitionExecResultMapper.selectByPrimaryKey(item.getReportId());
|
ApiDefinitionExecResult result = apiDefinitionExecResultMapper.selectByPrimaryKey(item.getReportId());
|
||||||
if (result != null && StringUtils.equalsAny(result.getStatus(), TestPlanReportStatus.RUNNING.name())) {
|
if (result != null && StringUtils.equalsAny(result.getStatus(), TestPlanReportStatus.RUNNING.name())) {
|
||||||
result.setStatus("timeout");
|
result.setStatus(ScenarioStatus.Timeout.name());
|
||||||
apiDefinitionExecResultMapper.updateByPrimaryKeySelective(result);
|
apiDefinitionExecResultMapper.updateByPrimaryKeySelective(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,8 +211,8 @@ public class ApiExecutionQueueService {
|
||||||
if (CollectionUtils.isNotEmpty(executionQueues)) {
|
if (CollectionUtils.isNotEmpty(executionQueues)) {
|
||||||
executionQueues.forEach(item -> {
|
executionQueues.forEach(item -> {
|
||||||
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(item.getReportId());
|
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(item.getReportId());
|
||||||
if (report != null && StringUtils.equalsAny(report.getStatus(), TestPlanReportStatus.RUNNING.name())) {
|
if (report != null && StringUtils.equalsAny(report.getStatus(), TestPlanReportStatus.RUNNING.name()) && report.getUpdateTime() < now) {
|
||||||
report.setStatus("timeout");
|
report.setStatus(ScenarioStatus.Timeout.name());
|
||||||
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
|
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -87,6 +87,7 @@ public class ApiScenarioReportService {
|
||||||
apiScenarioReportResultService.save(dto.getReportId(), requestResults);
|
apiScenarioReportResultService.save(dto.getReportId(), requestResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ApiScenarioReport testEnded(ResultDTO dto) {
|
public ApiScenarioReport testEnded(ResultDTO dto) {
|
||||||
if (!StringUtils.equals(dto.getReportType(), RunModeConstants.SET_REPORT.toString())) {
|
if (!StringUtils.equals(dto.getReportType(), RunModeConstants.SET_REPORT.toString())) {
|
||||||
// 更新控制台信息
|
// 更新控制台信息
|
||||||
|
@ -96,6 +97,15 @@ public class ApiScenarioReportService {
|
||||||
example.createCriteria().andReportIdEqualTo(dto.getReportId());
|
example.createCriteria().andReportIdEqualTo(dto.getReportId());
|
||||||
List<ApiScenarioReportResult> requestResults = apiScenarioReportResultMapper.selectByExample(example);
|
List<ApiScenarioReportResult> requestResults = apiScenarioReportResultMapper.selectByExample(example);
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(dto.getTestPlanReportId())) {
|
||||||
|
String status = getStatus(requestResults, dto);
|
||||||
|
Map<String, String> reportMap = new HashMap<String, String>() {{
|
||||||
|
this.put(dto.getReportId(), status);
|
||||||
|
}};
|
||||||
|
testPlanLog.info("TestPlanReportId" + JSONArray.toJSONString(dto.getReportId()) + " EXECUTE OVER. SCENARIO STATUS : " + JSONObject.toJSONString(reportMap));
|
||||||
|
TestPlanReportExecuteCatch.updateApiTestPlanExecuteInfo(dto.getTestPlanReportId(), null, reportMap, null);
|
||||||
|
}
|
||||||
|
|
||||||
ApiScenarioReport scenarioReport;
|
ApiScenarioReport scenarioReport;
|
||||||
if (StringUtils.equals(dto.getRunMode(), ApiRunMode.SCENARIO_PLAN.name())) {
|
if (StringUtils.equals(dto.getRunMode(), ApiRunMode.SCENARIO_PLAN.name())) {
|
||||||
scenarioReport = updatePlanCase(requestResults, dto);
|
scenarioReport = updatePlanCase(requestResults, dto);
|
||||||
|
@ -226,7 +236,7 @@ public class ApiScenarioReportService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApiScenarioReport updatePlanCase(List<ApiScenarioReportResult> requestResults, ResultDTO dto) {
|
public ApiScenarioReport updatePlanCase(List<ApiScenarioReportResult> requestResults, ResultDTO dto) {
|
||||||
long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), "Error")).count();
|
long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Error.name())).count();
|
||||||
TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(dto.getTestId());
|
TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(dto.getTestId());
|
||||||
if (testPlanApiScenario != null) {
|
if (testPlanApiScenario != null) {
|
||||||
if (errorSize > 0) {
|
if (errorSize > 0) {
|
||||||
|
@ -234,7 +244,7 @@ public class ApiScenarioReportService {
|
||||||
} else {
|
} else {
|
||||||
testPlanApiScenario.setLastResult(ScenarioStatus.Success.name());
|
testPlanApiScenario.setLastResult(ScenarioStatus.Success.name());
|
||||||
}
|
}
|
||||||
long successSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), "Success")).count();
|
long successSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Success.name())).count();
|
||||||
|
|
||||||
String passRate = new DecimalFormat("0%").format((float) successSize / requestResults.size());
|
String passRate = new DecimalFormat("0%").format((float) successSize / requestResults.size());
|
||||||
testPlanApiScenario.setPassRate(passRate);
|
testPlanApiScenario.setPassRate(passRate);
|
||||||
|
@ -245,7 +255,7 @@ public class ApiScenarioReportService {
|
||||||
// 更新场景状态
|
// 更新场景状态
|
||||||
ApiScenario scenario = apiScenarioMapper.selectByPrimaryKey(testPlanApiScenario.getApiScenarioId());
|
ApiScenario scenario = apiScenarioMapper.selectByPrimaryKey(testPlanApiScenario.getApiScenarioId());
|
||||||
if (scenario != null) {
|
if (scenario != null) {
|
||||||
scenario.setLastResult(errorSize > 0 ? "Fail" : "Success");
|
scenario.setLastResult(errorSize > 0 ? "Fail" : ScenarioStatus.Success.name());
|
||||||
scenario.setPassRate(passRate);
|
scenario.setPassRate(passRate);
|
||||||
scenario.setReportId(dto.getReportId());
|
scenario.setReportId(dto.getReportId());
|
||||||
int executeTimes = 0;
|
int executeTimes = 0;
|
||||||
|
@ -256,11 +266,7 @@ public class ApiScenarioReportService {
|
||||||
apiScenarioMapper.updateByPrimaryKey(scenario);
|
apiScenarioMapper.updateByPrimaryKey(scenario);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String status = errorSize > 0 || requestResults.isEmpty() ? "Error" : "Success";
|
String status = getStatus(requestResults, dto);
|
||||||
if (dto != null && dto.getArbitraryData() != null && dto.getArbitraryData().containsKey("TIMEOUT") && (Boolean) dto.getArbitraryData().get("TIMEOUT")) {
|
|
||||||
LoggerUtil.info("报告 【 " + dto.getReportId() + " 】资源 " + dto.getTestId() + " 执行超时");
|
|
||||||
status = "Timeout";
|
|
||||||
}
|
|
||||||
ApiScenarioReport report = editReport(dto.getReportType(), dto.getReportId(), status, dto.getRunMode());
|
ApiScenarioReport report = editReport(dto.getReportType(), dto.getReportId(), status, dto.getRunMode());
|
||||||
return report;
|
return report;
|
||||||
}
|
}
|
||||||
|
@ -269,15 +275,8 @@ public class ApiScenarioReportService {
|
||||||
List<String> testPlanReportIdList = new ArrayList<>();
|
List<String> testPlanReportIdList = new ArrayList<>();
|
||||||
StringBuilder scenarioNames = new StringBuilder();
|
StringBuilder scenarioNames = new StringBuilder();
|
||||||
|
|
||||||
Map<String, String> scenarioAndErrorMap = new HashMap<>();
|
long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Error.name())).count();
|
||||||
Map<String, String> planScenarioReportMap = new HashMap<>();
|
String status = getStatus(requestResults, dto);
|
||||||
long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), "Error")).count();
|
|
||||||
|
|
||||||
String status = errorSize > 0 || requestResults.isEmpty() ? "Error" : "Success";
|
|
||||||
if (dto != null && dto.getArbitraryData() != null && dto.getArbitraryData().containsKey("TIMEOUT") && (Boolean) dto.getArbitraryData().get("TIMEOUT")) {
|
|
||||||
LoggerUtil.info("报告 【 " + dto.getReportId() + " 】资源 " + dto.getTestId() + " 执行超时");
|
|
||||||
status = "Timeout";
|
|
||||||
}
|
|
||||||
ApiScenarioReport report = editReport(dto.getReportType(), dto.getReportId(), status, dto.getRunMode());
|
ApiScenarioReport report = editReport(dto.getReportType(), dto.getReportId(), status, dto.getRunMode());
|
||||||
if (report != null) {
|
if (report != null) {
|
||||||
if (StringUtils.isNotEmpty(dto.getTestPlanReportId()) && !testPlanReportIdList.contains(dto.getTestPlanReportId())) {
|
if (StringUtils.isNotEmpty(dto.getTestPlanReportId()) && !testPlanReportIdList.contains(dto.getTestPlanReportId())) {
|
||||||
|
@ -288,15 +287,12 @@ public class ApiScenarioReportService {
|
||||||
report.setScenarioId(testPlanApiScenario.getApiScenarioId());
|
report.setScenarioId(testPlanApiScenario.getApiScenarioId());
|
||||||
report.setEndTime(System.currentTimeMillis());
|
report.setEndTime(System.currentTimeMillis());
|
||||||
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
|
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
|
||||||
planScenarioReportMap.put(dto.getTestId(), report.getId());
|
|
||||||
if (errorSize > 0) {
|
if (errorSize > 0) {
|
||||||
scenarioAndErrorMap.put(testPlanApiScenario.getId(), TestPlanApiExecuteStatus.FAILD.name());
|
|
||||||
testPlanApiScenario.setLastResult(ScenarioStatus.Fail.name());
|
testPlanApiScenario.setLastResult(ScenarioStatus.Fail.name());
|
||||||
} else {
|
} else {
|
||||||
scenarioAndErrorMap.put(testPlanApiScenario.getId(), TestPlanApiExecuteStatus.SUCCESS.name());
|
|
||||||
testPlanApiScenario.setLastResult(ScenarioStatus.Success.name());
|
testPlanApiScenario.setLastResult(ScenarioStatus.Success.name());
|
||||||
}
|
}
|
||||||
long successSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), "Success")).count();
|
long successSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Success.name())).count();
|
||||||
String passRate = new DecimalFormat("0%").format((float) successSize / requestResults.size());
|
String passRate = new DecimalFormat("0%").format((float) successSize / requestResults.size());
|
||||||
testPlanApiScenario.setPassRate(passRate);
|
testPlanApiScenario.setPassRate(passRate);
|
||||||
|
|
||||||
|
@ -312,7 +308,7 @@ public class ApiScenarioReportService {
|
||||||
if (errorSize > 0) {
|
if (errorSize > 0) {
|
||||||
scenario.setLastResult("Fail");
|
scenario.setLastResult("Fail");
|
||||||
} else {
|
} else {
|
||||||
scenario.setLastResult("Success");
|
scenario.setLastResult(ScenarioStatus.Success.name());
|
||||||
}
|
}
|
||||||
scenario.setPassRate(passRate);
|
scenario.setPassRate(passRate);
|
||||||
scenario.setReportId(report.getId());
|
scenario.setReportId(report.getId());
|
||||||
|
@ -325,11 +321,6 @@ public class ApiScenarioReportService {
|
||||||
apiScenarioMapper.updateByPrimaryKey(scenario);
|
apiScenarioMapper.updateByPrimaryKey(scenario);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
testPlanLog.info("TestPlanReportId" + JSONArray.toJSONString(testPlanReportIdList) + " EXECUTE OVER. SCENARIO STATUS : " + JSONObject.toJSONString(scenarioAndErrorMap));
|
|
||||||
for (String item : testPlanReportIdList) {
|
|
||||||
TestPlanReportExecuteCatch.updateApiTestPlanExecuteInfo(item, null, scenarioAndErrorMap, null);
|
|
||||||
TestPlanReportExecuteCatch.updateTestPlanReport(item, null, planScenarioReportMap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return report;
|
return report;
|
||||||
}
|
}
|
||||||
|
@ -339,9 +330,9 @@ public class ApiScenarioReportService {
|
||||||
if (report != null) {
|
if (report != null) {
|
||||||
// 更新场景状态
|
// 更新场景状态
|
||||||
ApiScenarioReportResultExample example = new ApiScenarioReportResultExample();
|
ApiScenarioReportResultExample example = new ApiScenarioReportResultExample();
|
||||||
example.createCriteria().andReportIdEqualTo(reportId).andStatusEqualTo("Error");
|
example.createCriteria().andReportIdEqualTo(reportId).andStatusEqualTo(ScenarioStatus.Error.name());
|
||||||
long size = apiScenarioReportResultMapper.countByExample(example);
|
long size = apiScenarioReportResultMapper.countByExample(example);
|
||||||
report.setStatus(size > 0 ? "Error" : "Success");
|
report.setStatus(size > 0 ? ScenarioStatus.Error.name() : ScenarioStatus.Success.name());
|
||||||
report.setEndTime(System.currentTimeMillis());
|
report.setEndTime(System.currentTimeMillis());
|
||||||
// 更新控制台信息
|
// 更新控制台信息
|
||||||
apiScenarioReportStructureService.update(reportId, resultService.getJmeterLogger(reportId));
|
apiScenarioReportStructureService.update(reportId, resultService.getJmeterLogger(reportId));
|
||||||
|
@ -351,13 +342,10 @@ public class ApiScenarioReportService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApiScenarioReport updateScenario(List<ApiScenarioReportResult> requestResults, ResultDTO dto) {
|
public ApiScenarioReport updateScenario(List<ApiScenarioReportResult> requestResults, ResultDTO dto) {
|
||||||
long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), "Error")).count();
|
long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Error.name())).count();
|
||||||
// 更新报告状态
|
// 更新报告状态
|
||||||
String status = errorSize > 0 || requestResults.isEmpty() ? "Error" : "Success";
|
String status = getStatus(requestResults, dto);
|
||||||
if (dto != null && dto.getArbitraryData() != null && dto.getArbitraryData().containsKey("TIMEOUT") && (Boolean) dto.getArbitraryData().get("TIMEOUT")) {
|
|
||||||
LoggerUtil.info("报告 【 " + dto.getReportId() + " 】资源 " + dto.getTestId() + " 执行超时");
|
|
||||||
status = "Timeout";
|
|
||||||
}
|
|
||||||
ApiScenarioReport report = editReport(dto.getReportType(), dto.getReportId(), status, dto.getRunMode());
|
ApiScenarioReport report = editReport(dto.getReportType(), dto.getReportId(), status, dto.getRunMode());
|
||||||
// 更新场景状态
|
// 更新场景状态
|
||||||
ApiScenarioWithBLOBs scenario = apiScenarioMapper.selectByPrimaryKey(dto.getTestId());
|
ApiScenarioWithBLOBs scenario = apiScenarioMapper.selectByPrimaryKey(dto.getTestId());
|
||||||
|
@ -365,8 +353,8 @@ public class ApiScenarioReportService {
|
||||||
scenario = apiScenarioMapper.selectByPrimaryKey(report.getScenarioId());
|
scenario = apiScenarioMapper.selectByPrimaryKey(report.getScenarioId());
|
||||||
}
|
}
|
||||||
if (scenario != null) {
|
if (scenario != null) {
|
||||||
scenario.setLastResult(errorSize > 0 ? "Fail" : "Success");
|
scenario.setLastResult(errorSize > 0 ? "Fail" : ScenarioStatus.Success.name());
|
||||||
long successSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), "Success")).count();
|
long successSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Success.name())).count();
|
||||||
scenario.setPassRate(new DecimalFormat("0%").format((float) successSize / requestResults.size()));
|
scenario.setPassRate(new DecimalFormat("0%").format((float) successSize / requestResults.size()));
|
||||||
scenario.setReportId(dto.getReportId());
|
scenario.setReportId(dto.getReportId());
|
||||||
int executeTimes = 0;
|
int executeTimes = 0;
|
||||||
|
@ -417,7 +405,7 @@ public class ApiScenarioReportService {
|
||||||
|
|
||||||
String event;
|
String event;
|
||||||
String status;
|
String status;
|
||||||
if (StringUtils.equals(scenario.getLastResult(), "Success")) {
|
if (StringUtils.equals(scenario.getLastResult(), ScenarioStatus.Success.name())) {
|
||||||
event = NoticeConstants.Event.EXECUTE_SUCCESSFUL;
|
event = NoticeConstants.Event.EXECUTE_SUCCESSFUL;
|
||||||
status = "成功";
|
status = "成功";
|
||||||
} else {
|
} else {
|
||||||
|
@ -437,8 +425,8 @@ public class ApiScenarioReportService {
|
||||||
.operator(userId)
|
.operator(userId)
|
||||||
.context(context)
|
.context(context)
|
||||||
.subject("接口自动化通知")
|
.subject("接口自动化通知")
|
||||||
.successMailTemplate("api/ScenarioResult")
|
.successMailTemplate("api/ScenarioResultSuccess")
|
||||||
.failedMailTemplate("api/ScenarioResult")
|
.failedMailTemplate("api/ScenarioResultFailed")
|
||||||
.paramMap(paramMap)
|
.paramMap(paramMap)
|
||||||
.event(event)
|
.event(event)
|
||||||
.build();
|
.build();
|
||||||
|
@ -707,4 +695,14 @@ public class ApiScenarioReportService {
|
||||||
report.setScenarioId(scenarioId);
|
report.setScenarioId(scenarioId);
|
||||||
return report;
|
return report;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getStatus(List<ApiScenarioReportResult> requestResults, ResultDTO dto) {
|
||||||
|
long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Error.name())).count();
|
||||||
|
String status = errorSize > 0 || requestResults.isEmpty() ? ScenarioStatus.Error.name() : ScenarioStatus.Success.name();
|
||||||
|
if (dto != null && dto.getArbitraryData() != null && dto.getArbitraryData().containsKey("TIMEOUT") && (Boolean) dto.getArbitraryData().get("TIMEOUT")) {
|
||||||
|
LoggerUtil.info("报告 【 " + dto.getReportId() + " 】资源 " + dto.getTestId() + " 执行超时");
|
||||||
|
status = ScenarioStatus.Timeout.name();
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package io.metersphere.api.service;
|
||||||
import io.metersphere.api.dto.automation.ApiTestReportVariable;
|
import io.metersphere.api.dto.automation.ApiTestReportVariable;
|
||||||
import io.metersphere.api.jmeter.ExecutedHandleSingleton;
|
import io.metersphere.api.jmeter.ExecutedHandleSingleton;
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
|
import io.metersphere.base.mapper.ApiScenarioReportMapper;
|
||||||
import io.metersphere.commons.constants.ApiRunMode;
|
import io.metersphere.commons.constants.ApiRunMode;
|
||||||
import io.metersphere.commons.constants.NoticeConstants;
|
import io.metersphere.commons.constants.NoticeConstants;
|
||||||
import io.metersphere.commons.constants.ReportTriggerMode;
|
import io.metersphere.commons.constants.ReportTriggerMode;
|
||||||
|
@ -47,6 +48,8 @@ public class TestResultService {
|
||||||
private TestPlanTestCaseService testPlanTestCaseService;
|
private TestPlanTestCaseService testPlanTestCaseService;
|
||||||
@Resource
|
@Resource
|
||||||
private ApiTestCaseService apiTestCaseService;
|
private ApiTestCaseService apiTestCaseService;
|
||||||
|
@Resource
|
||||||
|
private ApiScenarioReportMapper apiScenarioReportMapper;
|
||||||
|
|
||||||
public void saveResults(ResultDTO dto) {
|
public void saveResults(ResultDTO dto) {
|
||||||
// 处理环境
|
// 处理环境
|
||||||
|
@ -70,6 +73,14 @@ public class TestResultService {
|
||||||
updateTestCaseStates(requestResults, dto.getRunMode());
|
updateTestCaseStates(requestResults, dto.getRunMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void editReportTime(ResultDTO dto) {
|
||||||
|
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(dto.getReportId());
|
||||||
|
if (report != null) {
|
||||||
|
report.setUpdateTime(System.currentTimeMillis());
|
||||||
|
apiScenarioReportMapper.updateByPrimaryKey(report);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void testEnded(ResultDTO dto) {
|
public void testEnded(ResultDTO dto) {
|
||||||
if (StringUtils.equalsAny(dto.getRunMode(), ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
|
if (StringUtils.equalsAny(dto.getRunMode(), ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
|
||||||
ApiScenarioReport scenarioReport = apiScenarioReportService.testEnded(dto);
|
ApiScenarioReport scenarioReport = apiScenarioReportService.testEnded(dto);
|
||||||
|
|
|
@ -114,6 +114,9 @@
|
||||||
<if test="request.platform != null and request.platform != ''">
|
<if test="request.platform != null and request.platform != ''">
|
||||||
and issues.platform = #{request.platform}
|
and issues.platform = #{request.platform}
|
||||||
</if>
|
</if>
|
||||||
|
<if test="request.id != null and request.id != ''">
|
||||||
|
and issues.id = #{request.id}
|
||||||
|
</if>
|
||||||
|
|
||||||
<!-- <if test="request.ids != null and request.ids.size() > 0">-->
|
<!-- <if test="request.ids != null and request.ids.size() > 0">-->
|
||||||
<!-- and issues.id in-->
|
<!-- and issues.id in-->
|
||||||
|
|
|
@ -3,6 +3,7 @@ package io.metersphere.job.sechedule;
|
||||||
import io.metersphere.commons.constants.ReportTriggerMode;
|
import io.metersphere.commons.constants.ReportTriggerMode;
|
||||||
import io.metersphere.commons.constants.ScheduleGroup;
|
import io.metersphere.commons.constants.ScheduleGroup;
|
||||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
import io.metersphere.track.service.TestPlanService;
|
import io.metersphere.track.service.TestPlanService;
|
||||||
import org.quartz.*;
|
import org.quartz.*;
|
||||||
|
|
||||||
|
@ -16,25 +17,10 @@ import org.quartz.*;
|
||||||
public class TestPlanTestJob extends MsScheduleJob {
|
public class TestPlanTestJob extends MsScheduleJob {
|
||||||
private String projectID;
|
private String projectID;
|
||||||
|
|
||||||
|
|
||||||
// private PerformanceTestService performanceTestService;
|
|
||||||
// private TestPlanScenarioCaseService testPlanScenarioCaseService;
|
|
||||||
// private TestPlanApiCaseService testPlanApiCaseService;
|
|
||||||
// private ApiTestCaseService apiTestCaseService;
|
|
||||||
// private TestPlanReportService testPlanReportService;
|
|
||||||
// private TestPlanLoadCaseService testPlanLoadCaseService;
|
|
||||||
private TestPlanService testPlanService;
|
private TestPlanService testPlanService;
|
||||||
|
|
||||||
public TestPlanTestJob() {
|
public TestPlanTestJob() {
|
||||||
// this.performanceTestService = CommonBeanFactory.getBean(PerformanceTestService.class);
|
|
||||||
// this.testPlanScenarioCaseService = CommonBeanFactory.getBean(TestPlanScenarioCaseService.class);
|
|
||||||
// this.testPlanApiCaseService = CommonBeanFactory.getBean(TestPlanApiCaseService.class);
|
|
||||||
// this.apiTestCaseService = CommonBeanFactory.getBean(ApiTestCaseService.class);
|
|
||||||
// this.testPlanReportService = CommonBeanFactory.getBean(TestPlanReportService.class);
|
|
||||||
// this.testPlanLoadCaseService = CommonBeanFactory.getBean(TestPlanLoadCaseService.class);
|
|
||||||
this.testPlanService = CommonBeanFactory.getBean(TestPlanService.class);
|
this.testPlanService = CommonBeanFactory.getBean(TestPlanService.class);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,7 +49,17 @@ public class TestPlanTestJob extends MsScheduleJob {
|
||||||
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
|
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
|
||||||
String config = jobDataMap.getString("config");
|
String config = jobDataMap.getString("config");
|
||||||
|
|
||||||
testPlanService.run(this.resourceId, this.projectID, this.userId, ReportTriggerMode.SCHEDULE.name(),config);
|
String runResourceId = this.resourceId;
|
||||||
|
String runProjectId = this.projectID;
|
||||||
|
String runUserId = this.userId;
|
||||||
|
Thread thread = new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
LogUtil.info("Start test_plan_scehdule. test_plan_id:" + runResourceId);
|
||||||
|
testPlanService.run(runResourceId, runProjectId, runUserId, ReportTriggerMode.SCHEDULE.name(),config);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JobKey getJobKey(String testId) {
|
public static JobKey getJobKey(String testId) {
|
||||||
|
|
|
@ -68,6 +68,14 @@ public class AppStartListener implements ApplicationListener<ApplicationReadyEve
|
||||||
|
|
||||||
@Value("${jmeter.home}")
|
@Value("${jmeter.home}")
|
||||||
private String jmeterHome;
|
private String jmeterHome;
|
||||||
|
@Value("${quartz.properties.org.quartz.jobStore.acquireTriggersWithinLock}")
|
||||||
|
private String acquireTriggersWithinLock;
|
||||||
|
@Value("${quartz.enabled}")
|
||||||
|
private boolean quartzEnable;
|
||||||
|
@Value("${quartz.scheduler-name}")
|
||||||
|
private String quartzScheduleName;
|
||||||
|
@Value("${quartz.thread-count}")
|
||||||
|
private int quartzThreadCount;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
|
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
|
||||||
|
@ -99,7 +107,12 @@ public class AppStartListener implements ApplicationListener<ApplicationReadyEve
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
LogUtil.info("开始启动定时任务。 相关设置:" +
|
||||||
|
"quartz.acquireTriggersWithinLock :" + acquireTriggersWithinLock + "\r\n" +
|
||||||
|
"quartz.enabled :" + quartzEnable + "\r\n" +
|
||||||
|
"quartz.scheduler-name :" + quartzScheduleName + "\r\n" +
|
||||||
|
"quartz.thread-count :" + quartzThreadCount + "\r\n"
|
||||||
|
);
|
||||||
scheduleService.startEnableSchedules();
|
scheduleService.startEnableSchedules();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,16 +153,27 @@ public class ReflexObjectUtil {
|
||||||
GsonDiff diff = new GsonDiff();
|
GsonDiff diff = new GsonDiff();
|
||||||
Object originalValue = originalColumns.get(i).getOriginalValue();
|
Object originalValue = originalColumns.get(i).getOriginalValue();
|
||||||
Object newValue = newColumns.get(i).getOriginalValue();
|
Object newValue = newColumns.get(i).getOriginalValue();
|
||||||
List<String> originalValueArray = JSON.parseArray(originalValue.toString(), String.class);
|
String oldTags = null;
|
||||||
|
if (originalValue != null && !StringUtils.equals("null", originalValue.toString())) {
|
||||||
|
List<String> originalValueArray = JSON.parseArray(originalValue.toString(), String.class);
|
||||||
|
Collections.sort(originalValueArray);
|
||||||
|
Object originalObject = JSON.toJSON(originalValueArray);
|
||||||
|
oldTags = ApiDefinitionDiffUtil.JSON_START + ((originalColumns.get(i) != null && originalObject != null) ? originalObject.toString() : "\"\"") + ApiDefinitionDiffUtil.JSON_END;
|
||||||
|
}
|
||||||
List<String> newValueArray = JSON.parseArray(newValue.toString(), String.class);
|
List<String> newValueArray = JSON.parseArray(newValue.toString(), String.class);
|
||||||
Collections.sort(originalValueArray);
|
|
||||||
Collections.sort(newValueArray);
|
Collections.sort(newValueArray);
|
||||||
Object originalObject = JSON.toJSON(originalValueArray);
|
|
||||||
Object newObject = JSON.toJSON(newValueArray);
|
Object newObject = JSON.toJSON(newValueArray);
|
||||||
String oldTags = ApiDefinitionDiffUtil.JSON_START + ((originalColumns.get(i) != null && originalObject != null) ? originalObject.toString() : "\"\"") + ApiDefinitionDiffUtil.JSON_END;
|
|
||||||
String newTags = ApiDefinitionDiffUtil.JSON_START + ((newColumns.get(i) != null && newObject != null) ? newObject.toString() : "\"\"") + ApiDefinitionDiffUtil.JSON_END;
|
String newTags = ApiDefinitionDiffUtil.JSON_START + ((newColumns.get(i) != null && newObject != null) ? newObject.toString() : "\"\"") + ApiDefinitionDiffUtil.JSON_END;
|
||||||
String diffStr = diff.diff(oldTags, newTags);
|
String diffValue;
|
||||||
String diffValue = diff.apply(newTags, diffStr);
|
if (oldTags != null) {
|
||||||
|
String diffStr = diff.diff(oldTags, newTags);
|
||||||
|
diffValue = diff.apply(newTags, diffStr);
|
||||||
|
} else {
|
||||||
|
int indexAdd = newTags.indexOf("[");
|
||||||
|
String substring = newTags.substring(0, indexAdd + 2);
|
||||||
|
String substring1 = newTags.substring(indexAdd + 2);
|
||||||
|
diffValue = substring + "++" + substring1;
|
||||||
|
}
|
||||||
column.setDiffValue(diffValue);
|
column.setDiffValue(diffValue);
|
||||||
}
|
}
|
||||||
// 深度对比
|
// 深度对比
|
||||||
|
|
|
@ -19,11 +19,10 @@ import io.metersphere.track.service.TestCaseReviewService;
|
||||||
import io.metersphere.track.service.TestCaseService;
|
import io.metersphere.track.service.TestCaseService;
|
||||||
import io.metersphere.track.service.TestPlanService;
|
import io.metersphere.track.service.TestPlanService;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.collections4.MapUtils;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang3.RegExUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||||
|
import org.apache.commons.text.StringSubstitutor;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
@ -128,29 +127,31 @@ public abstract class AbstractNoticeSender implements NoticeSender {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getContent(String template, Map<String, Object> context) {
|
protected String getContent(String template, Map<String, Object> context) {
|
||||||
if (MapUtils.isNotEmpty(context)) {
|
// 处理 null
|
||||||
for (String k : context.keySet()) {
|
context.forEach((k, v) -> {
|
||||||
if (context.get(k) != null) {
|
if (v == null) {
|
||||||
String value = handleTime(k, context);
|
context.put(k, "");
|
||||||
template = RegExUtils.replaceAll(template, "\\$\\{" + k + "}", value);
|
|
||||||
} else {
|
|
||||||
template = RegExUtils.replaceAll(template, "\\$\\{" + k + "}", "");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
return template;
|
// 处理时间格式的数据
|
||||||
|
handleTime(context);
|
||||||
|
StringSubstitutor sub = new StringSubstitutor(context);
|
||||||
|
return sub.replace(template);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String handleTime(String k, Map<String, Object> context) {
|
private void handleTime(Map<String, Object> context) {
|
||||||
String value = context.get(k).toString();
|
context.forEach((k, v) -> {
|
||||||
if (StringUtils.endsWithIgnoreCase(k, "Time")) {
|
if (StringUtils.endsWithIgnoreCase(k, "Time")) {
|
||||||
try {
|
try {
|
||||||
long time = Long.parseLong(value);
|
String value = v.toString();
|
||||||
value = DateFormatUtils.format(time, "yyyy-MM-dd HH:mm:ss");
|
long time = Long.parseLong(value);
|
||||||
} catch (Exception ignore) {
|
v = DateFormatUtils.format(time, "yyyy-MM-dd HH:mm:ss");
|
||||||
|
context.put(k, v);
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<UserDetail> getUserDetails(List<String> userIds) {
|
protected List<UserDetail> getUserDetails(List<String> userIds) {
|
||||||
|
|
|
@ -35,6 +35,8 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.alibaba.fastjson.serializer.SerializerFeature.WriteMapNullValue;
|
||||||
|
|
||||||
@Aspect
|
@Aspect
|
||||||
@Component
|
@Component
|
||||||
public class SendNoticeAspect {
|
public class SendNoticeAspect {
|
||||||
|
@ -81,7 +83,7 @@ public class SendNoticeAspect {
|
||||||
Expression titleExp = parser.parseExpression(target);
|
Expression titleExp = parser.parseExpression(target);
|
||||||
Object v = titleExp.getValue(context, Object.class);
|
Object v = titleExp.getValue(context, Object.class);
|
||||||
Map<String, Object> memberValues = (Map<String, Object>) value.get(invocationHandler);
|
Map<String, Object> memberValues = (Map<String, Object>) value.get(invocationHandler);
|
||||||
memberValues.put("source", JSON.toJSONString(v));
|
memberValues.put("source", JSON.toJSONString(v, WriteMapNullValue));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtil.error(e.getMessage(), e);
|
LogUtil.error(e.getMessage(), e);
|
||||||
|
@ -119,7 +121,7 @@ public class SendNoticeAspect {
|
||||||
Object v = titleExp.getValue(context, Object.class);
|
Object v = titleExp.getValue(context, Object.class);
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
Map<String, Object> memberValues = (Map<String, Object>) value.get(invocationHandler);
|
Map<String, Object> memberValues = (Map<String, Object>) value.get(invocationHandler);
|
||||||
memberValues.put("source", JSON.toJSONString(v));
|
memberValues.put("source", JSON.toJSONString(v, WriteMapNullValue));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package io.metersphere.performance.engine;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import io.metersphere.api.dto.RunRequest;
|
|
||||||
import io.metersphere.base.domain.LoadTestReportWithBLOBs;
|
import io.metersphere.base.domain.LoadTestReportWithBLOBs;
|
||||||
import io.metersphere.base.domain.TestResource;
|
import io.metersphere.base.domain.TestResource;
|
||||||
import io.metersphere.base.domain.TestResourcePool;
|
import io.metersphere.base.domain.TestResourcePool;
|
||||||
|
@ -13,6 +12,7 @@ import io.metersphere.commons.constants.ResourceStatusEnum;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
import io.metersphere.config.JmeterProperties;
|
import io.metersphere.config.JmeterProperties;
|
||||||
|
import io.metersphere.dto.JmeterRunRequestDTO;
|
||||||
import io.metersphere.performance.service.PerformanceTestService;
|
import io.metersphere.performance.service.PerformanceTestService;
|
||||||
import io.metersphere.service.TestResourcePoolService;
|
import io.metersphere.service.TestResourcePoolService;
|
||||||
import io.metersphere.service.TestResourceService;
|
import io.metersphere.service.TestResourceService;
|
||||||
|
@ -42,7 +42,7 @@ public abstract class AbstractEngine implements Engine {
|
||||||
GC_ALGO = CommonBeanFactory.getBean(JmeterProperties.class).getGcAlgo();
|
GC_ALGO = CommonBeanFactory.getBean(JmeterProperties.class).getGcAlgo();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initApiConfig(RunRequest runRequest) {
|
protected void initApiConfig(JmeterRunRequestDTO runRequest) {
|
||||||
String resourcePoolId = runRequest.getPoolId();
|
String resourcePoolId = runRequest.getPoolId();
|
||||||
resourcePool = testResourcePoolService.getResourcePool(resourcePoolId);
|
resourcePool = testResourcePoolService.getResourcePool(resourcePoolId);
|
||||||
if (resourcePool == null || StringUtils.equals(resourcePool.getStatus(), ResourceStatusEnum.DELETE.name())) {
|
if (resourcePool == null || StringUtils.equals(resourcePool.getStatus(), ResourceStatusEnum.DELETE.name())) {
|
||||||
|
|
|
@ -300,12 +300,20 @@ public class EngineFactory {
|
||||||
rootDocument = docBuilder.parse(inputSource);
|
rootDocument = docBuilder.parse(inputSource);
|
||||||
Element jmeterTestPlan = rootDocument.getDocumentElement();
|
Element jmeterTestPlan = rootDocument.getDocumentElement();
|
||||||
NodeList childNodes = jmeterTestPlan.getChildNodes();
|
NodeList childNodes = jmeterTestPlan.getChildNodes();
|
||||||
|
|
||||||
|
outer:
|
||||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||||
Node node = childNodes.item(i);
|
Node node = childNodes.item(i);
|
||||||
if (node instanceof Element) {
|
if (node instanceof Element) {
|
||||||
// jmeterTestPlan的子元素肯定是<hashTree></hashTree>
|
// jmeterTestPlan的子元素肯定是<hashTree></hashTree>
|
||||||
hashTree = (Element) node;
|
NodeList childNodes1 = node.getChildNodes();
|
||||||
break;
|
for (int j = 0; j < childNodes1.getLength(); j++) {
|
||||||
|
Node item = childNodes1.item(j);
|
||||||
|
if (StringUtils.equalsIgnoreCase("hashTree", item.getNodeName())) {
|
||||||
|
hashTree = (Element) node;
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -320,9 +328,19 @@ public class EngineFactory {
|
||||||
NodeList secondChildNodes = secondHashTree.getChildNodes();
|
NodeList secondChildNodes = secondHashTree.getChildNodes();
|
||||||
for (int j = 0; j < secondChildNodes.getLength(); j++) {
|
for (int j = 0; j < secondChildNodes.getLength(); j++) {
|
||||||
Node item = secondChildNodes.item(j);
|
Node item = secondChildNodes.item(j);
|
||||||
Node newNode = item.cloneNode(true);
|
if (StringUtils.equalsIgnoreCase("TestPlan", item.getNodeName())) {
|
||||||
rootDocument.adoptNode(newNode);
|
continue;
|
||||||
hashTree.appendChild(newNode);
|
}
|
||||||
|
if (StringUtils.equalsIgnoreCase("hashTree", item.getNodeName())) {
|
||||||
|
NodeList itemChildNodes = item.getChildNodes();
|
||||||
|
for (int k = 0; k < itemChildNodes.getLength(); k++) {
|
||||||
|
Node item1 = itemChildNodes.item(k);
|
||||||
|
Node newNode = item1.cloneNode(true);
|
||||||
|
rootDocument.adoptNode(newNode);
|
||||||
|
hashTree.appendChild(newNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.commons.utils.SessionUtils;
|
import io.metersphere.commons.utils.SessionUtils;
|
||||||
import io.metersphere.controller.request.EnvironmentGroupRequest;
|
import io.metersphere.controller.request.EnvironmentGroupRequest;
|
||||||
import io.metersphere.dto.EnvironmentGroupDTO;
|
import io.metersphere.dto.EnvironmentGroupDTO;
|
||||||
|
import io.metersphere.i18n.Translator;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -161,7 +162,7 @@ public class EnvironmentGroupService {
|
||||||
private void checkEnvironmentGroup(EnvironmentGroupRequest request) {
|
private void checkEnvironmentGroup(EnvironmentGroupRequest request) {
|
||||||
String name = request.getName();
|
String name = request.getName();
|
||||||
if (StringUtils.isBlank(name)) {
|
if (StringUtils.isBlank(name)) {
|
||||||
MSException.throwException("environment group name is null.");
|
MSException.throwException(Translator.get("null_environment_group_name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
EnvironmentGroupExample environmentGroupExample = new EnvironmentGroupExample();
|
EnvironmentGroupExample environmentGroupExample = new EnvironmentGroupExample();
|
||||||
|
@ -173,7 +174,7 @@ public class EnvironmentGroupService {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (environmentGroupMapper.countByExample(environmentGroupExample) > 0) {
|
if (environmentGroupMapper.countByExample(environmentGroupExample) > 0) {
|
||||||
MSException.throwException("环境组名称 " + request.getName() + " 已存在!");
|
MSException.throwException(Translator.get("environment_group_name")+request.getName()+Translator.get("environment_group_exist"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ public class IssueCommentController {
|
||||||
@PostMapping("/save")
|
@PostMapping("/save")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_REVIEW_READ_COMMENT)
|
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_REVIEW_READ_COMMENT)
|
||||||
@SendNotice(taskType = NoticeConstants.TaskType.DEFECT_TASK, target = "#targetClass.get(#request.issuesId)", targetClass = IssuesService.class,
|
@SendNotice(taskType = NoticeConstants.TaskType.DEFECT_TASK, target = "#targetClass.get(#request.issuesId)", targetClass = IssuesService.class,
|
||||||
event = NoticeConstants.Event.COMMENT, mailTemplate = "track/IssuesCommentUpdate", subject = "缺陷评论更新通知")
|
event = NoticeConstants.Event.COMMENT, mailTemplate = "track/IssuesCommentUpdate", subject = "缺陷")
|
||||||
public IssueComment saveComment(@RequestBody IssuesRelevanceRequest request) {
|
public IssueComment saveComment(@RequestBody IssuesRelevanceRequest request) {
|
||||||
request.setId(UUID.randomUUID().toString());
|
request.setId(UUID.randomUUID().toString());
|
||||||
return issueCommentService.saveComment(request);
|
return issueCommentService.saveComment(request);
|
||||||
|
|
|
@ -133,7 +133,7 @@ public class TestPlanController {
|
||||||
@PostMapping("/delete/{testPlanId}")
|
@PostMapping("/delete/{testPlanId}")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_PLAN_READ_DELETE)
|
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_PLAN_READ_DELETE)
|
||||||
@MsAuditLog(module = "track_test_plan", type = OperLogConstants.DELETE, beforeEvent = "#msClass.getLogDetails(#testPlanId)", msClass = TestPlanService.class)
|
@MsAuditLog(module = "track_test_plan", type = OperLogConstants.DELETE, beforeEvent = "#msClass.getLogDetails(#testPlanId)", msClass = TestPlanService.class)
|
||||||
@SendNotice(taskType = NoticeConstants.TaskType.TEST_PLAN_TASK, target = "#targetClass.getTestPlan(#testPlanId)", targetClass = TestPlanService.class,
|
@SendNotice(taskType = NoticeConstants.TaskType.TEST_PLAN_TASK, target = "#targetClass.get(#testPlanId)", targetClass = TestPlanService.class,
|
||||||
event = NoticeConstants.Event.DELETE, mailTemplate = "track/TestPlanDelete", subject = "测试计划通知")
|
event = NoticeConstants.Event.DELETE, mailTemplate = "track/TestPlanDelete", subject = "测试计划通知")
|
||||||
public int deleteTestPlan(@PathVariable String testPlanId) {
|
public int deleteTestPlan(@PathVariable String testPlanId) {
|
||||||
checkPermissionService.checkTestPlanOwner(testPlanId);
|
checkPermissionService.checkTestPlanOwner(testPlanId);
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package io.metersphere.track.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TestPlanReportExecuteCheckResultDTO {
|
||||||
|
private boolean isTimeOut;
|
||||||
|
private boolean isFinishedCaseChanged;
|
||||||
|
}
|
|
@ -81,7 +81,9 @@ public class TestPlanReportService {
|
||||||
@Resource
|
@Resource
|
||||||
ExtTestPlanApiCaseMapper extTestPlanApiCaseMapper;
|
ExtTestPlanApiCaseMapper extTestPlanApiCaseMapper;
|
||||||
@Resource
|
@Resource
|
||||||
ApiTestCaseMapper apiTestCaseMapper;
|
ExtApiDefinitionExecResultMapper extApiDefinitionExecResultMapper;
|
||||||
|
@Resource
|
||||||
|
ExtApiScenarioReportMapper extApiScenarioReportMapper;
|
||||||
@Resource
|
@Resource
|
||||||
LoadTestReportMapper loadTestReportMapper;
|
LoadTestReportMapper loadTestReportMapper;
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -551,8 +553,6 @@ public class TestPlanReportService {
|
||||||
boolean scenarioIsOk = executeInfo.isScenarioAllExecuted();
|
boolean scenarioIsOk = executeInfo.isScenarioAllExecuted();
|
||||||
boolean performanceIsOk = executeInfo.isLoadCaseAllExecuted();
|
boolean performanceIsOk = executeInfo.isLoadCaseAllExecuted();
|
||||||
|
|
||||||
testPlanLog.info("ReportId[" + testPlanReport.getId() + "] count over. Testplan Execute Result: Api is over ->" + apiCaseIsOk + "; scenario is over ->" + scenarioIsOk + "; performance is over ->" + performanceIsOk);
|
|
||||||
|
|
||||||
if (apiCaseIsOk) {
|
if (apiCaseIsOk) {
|
||||||
testPlanReport.setIsApiCaseExecuting(false);
|
testPlanReport.setIsApiCaseExecuting(false);
|
||||||
}
|
}
|
||||||
|
@ -1075,12 +1075,16 @@ public class TestPlanReportService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void countReport(String planReportId) {
|
public void countReport(String planReportId) {
|
||||||
boolean isTimeOut = this.checkTestPlanReportIsTimeOut(planReportId);
|
TestPlanReportExecuteCheckResultDTO checkResult = this.checkTestPlanReportIsTimeOut(planReportId);
|
||||||
if (isTimeOut) {
|
testPlanLog.info("Check PlanReport:" + planReportId + "; result: "+ JSON.toJSONString(checkResult));
|
||||||
|
if (checkResult.isTimeOut()) {
|
||||||
//判断是否超时。超时时强行停止任务
|
//判断是否超时。超时时强行停止任务
|
||||||
TestPlanReportExecuteCatch.finishAllTask(planReportId);
|
TestPlanReportExecuteCatch.finishAllTask(planReportId);
|
||||||
|
checkResult.setFinishedCaseChanged(true);
|
||||||
|
}
|
||||||
|
if(checkResult.isFinishedCaseChanged()){
|
||||||
|
this.updateExecuteApis(planReportId);
|
||||||
}
|
}
|
||||||
this.updateExecuteApis(planReportId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TestPlanSimpleReportDTO getReport(String reportId) {
|
public TestPlanSimpleReportDTO getReport(String reportId) {
|
||||||
|
@ -1216,19 +1220,61 @@ public class TestPlanReportService {
|
||||||
testPlanReportContentMapper.updateByExampleSelective(bloBs,example);
|
testPlanReportContentMapper.updateByExampleSelective(bloBs,example);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkTestPlanReportIsTimeOut(String planReportId) {
|
private TestPlanReportExecuteCheckResultDTO checkTestPlanReportIsTimeOut(String planReportId) {
|
||||||
|
//同步数据库更新状态信息
|
||||||
|
try {
|
||||||
|
this.syncReportStatus(planReportId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.info("联动数据库同步执行状态失败! " + e.getMessage());
|
||||||
|
LogUtil.error(e);
|
||||||
|
}
|
||||||
TestPlanExecuteInfo executeInfo = TestPlanReportExecuteCatch.getTestPlanExecuteInfo(planReportId);
|
TestPlanExecuteInfo executeInfo = TestPlanReportExecuteCatch.getTestPlanExecuteInfo(planReportId);
|
||||||
int unFinishNum = executeInfo.countUnFinishedNum();
|
TestPlanReportExecuteCheckResultDTO checkResult = executeInfo.countUnFinishedNum();
|
||||||
if (unFinishNum > 0) {
|
return checkResult;
|
||||||
//20分钟没有案例执行结果更新,则定位超时
|
}
|
||||||
long lastCountTime = executeInfo.getLastFinishedNumCountTime();
|
|
||||||
long nowTime = System.currentTimeMillis();
|
private void syncReportStatus(String planReportId) {
|
||||||
testPlanLog.info("ReportId: ["+planReportId+"]; timeCount:"+ (nowTime - lastCountTime));
|
if (TestPlanReportExecuteCatch.containsReport(planReportId)) {
|
||||||
if (nowTime - lastCountTime > 1200000) {
|
TestPlanExecuteInfo executeInfo = TestPlanReportExecuteCatch.getTestPlanExecuteInfo(planReportId);
|
||||||
return true;
|
if (executeInfo != null) {
|
||||||
|
//同步接口案例结果
|
||||||
|
Map<String, String> updateCaseStatusMap = new HashMap<>();
|
||||||
|
Map<String, String> apiCaseReportMap = executeInfo.getRunningApiCaseReportMap();
|
||||||
|
if (MapUtils.isNotEmpty(apiCaseReportMap)) {
|
||||||
|
List<ApiDefinitionExecResult> execList = extApiDefinitionExecResultMapper.selectStatusByIdList(apiCaseReportMap.keySet());
|
||||||
|
for (ApiDefinitionExecResult report : execList) {
|
||||||
|
String reportId = report.getId();
|
||||||
|
String status = report.getStatus();
|
||||||
|
if (!StringUtils.equalsAnyIgnoreCase(status, "Running", "Waiting")) {
|
||||||
|
String planCaseId = apiCaseReportMap.get(reportId);
|
||||||
|
if (StringUtils.isNotEmpty(planCaseId)) {
|
||||||
|
updateCaseStatusMap.put(planCaseId, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//同步场景结果
|
||||||
|
Map<String, String> updateScenarioStatusMap = new HashMap<>();
|
||||||
|
Map<String, String> scenarioReportMap = executeInfo.getRunningScenarioReportMap();
|
||||||
|
if (MapUtils.isNotEmpty(scenarioReportMap)) {
|
||||||
|
List<ApiScenarioReport> reportList = extApiScenarioReportMapper.selectStatusByIds(scenarioReportMap.keySet());
|
||||||
|
for (ApiScenarioReport report : reportList) {
|
||||||
|
String reportId = report.getId();
|
||||||
|
String status = report.getStatus();
|
||||||
|
if (!StringUtils.equalsAnyIgnoreCase(status, "Running", "Waiting")) {
|
||||||
|
String planScenarioId = scenarioReportMap.get(reportId);
|
||||||
|
if (StringUtils.isNotEmpty(planScenarioId)) {
|
||||||
|
updateScenarioStatusMap.put(planScenarioId, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testPlanLog.info("ReportID:"+planReportId+" 本次数据库同步,案例ID:"+JSON.toJSONString(apiCaseReportMap.keySet())+";场景ID:"+JSON.toJSONString(scenarioReportMap.keySet())+"; 同步结果,案例:"+JSON.toJSONString(updateCaseStatusMap)+";场景:"+JSON.toJSONString(updateScenarioStatusMap));
|
||||||
|
TestPlanReportExecuteCatch.updateApiTestPlanExecuteInfo(planReportId, updateCaseStatusMap, updateScenarioStatusMap, null);
|
||||||
|
}else {
|
||||||
|
testPlanLog.info("同步数据库查询执行信息失败! 报告ID在缓存中未找到!"+planReportId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void finishTestPlanReport(String planReportId) {
|
private void finishTestPlanReport(String planReportId) {
|
||||||
|
@ -1239,5 +1285,4 @@ public class TestPlanReportService {
|
||||||
}
|
}
|
||||||
TestPlanReportExecuteCatch.remove(planReportId);
|
TestPlanReportExecuteCatch.remove(planReportId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,6 +243,10 @@ public class TestPlanService {
|
||||||
return Optional.ofNullable(testPlanMapper.selectByPrimaryKey(testPlanId)).orElse(new TestPlanWithBLOBs());
|
return Optional.ofNullable(testPlanMapper.selectByPrimaryKey(testPlanId)).orElse(new TestPlanWithBLOBs());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TestPlanWithBLOBs get(String testPlanId) {
|
||||||
|
return testPlanMapper.selectByPrimaryKey(testPlanId);
|
||||||
|
}
|
||||||
|
|
||||||
public TestPlan editTestPlanWithRequest(AddTestPlanRequest request) {
|
public TestPlan editTestPlanWithRequest(AddTestPlanRequest request) {
|
||||||
List<String> principals = request.getPrincipals();
|
List<String> principals = request.getPrincipals();
|
||||||
if (!CollectionUtils.isEmpty(principals)) {
|
if (!CollectionUtils.isEmpty(principals)) {
|
||||||
|
@ -1116,8 +1120,8 @@ public class TestPlanService {
|
||||||
testPlanLoadCaseService.update(testPlanLoadCase);
|
testPlanLoadCaseService.update(testPlanLoadCase);
|
||||||
LogUtil.error(e);
|
LogUtil.error(e);
|
||||||
}
|
}
|
||||||
performaneThreadIDMap.put(performanceRequest.getTestPlanLoadId(), reportId);
|
|
||||||
if (StringUtils.isNotEmpty(reportId)) {
|
if (StringUtils.isNotEmpty(reportId)) {
|
||||||
|
performaneThreadIDMap.put(performanceRequest.getTestPlanLoadId(), reportId);
|
||||||
executePerformanceIdMap.put(performanceRequest.getTestPlanLoadId(), TestPlanApiExecuteStatus.RUNNING.name());
|
executePerformanceIdMap.put(performanceRequest.getTestPlanLoadId(), TestPlanApiExecuteStatus.RUNNING.name());
|
||||||
} else {
|
} else {
|
||||||
executePerformanceIdMap.put(performanceRequest.getTestPlanLoadId(), TestPlanApiExecuteStatus.PREPARE.name());
|
executePerformanceIdMap.put(performanceRequest.getTestPlanLoadId(), TestPlanApiExecuteStatus.PREPARE.name());
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class IndexWebSocket {
|
||||||
public void openSession(@PathParam("reportId") String reportId, Session session) {
|
public void openSession(@PathParam("reportId") String reportId, Session session) {
|
||||||
WebSocketUtils.ONLINE_USER_SESSIONS.put(reportId, session);
|
WebSocketUtils.ONLINE_USER_SESSIONS.put(reportId, session);
|
||||||
log.info("客户端: [" + reportId + "] : 连接成功!");
|
log.info("客户端: [" + reportId + "] : 连接成功!");
|
||||||
WebSocketUtils.sendMessageAll("客户端: [" + reportId + "] : 连接成功!");
|
//WebSocketUtils.sendMessageAll("客户端: [" + reportId + "] : 连接成功!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,7 +45,7 @@ public class IndexWebSocket {
|
||||||
WebSocketUtils.ONLINE_USER_SESSIONS.remove(reportId);
|
WebSocketUtils.ONLINE_USER_SESSIONS.remove(reportId);
|
||||||
log.info("[" + reportId + "] : 断开连接!");
|
log.info("[" + reportId + "] : 断开连接!");
|
||||||
//并且通知其他人当前用户已经断开连接了
|
//并且通知其他人当前用户已经断开连接了
|
||||||
WebSocketUtils.sendMessageAll("[" + reportId + "] : 断开连接!");
|
//WebSocketUtils.sendMessageAll("[" + reportId + "] : 断开连接!");
|
||||||
session.close();
|
session.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.metersphere.websocket.c.to.c;
|
package io.metersphere.websocket.c.to.c;
|
||||||
|
|
||||||
|
import io.metersphere.utils.LoggerUtil;
|
||||||
import io.metersphere.websocket.c.to.c.util.MsgDto;
|
import io.metersphere.websocket.c.to.c.util.MsgDto;
|
||||||
|
|
||||||
import javax.websocket.RemoteEndpoint;
|
import javax.websocket.RemoteEndpoint;
|
||||||
|
@ -12,9 +13,13 @@ public class WebSocketUtils {
|
||||||
|
|
||||||
// 单用户推送
|
// 单用户推送
|
||||||
public static void sendMessage(Session session, String message) {
|
public static void sendMessage(Session session, String message) {
|
||||||
if (session == null) { return; }
|
if (session == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
RemoteEndpoint.Async async = session.getAsyncRemote();
|
RemoteEndpoint.Async async = session.getAsyncRemote();
|
||||||
if (async == null) { return; }
|
if (async == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
async.sendText(message);
|
async.sendText(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,4 +35,20 @@ public class WebSocketUtils {
|
||||||
sendMessage(session, message);
|
sendMessage(session, message);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//当前的Session 移除
|
||||||
|
public static void onClose(String reportId) {
|
||||||
|
try {
|
||||||
|
if (WebSocketUtils.ONLINE_USER_SESSIONS.containsKey(reportId)) {
|
||||||
|
WebSocketUtils.ONLINE_USER_SESSIONS.get(reportId).close();
|
||||||
|
WebSocketUtils.ONLINE_USER_SESSIONS.remove(reportId);
|
||||||
|
}
|
||||||
|
if (WebSocketUtils.ONLINE_USER_SESSIONS.containsKey(("send." + reportId))) {
|
||||||
|
WebSocketUtils.ONLINE_USER_SESSIONS.get(("send." + reportId)).close();
|
||||||
|
WebSocketUtils.ONLINE_USER_SESSIONS.remove(("send." + reportId));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LoggerUtil.error("关闭socket失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
package io.metersphere.websocket.c.to.c.util;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author: jason
|
|
||||||
* @Date: 2020-12-23
|
|
||||||
*/
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Builder
|
|
||||||
@Data
|
|
||||||
public class SocketClient {
|
|
||||||
private Integer userId;
|
|
||||||
private String username;
|
|
||||||
}
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit a1e39f9c1baf30f52da50ab34ea1bacbfbeff60c
|
Subproject commit 3cac4fd4c1cb2b3dfb4bd82a6a09cc55ae2f2d34
|
|
@ -12,7 +12,7 @@ server.ssl.key-alias=localhost
|
||||||
|
|
||||||
# Hikari
|
# Hikari
|
||||||
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
|
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
|
||||||
spring.datasource.hikari.maximum-pool-size=100
|
spring.datasource.hikari.maximum-pool-size=200
|
||||||
spring.datasource.hikari.auto-commit=true
|
spring.datasource.hikari.auto-commit=true
|
||||||
spring.datasource.hikari.idle-timeout=10000
|
spring.datasource.hikari.idle-timeout=10000
|
||||||
spring.datasource.hikari.pool-name=DatebookHikariCP
|
spring.datasource.hikari.pool-name=DatebookHikariCP
|
||||||
|
@ -23,7 +23,7 @@ spring.datasource.hikari.connection-test-query=SELECT 1
|
||||||
spring.datasource.quartz.url=${spring.datasource.url}
|
spring.datasource.quartz.url=${spring.datasource.url}
|
||||||
spring.datasource.quartz.username=${spring.datasource.username}
|
spring.datasource.quartz.username=${spring.datasource.username}
|
||||||
spring.datasource.quartz.password=${spring.datasource.password}
|
spring.datasource.quartz.password=${spring.datasource.password}
|
||||||
spring.datasource.quartz.hikari.maximum-pool-size=50
|
spring.datasource.quartz.hikari.maximum-pool-size=200
|
||||||
spring.datasource.quartz.hikari.auto-commit=true
|
spring.datasource.quartz.hikari.auto-commit=true
|
||||||
spring.datasource.quartz.hikari.idle-timeout=10000
|
spring.datasource.quartz.hikari.idle-timeout=10000
|
||||||
spring.datasource.quartz.hikari.pool-name=DatebookHikariCP
|
spring.datasource.quartz.hikari.pool-name=DatebookHikariCP
|
||||||
|
@ -92,7 +92,8 @@ jmeter.home=/opt/jmeter
|
||||||
# quartz
|
# quartz
|
||||||
quartz.enabled=true
|
quartz.enabled=true
|
||||||
quartz.scheduler-name=msServerJob
|
quartz.scheduler-name=msServerJob
|
||||||
quartz.thread-count=30
|
quartz.thread-count=60
|
||||||
|
quartz.properties.org.quartz.jobStore.acquireTriggersWithinLock=true
|
||||||
# file upload
|
# file upload
|
||||||
spring.servlet.multipart.max-file-size=500MB
|
spring.servlet.multipart.max-file-size=500MB
|
||||||
spring.servlet.multipart.max-request-size=500MB
|
spring.servlet.multipart.max-request-size=500MB
|
||||||
|
|
|
@ -285,6 +285,10 @@ test_case_status=Case status
|
||||||
id_not_rightful=ID is not rightful
|
id_not_rightful=ID is not rightful
|
||||||
# mock
|
# mock
|
||||||
mock_warning=No matching Mock expectation was found
|
mock_warning=No matching Mock expectation was found
|
||||||
zentao_test_type_error=请求方式错误
|
zentao_test_type_error=invalid Zentao request
|
||||||
#项目报告
|
#项目报告
|
||||||
enterprise_test_report=Enterprise report
|
enterprise_test_report=Enterprise report
|
||||||
|
#环境组
|
||||||
|
null_environment_group_name = Environment group name is null
|
||||||
|
environment_group_name = Environment group name
|
||||||
|
environment_group_exist = already exists
|
||||||
|
|
|
@ -284,6 +284,10 @@ test_case_status=用例状态
|
||||||
id_not_rightful=ID 不合法
|
id_not_rightful=ID 不合法
|
||||||
# mock
|
# mock
|
||||||
mock_warning=未找到匹配的Mock期望
|
mock_warning=未找到匹配的Mock期望
|
||||||
zentao_test_type_error=invalid Zentao request
|
zentao_test_type_error=无效的 Zentao 请求
|
||||||
#项目报告
|
#项目报告
|
||||||
enterprise_test_report=项目报告
|
enterprise_test_report=项目报告
|
||||||
|
#环境组
|
||||||
|
null_environment_group_name = 环境组名称不存在
|
||||||
|
environment_group_name = 环境组名称
|
||||||
|
environment_group_exist = 已存在
|
|
@ -287,3 +287,7 @@ mock_warning=未找到匹配的Mock期望
|
||||||
zentao_test_type_error=請求方式錯誤
|
zentao_test_type_error=請求方式錯誤
|
||||||
#项目报告
|
#项目报告
|
||||||
enterprise_test_report=項目報告
|
enterprise_test_report=項目報告
|
||||||
|
#环境组
|
||||||
|
null_environment_group_name = 環境組名稱不存在
|
||||||
|
environment_group_name = 環境組名稱
|
||||||
|
environment_group_exist = 已存在
|
|
@ -6,7 +6,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div>
|
<div>
|
||||||
<p>${operator}执行接口用例: ${name}, 结果: ${status}</p>
|
<p>${operator}执行接口用例失败: ${name}</p>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -6,7 +6,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div>
|
<div>
|
||||||
<p>${operator}执行接口自动化: ${name}, 结果: ${status}</p>
|
<p>${operator}执行接口用例成功: ${name}</p>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>MeterSphere</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<p>${operator}执行接口自动化失败: ${name}</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>MeterSphere</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<p>${operator}执行接口自动化成功: ${name}</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -324,16 +324,21 @@ export default {
|
||||||
if (data) {
|
if (data) {
|
||||||
this.report = data;
|
this.report = data;
|
||||||
if (this.report.reportVersion && this.report.reportVersion > 1) {
|
if (this.report.reportVersion && this.report.reportVersion > 1) {
|
||||||
if (data.content) {
|
this.report.status = data.status;
|
||||||
let report = JSON.parse(data.content);
|
if (!this.isNotRunning) {
|
||||||
this.content = report;
|
setTimeout(this.getReport, 2000)
|
||||||
this.fullTreeNodes = report.steps;
|
} else {
|
||||||
this.content.console = report.console;
|
if (data.content) {
|
||||||
this.content.error = report.error;
|
let report = JSON.parse(data.content);
|
||||||
this.content.success = (report.total - report.error);
|
this.content = report;
|
||||||
this.totalTime = report.totalTime;
|
this.fullTreeNodes = report.steps;
|
||||||
|
this.content.console = report.console;
|
||||||
|
this.content.error = report.error;
|
||||||
|
this.content.success = (report.total - report.error);
|
||||||
|
this.totalTime = report.totalTime;
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
}
|
}
|
||||||
this.loading = false;
|
|
||||||
} else {
|
} else {
|
||||||
this.buildReport();
|
this.buildReport();
|
||||||
}
|
}
|
||||||
|
@ -528,10 +533,12 @@ export default {
|
||||||
.report-container .is-active .fail {
|
.report-container .is-active .fail {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.report-console {
|
.report-console {
|
||||||
height: calc(100vh - 270px);
|
height: calc(100vh - 270px);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.export-button {
|
.export-button {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
|
@ -356,7 +356,7 @@ export default {
|
||||||
if (e.data) {
|
if (e.data) {
|
||||||
this.runningEvaluation(e.data);
|
this.runningEvaluation(e.data);
|
||||||
}
|
}
|
||||||
if (e.data && e.data.indexOf("断开连接") !== -1) {
|
if (e.data && e.data.indexOf("MS_TEST_END") !== -1) {
|
||||||
this.getReport();
|
this.getReport();
|
||||||
this.messageWebSocket.close();
|
this.messageWebSocket.close();
|
||||||
scenario.$emit('hide', this.scenarioId);
|
scenario.$emit('hide', this.scenarioId);
|
||||||
|
|
|
@ -454,7 +454,8 @@ export default {
|
||||||
permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
|
permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "批量恢复", handleClick: this.handleBatchRestore
|
name: this.$t('commons.batch_restore'),
|
||||||
|
handleClick: this.handleBatchRestore
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
unTrashButtons: [
|
unTrashButtons: [
|
||||||
|
@ -794,7 +795,7 @@ export default {
|
||||||
|
|
||||||
// todo 选取全部数据
|
// todo 选取全部数据
|
||||||
if (this.condition.selectAll) {
|
if (this.condition.selectAll) {
|
||||||
this.$warning("暂不支持批量添加所有场景到测试计划!");
|
this.$warning(this.$t('api_test.scenario.warning_context'));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.planVisible = false;
|
this.planVisible = false;
|
||||||
|
@ -1010,7 +1011,7 @@ export default {
|
||||||
this.$get("/api/automation/checkScenarioEnv/" + this.currentScenario.id, res => {
|
this.$get("/api/automation/checkScenarioEnv/" + this.currentScenario.id, res => {
|
||||||
let data = res.data;
|
let data = res.data;
|
||||||
if (!data) {
|
if (!data) {
|
||||||
this.$warning("请为场景选择环境!");
|
this.$warning(this.$t('workspace.env_group.please_select_env_for_current_scenario'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.reportId = getUUID().substring(0, 8);
|
this.reportId = getUUID().substring(0, 8);
|
||||||
|
|
|
@ -789,7 +789,7 @@ export default {
|
||||||
}
|
}
|
||||||
this.runningEvaluation(e.data);
|
this.runningEvaluation(e.data);
|
||||||
this.message = getUUID();
|
this.message = getUUID();
|
||||||
if (e.data && e.data.indexOf("断开连接") !== -1) {
|
if (e.data && e.data.indexOf("MS_TEST_END") !== -1) {
|
||||||
this.runScenario = undefined;
|
this.runScenario = undefined;
|
||||||
this.debugLoading = false;
|
this.debugLoading = false;
|
||||||
this.message = "stop";
|
this.message = "stop";
|
||||||
|
|
|
@ -148,7 +148,7 @@
|
||||||
},
|
},
|
||||||
getConditions() {
|
getConditions() {
|
||||||
let sampleSelectRows = this.selectRows;
|
let sampleSelectRows = this.selectRows;
|
||||||
let param = buildBatchParam(this);
|
let param = buildBatchParam(this, undefined, this.projectId);
|
||||||
param.ids = Array.from(sampleSelectRows).map(row => row.id);
|
param.ids = Array.from(sampleSelectRows).map(row => row.id);
|
||||||
return param;
|
return param;
|
||||||
},
|
},
|
||||||
|
|
|
@ -282,7 +282,7 @@ export default {
|
||||||
},
|
},
|
||||||
getConditions() {
|
getConditions() {
|
||||||
let sampleSelectRows = this.$refs.table.getSelectRows();
|
let sampleSelectRows = this.$refs.table.getSelectRows();
|
||||||
let batchParam = buildBatchParam(this);
|
let batchParam = buildBatchParam(this, undefined, this.projectId);
|
||||||
let param = {};
|
let param = {};
|
||||||
if (batchParam.condition) {
|
if (batchParam.condition) {
|
||||||
param = batchParam.condition;
|
param = batchParam.condition;
|
||||||
|
|
|
@ -364,7 +364,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (databaseConfigsOptions.length > 0) {
|
if (databaseConfigsOptions.length > 0 && this.request.environmentId !== this.environment.id) {
|
||||||
this.request.dataSourceId = databaseConfigsOptions[0].id;
|
this.request.dataSourceId = databaseConfigsOptions[0].id;
|
||||||
this.request.environmentId = this.environment.id;
|
this.request.environmentId = this.environment.id;
|
||||||
}
|
}
|
||||||
|
@ -639,7 +639,7 @@ export default {
|
||||||
|
|
||||||
clickResource(resource) {
|
clickResource(resource) {
|
||||||
if (resource.refType && resource.refType === 'API') {
|
if (resource.refType && resource.refType === 'API') {
|
||||||
if(resource.protocol==='dubbo://'){
|
if (resource.protocol === 'dubbo://') {
|
||||||
resource.protocol = 'DUBBO'
|
resource.protocol = 'DUBBO'
|
||||||
}
|
}
|
||||||
let definitionData = this.$router.resolve({
|
let definitionData = this.$router.resolve({
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
:placeholder="$t('api_test.definition.request.run_env')"
|
:placeholder="$t('api_test.definition.request.run_env')"
|
||||||
clearable>
|
clearable>
|
||||||
<el-option v-for="(environment, index) in environments" :key="index"
|
<el-option v-for="(environment, index) in environments" :key="index"
|
||||||
:label="environment.name + (environment.config.httpConfig.socket ? (': ' + environment.config.httpConfig.protocol + '://' + environment.config.httpConfig.socket) : '')"
|
:label="environment.name"
|
||||||
:value="environment.id"/>
|
:value="environment.id"/>
|
||||||
<template v-slot:empty>
|
<template v-slot:empty>
|
||||||
<div class="empty-environment">
|
<div class="empty-environment">
|
||||||
|
|
|
@ -945,7 +945,7 @@ export default {
|
||||||
apiNames += ";" + item;
|
apiNames += ";" + item;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.$error("请先恢复[" + apiNames + "]接口");
|
this.$error(this.$t('api_test.definition.case_reduction_error_text') + "[" + apiNames + "]" + this.$t("api_test.home_page.api_details_card.title"));
|
||||||
} else {
|
} else {
|
||||||
this.$success(this.$t('commons.save_success'));
|
this.$success(this.$t('commons.save_success'));
|
||||||
}
|
}
|
||||||
|
@ -971,7 +971,7 @@ export default {
|
||||||
apiNames += ";" + item;
|
apiNames += ";" + item;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.$error("请先恢复[" + apiNames + "]接口");
|
this.$error(this.$t('api_test.definition.case_reduction_error_text') + "[" + apiNames + "]" + this.$t("api_test.home_page.api_details_card.title"));
|
||||||
} else {
|
} else {
|
||||||
this.$success(this.$t('commons.save_success'));
|
this.$success(this.$t('commons.save_success'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -302,7 +302,8 @@ export default {
|
||||||
permissions: ['PROJECT_API_DEFINITION:READ+DELETE_API']
|
permissions: ['PROJECT_API_DEFINITION:READ+DELETE_API']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "批量恢复", handleClick: this.handleBatchRestore
|
name: this.$t('commons.batch_restore'),
|
||||||
|
handleClick: this.handleBatchRestore
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
tableOperatorButtons: [],
|
tableOperatorButtons: [],
|
||||||
|
|
|
@ -4,12 +4,16 @@
|
||||||
<el-col>
|
<el-col>
|
||||||
<div style="font-size: 14px;color: #AAAAAA;float: left">{{ $t('api_report.response_code') }} :</div>
|
<div style="font-size: 14px;color: #AAAAAA;float: left">{{ $t('api_report.response_code') }} :</div>
|
||||||
<el-tooltip
|
<el-tooltip
|
||||||
|
v-if="responseResult.responseCode"
|
||||||
:content="responseResult.responseCode"
|
:content="responseResult.responseCode"
|
||||||
placement="top">
|
placement="top">
|
||||||
<div class="node-title" :class="response && response.success ?'ms-req-success':'ms-req-error'">
|
<div class="node-title" :class="response && response.success ?'ms-req-success':'ms-req-error'">
|
||||||
{{ responseResult && responseResult.responseCode ? responseResult.responseCode : '0' }}
|
{{ responseResult && responseResult.responseCode ? responseResult.responseCode : '0' }}
|
||||||
</div>
|
</div>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
<div v-else class="node-title" :class="response && response.success ?'ms-req-success':'ms-req-error'">
|
||||||
|
{{ responseResult && responseResult.responseCode ? responseResult.responseCode : '0' }}
|
||||||
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col>
|
<el-col>
|
||||||
<div style="font-size: 14px;color: #AAAAAA;float: left">{{ $t('api_report.response_time') }} :</div>
|
<div style="font-size: 14px;color: #AAAAAA;float: left">{{ $t('api_report.response_time') }} :</div>
|
||||||
|
|
|
@ -165,7 +165,7 @@ export default {
|
||||||
if (now - d.createTime > 10 * 1000) {
|
if (now - d.createTime > 10 * 1000) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
d.user = this.userMap[d.operator];
|
d.user = this.userMap[d.operator] || {name: 'MS'};
|
||||||
let message = d.user.name + getOperation(d.operation) + getResource(d) + ": " + d.resourceName;
|
let message = d.user.name + getOperation(d.operation) + getResource(d) + ": " + d.resourceName;
|
||||||
let title = d.type === 'MENTIONED_ME' ? this.$t('commons.mentioned_me_notice') : this.$t('commons.system_notice');
|
let title = d.type === 'MENTIONED_ME' ? this.$t('commons.mentioned_me_notice') : this.$t('commons.system_notice');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
|
@ -443,7 +443,7 @@ export default {
|
||||||
created() {
|
created() {
|
||||||
this.isReadOnly = !hasPermission('PROJECT_PERFORMANCE_REPORT:READ+DELETE');
|
this.isReadOnly = !hasPermission('PROJECT_PERFORMANCE_REPORT:READ+DELETE');
|
||||||
this.reportId = this.$route.path.split('/')[4];
|
this.reportId = this.$route.path.split('/')[4];
|
||||||
if (!this.reportId && this.perReportId) {
|
if (this.perReportId) {
|
||||||
this.reportId = this.perReportId;
|
this.reportId = this.perReportId;
|
||||||
}
|
}
|
||||||
this.getReport(this.reportId);
|
this.getReport(this.reportId);
|
||||||
|
@ -452,6 +452,9 @@ export default {
|
||||||
'$route'(to) {
|
'$route'(to) {
|
||||||
if (to.name === "perReportView") {
|
if (to.name === "perReportView") {
|
||||||
this.reportId = to.path.split('/')[4];
|
this.reportId = to.path.split('/')[4];
|
||||||
|
if (this.perReportId) {
|
||||||
|
this.reportId = this.perReportId;
|
||||||
|
}
|
||||||
this.getReport(this.reportId);
|
this.getReport(this.reportId);
|
||||||
this.initBreadcrumb((response) => {
|
this.initBreadcrumb((response) => {
|
||||||
this.initReportTimeInfo();
|
this.initReportTimeInfo();
|
||||||
|
|
|
@ -171,7 +171,6 @@ export default {
|
||||||
created() {
|
created() {
|
||||||
this.data = [];
|
this.data = [];
|
||||||
this.instances = [];
|
this.instances = [];
|
||||||
this.id = this.$route.path.split('/')[4];
|
|
||||||
this.getResource();
|
this.getResource();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -350,13 +349,6 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$route'(to) {
|
|
||||||
if (to.name === "perReportView") {
|
|
||||||
this.id = to.path.split('/')[4];
|
|
||||||
this.init = false;
|
|
||||||
this.getResource();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
report: {
|
report: {
|
||||||
handler(val) {
|
handler(val) {
|
||||||
if (!val.status || !val.id) {
|
if (!val.status || !val.id) {
|
||||||
|
|
|
@ -251,7 +251,7 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<div class="title">{{ $t('load_test.pressure_prediction_chart') }}</div>
|
<div class="title">{{ $t('load_test.pressure_prediction_chart') }}</div>
|
||||||
<ms-chart class="chart-container" ref="chart1" :options="options" :autoresize="true"></ms-chart>
|
<ms-chart v-if="rampUpTimeVisible" class="chart-container" ref="chart1" :options="options" :autoresize="true"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,10 +28,12 @@
|
||||||
size="lg" @click="unFullScreen"/>
|
size="lg" @click="unFullScreen"/>
|
||||||
</div>
|
</div>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row style="overflow: auto">
|
<el-row>
|
||||||
<ms-chart ref="chart1" v-if="!loading" :options="dataOption"
|
<div class="chart-style">
|
||||||
:style="{width: chartWidthNumber+'px', height: (h-50) + 'px'}" class="chart-config" :autoresize="true"
|
<ms-chart ref="chart1" v-if="!loading" :options="dataOption"
|
||||||
id="picChart"/>
|
:style="{width: chartWidthNumber+'px', height: (h-70) + 'px'}" class="chart-config" :autoresize="true"
|
||||||
|
id="picChart"/>
|
||||||
|
</div>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
|
@ -73,7 +75,7 @@ export default {
|
||||||
{id: 'pie', name: this.$t('commons.report_statistics.pie')}
|
{id: 'pie', name: this.$t('commons.report_statistics.pie')}
|
||||||
],
|
],
|
||||||
order: "",
|
order: "",
|
||||||
orders: [{id: '', name: '默认排序'}, {id: 'desc', name: this.$t('commons.report_statistics.desc')}, {
|
orders: [{id: '', name: this.$t('commons.sort_default')}, {id: 'desc', name: this.$t('commons.report_statistics.desc')}, {
|
||||||
id: 'asc',
|
id: 'asc',
|
||||||
name: this.$t('commons.report_statistics.asc')
|
name: this.$t('commons.report_statistics.asc')
|
||||||
}],
|
}],
|
||||||
|
@ -223,6 +225,9 @@ export default {
|
||||||
height: calc(100vh / 1.95);
|
height: calc(100vh / 1.95);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chart-style{
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
.tip {
|
.tip {
|
||||||
float: left;
|
float: left;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
chartType: "line",
|
chartType: "line",
|
||||||
charts: [{id: 'line', name: this.$t('commons.report_statistics.line')}, {id: 'bar', name: this.$t('commons.report_statistics.bar')}],
|
charts: [{id: 'line', name: this.$t('commons.report_statistics.line')}, {id: 'bar', name: this.$t('commons.report_statistics.bar')}],
|
||||||
order: "",
|
order: "",
|
||||||
orders: [{id: '', name: '默认排序'},{id: 'desc', name: this.$t('commons.report_statistics.desc')}, {id: 'asc', name: this.$t('commons.report_statistics.asc')}],
|
orders: [{id: '', name: this.$t('commons.sort_default')},{id: 'desc', name: this.$t('commons.report_statistics.desc')}, {id: 'asc', name: this.$t('commons.report_statistics.asc')}],
|
||||||
loading: false,
|
loading: false,
|
||||||
options: {},
|
options: {},
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,8 +88,8 @@
|
||||||
{id: 'BATCH_UPDATE', label: this.$t('api_test.definition.request.batch_edit')},
|
{id: 'BATCH_UPDATE', label: this.$t('api_test.definition.request.batch_edit')},
|
||||||
{id: 'BATCH_ADD', label: this.$t('commons.batch_add')},
|
{id: 'BATCH_ADD', label: this.$t('commons.batch_add')},
|
||||||
{id: 'UN_ASSOCIATE_CASE', label: this.$t('test_track.case.unlink')},
|
{id: 'UN_ASSOCIATE_CASE', label: this.$t('test_track.case.unlink')},
|
||||||
{id: 'BATCH_RESTORE', label: "批量恢复"},
|
{id: 'BATCH_RESTORE', label: this.$t('commons.batch_restore')},
|
||||||
{id: 'BATCH_GC', label: "批量回收"}
|
{id: 'BATCH_GC', label: this.$t('commons.batch_gc')}
|
||||||
],
|
],
|
||||||
LOG_TYPE_MAP: new Map([
|
LOG_TYPE_MAP: new Map([
|
||||||
['CREATE', this.$t('api_test.definition.request.create_info')],
|
['CREATE', this.$t('api_test.definition.request.create_info')],
|
||||||
|
|
|
@ -56,50 +56,144 @@ export function LOG_TYPE_MAP(_this) {
|
||||||
return LOG_TYPE_MAP;
|
return LOG_TYPE_MAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SYSLIST(){
|
export function SYSLIST() {
|
||||||
let sysList = [
|
let sysList = [
|
||||||
{
|
{
|
||||||
label: i18n.t('test_track.test_track'), value: i18n.t('test_track.test_track'), children: [
|
label: i18n.t('test_track.test_track'), value: i18n.t('test_track.test_track'), children: [
|
||||||
{label: i18n.t('permission.project_track_case.name'), value: i18n.t('permission.project_track_case.name'), leaf: true},
|
{
|
||||||
|
label: i18n.t('permission.project_track_case.name'),
|
||||||
|
value: i18n.t('permission.project_track_case.name'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
{label: i18n.t('test_track.review.test_review'), value: i18n.t('test_track.review.test_review'), leaf: true},
|
{label: i18n.t('test_track.review.test_review'), value: i18n.t('test_track.review.test_review'), leaf: true},
|
||||||
{label: i18n.t('test_track.plan.test_plan'), value: i18n.t('test_track.plan.test_plan'), leaf: true},
|
{label: i18n.t('test_track.plan.test_plan'), value: i18n.t('test_track.plan.test_plan'), leaf: true},
|
||||||
{label: i18n.t('test_track.issue.issue_management'), value: i18n.t('test_track.issue.issue_management'), leaf: true},
|
{
|
||||||
|
label: i18n.t('test_track.issue.issue_management'),
|
||||||
|
value: i18n.t('test_track.issue.issue_management'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
{label: i18n.t('commons.report'), value: i18n.t('commons.report'), leaf: true}]
|
{label: i18n.t('commons.report'), value: i18n.t('commons.report'), leaf: true}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: i18n.t('commons.api'), value: i18n.t('commons.api'), children: [
|
label: i18n.t('commons.api'), value: i18n.t('commons.api'), children: [
|
||||||
{label: i18n.t('workstation.table_name.api_definition'), value: i18n.t('workstation.table_name.api_definition'), leaf: true},
|
{
|
||||||
{label: i18n.t('workstation.table_name.api_automation'), value: i18n.t('workstation.table_name.api_automation'), leaf: true},
|
label: i18n.t('workstation.table_name.api_definition'),
|
||||||
{label: i18n.t('permission.project_api_report.name'), value: i18n.t('permission.project_api_report.name'), leaf: true}]
|
value: i18n.t('workstation.table_name.api_definition'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('workstation.table_name.api_automation'),
|
||||||
|
value: i18n.t('workstation.table_name.api_automation'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('permission.project_api_report.name'),
|
||||||
|
value: i18n.t('permission.project_api_report.name'),
|
||||||
|
leaf: true
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: i18n.t('workstation.table_name.performance'), value: i18n.t('workstation.table_name.performance'), children: [
|
label: i18n.t('workstation.table_name.performance'),
|
||||||
{label: i18n.t('workstation.table_name.performance'), value: i18n.t('workstation.table_name.performance'), leaf: true},
|
value: i18n.t('workstation.table_name.performance'),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: i18n.t('workstation.table_name.performance'),
|
||||||
|
value: i18n.t('workstation.table_name.performance'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
{label: i18n.t('report.load_test_report'), value: i18n.t('report.load_test_report'), leaf: true}]
|
{label: i18n.t('report.load_test_report'), value: i18n.t('report.load_test_report'), leaf: true}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: i18n.t('commons.system_setting'), value: i18n.t('commons.system_setting'), children: [
|
label: i18n.t('commons.system_setting'), value: i18n.t('commons.system_setting'), children: [
|
||||||
{label: i18n.t('commons.system')+"-"+i18n.t('commons.user'), value: i18n.t('commons.system')+"-"+i18n.t('commons.user'), leaf: true},
|
{
|
||||||
{label: i18n.t('commons.system')+"-"+i18n.t('commons.test_resource_pool'), value: i18n.t('commons.system')+"-"+i18n.t('commons.test_resource_pool'), leaf: true},
|
label: i18n.t('commons.system') + "-" + i18n.t('commons.user'),
|
||||||
{label: i18n.t('commons.system')+"-"+i18n.t('commons.system_parameter_setting'), value: i18n.t('commons.system')+"-"+i18n.t('commons.system_parameter_setting'), leaf: true},
|
value: i18n.t('commons.system') + "-" + i18n.t('commons.user'),
|
||||||
{label: i18n.t('commons.system')+"-"+i18n.t('commons.quota'), value: i18n.t('commons.system')+"-"+i18n.t('commons.quota'), leaf: true},
|
leaf: true
|
||||||
{label: i18n.t('commons.system')+"-"+i18n.t('license.title'), value: i18n.t('commons.system')+"-"+i18n.t('license.title'), leaf: true},
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('commons.system') + "-" + i18n.t('commons.test_resource_pool'),
|
||||||
|
value: i18n.t('commons.system') + "-" + i18n.t('commons.test_resource_pool'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('commons.system') + "-" + i18n.t('commons.system_parameter_setting'),
|
||||||
|
value: i18n.t('commons.system') + "-" + i18n.t('commons.system_parameter_setting'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('commons.system') + "-" + i18n.t('commons.quota'),
|
||||||
|
value: i18n.t('commons.system') + "-" + i18n.t('commons.quota'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('commons.system') + "-" + i18n.t('license.title'),
|
||||||
|
value: i18n.t('commons.system') + "-" + i18n.t('license.title'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
|
||||||
{label: i18n.t('commons.workspace'), value: i18n.t('commons.workspace'), leaf: true},
|
{label: i18n.t('commons.workspace'), value: i18n.t('commons.workspace'), leaf: true},
|
||||||
{label: i18n.t('commons.workspace')+"-"+i18n.t('permission.workspace_service.name'), value: i18n.t('commons.workspace')+"-"+i18n.t('permission.workspace_service.name'), leaf: true},
|
{
|
||||||
{label: i18n.t('commons.workspace')+"-"+i18n.t('permission.workspace_message.name'), value: i18n.t('commons.workspace')+"-"+i18n.t('permission.workspace_message.name'), leaf: true},
|
label: i18n.t('commons.workspace') + "-" + i18n.t('permission.workspace_service.name'),
|
||||||
{label: i18n.t('commons.workspace')+"-"+i18n.t('permission.project_user.name'), value: i18n.t('commons.workspace')+"-"+i18n.t('permission.project_user.name'), leaf: true},
|
value: i18n.t('commons.workspace') + "-" + i18n.t('permission.workspace_service.name'),
|
||||||
{label: i18n.t('commons.workspace')+"-"+i18n.t('permission.workspace_template.name'), value: i18n.t('commons.workspace')+"-"+i18n.t('permission.workspace_template.name'), leaf: true},
|
leaf: true
|
||||||
{label: i18n.t('commons.workspace')+"-"+i18n.t('permission.workspace_project_manager.name'), value: i18n.t('commons.workspace')+"-"+i18n.t('permission.workspace_project_manager.name'), leaf: true},
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('commons.workspace') + "-" + i18n.t('permission.workspace_message.name'),
|
||||||
|
value: i18n.t('commons.workspace') + "-" + i18n.t('permission.workspace_message.name'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('commons.workspace') + "-" + i18n.t('permission.project_user.name'),
|
||||||
|
value: i18n.t('commons.workspace') + "-" + i18n.t('permission.project_user.name'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('commons.workspace') + "-" + i18n.t('permission.workspace_template.name'),
|
||||||
|
value: i18n.t('commons.workspace') + "-" + i18n.t('permission.workspace_template.name'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('commons.workspace') + "-" + i18n.t('permission.workspace_project_manager.name'),
|
||||||
|
value: i18n.t('commons.workspace') + "-" + i18n.t('permission.workspace_project_manager.name'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
|
||||||
{label: i18n.t('commons.project')+"-"+i18n.t('project.manager'), value: i18n.t('commons.project')+"-"+i18n.t('project.manager'), leaf: true},
|
{
|
||||||
{label: i18n.t('commons.project')+"-"+i18n.t('permission.project_user.name'), value: i18n.t('commons.project')+"-"+i18n.t('permission.project_user.name'), leaf: true},
|
label: i18n.t('commons.project') + "-" + i18n.t('project.manager'),
|
||||||
{label: i18n.t('commons.project')+"-"+i18n.t('api_test.jar_config.jar_manage'), value: i18n.t('commons.project')+"-"+i18n.t('api_test.jar_config.jar_manage'), leaf: true},
|
value: i18n.t('commons.project') + "-" + i18n.t('project.manager'),
|
||||||
{label: i18n.t('commons.project')+"-"+i18n.t('permission.workspace_project_environment.name'), value: i18n.t('commons.project')+"-"+i18n.t('permission.workspace_project_environment.name'), leaf: true},
|
leaf: true
|
||||||
{label: i18n.t('commons.project')+"-"+i18n.t('permission.project_file.name'), value: i18n.t('commons.project')+"-"+i18n.t('permission.project_file.name'), leaf: true},
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('commons.project') + "-" + i18n.t('permission.project_user.name'),
|
||||||
|
value: i18n.t('commons.project') + "-" + i18n.t('permission.project_user.name'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('commons.project') + "-" + i18n.t('api_test.jar_config.jar_manage'),
|
||||||
|
value: i18n.t('commons.project') + "-" + i18n.t('api_test.jar_config.jar_manage'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('commons.project') + "-" + i18n.t('permission.workspace_project_environment.name'),
|
||||||
|
value: i18n.t('commons.project') + "-" + i18n.t('permission.workspace_project_environment.name'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('commons.project') + "-" + i18n.t('permission.project_file.name'),
|
||||||
|
value: i18n.t('commons.project') + "-" + i18n.t('permission.project_file.name'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
|
||||||
{label: i18n.t('commons.personal_information')+"-"+i18n.t('commons.personal_setting'), value: i18n.t('commons.personal_information')+"-"+i18n.t('commons.personal_setting'), leaf: true},
|
{
|
||||||
{label: i18n.t('commons.personal_information')+"-API Keys", value: i18n.t('commons.personal_information')+"-API Keys", leaf: true}
|
label: i18n.t('commons.personal_information') + "-" + i18n.t('commons.personal_setting'),
|
||||||
|
value: i18n.t('commons.personal_information') + "-" + i18n.t('commons.personal_setting'),
|
||||||
|
leaf: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.t('commons.personal_information') + "-API Keys",
|
||||||
|
value: i18n.t('commons.personal_information') + "-API Keys",
|
||||||
|
leaf: true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -121,76 +215,120 @@ export function getUrl(d) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (d.operModule) {
|
switch (d.operModule) {
|
||||||
case "接口自动化" || "Api automation" || "接口自動化":
|
case "接口自动化" :
|
||||||
|
case "Api automation" :
|
||||||
|
case"接口自動化":
|
||||||
url += "/api/automation?resourceId=" + resourceId;
|
url += "/api/automation?resourceId=" + resourceId;
|
||||||
break;
|
break;
|
||||||
case "测试计划" || "測試計劃" || "Test plan":
|
case "测试计划" :
|
||||||
|
case "測試計劃" :
|
||||||
|
case "Test plan":
|
||||||
url += "/track/plan/view/" + resourceId;
|
url += "/track/plan/view/" + resourceId;
|
||||||
break;
|
break;
|
||||||
case "用例评审" || "Case review" || "用例評審":
|
case "用例评审" :
|
||||||
|
case "Case review" :
|
||||||
|
case "用例評審":
|
||||||
url += "/track/review/view/" + resourceId;
|
url += "/track/review/view/" + resourceId;
|
||||||
break;
|
break;
|
||||||
case "缺陷管理" || "Defect management":
|
case "缺陷管理" :
|
||||||
|
case "Defect management":
|
||||||
url += "/track/issue";
|
url += "/track/issue";
|
||||||
break;
|
break;
|
||||||
case "SWAGGER_TASK" :
|
case "SWAGGER_TASK" :
|
||||||
url += "/api/definition";
|
url += "/api/definition";
|
||||||
break;
|
break;
|
||||||
case "接口定义" || "接口定義" || "Api definition":
|
case "接口定义" :
|
||||||
|
case "接口定義" :
|
||||||
|
case "Api definition":
|
||||||
url += "/api/definition?resourceId=" + resourceId;
|
url += "/api/definition?resourceId=" + resourceId;
|
||||||
break;
|
break;
|
||||||
case "接口定义用例" || "接口定義用例" || "Api definition case":
|
case "接口定义用例" :
|
||||||
|
case "接口定義用例":
|
||||||
|
case "Api definition case":
|
||||||
url += "/api/definition?caseId=" + resourceId;
|
url += "/api/definition?caseId=" + resourceId;
|
||||||
break;
|
break;
|
||||||
case "测试报告" || "測試報告" || "Test Report":
|
case "测试报告" :
|
||||||
|
case "測試報告" :
|
||||||
|
case "Test Report":
|
||||||
url += "/api/automation/report";
|
url += "/api/automation/report";
|
||||||
break;
|
break;
|
||||||
case "性能测试报告" || "性能測試報告" || "Performance test report" :
|
case "性能测试报告" :
|
||||||
|
case "性能測試報告" :
|
||||||
|
case "Performance test report" :
|
||||||
url += "/performance/report/all";
|
url += "/performance/report/all";
|
||||||
break;
|
break;
|
||||||
case "性能测试" || "性能測試" || "Performance test" :
|
case "性能测试" :
|
||||||
|
case "性能測試" :
|
||||||
|
case "Performance test" :
|
||||||
url += "/performance/test/edit/" + resourceId;
|
url += "/performance/test/edit/" + resourceId;
|
||||||
break;
|
break;
|
||||||
case "测试用例" || "測試用例" || "Test case":
|
case "测试用例" :
|
||||||
|
case "測試用例" :
|
||||||
|
case "Test case":
|
||||||
url += "/track/case/all?resourceId=" + resourceId;
|
url += "/track/case/all?resourceId=" + resourceId;
|
||||||
break;
|
break;
|
||||||
case "系统-用户" || "系统-用户" || "System user":
|
case "系统-用户":
|
||||||
|
case "System user":
|
||||||
url += "/setting/user";
|
url += "/setting/user";
|
||||||
break;
|
break;
|
||||||
case "系统-组织" || "系統-組織" || "System organization":
|
case "系统-组织" :
|
||||||
|
case "系統-組織" :
|
||||||
|
case "System organization":
|
||||||
url += "/setting/organization";
|
url += "/setting/organization";
|
||||||
break;
|
break;
|
||||||
case "工作空间" || "系统-工作空间" || "workspace" :
|
case "工作空间" :
|
||||||
|
case "系统-工作空间" :
|
||||||
|
case "workspace" :
|
||||||
url += "/setting/systemworkspace";
|
url += "/setting/systemworkspace";
|
||||||
break;
|
break;
|
||||||
case "用户组与权限" || "用戶組與權限" || "Group" :
|
case "用户组与权限" :
|
||||||
|
case "用戶組與權限" :
|
||||||
|
case "Group" :
|
||||||
url += "/setting/usergroup";
|
url += "/setting/usergroup";
|
||||||
break;
|
break;
|
||||||
case "系统-测试资源池" || "系统-測試資源池" || "System test resource" :
|
case "系统-测试资源池":
|
||||||
|
case "系统-測試資源池" :
|
||||||
|
case "System test resource" :
|
||||||
url += "/setting/testresourcepool";
|
url += "/setting/testresourcepool";
|
||||||
break;
|
break;
|
||||||
case "系统-系统参数设置" || "系统-系統參數設置" || "System parameter setting" :
|
case "系统-系统参数设置":
|
||||||
|
case "系统-系統參數設置" :
|
||||||
|
case "System parameter setting" :
|
||||||
url += "/setting/systemparametersetting";
|
url += "/setting/systemparametersetting";
|
||||||
break;
|
break;
|
||||||
case "工作空间-成员" || "工作空間-成員" || "Workspace member" :
|
case "工作空间-成员" :
|
||||||
|
case "工作空間-成員" :
|
||||||
|
case "Workspace member" :
|
||||||
url += "/setting/member";
|
url += "/setting/member";
|
||||||
break;
|
break;
|
||||||
case "项目-项目管理" || "項目-項目管理" || "Project project manager" :
|
case "项目-项目管理" :
|
||||||
|
case "項目-項目管理" :
|
||||||
|
case "Project project manager" :
|
||||||
url += "/setting/project/:type";
|
url += "/setting/project/:type";
|
||||||
break;
|
break;
|
||||||
case "项目-环境设置" || "項目-環境設置" || "Project environment setting" :
|
case "项目-环境设置" :
|
||||||
|
case "項目-環境設置" :
|
||||||
|
case "Project environment setting" :
|
||||||
url += "/project/env";
|
url += "/project/env";
|
||||||
break;
|
break;
|
||||||
case "工作空间-模版设置-自定义字段" || "工作空間-模版設置-自定義字段" || "Workspace template settings field" :
|
case "工作空间-模版设置-自定义字段" :
|
||||||
|
case "工作空間-模版設置-自定義字段" :
|
||||||
|
case "Workspace template settings field" :
|
||||||
url += "/setting/workspace/template/field";
|
url += "/setting/workspace/template/field";
|
||||||
break;
|
break;
|
||||||
case "工作空间-模版设置-用例模版" || "工作空間-模版設置-用例模板" || "Workspace template settings case" :
|
case "工作空间-模版设置-用例模版" :
|
||||||
|
case "工作空間-模版設置-用例模板" :
|
||||||
|
case "Workspace template settings case" :
|
||||||
url += "/setting/workspace/template/case";
|
url += "/setting/workspace/template/case";
|
||||||
break;
|
break;
|
||||||
case "工作空间-模版设置-缺陷模版" || "工作空間-模版設置-缺陷模板" || "Workspace template settings issue" :
|
case "工作空间-模版设置-缺陷模版" :
|
||||||
|
case "工作空間-模版設置-缺陷模板" :
|
||||||
|
case "Workspace template settings issue" :
|
||||||
url += "/setting/workspace/template/issues";
|
url += "/setting/workspace/template/issues";
|
||||||
break;
|
break;
|
||||||
case "项目-成员" || "項目-成員" || "Project member" :
|
case "项目-成员":
|
||||||
|
case "項目-成員" :
|
||||||
|
case "Project member" :
|
||||||
url += "/project/member";
|
url += "/project/member";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -339,7 +339,7 @@ export default {
|
||||||
this.$warning(this.$t('commons.check_project_tip'));
|
this.$warning(this.$t('commons.check_project_tip'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.showPublic = true
|
this.showPublic = false
|
||||||
if (tab.name === 'add') {
|
if (tab.name === 'add') {
|
||||||
let label = this.$t('test_track.case.create');
|
let label = this.$t('test_track.case.create');
|
||||||
let name = getUUID().substring(0, 8);
|
let name = getUUID().substring(0, 8);
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
:key="index"
|
:key="index"
|
||||||
:comment="comment"
|
:comment="comment"
|
||||||
:read-only="readOnly"
|
:read-only="readOnly"
|
||||||
@refresh="getComments()"/>
|
@refresh="getComments()" api-url="/test/case"/>
|
||||||
<div v-if="comments.length === 0" style="text-align: center">
|
<div v-if="comments.length === 0" style="text-align: center">
|
||||||
<i class="el-icon-chat-line-square" style="font-size: 15px;color: #8a8b8d;">
|
<i class="el-icon-chat-line-square" style="font-size: 15px;color: #8a8b8d;">
|
||||||
<span style="font-size: 15px; color: #8a8b8d;">
|
<span style="font-size: 15px; color: #8a8b8d;">
|
||||||
|
|
|
@ -115,7 +115,7 @@
|
||||||
<review-comment-item v-for="(comment,index) in comments"
|
<review-comment-item v-for="(comment,index) in comments"
|
||||||
:key="index"
|
:key="index"
|
||||||
:comment="comment"
|
:comment="comment"
|
||||||
@refresh="getComments"/>
|
@refresh="getComments" api-url="/test/case"/>
|
||||||
<div v-if="comments.length === 0" style="text-align: center">
|
<div v-if="comments.length === 0" style="text-align: center">
|
||||||
<i class="el-icon-chat-line-square" style="font-size: 15px;color: #8a8b8d;">
|
<i class="el-icon-chat-line-square" style="font-size: 15px;color: #8a8b8d;">
|
||||||
<span style="font-size: 15px; color: #8a8b8d;">
|
<span style="font-size: 15px; color: #8a8b8d;">
|
||||||
|
|
|
@ -102,7 +102,7 @@
|
||||||
<review-comment-item v-for="(comment,index) in comments"
|
<review-comment-item v-for="(comment,index) in comments"
|
||||||
:key="index"
|
:key="index"
|
||||||
:comment="comment"
|
:comment="comment"
|
||||||
@refresh="getComments" :disabled="true"/>
|
@refresh="getComments" :disabled="true" api-url="/test/case"/>
|
||||||
<div v-if="comments.length === 0" style="text-align: center">
|
<div v-if="comments.length === 0" style="text-align: center">
|
||||||
<i class="el-icon-chat-line-square" style="font-size: 15px;color: #8a8b8d;">
|
<i class="el-icon-chat-line-square" style="font-size: 15px;color: #8a8b8d;">
|
||||||
<span style="font-size: 15px; color: #8a8b8d;">
|
<span style="font-size: 15px; color: #8a8b8d;">
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-loading="result.loading">
|
<div v-loading="result.loading">
|
||||||
<div v-for="pe in data" :key="pe.id" style="margin-left: 20px;">
|
<div v-for="pe in data" :key="pe.id" style="margin-left: 20px;">
|
||||||
<el-select v-model="pe['selectEnv']" placeholder="请选择环境" style="margin-top: 8px;width: 200px;" size="small">
|
<el-select v-model="pe['selectEnv']" :placeholder="$t('api_test.environment.select_environment')"
|
||||||
|
style="margin-top: 8px;width: 200px;" size="small">
|
||||||
<el-option v-for="(environment, index) in pe.envs" :key="index"
|
<el-option v-for="(environment, index) in pe.envs" :key="index"
|
||||||
:label="environment.name"
|
:label="environment.name"
|
||||||
:value="environment.id"/>
|
:value="environment.id"/>
|
||||||
<el-button class="ms-scenario-button" v-if="isShowConfirmButton(pe.id)" size="mini" type="primary" @click="openEnvironmentConfig(pe.id)">
|
<el-button class="ms-scenario-button" v-if="isShowConfirmButton(pe.id)" size="mini" type="primary"
|
||||||
|
@click="openEnvironmentConfig(pe.id)">
|
||||||
{{ $t('api_test.environment.environment_config') }}
|
{{ $t('api_test.environment.environment_config') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<template v-slot:empty>
|
<template v-slot:empty>
|
||||||
<div v-if="isShowConfirmButton(pe.id)" class="empty-environment">
|
<div v-if="isShowConfirmButton(pe.id)" class="empty-environment">
|
||||||
<el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig(pe.id)">
|
<el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig(pe.id)">
|
||||||
{{ $t('api_test.environment.environment_config') }}
|
{{ $t('api_test.environment.environment_config') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
@ -21,7 +23,8 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-button type="primary" @click="handleConfirm" size="small" class="env-confirm">确 定</el-button>
|
<el-button type="primary" @click="handleConfirm" size="small" class="env-confirm">{{ $t('commons.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
|
||||||
<!-- 环境配置 -->
|
<!-- 环境配置 -->
|
||||||
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/>
|
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/>
|
||||||
|
|
|
@ -41,6 +41,9 @@ import {addIssueHotBox, getSelectedNodeData, handleIssueAdd, handleIssueBatch} f
|
||||||
import IssueRelateList from "@/business/components/track/case/components/IssueRelateList";
|
import IssueRelateList from "@/business/components/track/case/components/IssueRelateList";
|
||||||
import TestPlanIssueEdit from "@/business/components/track/case/components/TestPlanIssueEdit";
|
import TestPlanIssueEdit from "@/business/components/track/case/components/TestPlanIssueEdit";
|
||||||
import {getIssuesById} from "@/network/Issue";
|
import {getIssuesById} from "@/network/Issue";
|
||||||
|
|
||||||
|
const {getIssuesListById} = require("@/network/Issue");
|
||||||
|
const {getCurrentWorkspaceId} = require("@/common/js/utils");
|
||||||
export default {
|
export default {
|
||||||
name: "TestCaseMinder",
|
name: "TestCaseMinder",
|
||||||
components: {TestPlanIssueEdit, IssueRelateList, MsModuleMinder},
|
components: {TestPlanIssueEdit, IssueRelateList, MsModuleMinder},
|
||||||
|
@ -84,7 +87,11 @@ name: "TestCaseMinder",
|
||||||
moveEnable() {
|
moveEnable() {
|
||||||
// 如果不是默认的排序条件不能调换位置
|
// 如果不是默认的排序条件不能调换位置
|
||||||
return !this.condition.orders || this.condition.orders.length < 1;
|
return !this.condition.orders || this.condition.orders.length < 1;
|
||||||
|
},
|
||||||
|
workspaceId(){
|
||||||
|
return getCurrentWorkspaceId();
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
selectNode() {
|
selectNode() {
|
||||||
|
@ -119,7 +126,7 @@ name: "TestCaseMinder",
|
||||||
isNotDisableNode = true;
|
isNotDisableNode = true;
|
||||||
}
|
}
|
||||||
if (node.data.type === 'issue') {
|
if (node.data.type === 'issue') {
|
||||||
getIssuesById(node.data.id, (data) => {
|
getIssuesListById(node.data.id, this.projectId,this.workspaceId,(data) => {
|
||||||
data.customFields = JSON.parse(data.customFields);
|
data.customFields = JSON.parse(data.customFields);
|
||||||
this.$refs.issueEdit.open(data);
|
this.$refs.issueEdit.open(data);
|
||||||
});
|
});
|
||||||
|
|
|
@ -88,7 +88,7 @@ export default {
|
||||||
}
|
}
|
||||||
this.result = this.$post('/issues/comment/save', comment, () => {
|
this.result = this.$post('/issues/comment/save', comment, () => {
|
||||||
this.$success(this.$t('test_track.comment.send_success'));
|
this.$success(this.$t('test_track.comment.send_success'));
|
||||||
this.refresh(comment.IssueId);
|
this.refresh(comment.issuesId);
|
||||||
this.from.description = '';
|
this.from.description = '';
|
||||||
this.dialogTableVisible = false;
|
this.dialogTableVisible = false;
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,10 +29,10 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
open(data) {
|
open(data, type) {
|
||||||
this.visible = true;
|
this.visible = true;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.issueEditDetail.open(data);
|
this.$refs.issueEditDetail.open(data, type);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleClose() {
|
handleClose() {
|
||||||
|
|
|
@ -165,7 +165,8 @@ export default {
|
||||||
title: '',
|
title: '',
|
||||||
description: '',
|
description: '',
|
||||||
creator: null,
|
creator: null,
|
||||||
remark: null
|
remark: null,
|
||||||
|
tapdUsers:[]
|
||||||
},
|
},
|
||||||
tapdUsers: [],
|
tapdUsers: [],
|
||||||
zentaoUsers: [],
|
zentaoUsers: [],
|
||||||
|
@ -234,8 +235,9 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
open(data) {
|
open(data, type) {
|
||||||
this.result.loading = true;
|
this.result.loading = true;
|
||||||
|
this.type = type;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
getIssuePartTemplateWithProject((template, project) => {
|
getIssuePartTemplateWithProject((template, project) => {
|
||||||
this.currentProject = project;
|
this.currentProject = project;
|
||||||
|
@ -243,17 +245,18 @@ export default {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if(data&&data.id){
|
if (data && data.id) {
|
||||||
this.$get('/issues/follow/' + data.id, response => {
|
this.$get('/issues/follow/' + data.id, response => {
|
||||||
this.form.follows = response.data;
|
this.form.follows = response.data;
|
||||||
for (let i = 0; i < response.data.length; i++) {
|
for (let i = 0; i < response.data.length; i++) {
|
||||||
if(response.data[i]===this.currentUser().id){
|
if (response.data[i] === this.currentUser().id) {
|
||||||
this.showFollow = true;
|
this.showFollow = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}else {
|
} else {
|
||||||
|
this.issueId = null;
|
||||||
this.form.follows = [];
|
this.form.follows = [];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -324,6 +327,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.customFieldForm = parseCustomField(this.form, this.issueTemplate, this.customFieldRules);
|
this.customFieldForm = parseCustomField(this.form, this.issueTemplate, this.customFieldRules);
|
||||||
|
this.comments = [];
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
if (this.$refs.testCaseIssueList) {
|
if (this.$refs.testCaseIssueList) {
|
||||||
this.$refs.testCaseIssueList.initTableData();
|
this.$refs.testCaseIssueList.initTableData();
|
||||||
|
@ -421,6 +425,10 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openComment() {
|
openComment() {
|
||||||
|
if (!this.issueId) {
|
||||||
|
this.$warning(this.$t('test_track.issue.save_before_open_comment'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.$refs.issueComment.open();
|
this.$refs.issueComment.open();
|
||||||
},
|
},
|
||||||
getComments() {
|
getComments() {
|
||||||
|
|
|
@ -295,17 +295,17 @@ export default {
|
||||||
|
|
||||||
},
|
},
|
||||||
handleEdit(data) {
|
handleEdit(data) {
|
||||||
this.$refs.issueEdit.open(data);
|
this.$refs.issueEdit.open(data, 'edit');
|
||||||
},
|
},
|
||||||
handleCreate() {
|
handleCreate() {
|
||||||
this.$refs.issueEdit.open();
|
this.$refs.issueEdit.open(null, 'add');
|
||||||
},
|
},
|
||||||
handleCopy(data) {
|
handleCopy(data) {
|
||||||
let copyData = {};
|
let copyData = {};
|
||||||
Object.assign(copyData, data);
|
Object.assign(copyData, data);
|
||||||
copyData.id = null;
|
copyData.id = null;
|
||||||
copyData.name = data.name + '_copy';
|
copyData.name = data.name + '_copy';
|
||||||
this.$refs.issueEdit.open(copyData);
|
this.$refs.issueEdit.open(copyData, 'copy');
|
||||||
},
|
},
|
||||||
handleDelete(data) {
|
handleDelete(data) {
|
||||||
this.page.result = this.$get('issues/delete/' + data.id, () => {
|
this.page.result = this.$get('issues/delete/' + data.id, () => {
|
||||||
|
|
|
@ -450,7 +450,9 @@ export default {
|
||||||
if (this.planId) {
|
if (this.planId) {
|
||||||
this.$post("/test/plan/scenario/case/run", param, response => {
|
this.$post("/test/plan/scenario/case/run", param, response => {
|
||||||
this.runVisible = true;
|
this.runVisible = true;
|
||||||
this.reportId = response.data;
|
if (response.data && response.data.length > 0) {
|
||||||
|
this.reportId = response.data[0].reportId;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (this.reviewId) {
|
if (this.reviewId) {
|
||||||
|
|
|
@ -19,46 +19,45 @@
|
||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
<span class="comment-delete">
|
<span class="comment-delete">
|
||||||
<el-link icon="el-icon-edit" v-if="!isImage" style="font-size: 9px;margin-right: 6px;" @click="openEdit" :disabled="readOnly"/>
|
<el-link icon="el-icon-edit" style="font-size: 9px;margin-right: 6px;" @click="openEdit" :disabled="readOnly"/>
|
||||||
<el-link icon="el-icon-close" @click="deleteComment" :disabled="readOnly"/>
|
<el-link icon="el-icon-close" @click="deleteComment" :disabled="readOnly"/>
|
||||||
</span>
|
</span>
|
||||||
<br/>
|
<br/>
|
||||||
<!-- <div class="comment-desc" style="font-size: 10px;color: #303133">-->
|
|
||||||
<!-- <pre>{{ comment.description }}</pre>-->
|
<div v-if="!isImage" class="comment-desc" style="font-size: 10px;color: #303133">
|
||||||
<!-- </div>-->
|
|
||||||
<div v-if="!isImage" class="comment-desc" style="font-size: 10px;color: #303133">
|
|
||||||
<pre>{{ comment.description }}</pre>
|
<pre>{{ comment.description }}</pre>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="isImage" class="demo-image__preview">
|
<div v-if="isImage" class="demo-image__preview">
|
||||||
<pre>{{ imgDescription }}</pre>
|
<pre>{{ imgDescription }}</pre>
|
||||||
<el-image
|
<el-image
|
||||||
:z-index="imageIndex"
|
:z-index="imageIndex"
|
||||||
style="width: 100px; height: 100px;"
|
style="width: 100px; height: 100px;"
|
||||||
fit="contain"
|
fit="contain"
|
||||||
:src="src"
|
:src="src"
|
||||||
:preview-src-list="srcList">
|
:preview-src-list="srcList">
|
||||||
</el-image>
|
</el-image>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog :visible.sync="visible"
|
||||||
:title="$t('commons.edit')"
|
:title="$t('commons.edit')"
|
||||||
:visible.sync="visible"
|
:destroy-on-close="true"
|
||||||
width="30%"
|
:close-on-click-modal="false"
|
||||||
:destroy-on-close="true"
|
append-to-body>
|
||||||
:append-to-body="true"
|
|
||||||
:close-on-click-modal="false"
|
<div>
|
||||||
show-close>
|
<div class="editors_div_style">
|
||||||
<el-input
|
<div id="editorsDiv">
|
||||||
type="textarea"
|
<ms-mark-down-text prop="description" :data="comment" :toolbars="toolbars"/>
|
||||||
:rows="5"
|
</div>
|
||||||
v-model="description">
|
</div>
|
||||||
</el-input>
|
<div>
|
||||||
<span slot="footer" class="dialog-footer">
|
<el-button type="primary" size="mini" class="send-btn" @click="editComment">
|
||||||
<ms-dialog-footer
|
{{ $t('test_track.comment.send') }}
|
||||||
@cancel="visible = false"
|
</el-button>
|
||||||
@confirm="editComment"/>
|
</div>
|
||||||
</span>
|
</div>
|
||||||
|
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -66,10 +65,11 @@
|
||||||
<script>
|
<script>
|
||||||
import MsDialogFooter from "@/business/components/common/components/MsDialogFooter";
|
import MsDialogFooter from "@/business/components/common/components/MsDialogFooter";
|
||||||
import {getCurrentUser} from "@/common/js/utils";
|
import {getCurrentUser} from "@/common/js/utils";
|
||||||
|
import MsMarkDownText from "@/business/components/track/case/components/MsMarkDownText";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ReviewCommentItem",
|
name: "ReviewCommentItem",
|
||||||
components: {MsDialogFooter},
|
components: {MsDialogFooter, MsMarkDownText},
|
||||||
props: {
|
props: {
|
||||||
comment: Object,
|
comment: Object,
|
||||||
readOnly: {
|
readOnly: {
|
||||||
|
@ -83,16 +83,51 @@ export default {
|
||||||
return {
|
return {
|
||||||
visible: false,
|
visible: false,
|
||||||
imgDescription: "",
|
imgDescription: "",
|
||||||
imageIndex:99999,
|
imageIndex: 99999,
|
||||||
src:"",
|
src: "",
|
||||||
srcList:[],
|
srcList: [],
|
||||||
imgNameList:[],
|
imgNameList: [],
|
||||||
description: "",
|
description: "",
|
||||||
imageMatchPattern:"(\\!\\[)\\S+]\\(\\S+\\)",
|
imageMatchPattern: "(\\!\\[)\\S+]\\(\\S+\\)",
|
||||||
|
toolbars: {
|
||||||
|
bold: false, // 粗体
|
||||||
|
italic: false, // 斜体
|
||||||
|
header: false, // 标题
|
||||||
|
underline: false, // 下划线
|
||||||
|
strikethrough: false, // 中划线
|
||||||
|
mark: false, // 标记
|
||||||
|
superscript: false, // 上角标
|
||||||
|
subscript: false, // 下角标
|
||||||
|
quote: false, // 引用
|
||||||
|
ol: false, // 有序列表
|
||||||
|
ul: false, // 无序列表
|
||||||
|
link: false, // 链接
|
||||||
|
imagelink: true, // 图片链接
|
||||||
|
code: false, // code
|
||||||
|
table: false, // 表格
|
||||||
|
fullscreen: false, // 全屏编辑
|
||||||
|
readmodel: false, // 沉浸式阅读
|
||||||
|
htmlcode: false, // 展示html源码
|
||||||
|
help: false, // 帮助
|
||||||
|
/* 1.3.5 */
|
||||||
|
undo: false, // 上一步
|
||||||
|
redo: false, // 下一步
|
||||||
|
trash: false, // 清空
|
||||||
|
save: false, // 保存(触发events中的save事件)
|
||||||
|
/* 1.4.2 */
|
||||||
|
navigation: false, // 导航目录
|
||||||
|
/* 2.1.8 */
|
||||||
|
alignleft: false, // 左对齐
|
||||||
|
aligncenter: false, // 居中
|
||||||
|
alignright: false, // 右对齐
|
||||||
|
/* 2.2.1 */
|
||||||
|
subfield: false, // 单双栏模式
|
||||||
|
preview: false, // 预览
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed:{
|
computed: {
|
||||||
isImage(){
|
isImage() {
|
||||||
return this.checkImage(this.comment.description);
|
return this.checkImage(this.comment.description);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -102,7 +137,7 @@ export default {
|
||||||
this.$warning(this.$t('test_track.comment.cannot_delete'));
|
this.$warning(this.$t('test_track.comment.cannot_delete'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(this.imgNameList.length > 0){
|
if (this.imgNameList.length > 0) {
|
||||||
this.imgNameList.forEach(imgName => {
|
this.imgNameList.forEach(imgName => {
|
||||||
this.$get('/resource/md/delete/' + imgName);
|
this.$get('/resource/md/delete/' + imgName);
|
||||||
});
|
});
|
||||||
|
@ -121,90 +156,91 @@ export default {
|
||||||
this.visible = true;
|
this.visible = true;
|
||||||
},
|
},
|
||||||
editComment() {
|
editComment() {
|
||||||
this.$post(this.apiUrl + "/comment/edit", {id: this.comment.id, description: this.description}, () => {
|
this.$post(this.apiUrl + "/comment/edit", {id: this.comment.id, description: this.comment.description}, () => {
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
this.$success(this.$t('commons.modify_success'));
|
this.$success(this.$t('commons.modify_success'));
|
||||||
this.$emit("refresh");
|
this.$emit("refresh");
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
checkImage(){
|
checkImage() {
|
||||||
|
this.srcList = [];
|
||||||
let param = this.comment.description;
|
let param = this.comment.description;
|
||||||
let returnFlag = false;
|
let returnFlag = false;
|
||||||
if(param){
|
if (param) {
|
||||||
let message = param+"";
|
let message = param + "";
|
||||||
let matchIndex = message.indexOf("](/resource/md/get/");
|
let matchIndex = message.indexOf("](/resource/md/get/");
|
||||||
if(matchIndex > 0){
|
if (matchIndex > 0) {
|
||||||
let messageSplitArr = message.split("](/resource/md/get/");
|
let messageSplitArr = message.split("](/resource/md/get/");
|
||||||
for(let itemIndex = 0;itemIndex < messageSplitArr.length; itemIndex ++){
|
for (let itemIndex = 0; itemIndex < messageSplitArr.length; itemIndex++) {
|
||||||
let itemStr = messageSplitArr[itemIndex];
|
let itemStr = messageSplitArr[itemIndex];
|
||||||
let picNameIndex = itemStr.indexOf("![");
|
let picNameIndex = itemStr.indexOf("![");
|
||||||
if( picNameIndex < 0){
|
if (picNameIndex < 0) {
|
||||||
let endUrlIndex = itemStr.indexOf(")");
|
let endUrlIndex = itemStr.indexOf(")");
|
||||||
if( endUrlIndex > 0){
|
if (endUrlIndex > 0) {
|
||||||
let itemStrArr = itemStr.substr(0,endUrlIndex);
|
let itemStrArr = itemStr.substr(0, endUrlIndex);
|
||||||
//if(imgNameList.)
|
//if(imgNameList.)
|
||||||
if(this.imgNameList.indexOf(itemStrArr) < 0){
|
if (this.imgNameList.indexOf(itemStrArr) < 0) {
|
||||||
this.imgNameList.push(itemStrArr);
|
this.imgNameList.push(itemStrArr);
|
||||||
}
|
}
|
||||||
|
|
||||||
let imgUrl = "/resource/md/get/"+itemStrArr;
|
let imgUrl = "/resource/md/get/" + itemStrArr;
|
||||||
this.src = imgUrl;
|
this.src = imgUrl;
|
||||||
if(this.srcList.indexOf(itemStrArr) < 0){
|
if (this.srcList.indexOf(itemStrArr) < 0) {
|
||||||
this.srcList.push(imgUrl);
|
this.srcList.push(imgUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
let inputStr = itemStr.substr(0,picNameIndex);
|
let inputStr = itemStr.substr(0, picNameIndex);
|
||||||
if(this.imgDescription === ""){
|
if (this.imgDescription === "") {
|
||||||
this.imgDescription = inputStr;
|
this.imgDescription = inputStr;
|
||||||
}else {
|
} else {
|
||||||
this.imgDescription = "\n" + inputStr;
|
this.imgDescription = "\n" + inputStr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
let imgUrlIndex = message.indexOf("](http");
|
let imgUrlIndex = message.indexOf("](http");
|
||||||
if(imgUrlIndex > 0){
|
if (imgUrlIndex > 0) {
|
||||||
let imgUrlSplitArr = message.split("](http");
|
let imgUrlSplitArr = message.split("](http");
|
||||||
for(let itemIndex = 0;itemIndex < imgUrlSplitArr.length; itemIndex ++){
|
for (let itemIndex = 0; itemIndex < imgUrlSplitArr.length; itemIndex++) {
|
||||||
let itemStr = imgUrlSplitArr[itemIndex];
|
let itemStr = imgUrlSplitArr[itemIndex];
|
||||||
let picNameIndex = itemStr.indexOf("![");
|
let picNameIndex = itemStr.indexOf("![");
|
||||||
if( picNameIndex < 0){
|
if (picNameIndex < 0) {
|
||||||
let endUrlIndex = itemStr.indexOf(")");
|
let endUrlIndex = itemStr.indexOf(")");
|
||||||
if( endUrlIndex > 0){
|
if (endUrlIndex > 0) {
|
||||||
let itemStrArr = itemStr.substr(0,endUrlIndex);
|
let itemStrArr = itemStr.substr(0, endUrlIndex);
|
||||||
//if(imgNameList.)
|
//if(imgNameList.)
|
||||||
if(this.imgNameList.indexOf(itemStrArr) < 0){
|
if (this.imgNameList.indexOf(itemStrArr) < 0) {
|
||||||
this.imgNameList.push(itemStrArr);
|
this.imgNameList.push(itemStrArr);
|
||||||
}
|
}
|
||||||
let imgUrl = "http"+itemStrArr;
|
let imgUrl = "http" + itemStrArr;
|
||||||
this.src = imgUrl;
|
this.src = imgUrl;
|
||||||
if(this.srcList.indexOf(itemStrArr) < 0){
|
if (this.srcList.indexOf(itemStrArr) < 0) {
|
||||||
this.srcList.push(imgUrl);
|
this.srcList.push(imgUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
let inputStr = itemStr.substr(0,picNameIndex);
|
let inputStr = itemStr.substr(0, picNameIndex);
|
||||||
if(this.imgDescription === ""){
|
if (this.imgDescription === "") {
|
||||||
this.imgDescription = inputStr;
|
this.imgDescription = inputStr;
|
||||||
}else {
|
} else {
|
||||||
this.imgDescription = "\n" + inputStr;
|
this.imgDescription = "\n" + inputStr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(this.srcList.length > 0){
|
if (this.srcList.length > 0) {
|
||||||
returnFlag = true;
|
returnFlag = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return returnFlag;
|
return returnFlag;
|
||||||
},
|
},
|
||||||
checkByUrls(url){
|
checkByUrls(url) {
|
||||||
let checkResultFlag = false;
|
let checkResultFlag = false;
|
||||||
if(this.imgNameList.length > 0){
|
if (this.imgNameList.length > 0) {
|
||||||
this.imgNameList.forEach(imgName => {
|
this.imgNameList.forEach(imgName => {
|
||||||
if(imgName === url){
|
if (imgName === url) {
|
||||||
checkResultFlag = true;
|
checkResultFlag = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -269,6 +305,11 @@ pre {
|
||||||
}
|
}
|
||||||
|
|
||||||
/deep/ .el-button--mini, .el-button--mini.is-round {
|
/deep/ .el-button--mini, .el-button--mini.is-round {
|
||||||
padding: 4px 9px;
|
padding: 7px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.send-btn {
|
||||||
|
margin-top: 5px;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit a2a8dde5beb470590e7860e9d4376a56ce41d791
|
Subproject commit 88b54ba98e8e0bdc6262f63310424263309493ea
|
|
@ -189,7 +189,7 @@ export let CUSTOM_TABLE_HEADER = {
|
||||||
{id: 'createUser', key: '7', label: 'commons.create_user'},
|
{id: 'createUser', key: '7', label: 'commons.create_user'},
|
||||||
{id: 'createTime', key: '8', label: 'commons.create_time'},
|
{id: 'createTime', key: '8', label: 'commons.create_time'},
|
||||||
{id: 'desc', key: '9', label: 'test_track.case.case_desc'},
|
{id: 'desc', key: '9', label: 'test_track.case.case_desc'},
|
||||||
{id: 'lastExecResult', key: '10', label: 'test_track.plan_view.execute_result'},
|
{id: 'lastExecResult', key: '0', label: 'test_track.plan_view.execute_result'},
|
||||||
],
|
],
|
||||||
//缺陷列表
|
//缺陷列表
|
||||||
ISSUE_LIST: [
|
ISSUE_LIST: [
|
||||||
|
|
|
@ -191,14 +191,14 @@ export function getLabel(vueObj, type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function buildBatchParam(vueObj, selectIds) {
|
export function buildBatchParam(vueObj, selectIds, projectId) {
|
||||||
let param = {};
|
let param = {};
|
||||||
if (vueObj.selectRows) {
|
if (vueObj.selectRows) {
|
||||||
param.ids = selectIds ? selectIds: Array.from(vueObj.selectRows).map(row => row.id);
|
param.ids = selectIds ? selectIds: Array.from(vueObj.selectRows).map(row => row.id);
|
||||||
} else {
|
} else {
|
||||||
param.ids = selectIds;
|
param.ids = selectIds;
|
||||||
}
|
}
|
||||||
param.projectId = getCurrentProjectID();
|
param.projectId = projectId ? projectId : getCurrentProjectID();
|
||||||
param.condition = vueObj.condition;
|
param.condition = vueObj.condition;
|
||||||
return param;
|
return param;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,15 @@ export default {
|
||||||
yes: "yes",
|
yes: "yes",
|
||||||
no: "no",
|
no: "no",
|
||||||
example: "Demo",
|
example: "Demo",
|
||||||
|
subject: "Subject",
|
||||||
excelFile: "Excel",
|
excelFile: "Excel",
|
||||||
xmindFile: "Xmind",
|
xmindFile: "Xmind",
|
||||||
default: "default",
|
default: "default",
|
||||||
|
sort_default: "Default",
|
||||||
please_select_import_mode: 'Please select import mode',
|
please_select_import_mode: 'Please select import mode',
|
||||||
please_select_import_module: 'Please select import module',
|
please_select_import_module: 'Please select import module',
|
||||||
pass_rate: 'Pass rate',
|
pass_rate: 'Pass Rate',
|
||||||
execution_times: 'Execution times',
|
execution_times: 'Execution Times',
|
||||||
cover: 'Cover',
|
cover: 'Cover',
|
||||||
module_title: 'Default module',
|
module_title: 'Default module',
|
||||||
save_data_when_page_change: 'Save when page change',
|
save_data_when_page_change: 'Save when page change',
|
||||||
|
@ -68,18 +70,18 @@ export default {
|
||||||
input_limit: 'Within {0} and {1} characters',
|
input_limit: 'Within {0} and {1} characters',
|
||||||
login: 'Sign In',
|
login: 'Sign In',
|
||||||
welcome: 'One-stop open source continuous testing platform',
|
welcome: 'One-stop open source continuous testing platform',
|
||||||
theme_color:'Theme color',
|
theme_color: 'Theme color',
|
||||||
username: 'Username',
|
username: 'Username',
|
||||||
password: 'Password',
|
password: 'Password',
|
||||||
input_username: 'Please enter username',
|
input_username: 'Please enter username',
|
||||||
input_password: 'Please enter password',
|
input_password: 'Please enter password',
|
||||||
test: 'Test',
|
test: 'Test',
|
||||||
create_time: 'Created Time',
|
create_time: 'Created Time',
|
||||||
update_user_id:'Updater ID',
|
update_user_id: 'Updater ID',
|
||||||
update_time: 'Updated Time',
|
update_time: 'Updated Time',
|
||||||
delete_time: 'Delete Time',
|
delete_time: 'Delete Time',
|
||||||
delete_user: 'Deleted by',
|
delete_user: 'Deleted By',
|
||||||
delete_user_id:'Deleted by id',
|
delete_user_id: 'Deleted by id',
|
||||||
add: 'Add',
|
add: 'Add',
|
||||||
preview: 'Preview',
|
preview: 'Preview',
|
||||||
member: 'Member',
|
member: 'Member',
|
||||||
|
@ -325,6 +327,11 @@ export default {
|
||||||
send: "Send",
|
send: "Send",
|
||||||
save_as_draft: "Draft",
|
save_as_draft: "Draft",
|
||||||
},
|
},
|
||||||
|
table: {
|
||||||
|
draft: "Draft",
|
||||||
|
sended: "Send",
|
||||||
|
send_error: "Send error",
|
||||||
|
},
|
||||||
project_report: {
|
project_report: {
|
||||||
create_report: "Create report",
|
create_report: "Create report",
|
||||||
report_name: "Report name",
|
report_name: "Report name",
|
||||||
|
@ -393,20 +400,20 @@ export default {
|
||||||
system_project: "Project",
|
system_project: "Project",
|
||||||
user_unit: "",
|
user_unit: "",
|
||||||
workspace_unit: "",
|
workspace_unit: "",
|
||||||
dash_board:'DashBoard',
|
dash_board: 'DashBoard',
|
||||||
all_project:'All Project',
|
all_project: 'All Project',
|
||||||
to_be_completed:'Unfinished',
|
to_be_completed: 'Unfinished',
|
||||||
pending_upgrade:'To be update',
|
pending_upgrade: 'To be update',
|
||||||
information:'Information',
|
information: 'Information',
|
||||||
nick_name:'Nick name',
|
nick_name: 'Nick name',
|
||||||
resourceId:'Resource ID',
|
resourceId: 'Resource ID',
|
||||||
num:'Number',
|
num: 'Number',
|
||||||
original_state:'Original State',
|
original_state: 'Original State',
|
||||||
custom_num:'CustomNum',
|
custom_num: 'CustomNum',
|
||||||
version:'Version',
|
version: 'Version',
|
||||||
is_new:"Is new",
|
is_new: "Is new",
|
||||||
form_config:"Form config",
|
form_config: "Form config",
|
||||||
form_content:"Form content"
|
form_content: "Form content"
|
||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
normal_Login: "Normal Login",
|
normal_Login: "Normal Login",
|
||||||
|
@ -427,25 +434,25 @@ export default {
|
||||||
invalid: 'invalid',
|
invalid: 'invalid',
|
||||||
expired: 'expired',
|
expired: 'expired',
|
||||||
},
|
},
|
||||||
workstation:{
|
workstation: {
|
||||||
dash_board: 'My DashBoard',
|
dash_board: 'My DashBoard',
|
||||||
upcoming: 'My Upcoming',
|
upcoming: 'My Upcoming',
|
||||||
focus: 'My Focus',
|
focus: 'My Focus',
|
||||||
creation: 'My Creation',
|
creation: 'My Creation',
|
||||||
creation_case:'My Creation Case',
|
creation_case: 'My Creation Case',
|
||||||
creation_issue:'My Creation Issue',
|
creation_issue: 'My Creation Issue',
|
||||||
creation_case_tip: 'No use case has been created yet, create it now',
|
creation_case_tip: 'No use case has been created yet, create it now',
|
||||||
creation_issue_tip:'No defects have been created yet, create them now',
|
creation_issue_tip: 'No defects have been created yet, create them now',
|
||||||
table_name:{
|
table_name: {
|
||||||
track_case:'Track Case',
|
track_case: 'Track Case',
|
||||||
track_plan:'Track Plan',
|
track_plan: 'Track Plan',
|
||||||
track_review:'Track Review',
|
track_review: 'Track Review',
|
||||||
track_issue:'Track Issue',
|
track_issue: 'Track Issue',
|
||||||
api_definition:'Api Definition',
|
api_definition: 'Api Definition',
|
||||||
api_automation:'Api Automation',
|
api_automation: 'Api Automation',
|
||||||
api_case:'Api Case',
|
api_case: 'Api Case',
|
||||||
performance:'Performance',
|
performance: 'Performance',
|
||||||
scenario_case:'Scenario Case'
|
scenario_case: 'Scenario Case'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
display: {
|
display: {
|
||||||
|
@ -511,7 +518,7 @@ export default {
|
||||||
option_value_check: 'Please fill in the full option values',
|
option_value_check: 'Please fill in the full option values',
|
||||||
},
|
},
|
||||||
workspace: {
|
workspace: {
|
||||||
id:'Workspace ID',
|
id: 'Workspace ID',
|
||||||
create: 'Create Workspace',
|
create: 'Create Workspace',
|
||||||
update: 'Update Workspace',
|
update: 'Update Workspace',
|
||||||
delete: 'Delete Workspace',
|
delete: 'Delete Workspace',
|
||||||
|
@ -632,12 +639,12 @@ export default {
|
||||||
zentao_request: 'Zentao request',
|
zentao_request: 'Zentao request',
|
||||||
input_zentao_request: 'Please enter zentao request type',
|
input_zentao_request: 'Please enter zentao request type',
|
||||||
input_zentao_url: 'Please enter Zentao address, for example: http://xx.xx.xx.xx/zentao/',
|
input_zentao_url: 'Please enter Zentao address, for example: http://xx.xx.xx.xx/zentao/',
|
||||||
zentao_info:'Zentao Information',
|
zentao_info: 'Zentao Information',
|
||||||
zentao_account:'Zentao Account',
|
zentao_account: 'Zentao Account',
|
||||||
zentao_password:'Zentao Password',
|
zentao_password: 'Zentao Password',
|
||||||
zentao_prompt_information:'This information is the username and password of the user who submitted the defect through ZenTao. If not filled in, the default information configured in the workspace will be used',
|
zentao_prompt_information: 'This information is the username and password of the user who submitted the defect through ZenTao. If not filled in, the default information configured in the workspace will be used',
|
||||||
zentao_config_tip:"Refer to the value of $config->requestType in the ZenTao configuration file",
|
zentao_config_tip: "Refer to the value of $config->requestType in the ZenTao configuration file",
|
||||||
zentao_config_path:"Configuration file reference path: /opt/zbox/app/zentao/config/my.php",
|
zentao_config_path: "Configuration file reference path: /opt/zbox/app/zentao/config/my.php",
|
||||||
use_tip: 'Usage guidelines:',
|
use_tip: 'Usage guidelines:',
|
||||||
use_tip_tapd: 'Basic Auth account information is queried in "Company Management-Security and Integration-Open Platform"',
|
use_tip_tapd: 'Basic Auth account information is queried in "Company Management-Security and Integration-Open Platform"',
|
||||||
use_tip_jira: 'Jira software server authentication information is account password, Jira software cloud authentication information is account + token (account settings-security-create API token)',
|
use_tip_jira: 'Jira software server authentication information is account password, Jira software cloud authentication information is account + token (account settings-security-create API token)',
|
||||||
|
@ -664,11 +671,11 @@ export default {
|
||||||
input_azure_url: 'Please enter Azure Devops Url',
|
input_azure_url: 'Please enter Azure Devops Url',
|
||||||
input_azure_id: 'Please enter Azure Organization ID',
|
input_azure_id: 'Please enter Azure Organization ID',
|
||||||
use_tip_azure: 'Azure Devops URL+PersonalAccessTokens(User Settings-Personal Access Tokens-New Token)',
|
use_tip_azure: 'Azure Devops URL+PersonalAccessTokens(User Settings-Personal Access Tokens-New Token)',
|
||||||
jira_prompt_information:'This information is the user authentication information for submitting defects through Jira. If it is not filled in, the default information configured in the workspace will be used'
|
jira_prompt_information: 'This information is the user authentication information for submitting defects through Jira. If it is not filled in, the default information configured in the workspace will be used'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
project: {
|
project: {
|
||||||
id:'Project ID',
|
id: 'Project ID',
|
||||||
name: 'Project name',
|
name: 'Project name',
|
||||||
recent: 'Recent Projects',
|
recent: 'Recent Projects',
|
||||||
create: 'Create Project',
|
create: 'Create Project',
|
||||||
|
@ -706,7 +713,7 @@ export default {
|
||||||
create: "Create Custom Code",
|
create: "Create Custom Code",
|
||||||
update: "Update Custom Code",
|
update: "Update Custom Code",
|
||||||
delete: "Delete Custom Code",
|
delete: "Delete Custom Code",
|
||||||
language: "language",
|
language: "Language",
|
||||||
relate_tip: "Create in the Project Settings -> Custom Code Snippet menu",
|
relate_tip: "Create in the Project Settings -> Custom Code Snippet menu",
|
||||||
select_tip: "Please select a custom code!",
|
select_tip: "Please select a custom code!",
|
||||||
none_content: "The custom code snippet is empty!",
|
none_content: "The custom code snippet is empty!",
|
||||||
|
@ -772,7 +779,7 @@ export default {
|
||||||
no_such_user: 'Without this user information, please enter the correct user ID or user Email!',
|
no_such_user: 'Without this user information, please enter the correct user ID or user Email!',
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
id:'User ID',
|
id: 'User ID',
|
||||||
create: 'Create',
|
create: 'Create',
|
||||||
modify: 'Modify',
|
modify: 'Modify',
|
||||||
input_name: 'Please enter a user name',
|
input_name: 'Please enter a user name',
|
||||||
|
@ -798,7 +805,7 @@ export default {
|
||||||
add_project_batch: 'Batch Add User To Project',
|
add_project_batch: 'Batch Add User To Project',
|
||||||
add_workspace_batch: "Batch Add User To Workspace",
|
add_workspace_batch: "Batch Add User To Workspace",
|
||||||
add_project_batch_tip: 'Add a read-only user group for members by default (system)',
|
add_project_batch_tip: 'Add a read-only user group for members by default (system)',
|
||||||
import_user_tip:'User group only supports system default user group',
|
import_user_tip: 'User group only supports system default user group',
|
||||||
},
|
},
|
||||||
group: {
|
group: {
|
||||||
add: 'Add User Group',
|
add: 'Add User Group',
|
||||||
|
@ -843,7 +850,7 @@ export default {
|
||||||
add: 'Add Role',
|
add: 'Add Role',
|
||||||
},
|
},
|
||||||
report: {
|
report: {
|
||||||
id:'Report ID',
|
id: 'Report ID',
|
||||||
api_test_report: 'Api Test Report',
|
api_test_report: 'Api Test Report',
|
||||||
load_test_report: 'Load Test Report',
|
load_test_report: 'Load Test Report',
|
||||||
test_plan_report: 'Test Plan Report',
|
test_plan_report: 'Test Plan Report',
|
||||||
|
@ -890,13 +897,13 @@ export default {
|
||||||
delete_batch_confirm: 'Confirm batch delete report',
|
delete_batch_confirm: 'Confirm batch delete report',
|
||||||
response_time: 'Response Time(s)',
|
response_time: 'Response Time(s)',
|
||||||
max_users: 'VUs',
|
max_users: 'VUs',
|
||||||
file_id:'Report File ID',
|
file_id: 'Report File ID',
|
||||||
avg_response_time:'Average Response Time',
|
avg_response_time: 'Average Response Time',
|
||||||
tps:'Transactions Per Second',
|
tps: 'Transactions Per Second',
|
||||||
plan_share_url:'Whether the link jump is logged in'
|
plan_share_url: 'Whether the link jump is logged in'
|
||||||
},
|
},
|
||||||
load_test: {
|
load_test: {
|
||||||
id:'Load Test ID',
|
id: 'Load Test ID',
|
||||||
concurrency_thread_group: 'Concurrent read group',
|
concurrency_thread_group: 'Concurrent read group',
|
||||||
thread_group: 'ThreadGroup',
|
thread_group: 'ThreadGroup',
|
||||||
completed_test_report: 'Completed test report',
|
completed_test_report: 'Completed test report',
|
||||||
|
@ -921,11 +928,11 @@ export default {
|
||||||
test_name_is_null: 'Test name cannot be empty! ',
|
test_name_is_null: 'Test name cannot be empty! ',
|
||||||
project_is_null: 'Project cannot be empty! ',
|
project_is_null: 'Project cannot be empty! ',
|
||||||
jmx_is_null: 'Must contain a JMX file, and can only contain a JMX file!',
|
jmx_is_null: 'Must contain a JMX file, and can only contain a JMX file!',
|
||||||
file_name: 'File name',
|
file_name: 'File Name',
|
||||||
file_size: 'File size',
|
file_size: 'File size',
|
||||||
file_type: 'File Type',
|
file_type: 'File Type',
|
||||||
file_status: 'File Status',
|
file_status: 'File Status',
|
||||||
last_modify_time: 'Modify time',
|
last_modify_time: 'Modify Time',
|
||||||
upload_tips: 'Drag files here, or <em> click to upload </em>',
|
upload_tips: 'Drag files here, or <em> click to upload </em>',
|
||||||
upload_type: 'Only JMX/CSV/JAR files can be uploaded',
|
upload_type: 'Only JMX/CSV/JAR files can be uploaded',
|
||||||
related_file_not_found: "No related test file found!",
|
related_file_not_found: "No related test file found!",
|
||||||
|
@ -1018,7 +1025,7 @@ export default {
|
||||||
LatencyChart: 'Latency',
|
LatencyChart: 'Latency',
|
||||||
BytesThroughputChart: 'Bytes',
|
BytesThroughputChart: 'Bytes',
|
||||||
Network: 'Network',
|
Network: 'Network',
|
||||||
url:'URL'
|
url: 'URL'
|
||||||
},
|
},
|
||||||
add_monitor: 'Add Monitor',
|
add_monitor: 'Add Monitor',
|
||||||
monitor_item: 'Monitor',
|
monitor_item: 'Monitor',
|
||||||
|
@ -1063,7 +1070,7 @@ export default {
|
||||||
upload_limit_size: "Upload file size cannot exceed 30MB!",
|
upload_limit_size: "Upload file size cannot exceed 30MB!",
|
||||||
upload_limit_size_warn: "Upload file size cannot exceed {0} MB!",
|
upload_limit_size_warn: "Upload file size cannot exceed {0} MB!",
|
||||||
upload_limit: "Upload file size cannot exceed",
|
upload_limit: "Upload file size cannot exceed",
|
||||||
upload_tip:"Only upload JAR packages"
|
upload_tip: "Only upload JAR packages"
|
||||||
},
|
},
|
||||||
batch_menus: {
|
batch_menus: {
|
||||||
select_all_data: "Select all datas({0})",
|
select_all_data: "Select all datas({0})",
|
||||||
|
@ -1079,7 +1086,7 @@ export default {
|
||||||
update_time: "Update time"
|
update_time: "Update time"
|
||||||
},
|
},
|
||||||
expect_detail: "Expect",
|
expect_detail: "Expect",
|
||||||
request_condition:"Request Condition",
|
request_condition: "Request Condition",
|
||||||
base_info: "Base info",
|
base_info: "Base info",
|
||||||
req_param: "Request params",
|
req_param: "Request params",
|
||||||
rsp_param: "Response Params",
|
rsp_param: "Response Params",
|
||||||
|
@ -1096,22 +1103,22 @@ export default {
|
||||||
api_title: "Api Test",
|
api_title: "Api Test",
|
||||||
case_title: "Test Case",
|
case_title: "Test Case",
|
||||||
doc_title: "DOC",
|
doc_title: "DOC",
|
||||||
api_name: "Api name",
|
api_name: "Api Name",
|
||||||
api_status: "Api status",
|
api_status: "Api Status",
|
||||||
api_type: "Api type",
|
api_type: "Api Type",
|
||||||
api_agreement: "Method",
|
api_agreement: "Method",
|
||||||
api_path: "Api path",
|
api_path: "Api Path",
|
||||||
api_definition_path: "API Path",
|
api_definition_path: "API Path",
|
||||||
api_case_path: "Case Path",
|
api_case_path: "Case Path",
|
||||||
api_principal: "Api principal",
|
api_principal: "Api Principal",
|
||||||
api_last_time: "Last update time",
|
api_last_time: "Last Update Time",
|
||||||
api_case_number: "Cases",
|
api_case_number: "Cases",
|
||||||
api_case_status: "Case status",
|
api_case_status: "Case Status",
|
||||||
api_case_passing_rate: "Use case pass rate",
|
api_case_passing_rate: "Use Case Pass Rate",
|
||||||
create_tip: "Note: Detailed interface information can be filled out on the edit page",
|
create_tip: "Note: Detailed interface information can be filled out on the edit page",
|
||||||
api_import: "Api Import",
|
api_import: "Api Import",
|
||||||
check_select: "Please check the API",
|
check_select: "Please check the API",
|
||||||
api_project:"Project",
|
api_project: "Project",
|
||||||
select_comp: {
|
select_comp: {
|
||||||
no_data: "No Data",
|
no_data: "No Data",
|
||||||
add_data: "Add Data"
|
add_data: "Add Data"
|
||||||
|
@ -1233,7 +1240,7 @@ export default {
|
||||||
none: "None"
|
none: "None"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
case_reduction_error_text:"Please restore first"
|
case_reduction_error_text: "Please restore first"
|
||||||
},
|
},
|
||||||
automation: {
|
automation: {
|
||||||
open_expansion: "One-click expansion",
|
open_expansion: "One-click expansion",
|
||||||
|
@ -1264,15 +1271,15 @@ export default {
|
||||||
scenario_test: "Scenario test",
|
scenario_test: "Scenario test",
|
||||||
scenario_list: "Scenario List",
|
scenario_list: "Scenario List",
|
||||||
add_scenario: "Add scenario",
|
add_scenario: "Add scenario",
|
||||||
scenario_name: "Scenario name",
|
scenario_name: "Scenario Name",
|
||||||
case_level: "Case level",
|
case_level: "Case Level",
|
||||||
tag: "Tag",
|
tag: "Tag",
|
||||||
creator: "Creator",
|
creator: "Creator",
|
||||||
update_time: "Update time",
|
update_time: "Update Time",
|
||||||
step: "Step",
|
step: "Step",
|
||||||
last_result: "Last result",
|
last_result: "Last Result",
|
||||||
last_result_id:'Last result id',
|
last_result_id: 'Last result id',
|
||||||
passing_rate: "Passing rate",
|
passing_rate: "Passing Rate",
|
||||||
success: "Success",
|
success: "Success",
|
||||||
fail: "Fail",
|
fail: "Fail",
|
||||||
saved: "Saved",
|
saved: "Saved",
|
||||||
|
@ -1295,9 +1302,9 @@ export default {
|
||||||
select_table: "Select table",
|
select_table: "Select table",
|
||||||
select_all: "Select all",
|
select_all: "Select all",
|
||||||
check_case: "Please check the Scene Use Case",
|
check_case: "Please check the Scene Use Case",
|
||||||
api_none:"The original api does not exist",
|
api_none: "The original api does not exist",
|
||||||
case_none:"The original case does not exist",
|
case_none: "The original case does not exist",
|
||||||
num_none:"The original scene does not exist"
|
num_none: "The original scene does not exist"
|
||||||
},
|
},
|
||||||
report_name_info: 'Please enter the registration name',
|
report_name_info: 'Please enter the registration name',
|
||||||
save_case_info: 'Please save the use case first',
|
save_case_info: 'Please save the use case first',
|
||||||
|
@ -1314,7 +1321,7 @@ export default {
|
||||||
generate_report: "Generate report",
|
generate_report: "Generate report",
|
||||||
},
|
},
|
||||||
environment: {
|
environment: {
|
||||||
id:'Environment ID',
|
id: 'Environment ID',
|
||||||
create: 'Create environment',
|
create: 'Create environment',
|
||||||
name: "Environment Name",
|
name: "Environment Name",
|
||||||
socket: "Socket",
|
socket: "Socket",
|
||||||
|
@ -1340,7 +1347,7 @@ export default {
|
||||||
copy_warning: "Domain names whose enabling conditions are'none' do not support copying!"
|
copy_warning: "Domain names whose enabling conditions are'none' do not support copying!"
|
||||||
},
|
},
|
||||||
scenario: {
|
scenario: {
|
||||||
id:"Scenario ID",
|
id: "Scenario ID",
|
||||||
scenario: "Scenario",
|
scenario: "Scenario",
|
||||||
dubbo: "Dubbo Config",
|
dubbo: "Dubbo Config",
|
||||||
config: "Scenario Config",
|
config: "Scenario Config",
|
||||||
|
@ -1423,54 +1430,54 @@ export default {
|
||||||
condition_variable: "Variable, e.g: ${var}",
|
condition_variable: "Variable, e.g: ${var}",
|
||||||
wait: "wait",
|
wait: "wait",
|
||||||
|
|
||||||
all_name:"name",
|
all_name: "name",
|
||||||
all_url:"url",
|
all_url: "url",
|
||||||
boolean:"Boolean value",
|
boolean: "Boolean value",
|
||||||
capitalize:"Start with a capital letter",
|
capitalize: "Start with a capital letter",
|
||||||
cfirst:"Last name (Chinese)",
|
cfirst: "Last name (Chinese)",
|
||||||
character:"character",
|
character: "character",
|
||||||
city:"city",
|
city: "city",
|
||||||
clast:"First name (Chinese)",
|
clast: "First name (Chinese)",
|
||||||
cname:"Chinese name",
|
cname: "Chinese name",
|
||||||
color:"colour",
|
color: "colour",
|
||||||
county:"county",
|
county: "county",
|
||||||
ctitle:"Chinese title",
|
ctitle: "Chinese title",
|
||||||
dataImage:"Data image",
|
dataImage: "Data image",
|
||||||
date:"date",
|
date: "date",
|
||||||
datetime:"Date time",
|
datetime: "Date time",
|
||||||
domain:"field",
|
domain: "field",
|
||||||
email:"E-mail",
|
email: "E-mail",
|
||||||
first:"surname",
|
first: "surname",
|
||||||
float:"Floating point number",
|
float: "Floating point number",
|
||||||
guid:"guid",
|
guid: "guid",
|
||||||
hex:"hexadecimal",
|
hex: "hexadecimal",
|
||||||
hsl:"hsl",
|
hsl: "hsl",
|
||||||
id:"id",
|
id: "id",
|
||||||
img:"Picture address",
|
img: "Picture address",
|
||||||
increment:"increment",
|
increment: "increment",
|
||||||
integer:"integer",
|
integer: "integer",
|
||||||
ip:"intellectual property right",
|
ip: "intellectual property right",
|
||||||
last:"name",
|
last: "name",
|
||||||
lower:"Lowercase letters",
|
lower: "Lowercase letters",
|
||||||
natural:"Natural number",
|
natural: "Natural number",
|
||||||
now:"current time ",
|
now: "current time ",
|
||||||
paragraph:"paragraph",
|
paragraph: "paragraph",
|
||||||
pick:"choice",
|
pick: "choice",
|
||||||
protocol:"agreement",
|
protocol: "agreement",
|
||||||
province:"province",
|
province: "province",
|
||||||
range:"Range",
|
range: "Range",
|
||||||
region:"region",
|
region: "region",
|
||||||
rgb:"rgb",
|
rgb: "rgb",
|
||||||
rgba:"rgba",
|
rgba: "rgba",
|
||||||
sentence:"sentence",
|
sentence: "sentence",
|
||||||
shuffle:"shuffle the cards",
|
shuffle: "shuffle the cards",
|
||||||
string:"character string",
|
string: "character string",
|
||||||
time:"time",
|
time: "time",
|
||||||
title:"title",
|
title: "title",
|
||||||
tld:"tld",
|
tld: "tld",
|
||||||
upper:"capital",
|
upper: "capital",
|
||||||
word:"Words",
|
word: "Words",
|
||||||
zip:"Postal Code",
|
zip: "Postal Code",
|
||||||
|
|
||||||
assertions: {
|
assertions: {
|
||||||
label: "Assertion",
|
label: "Assertion",
|
||||||
|
@ -1730,7 +1737,7 @@ export default {
|
||||||
title: "Updated interfaces in the past 7 days",
|
title: "Updated interfaces in the past 7 days",
|
||||||
table_coloum: {
|
table_coloum: {
|
||||||
index: "ID",
|
index: "ID",
|
||||||
api_name: "Api name",
|
api_name: "Api Name",
|
||||||
path: "path",
|
path: "path",
|
||||||
api_status: "Api status",
|
api_status: "Api status",
|
||||||
update_time: "Update time",
|
update_time: "Update time",
|
||||||
|
@ -1843,7 +1850,7 @@ export default {
|
||||||
recent_plan: "My recent plan",
|
recent_plan: "My recent plan",
|
||||||
recent_case: "My recent case",
|
recent_case: "My recent case",
|
||||||
recent_review: "My recent review",
|
recent_review: "My recent review",
|
||||||
pass_rate: "Pass rate",
|
pass_rate: "Pass Rate",
|
||||||
execution_result: ": Please select the execution result",
|
execution_result: ": Please select the execution result",
|
||||||
actual_result: ": The actual result is empty",
|
actual_result: ": The actual result is empty",
|
||||||
cancel_relevance_success: "Unlinked successfully",
|
cancel_relevance_success: "Unlinked successfully",
|
||||||
|
@ -1853,14 +1860,14 @@ export default {
|
||||||
performance_test_case: "Performance Case",
|
performance_test_case: "Performance Case",
|
||||||
scenario_test_case: "Scenario Case",
|
scenario_test_case: "Scenario Case",
|
||||||
report_statistics: "Report Statistics",
|
report_statistics: "Report Statistics",
|
||||||
sort:'Sort',
|
sort: 'Sort',
|
||||||
other_test_name:'Other Test Name',
|
other_test_name: 'Other Test Name',
|
||||||
demand:{
|
demand: {
|
||||||
id:'Demand ID',
|
id: 'Demand ID',
|
||||||
name:'Demand Name'
|
name: 'Demand Name'
|
||||||
},
|
},
|
||||||
step_model:'Step Model',
|
step_model: 'Step Model',
|
||||||
automatic_status_update:"Automatic Status Update",
|
automatic_status_update: "Automatic Status Update",
|
||||||
case: {
|
case: {
|
||||||
list: "List",
|
list: "List",
|
||||||
minder: "Minder",
|
minder: "Minder",
|
||||||
|
@ -1892,7 +1899,7 @@ export default {
|
||||||
manual: "Manual",
|
manual: "Manual",
|
||||||
create: "Create test case",
|
create: "Create test case",
|
||||||
case_type: "Case Type",
|
case_type: "Case Type",
|
||||||
name: "Test case name",
|
name: "Test Case Name",
|
||||||
module: "Module",
|
module: "Module",
|
||||||
project: 'Project',
|
project: 'Project',
|
||||||
maintainer: "Maintainer",
|
maintainer: "Maintainer",
|
||||||
|
@ -1951,9 +1958,9 @@ export default {
|
||||||
attachment: "Attachment",
|
attachment: "Attachment",
|
||||||
upload_time: "Upload Time",
|
upload_time: "Upload Time",
|
||||||
total: "Total Case",
|
total: "Total Case",
|
||||||
node_id:"Node ID",
|
node_id: "Node ID",
|
||||||
node_path:"Node Path",
|
node_path: "Node Path",
|
||||||
match_rule:"Test Case Match Rule",
|
match_rule: "Test Case Match Rule",
|
||||||
import: {
|
import: {
|
||||||
import: "Import test case",
|
import: "Import test case",
|
||||||
case_import: "Import test case",
|
case_import: "Import test case",
|
||||||
|
@ -1985,11 +1992,11 @@ export default {
|
||||||
export_tip: "Switch to Interface List and check Use Case Export"
|
export_tip: "Switch to Interface List and check Use Case Export"
|
||||||
},
|
},
|
||||||
case_desc: "Case Desc",
|
case_desc: "Case Desc",
|
||||||
passing_rate:'Case Pass Rate'
|
passing_rate: 'Case Pass Rate'
|
||||||
},
|
},
|
||||||
plan: {
|
plan: {
|
||||||
test_plan: "Plan",
|
test_plan: "Plan",
|
||||||
test_plan_id:'Plan ID',
|
test_plan_id: 'Plan ID',
|
||||||
create_plan: "Create test plan",
|
create_plan: "Create test plan",
|
||||||
edit_plan: "Edit test plan",
|
edit_plan: "Edit test plan",
|
||||||
plan_name: "Name",
|
plan_name: "Name",
|
||||||
|
@ -2026,10 +2033,10 @@ export default {
|
||||||
api_case: "Api case",
|
api_case: "Api case",
|
||||||
scenario_case: "Scenario case",
|
scenario_case: "Scenario case",
|
||||||
execute_result: "Execute Result",
|
execute_result: "Execute Result",
|
||||||
execute_time:'Execute Time',
|
execute_time: 'Execute Time',
|
||||||
is_api_case_executing:"Api Case Executing",
|
is_api_case_executing: "Api Case Executing",
|
||||||
is_scenario_executing:'Scenario Executing',
|
is_scenario_executing: 'Scenario Executing',
|
||||||
is_performance_executing:'Performance Executing',
|
is_performance_executing: 'Performance Executing',
|
||||||
test_plan_test_case_count: "Track case count",
|
test_plan_test_case_count: "Track case count",
|
||||||
test_plan_api_case_count: "Api case count",
|
test_plan_api_case_count: "Api case count",
|
||||||
test_plan_api_scenario_count: "Scenario case count",
|
test_plan_api_scenario_count: "Scenario case count",
|
||||||
|
@ -2078,7 +2085,7 @@ export default {
|
||||||
comment: {
|
comment: {
|
||||||
no_comment: "No Comment",
|
no_comment: "No Comment",
|
||||||
send_comment: "Post a comment (Ctrl + Enter to send)",
|
send_comment: "Post a comment (Ctrl + Enter to send)",
|
||||||
send: "Send",
|
send: "Confirm",
|
||||||
description_is_null: "Comment content cannot be empty!",
|
description_is_null: "Comment content cannot be empty!",
|
||||||
send_success: "Comment successful!",
|
send_success: "Comment successful!",
|
||||||
},
|
},
|
||||||
|
@ -2093,7 +2100,7 @@ export default {
|
||||||
cannot_delete: "Cannot delete this comment!",
|
cannot_delete: "Cannot delete this comment!",
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
id:'Module ID',
|
id: 'Module ID',
|
||||||
search: "Search module",
|
search: "Search module",
|
||||||
rename: "Rename",
|
rename: "Rename",
|
||||||
add_submodule: "Add submodule",
|
add_submodule: "Add submodule",
|
||||||
|
@ -2136,7 +2143,7 @@ export default {
|
||||||
relevance_test_case: "Relevance case",
|
relevance_test_case: "Relevance case",
|
||||||
cancel_all_relevance: "Unlink all",
|
cancel_all_relevance: "Unlink all",
|
||||||
executor: "Executor",
|
executor: "Executor",
|
||||||
executor_match_rule:"Executor Match Rule",
|
executor_match_rule: "Executor Match Rule",
|
||||||
execute_result: "Result",
|
execute_result: "Result",
|
||||||
pass: "Pass",
|
pass: "Pass",
|
||||||
not_pass: "UnPass",
|
not_pass: "UnPass",
|
||||||
|
@ -2161,7 +2168,7 @@ export default {
|
||||||
submit_issues: "Commit issues",
|
submit_issues: "Commit issues",
|
||||||
operate_step: "Operate step",
|
operate_step: "Operate step",
|
||||||
edit_component: "Edit component",
|
edit_component: "Edit component",
|
||||||
component:"component",
|
component: "component",
|
||||||
base_info: "Base info",
|
base_info: "Base info",
|
||||||
mock_info: "Mock service",
|
mock_info: "Mock service",
|
||||||
test_result: "Test result",
|
test_result: "Test result",
|
||||||
|
@ -2194,7 +2201,7 @@ export default {
|
||||||
issue: "Issue",
|
issue: "Issue",
|
||||||
issue_management: "Issue Management",
|
issue_management: "Issue Management",
|
||||||
platform_status: "Platform Status",
|
platform_status: "Platform Status",
|
||||||
issue_resource: "Issue source",
|
issue_resource: "Issue Source",
|
||||||
create_issue: "Create Issue",
|
create_issue: "Create Issue",
|
||||||
add_issue: "Add Issue",
|
add_issue: "Add Issue",
|
||||||
issue_list: "Issue List",
|
issue_list: "Issue List",
|
||||||
|
@ -2206,7 +2213,7 @@ export default {
|
||||||
description: "Issue Describe",
|
description: "Issue Describe",
|
||||||
status: "Issue Status",
|
status: "Issue Status",
|
||||||
platform: "Platform",
|
platform: "Platform",
|
||||||
issue_project:"Project",
|
issue_project: "Project",
|
||||||
operate: "Operate",
|
operate: "Operate",
|
||||||
close: "Close",
|
close: "Close",
|
||||||
delete: "Delete",
|
delete: "Delete",
|
||||||
|
@ -2216,12 +2223,12 @@ export default {
|
||||||
status_new: 'new',
|
status_new: 'new',
|
||||||
status_resolved: 'resolved',
|
status_resolved: 'resolved',
|
||||||
status_closed: 'closed',
|
status_closed: 'closed',
|
||||||
status_active:'active',
|
status_active: 'active',
|
||||||
status_delete:'delete',
|
status_delete: 'delete',
|
||||||
status_in_progress: 'in_progress',
|
status_in_progress: 'in_progress',
|
||||||
status_rejected: 'rejected',
|
status_rejected: 'rejected',
|
||||||
status_upcoming:'upcoming',
|
status_upcoming: 'upcoming',
|
||||||
status_reopened:'reopened',
|
status_reopened: 'reopened',
|
||||||
please_choose_current_owner: "Please choose current owner",
|
please_choose_current_owner: "Please choose current owner",
|
||||||
tapd_current_owner: "Tapd Current Owner",
|
tapd_current_owner: "Tapd Current Owner",
|
||||||
zentao_bug_build: "Zentao Impact version",
|
zentao_bug_build: "Zentao Impact version",
|
||||||
|
@ -2229,7 +2236,8 @@ export default {
|
||||||
third_party_integrated: "Third-party Platform Integrated",
|
third_party_integrated: "Third-party Platform Integrated",
|
||||||
use_third_party: "Enable Jira Issue Template",
|
use_third_party: "Enable Jira Issue Template",
|
||||||
update_third_party_bugs: "Update the defects of third-party platforms",
|
update_third_party_bugs: "Update the defects of third-party platforms",
|
||||||
sync_bugs: "Synchronization Issue"
|
sync_bugs: "Synchronization Issue",
|
||||||
|
save_before_open_comment: "Please save issue before comment",
|
||||||
},
|
},
|
||||||
report: {
|
report: {
|
||||||
name: "Test Plan Report",
|
name: "Test Plan Report",
|
||||||
|
@ -2267,11 +2275,11 @@ export default {
|
||||||
issue_list: "Issue List",
|
issue_list: "Issue List",
|
||||||
all_case: "All Case",
|
all_case: "All Case",
|
||||||
},
|
},
|
||||||
reporter:'Reporter',
|
reporter: 'Reporter',
|
||||||
lastmodify:'Last Modify'
|
lastmodify: 'Last Modify'
|
||||||
},
|
},
|
||||||
test_resource_pool: {
|
test_resource_pool: {
|
||||||
id:'Resource Pool ID',
|
id: 'Resource Pool ID',
|
||||||
type: 'type',
|
type: 'type',
|
||||||
enable_disable: 'Enable / Disable',
|
enable_disable: 'Enable / Disable',
|
||||||
search_by_name: 'Search by name',
|
search_by_name: 'Search by name',
|
||||||
|
@ -2364,7 +2372,7 @@ export default {
|
||||||
task_config: "Task Config",
|
task_config: "Task Config",
|
||||||
test_name: 'Test Name',
|
test_name: 'Test Name',
|
||||||
running_rule: 'Rule',
|
running_rule: 'Rule',
|
||||||
job:'Job',
|
job: 'Job',
|
||||||
job_status: 'Status',
|
job_status: 'Status',
|
||||||
running_task: 'Running Task',
|
running_task: 'Running Task',
|
||||||
please_input_cron_expression: "Please Input Cron Expression",
|
please_input_cron_expression: "Please Input Cron Expression",
|
||||||
|
@ -2497,7 +2505,7 @@ export default {
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
title: 'Module Management',
|
title: 'Module Management',
|
||||||
path:'Module Path'
|
path: 'Module Path'
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
header_display_field: 'Header display field',
|
header_display_field: 'Header display field',
|
||||||
|
@ -2534,7 +2542,7 @@ export default {
|
||||||
script_entry: "Script execution entry",
|
script_entry: "Script execution entry",
|
||||||
plugin_id: "Plug-in Id",
|
plugin_id: "Plug-in Id",
|
||||||
script_view: "View script",
|
script_view: "View script",
|
||||||
warning_tip:'Script content not found'
|
warning_tip: 'Script content not found'
|
||||||
},
|
},
|
||||||
mail: {
|
mail: {
|
||||||
input_mail_subject: "Please input subject",
|
input_mail_subject: "Please input subject",
|
||||||
|
|
|
@ -7,9 +7,11 @@ export default {
|
||||||
yes: "是",
|
yes: "是",
|
||||||
no: "否",
|
no: "否",
|
||||||
example: "示例",
|
example: "示例",
|
||||||
|
subject: "主题",
|
||||||
excelFile: "表格文件.xls",
|
excelFile: "表格文件.xls",
|
||||||
xmindFile: "思维导图.xmind",
|
xmindFile: "思维导图.xmind",
|
||||||
default: "默认值",
|
default: "默认值",
|
||||||
|
sort_default: "默认排序",
|
||||||
please_select_import_mode: '请选择导入模式',
|
please_select_import_mode: '请选择导入模式',
|
||||||
please_select_import_module: '请选择导入模块',
|
please_select_import_module: '请选择导入模块',
|
||||||
pass_rate: '通过率',
|
pass_rate: '通过率',
|
||||||
|
@ -326,6 +328,11 @@ export default {
|
||||||
send: "发送",
|
send: "发送",
|
||||||
save_as_draft: "保存草稿",
|
save_as_draft: "保存草稿",
|
||||||
},
|
},
|
||||||
|
table: {
|
||||||
|
draft: "草稿箱",
|
||||||
|
sended: "已发送",
|
||||||
|
send_error: "发送失败",
|
||||||
|
},
|
||||||
project_report: {
|
project_report: {
|
||||||
create_report: "创建报告",
|
create_report: "创建报告",
|
||||||
report_name: "报告名称",
|
report_name: "报告名称",
|
||||||
|
@ -2082,7 +2089,7 @@ export default {
|
||||||
comment: {
|
comment: {
|
||||||
no_comment: "暂无评论",
|
no_comment: "暂无评论",
|
||||||
send_comment: "发表评论(Ctrl+Enter发送)",
|
send_comment: "发表评论(Ctrl+Enter发送)",
|
||||||
send: "发送",
|
send: "确定",
|
||||||
description_is_null: "评论内容不能为空!",
|
description_is_null: "评论内容不能为空!",
|
||||||
send_success: "评论成功!",
|
send_success: "评论成功!",
|
||||||
cannot_edit: "无法编辑此评论!",
|
cannot_edit: "无法编辑此评论!",
|
||||||
|
@ -2233,7 +2240,8 @@ export default {
|
||||||
third_party_integrated: "集成第三方平台",
|
third_party_integrated: "集成第三方平台",
|
||||||
use_third_party: "使用 Jira 缺陷模板",
|
use_third_party: "使用 Jira 缺陷模板",
|
||||||
update_third_party_bugs: "更新第三方平台的缺陷",
|
update_third_party_bugs: "更新第三方平台的缺陷",
|
||||||
sync_bugs: "同步缺陷"
|
sync_bugs: "同步缺陷",
|
||||||
|
save_before_open_comment: "请先保存缺陷再添加评论",
|
||||||
},
|
},
|
||||||
report: {
|
report: {
|
||||||
name: "测试计划报告",
|
name: "测试计划报告",
|
||||||
|
|
|
@ -7,9 +7,11 @@ export default {
|
||||||
yes: "是",
|
yes: "是",
|
||||||
no: "否",
|
no: "否",
|
||||||
example: "示例",
|
example: "示例",
|
||||||
|
subject: "主題",
|
||||||
excelFile: "表格文件.xls",
|
excelFile: "表格文件.xls",
|
||||||
xmindFile: "思維導圖.xmind",
|
xmindFile: "思維導圖.xmind",
|
||||||
default: "默認值",
|
default: "默認值",
|
||||||
|
sort_default: "默認排序",
|
||||||
please_select_import_mode: '請選擇導入模式',
|
please_select_import_mode: '請選擇導入模式',
|
||||||
please_select_import_module: '請選擇導入模塊',
|
please_select_import_module: '請選擇導入模塊',
|
||||||
pass_rate: '通過率',
|
pass_rate: '通過率',
|
||||||
|
@ -326,6 +328,11 @@ export default {
|
||||||
send: "發送",
|
send: "發送",
|
||||||
save_as_draft: "保存草稿",
|
save_as_draft: "保存草稿",
|
||||||
},
|
},
|
||||||
|
table: {
|
||||||
|
draft: "草稿箱",
|
||||||
|
sended: "已發送",
|
||||||
|
send_error: "發送失敗",
|
||||||
|
},
|
||||||
project_report: {
|
project_report: {
|
||||||
create_report: "創建報告",
|
create_report: "創建報告",
|
||||||
report_name: "報告名稱",
|
report_name: "報告名稱",
|
||||||
|
@ -2082,7 +2089,7 @@ export default {
|
||||||
comment: {
|
comment: {
|
||||||
no_comment: "暫無評論",
|
no_comment: "暫無評論",
|
||||||
send_comment: "發表評論(Ctrl+Enter發送)",
|
send_comment: "發表評論(Ctrl+Enter發送)",
|
||||||
send: "發送",
|
send: "確定",
|
||||||
description_is_null: "評論內容不能為空!",
|
description_is_null: "評論內容不能為空!",
|
||||||
send_success: "評論成功!",
|
send_success: "評論成功!",
|
||||||
cannot_edit: "無法編輯此評論!",
|
cannot_edit: "無法編輯此評論!",
|
||||||
|
@ -2233,7 +2240,8 @@ export default {
|
||||||
third_party_integrated: "集成第三方平臺",
|
third_party_integrated: "集成第三方平臺",
|
||||||
use_third_party: "使用 Jira 缺陷模板",
|
use_third_party: "使用 Jira 缺陷模板",
|
||||||
update_third_party_bugs: "更新第三方平臺的缺陷",
|
update_third_party_bugs: "更新第三方平臺的缺陷",
|
||||||
sync_bugs: "同步缺陷"
|
sync_bugs: "同步缺陷",
|
||||||
|
save_before_open_comment: "請先保存缺陷再添加評論",
|
||||||
},
|
},
|
||||||
report: {
|
report: {
|
||||||
name: "測試計劃報告",
|
name: "測試計劃報告",
|
||||||
|
|
|
@ -37,6 +37,19 @@ export function getIssuesById(id, callback) {
|
||||||
return id ? baseGet('/issues/get/' + id, callback) : {};
|
return id ? baseGet('/issues/get/' + id, callback) : {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getIssuesListById(id,projectId,workspaceId,callback) {
|
||||||
|
let condition ={
|
||||||
|
id:id,
|
||||||
|
projectId : projectId,
|
||||||
|
workspaceId: workspaceId
|
||||||
|
};
|
||||||
|
return post('issues/list/' + 1 + '/' + 10, condition, (response) => {
|
||||||
|
if (callback) {
|
||||||
|
callback(response.data.listObject[0]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function getIssuesByPlanId(planId, callback) {
|
export function getIssuesByPlanId(planId, callback) {
|
||||||
return planId ? baseGet('/issues/plan/get/' + planId, callback) : {};
|
return planId ? baseGet('/issues/plan/get/' + planId, callback) : {};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue