Merge branch 'master' into v1.7
This commit is contained in:
commit
90d8161b5e
|
@ -158,7 +158,8 @@ public class MsHTTPSamplerProxy extends MsTestElement {
|
||||||
if (!path.startsWith("/")) {
|
if (!path.startsWith("/")) {
|
||||||
path = "/" + path;
|
path = "/" + path;
|
||||||
}
|
}
|
||||||
path = sampler.getProtocol() + "://" + sampler.getDomain() + ":" + sampler.getPort() + path;
|
String port = sampler.getPort() != 80 ? ":" + sampler.getPort() : "";
|
||||||
|
path = sampler.getProtocol() + "://" + sampler.getDomain() + port + path;
|
||||||
}
|
}
|
||||||
sampler.setPath(path);
|
sampler.setPath(path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import org.apache.jmeter.testelement.TestElement;
|
||||||
import org.apache.jorphan.collections.HashTree;
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ -51,7 +50,7 @@ public class MsJDBCSampler extends MsTestElement {
|
||||||
@JSONField(ordinal = 28)
|
@JSONField(ordinal = 28)
|
||||||
private String dataSourceId;
|
private String dataSourceId;
|
||||||
@JSONField(ordinal = 29)
|
@JSONField(ordinal = 29)
|
||||||
private String protocol="SQL";
|
private String protocol = "SQL";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||||
|
@ -62,7 +61,8 @@ public class MsJDBCSampler extends MsTestElement {
|
||||||
this.getRefElement(this);
|
this.getRefElement(this);
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotEmpty(dataSourceId)) {
|
if (StringUtils.isNotEmpty(dataSourceId)) {
|
||||||
initDataSource();
|
this.dataSource = null;
|
||||||
|
this.initDataSource();
|
||||||
}
|
}
|
||||||
if (this.dataSource == null) {
|
if (this.dataSource == null) {
|
||||||
MSException.throwException("数据源为空无法执行");
|
MSException.throwException("数据源为空无法执行");
|
||||||
|
@ -79,14 +79,16 @@ public class MsJDBCSampler extends MsTestElement {
|
||||||
|
|
||||||
private void initDataSource() {
|
private void initDataSource() {
|
||||||
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
|
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
|
||||||
ApiTestEnvironmentWithBLOBs environment = environmentService.get(this.dataSourceId);
|
ApiTestEnvironmentWithBLOBs environment = environmentService.get(environmentId);
|
||||||
if (environment != null && environment.getConfig() != null) {
|
if (environment != null && environment.getConfig() != null) {
|
||||||
EnvironmentConfig config = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class);
|
EnvironmentConfig envConfig = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class);
|
||||||
if (CollectionUtils.isNotEmpty(config.getDatabaseConfigs())) {
|
if (CollectionUtils.isNotEmpty(envConfig.getDatabaseConfigs())) {
|
||||||
List<DatabaseConfig> databaseConfigs = config.getDatabaseConfigs().stream().filter((DatabaseConfig d) -> this.dataSourceId.equals(d.getId())).collect(Collectors.toList());
|
envConfig.getDatabaseConfigs().forEach(item -> {
|
||||||
if (CollectionUtils.isNotEmpty(databaseConfigs)) {
|
if (item.getId().equals(this.dataSourceId)) {
|
||||||
this.dataSource = databaseConfigs.get(0);
|
this.dataSource = item;
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,12 +227,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
LogUtil.error(e.getMessage(), e);
|
LogUtil.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
sendTask(report, reportUrl, testResult);
|
sendTask(report, reportUrl, testResult);
|
||||||
} catch (Exception e) {
|
|
||||||
LogUtil.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void sendTask(ApiTestReport report, String reportUrl, TestResult testResult) {
|
private static void sendTask(ApiTestReport report, String reportUrl, TestResult testResult) {
|
||||||
|
@ -297,6 +292,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
requestResult.setHeaders(result.getRequestHeaders());
|
requestResult.setHeaders(result.getRequestHeaders());
|
||||||
requestResult.setRequestSize(result.getSentBytes());
|
requestResult.setRequestSize(result.getSentBytes());
|
||||||
requestResult.setStartTime(result.getStartTime());
|
requestResult.setStartTime(result.getStartTime());
|
||||||
|
requestResult.setEndTime(result.getEndTime());
|
||||||
requestResult.setTotalAssertions(result.getAssertionResults().length);
|
requestResult.setTotalAssertions(result.getAssertionResults().length);
|
||||||
requestResult.setSuccess(result.isSuccessful());
|
requestResult.setSuccess(result.isSuccessful());
|
||||||
requestResult.setError(result.getErrorCount());
|
requestResult.setError(result.getErrorCount());
|
||||||
|
@ -336,7 +332,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
requestResult.addPassAssertions();
|
requestResult.addPassAssertions();
|
||||||
}
|
}
|
||||||
//xpath 提取错误会添加断言错误
|
//xpath 提取错误会添加断言错误
|
||||||
if (StringUtils.isBlank(responseAssertionResult.getMessage()) || !responseAssertionResult.getMessage().contains("The required item type of the first operand of")) {
|
if (StringUtils.isBlank(responseAssertionResult.getMessage()) || !responseAssertionResult.getName().endsWith("XPath2Extractor")) {
|
||||||
responseResult.getAssertions().add(responseAssertionResult);
|
responseResult.getAssertions().add(responseAssertionResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ public class RequestResult {
|
||||||
|
|
||||||
private long startTime;
|
private long startTime;
|
||||||
|
|
||||||
|
private long endTime;
|
||||||
|
|
||||||
private int error;
|
private int error;
|
||||||
|
|
||||||
private boolean success;
|
private boolean success;
|
||||||
|
|
|
@ -217,7 +217,7 @@ public class ApiAutomationService {
|
||||||
ids.add(scenarioId);
|
ids.add(scenarioId);
|
||||||
deleteApiScenarioReport(ids);
|
deleteApiScenarioReport(ids);
|
||||||
|
|
||||||
scheduleService.deleteByResourceId(scenarioId);
|
scheduleService.deleteScheduleAndJobByResourceId(scenarioId,ScheduleGroup.API_SCENARIO_TEST.name());
|
||||||
TestPlanApiScenarioExample example = new TestPlanApiScenarioExample();
|
TestPlanApiScenarioExample example = new TestPlanApiScenarioExample();
|
||||||
example.createCriteria().andApiScenarioIdEqualTo(scenarioId);
|
example.createCriteria().andApiScenarioIdEqualTo(scenarioId);
|
||||||
List<TestPlanApiScenario> testPlanApiScenarioList = testPlanApiScenarioMapper.selectByExample(example);
|
List<TestPlanApiScenario> testPlanApiScenarioList = testPlanApiScenarioMapper.selectByExample(example);
|
||||||
|
@ -282,6 +282,10 @@ public class ApiAutomationService {
|
||||||
|
|
||||||
public void removeToGc(List<String> apiIds) {
|
public void removeToGc(List<String> apiIds) {
|
||||||
extApiScenarioMapper.removeToGc(apiIds);
|
extApiScenarioMapper.removeToGc(apiIds);
|
||||||
|
//将这些场景的定时任务删除掉
|
||||||
|
for (String id : apiIds) {
|
||||||
|
scheduleService.deleteScheduleAndJobByResourceId(id,ScheduleGroup.API_SCENARIO_TEST.name());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reduction(List<SaveApiScenarioRequest> requests) {
|
public void reduction(List<SaveApiScenarioRequest> requests) {
|
||||||
|
|
|
@ -323,7 +323,9 @@ public class ApiDefinitionService {
|
||||||
apiDefinitionMapper.updateByPrimaryKeyWithBLOBs(apiDefinition);
|
apiDefinitionMapper.updateByPrimaryKeyWithBLOBs(apiDefinition);
|
||||||
}
|
}
|
||||||
} else if (StringUtils.equals("incrementalMerge", apiTestImportRequest.getModeId())) {
|
} else if (StringUtils.equals("incrementalMerge", apiTestImportRequest.getModeId())) {
|
||||||
batchMapper.insert(apiDefinition);
|
if (CollectionUtils.isEmpty(sameRequest)) {
|
||||||
|
batchMapper.insert(apiDefinition);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (CollectionUtils.isEmpty(sameRequest)) {
|
if (CollectionUtils.isEmpty(sameRequest)) {
|
||||||
batchMapper.insert(apiDefinition);
|
batchMapper.insert(apiDefinition);
|
||||||
|
|
|
@ -163,6 +163,7 @@ public class ApiScenarioReportService {
|
||||||
String passRate = new DecimalFormat("0%").format((float) scenarioResult.getSuccess() / (scenarioResult.getSuccess() + scenarioResult.getError()));
|
String passRate = new DecimalFormat("0%").format((float) scenarioResult.getSuccess() / (scenarioResult.getSuccess() + scenarioResult.getError()));
|
||||||
testPlanApiScenario.setPassRate(passRate);
|
testPlanApiScenario.setPassRate(passRate);
|
||||||
testPlanApiScenario.setReportId(report.getId());
|
testPlanApiScenario.setReportId(report.getId());
|
||||||
|
testPlanApiScenario.setUpdateTime(System.currentTimeMillis());
|
||||||
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
|
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
|
||||||
}
|
}
|
||||||
returnReport = report;
|
returnReport = report;
|
||||||
|
@ -220,6 +221,7 @@ public class ApiScenarioReportService {
|
||||||
apiScenarioReportDetailMapper.insert(detail);
|
apiScenarioReportDetailMapper.insert(detail);
|
||||||
|
|
||||||
testPlanApiScenario.setReportId(report.getId());
|
testPlanApiScenario.setReportId(report.getId());
|
||||||
|
testPlanApiScenario.setUpdateTime(System.currentTimeMillis());
|
||||||
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
|
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
|
||||||
|
|
||||||
lastReport = report;
|
lastReport = report;
|
||||||
|
@ -343,13 +345,41 @@ public class ApiScenarioReportService {
|
||||||
ids = allIds.stream().filter(id -> !reportRequest.getUnSelectIds().contains(id)).collect(Collectors.toList());
|
ids = allIds.stream().filter(id -> !reportRequest.getUnSelectIds().contains(id)).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiScenarioReportDetailExample detailExample = new ApiScenarioReportDetailExample();
|
//为预防数量太多,调用删除方法时引起SQL过长的Bug,此处采取分批执行的方式。
|
||||||
detailExample.createCriteria().andReportIdIn(ids);
|
//每次处理的数据数量
|
||||||
apiScenarioReportDetailMapper.deleteByExample(detailExample);
|
int handleCount = 7000;
|
||||||
|
//每次处理的集合
|
||||||
|
List<String> handleIdList = new ArrayList<>(handleCount);
|
||||||
|
while (ids.size() > handleCount){
|
||||||
|
handleIdList = new ArrayList<>(handleCount);
|
||||||
|
List<String> otherIdList = new ArrayList<>();
|
||||||
|
for (int index = 0;index < ids.size();index++){
|
||||||
|
if(index<handleCount){
|
||||||
|
handleIdList.add(ids.get(index));
|
||||||
|
}else{
|
||||||
|
otherIdList.add(ids.get(index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//处理本次的数据
|
||||||
|
ApiScenarioReportDetailExample detailExample = new ApiScenarioReportDetailExample();
|
||||||
|
detailExample.createCriteria().andReportIdIn(handleIdList);
|
||||||
|
apiScenarioReportDetailMapper.deleteByExample(detailExample);
|
||||||
|
ApiScenarioReportExample apiTestReportExample = new ApiScenarioReportExample();
|
||||||
|
apiTestReportExample.createCriteria().andIdIn(handleIdList);
|
||||||
|
apiScenarioReportMapper.deleteByExample(apiTestReportExample);
|
||||||
|
//转存剩余的数据
|
||||||
|
ids = otherIdList;
|
||||||
|
}
|
||||||
|
|
||||||
ApiScenarioReportExample apiTestReportExample = new ApiScenarioReportExample();
|
//处理最后剩余的数据
|
||||||
apiTestReportExample.createCriteria().andIdIn(ids);
|
if(!ids.isEmpty()){
|
||||||
apiScenarioReportMapper.deleteByExample(apiTestReportExample);
|
ApiScenarioReportDetailExample detailExample = new ApiScenarioReportDetailExample();
|
||||||
|
detailExample.createCriteria().andReportIdIn(ids);
|
||||||
|
apiScenarioReportDetailMapper.deleteByExample(detailExample);
|
||||||
|
ApiScenarioReportExample apiTestReportExample = new ApiScenarioReportExample();
|
||||||
|
apiTestReportExample.createCriteria().andIdIn(ids);
|
||||||
|
apiScenarioReportMapper.deleteByExample(apiTestReportExample);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long countByProjectID(String projectId) {
|
public long countByProjectID(String projectId) {
|
||||||
|
|
|
@ -134,7 +134,9 @@ public class HistoricalDataUpgradeService {
|
||||||
request1.getBody().setType(Body.FORM_DATA);
|
request1.getBody().setType(Body.FORM_DATA);
|
||||||
}
|
}
|
||||||
if ("json".equals(request1.getBody().getFormat())) {
|
if ("json".equals(request1.getBody().getFormat())) {
|
||||||
request1.getBody().setType(Body.JSON);
|
if ("Raw".equals(request1.getBody().getType())) {
|
||||||
|
request1.getBody().setType(Body.JSON);
|
||||||
|
}
|
||||||
if (CollectionUtils.isEmpty(request1.getHeaders())) {
|
if (CollectionUtils.isEmpty(request1.getHeaders())) {
|
||||||
List<KeyValue> headers = new LinkedList<>();
|
List<KeyValue> headers = new LinkedList<>();
|
||||||
headers.add(new KeyValue("Content-Type", "application/json"));
|
headers.add(new KeyValue("Content-Type", "application/json"));
|
||||||
|
|
|
@ -33,5 +33,4 @@ public interface ScheduleMapper {
|
||||||
int updateByPrimaryKeyWithBLOBs(Schedule record);
|
int updateByPrimaryKeyWithBLOBs(Schedule record);
|
||||||
|
|
||||||
int updateByPrimaryKey(Schedule record);
|
int updateByPrimaryKey(Schedule record);
|
||||||
|
|
||||||
}
|
}
|
|
@ -219,7 +219,8 @@
|
||||||
</if>
|
</if>
|
||||||
<if test="request.name != null">
|
<if test="request.name != null">
|
||||||
and (api_definition.name like CONCAT('%', #{request.name},'%')
|
and (api_definition.name like CONCAT('%', #{request.name},'%')
|
||||||
or api_definition.tags like CONCAT('%', #{request.name},'%'))
|
or api_definition.tags like CONCAT('%', #{request.name},'%')
|
||||||
|
or api_definition.num like CONCAT('%', #{request.name},'%'))
|
||||||
</if>
|
</if>
|
||||||
<if test="request.protocol != null">
|
<if test="request.protocol != null">
|
||||||
AND api_definition.protocol = #{request.protocol}
|
AND api_definition.protocol = #{request.protocol}
|
||||||
|
|
|
@ -143,7 +143,9 @@
|
||||||
</if>
|
</if>
|
||||||
|
|
||||||
<if test="request.name != null">
|
<if test="request.name != null">
|
||||||
and (api_scenario.name like CONCAT('%', #{request.name},'%') or api_scenario.tags like CONCAT('%', #{request.name},'%'))
|
and (api_scenario.name like CONCAT('%', #{request.name},'%')
|
||||||
|
or api_scenario.tags like CONCAT('%', #{request.name},'%')
|
||||||
|
or api_scenario.num like CONCAT('%', #{request.name},'%'))
|
||||||
</if>
|
</if>
|
||||||
<if test="request.workspaceId != null">
|
<if test="request.workspaceId != null">
|
||||||
AND project.workspace_id = #{request.workspaceId}
|
AND project.workspace_id = #{request.workspaceId}
|
||||||
|
|
|
@ -284,7 +284,9 @@
|
||||||
</foreach>
|
</foreach>
|
||||||
</if>
|
</if>
|
||||||
<if test="request.name != null and request.name!=''">
|
<if test="request.name != null and request.name!=''">
|
||||||
and (t1.name like CONCAT('%', #{request.name},'%') or t1.tags like CONCAT('%', #{request.name},'%'))
|
and (t1.name like CONCAT('%', #{request.name},'%')
|
||||||
|
or t1.tags like CONCAT('%', #{request.name},'%')
|
||||||
|
or t1.num like CONCAT('%', #{request.name},'%'))
|
||||||
</if>
|
</if>
|
||||||
<if test="request.createTime > 0">
|
<if test="request.createTime > 0">
|
||||||
and t1.create_time >= #{request.createTime}
|
and t1.create_time >= #{request.createTime}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
select
|
select
|
||||||
t.id, t.environment_id, t.create_time, t.update_time, t.last_result, t.pass_rate, t.report_id,
|
t.id, t.environment_id, t.create_time, t.update_time, t.last_result, t.pass_rate, t.report_id,
|
||||||
c.id as case_id, c.project_id, c.user_id,c.api_scenario_module_id, c.module_path, c.name, c.level,
|
c.id as case_id, c.project_id, c.user_id,c.api_scenario_module_id, c.module_path, c.name, c.level,
|
||||||
c.status, c.principal, c.step_total, c.follow_people, c.schedule, c.description,
|
c.status, c.principal, c.step_total, c.follow_people, c.schedule, c.description, c.tags, c.num,
|
||||||
p.name as project_name, p.id as project_id, u.name as user_name
|
p.name as project_name, p.id as project_id, u.name as user_name
|
||||||
from
|
from
|
||||||
test_plan_api_scenario t
|
test_plan_api_scenario t
|
||||||
|
@ -44,7 +44,9 @@
|
||||||
</foreach>
|
</foreach>
|
||||||
</if>
|
</if>
|
||||||
<if test="request.name != null and request.name!=''">
|
<if test="request.name != null and request.name!=''">
|
||||||
and c.name like CONCAT('%', #{request.name},'%')
|
and (c.name like CONCAT('%', #{request.name},'%')
|
||||||
|
or c.num like CONCAT('%', #{request.name},'%')
|
||||||
|
or c.tags like CONCAT('%', #{request.name},'%'))
|
||||||
</if>
|
</if>
|
||||||
<if test="request.status != null and request.status!=''">
|
<if test="request.status != null and request.status!=''">
|
||||||
and t.last_result like CONCAT('%', #{request.status},'%')
|
and t.last_result like CONCAT('%', #{request.status},'%')
|
||||||
|
|
|
@ -122,7 +122,7 @@
|
||||||
|
|
||||||
<select id="list" resultType="io.metersphere.track.dto.TestPlanCaseDTO">
|
<select id="list" resultType="io.metersphere.track.dto.TestPlanCaseDTO">
|
||||||
select test_plan_test_case.id as id, test_case.id as caseId, test_case.name, test_case.priority,
|
select test_plan_test_case.id as id, test_case.id as caseId, test_case.name, test_case.priority,
|
||||||
test_case.type,test_case.test_id as testId,test_case.node_id,
|
test_case.type,test_case.test_id as testId,test_case.node_id, test_case.tags,
|
||||||
test_case.node_path, test_case.method, test_case.num, test_plan_test_case.executor, test_plan_test_case.status,
|
test_case.node_path, test_case.method, test_case.num, test_plan_test_case.executor, test_plan_test_case.status,
|
||||||
test_plan_test_case.update_time, test_case_node.name as model, project.name as projectName,
|
test_plan_test_case.update_time, test_case_node.name as model, project.name as projectName,
|
||||||
test_plan_test_case.plan_id as planId
|
test_plan_test_case.plan_id as planId
|
||||||
|
@ -139,7 +139,7 @@
|
||||||
</if>
|
</if>
|
||||||
<if test="request.name != null">
|
<if test="request.name != null">
|
||||||
and (test_case.name like CONCAT('%', #{request.name},'%') or test_case.num like
|
and (test_case.name like CONCAT('%', #{request.name},'%') or test_case.num like
|
||||||
CONCAT('%',#{request.name},'%'))
|
CONCAT('%',#{request.name},'%') or test_case.tags like CONCAT('%', #{request.name},'%'))
|
||||||
</if>
|
</if>
|
||||||
<if test="request.id != null">
|
<if test="request.id != null">
|
||||||
and test_case.id = #{request.id}
|
and test_case.id = #{request.id}
|
||||||
|
|
|
@ -28,6 +28,7 @@ public class ShiroUtils {
|
||||||
filterChainDefinitionMap.put("/authsource/list/allenable", "anon");
|
filterChainDefinitionMap.put("/authsource/list/allenable", "anon");
|
||||||
filterChainDefinitionMap.put("/sso/signin", "anon");
|
filterChainDefinitionMap.put("/sso/signin", "anon");
|
||||||
filterChainDefinitionMap.put("/sso/callback", "anon");
|
filterChainDefinitionMap.put("/sso/callback", "anon");
|
||||||
|
filterChainDefinitionMap.put("/license/valid", "anon");
|
||||||
|
|
||||||
// for swagger
|
// for swagger
|
||||||
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
|
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
|
||||||
|
|
|
@ -105,25 +105,27 @@ public class TestPlanTestJob extends MsScheduleJob {
|
||||||
//需要更新这里来保证PlanCase的状态能正常更改
|
//需要更新这里来保证PlanCase的状态能正常更改
|
||||||
apiTestCaseService.run(blobs,UUID.randomUUID().toString(),testPlanReport.getId(),this.resourceId,ApiRunMode.SCHEDULE_API_PLAN.name());
|
apiTestCaseService.run(blobs,UUID.randomUUID().toString(),testPlanReport.getId(),this.resourceId,ApiRunMode.SCHEDULE_API_PLAN.name());
|
||||||
}
|
}
|
||||||
LogUtil.info("-------------- testplan schedule ---------- api case over -----------------");
|
|
||||||
//执行场景执行任务
|
|
||||||
SchedulePlanScenarioExecuteRequest scenarioRequest = new SchedulePlanScenarioExecuteRequest();
|
|
||||||
String senarionReportID = UUID.randomUUID().toString();
|
|
||||||
scenarioRequest.setId(senarionReportID);
|
|
||||||
scenarioRequest.setReportId(senarionReportID);
|
|
||||||
scenarioRequest.setProjectId(projectID);
|
|
||||||
scenarioRequest.setTriggerMode(ReportTriggerMode.SCHEDULE.name());
|
|
||||||
scenarioRequest.setExecuteType(ExecuteType.Saved.name());
|
|
||||||
Map<String, Map<String,String>> testPlanScenarioIdMap = new HashMap<>();
|
|
||||||
testPlanScenarioIdMap.put(resourceId, this.planScenarioIdMap);
|
|
||||||
scenarioRequest.setTestPlanScenarioIDMap(testPlanScenarioIdMap);
|
|
||||||
scenarioRequest.setReportUserID(this.userId);
|
|
||||||
scenarioRequest.setTestPlanID(this.resourceId);
|
|
||||||
scenarioRequest.setRunMode(ApiRunMode.SCHEDULE_SCENARIO_PLAN.name());
|
|
||||||
scenarioRequest.setTestPlanReportId(testPlanReport.getId());
|
|
||||||
testPlanService.runScenarioCase(scenarioRequest);
|
|
||||||
LogUtil.info("-------------- testplan schedule ---------- scenario case over -----------------");
|
|
||||||
|
|
||||||
|
//执行场景执行任务
|
||||||
|
if(!planScenarioIdMap.isEmpty()){
|
||||||
|
LogUtil.info("-------------- testplan schedule ---------- api case over -----------------");
|
||||||
|
SchedulePlanScenarioExecuteRequest scenarioRequest = new SchedulePlanScenarioExecuteRequest();
|
||||||
|
String senarionReportID = UUID.randomUUID().toString();
|
||||||
|
scenarioRequest.setId(senarionReportID);
|
||||||
|
scenarioRequest.setReportId(senarionReportID);
|
||||||
|
scenarioRequest.setProjectId(projectID);
|
||||||
|
scenarioRequest.setTriggerMode(ReportTriggerMode.SCHEDULE.name());
|
||||||
|
scenarioRequest.setExecuteType(ExecuteType.Saved.name());
|
||||||
|
Map<String, Map<String,String>> testPlanScenarioIdMap = new HashMap<>();
|
||||||
|
testPlanScenarioIdMap.put(resourceId, this.planScenarioIdMap);
|
||||||
|
scenarioRequest.setTestPlanScenarioIDMap(testPlanScenarioIdMap);
|
||||||
|
scenarioRequest.setReportUserID(this.userId);
|
||||||
|
scenarioRequest.setTestPlanID(this.resourceId);
|
||||||
|
scenarioRequest.setRunMode(ApiRunMode.SCHEDULE_SCENARIO_PLAN.name());
|
||||||
|
scenarioRequest.setTestPlanReportId(testPlanReport.getId());
|
||||||
|
testPlanService.runScenarioCase(scenarioRequest);
|
||||||
|
LogUtil.info("-------------- testplan schedule ---------- scenario case over -----------------");
|
||||||
|
}
|
||||||
//执行性能测试任务
|
//执行性能测试任务
|
||||||
List<String> performaneReportIDList = new ArrayList<>();
|
List<String> performaneReportIDList = new ArrayList<>();
|
||||||
for (Map.Entry<String,String> entry: this.performanceIdMap.entrySet()) {
|
for (Map.Entry<String,String> entry: this.performanceIdMap.entrySet()) {
|
||||||
|
|
|
@ -20,10 +20,13 @@ public class MailNoticeSender extends AbstractNoticeSender {
|
||||||
private MailService mailService;
|
private MailService mailService;
|
||||||
|
|
||||||
private void sendMail(MessageDetail messageDetail, String context, NoticeModel noticeModel) throws MessagingException {
|
private void sendMail(MessageDetail messageDetail, String context, NoticeModel noticeModel) throws MessagingException {
|
||||||
|
LogUtil.info("发送邮件开始 ");
|
||||||
JavaMailSenderImpl javaMailSender = mailService.getMailSender();
|
JavaMailSenderImpl javaMailSender = mailService.getMailSender();
|
||||||
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
|
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
|
||||||
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
|
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
|
||||||
helper.setFrom(javaMailSender.getUsername());
|
helper.setFrom(javaMailSender.getUsername());
|
||||||
|
LogUtil.info("发件人地址"+javaMailSender.getUsername());
|
||||||
|
LogUtil.info("helper"+helper);
|
||||||
helper.setSubject("MeterSphere " + noticeModel.getSubject());
|
helper.setSubject("MeterSphere " + noticeModel.getSubject());
|
||||||
List<String> emails = super.getUserEmails(messageDetail.getUserIds());
|
List<String> emails = super.getUserEmails(messageDetail.getUserIds());
|
||||||
String[] users = emails.toArray(new String[0]);
|
String[] users = emails.toArray(new String[0]);
|
||||||
|
@ -38,6 +41,7 @@ public class MailNoticeSender extends AbstractNoticeSender {
|
||||||
String context = super.getHtmlContext(messageDetail, noticeModel);
|
String context = super.getHtmlContext(messageDetail, noticeModel);
|
||||||
try {
|
try {
|
||||||
sendMail(messageDetail, context, noticeModel);
|
sendMail(messageDetail, context, noticeModel);
|
||||||
|
LogUtil.info("发送邮件结束");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtil.error(e);
|
LogUtil.error(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,14 +53,14 @@ public class MailService {
|
||||||
props.put("mail.smtp.starttls.enable", result);
|
props.put("mail.smtp.starttls.enable", result);
|
||||||
props.put("mail.smtp.starttls.required", result);
|
props.put("mail.smtp.starttls.required", result);
|
||||||
break;
|
break;
|
||||||
case "smtp.anon":
|
/* case "smtp.anon":
|
||||||
boolean isAnon = BooleanUtils.toBoolean(p.getParamValue());
|
boolean isAnon = BooleanUtils.toBoolean(p.getParamValue());
|
||||||
if (isAnon) {
|
if (isAnon) {
|
||||||
props.put("mail.smtp.auth", "false");
|
props.put("mail.smtp.auth", "false");
|
||||||
javaMailSender.setUsername(null);
|
javaMailSender.setUsername(null);
|
||||||
javaMailSender.setPassword(null);
|
javaMailSender.setPassword(null);
|
||||||
}
|
}
|
||||||
break;
|
break;*/
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,7 @@ import io.metersphere.commons.utils.SessionUtils;
|
||||||
import io.metersphere.controller.request.OrderRequest;
|
import io.metersphere.controller.request.OrderRequest;
|
||||||
import io.metersphere.controller.request.QueryScheduleRequest;
|
import io.metersphere.controller.request.QueryScheduleRequest;
|
||||||
import io.metersphere.dto.ScheduleDao;
|
import io.metersphere.dto.ScheduleDao;
|
||||||
import io.metersphere.job.sechedule.ApiScenarioTestJob;
|
import io.metersphere.job.sechedule.*;
|
||||||
import io.metersphere.job.sechedule.ApiTestJob;
|
|
||||||
import io.metersphere.job.sechedule.ScheduleManager;
|
|
||||||
import io.metersphere.job.sechedule.TestPlanTestJob;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.quartz.JobKey;
|
import org.quartz.JobKey;
|
||||||
import org.quartz.SchedulerException;
|
import org.quartz.SchedulerException;
|
||||||
|
@ -98,6 +95,25 @@ public class ScheduleService {
|
||||||
return scheduleMapper.deleteByExample(scheduleExample);
|
return scheduleMapper.deleteByExample(scheduleExample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int deleteScheduleAndJobByResourceId(String resourceId,String group) {
|
||||||
|
ScheduleExample scheduleExample = new ScheduleExample();
|
||||||
|
scheduleExample.createCriteria().andResourceIdEqualTo(resourceId);
|
||||||
|
removeJob(resourceId,group);
|
||||||
|
return scheduleMapper.deleteByExample(scheduleExample);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeJob(String resourceId,String group) {
|
||||||
|
if(StringUtils.equals(ScheduleGroup.API_SCENARIO_TEST.name(),group)){
|
||||||
|
scheduleManager.removeJob(ApiScenarioTestJob.getJobKey(resourceId), ApiScenarioTestJob.getTriggerKey(resourceId));
|
||||||
|
}else if(StringUtils.equals(ScheduleGroup.TEST_PLAN_TEST.name(),group)){
|
||||||
|
scheduleManager.removeJob(TestPlanTestJob.getJobKey(resourceId), TestPlanTestJob.getTriggerKey(resourceId));
|
||||||
|
}else if(StringUtils.equals(ScheduleGroup.SWAGGER_IMPORT.name(),group)){
|
||||||
|
scheduleManager.removeJob(SwaggerUrlImportJob.getJobKey(resourceId), SwaggerUrlImportJob.getTriggerKey(resourceId));
|
||||||
|
}else{
|
||||||
|
scheduleManager.removeJob(ApiTestJob.getJobKey(resourceId), ApiTestJob.getTriggerKey(resourceId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public List<Schedule> listSchedule() {
|
public List<Schedule> listSchedule() {
|
||||||
ScheduleExample example = new ScheduleExample();
|
ScheduleExample example = new ScheduleExample();
|
||||||
return scheduleMapper.selectByExample(example);
|
return scheduleMapper.selectByExample(example);
|
||||||
|
|
|
@ -115,6 +115,7 @@ public class TestPlanApiCaseService {
|
||||||
TestPlanApiCase apiCase = new TestPlanApiCase();
|
TestPlanApiCase apiCase = new TestPlanApiCase();
|
||||||
apiCase.setId(id);
|
apiCase.setId(id);
|
||||||
apiCase.setStatus(status);
|
apiCase.setStatus(status);
|
||||||
|
apiCase.setUpdateTime(System.currentTimeMillis());
|
||||||
testPlanApiCaseMapper.updateByPrimaryKeySelective(apiCase);
|
testPlanApiCaseMapper.updateByPrimaryKeySelective(apiCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -281,6 +281,18 @@ public class TestPlanReportService {
|
||||||
component.afterBuild(testCaseReportMetricDTO);
|
component.afterBuild(testCaseReportMetricDTO);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (StringUtils.equals(ReportTriggerMode.SCHEDULE.name(),triggerMode)
|
||||||
|
&&StringUtils.equals(resourceRunMode, ApiRunMode.SCHEDULE_PERFORMANCE_TEST.name())) {
|
||||||
|
//如果是性能测试作为触发,由于延迟原因可能会出现报告已经结束但是状态还是进行中的状态
|
||||||
|
List<TestCaseReportStatusResultDTO> loadResult = testCaseReportMetricDTO.getExecuteResult().getLoadResult();
|
||||||
|
for (TestCaseReportStatusResultDTO dto: loadResult) {
|
||||||
|
if(StringUtils.equals(dto.getStatus(),TestPlanTestCaseStatus.Underway.name())){
|
||||||
|
dto.setStatus(TestPlanTestCaseStatus.Pass.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testCaseReportMetricDTO.getExecuteResult().setLoadResult(loadResult);
|
||||||
|
}
|
||||||
|
|
||||||
TestPlanReportDataExample example = new TestPlanReportDataExample();
|
TestPlanReportDataExample example = new TestPlanReportDataExample();
|
||||||
example.createCriteria().andTestPlanReportIdEqualTo(planReportId);
|
example.createCriteria().andTestPlanReportIdEqualTo(planReportId);
|
||||||
List<TestPlanReportDataWithBLOBs> testPlanReportDataList = testPlanReportDataMapper.selectByExampleWithBLOBs(example);
|
List<TestPlanReportDataWithBLOBs> testPlanReportDataList = testPlanReportDataMapper.selectByExampleWithBLOBs(example);
|
||||||
|
@ -437,7 +449,7 @@ public class TestPlanReportService {
|
||||||
if(loadTestReportFromDatabase == null){
|
if(loadTestReportFromDatabase == null){
|
||||||
//检查错误数据
|
//检查错误数据
|
||||||
if(errorDataCheckMap.containsKey(loadTestReportId)){
|
if(errorDataCheckMap.containsKey(loadTestReportId)){
|
||||||
if(errorDataCheckMap.get(loadTestReportId)>20){
|
if(errorDataCheckMap.get(loadTestReportId)>10){
|
||||||
performaneReportIDList.remove(loadTestReportId);
|
performaneReportIDList.remove(loadTestReportId);
|
||||||
}else {
|
}else {
|
||||||
errorDataCheckMap.put(loadTestReportId,errorDataCheckMap.get(loadTestReportId)+1);
|
errorDataCheckMap.put(loadTestReportId,errorDataCheckMap.get(loadTestReportId)+1);
|
||||||
|
|
|
@ -28,6 +28,7 @@ import io.metersphere.dto.BaseSystemConfigDTO;
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.notice.sender.NoticeModel;
|
import io.metersphere.notice.sender.NoticeModel;
|
||||||
import io.metersphere.notice.service.NoticeSendService;
|
import io.metersphere.notice.service.NoticeSendService;
|
||||||
|
import io.metersphere.service.ScheduleService;
|
||||||
import io.metersphere.service.SystemParameterService;
|
import io.metersphere.service.SystemParameterService;
|
||||||
import io.metersphere.track.Factory.ReportComponentFactory;
|
import io.metersphere.track.Factory.ReportComponentFactory;
|
||||||
import io.metersphere.track.domain.ReportComponent;
|
import io.metersphere.track.domain.ReportComponent;
|
||||||
|
@ -62,6 +63,8 @@ public class TestPlanService {
|
||||||
@Resource
|
@Resource
|
||||||
ExtTestPlanMapper extTestPlanMapper;
|
ExtTestPlanMapper extTestPlanMapper;
|
||||||
@Resource
|
@Resource
|
||||||
|
ScheduleService scheduleService;
|
||||||
|
@Resource
|
||||||
ExtTestPlanTestCaseMapper extTestPlanTestCaseMapper;
|
ExtTestPlanTestCaseMapper extTestPlanTestCaseMapper;
|
||||||
@Resource
|
@Resource
|
||||||
TestCaseMapper testCaseMapper;
|
TestCaseMapper testCaseMapper;
|
||||||
|
@ -315,6 +318,10 @@ public class TestPlanService {
|
||||||
testPlanProjectService.deleteTestPlanProjectByPlanId(planId);
|
testPlanProjectService.deleteTestPlanProjectByPlanId(planId);
|
||||||
testPlanApiCaseService.deleteByPlanId(planId);
|
testPlanApiCaseService.deleteByPlanId(planId);
|
||||||
testPlanScenarioCaseService.deleteByPlanId(planId);
|
testPlanScenarioCaseService.deleteByPlanId(planId);
|
||||||
|
|
||||||
|
//删除定时任务
|
||||||
|
scheduleService.deleteScheduleAndJobByResourceId(planId,ScheduleGroup.TEST_PLAN_TEST.name());
|
||||||
|
|
||||||
int num = testPlanMapper.deleteByPrimaryKey(planId);
|
int num = testPlanMapper.deleteByPrimaryKey(planId);
|
||||||
List<String> relatedUsers = new ArrayList<>();
|
List<String> relatedUsers = new ArrayList<>();
|
||||||
AddTestPlanRequest testPlans = new AddTestPlanRequest();
|
AddTestPlanRequest testPlans = new AddTestPlanRequest();
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 387ca56312b62ae5edb3d7f34afa08946d86d621
|
Subproject commit 26d36f3f81e889f58eed7c6903252a129b301d98
|
|
@ -1,11 +1,11 @@
|
||||||
create table swagger_url_project
|
create table swagger_url_project
|
||||||
(
|
(
|
||||||
id varchar(255) not null,
|
id varchar(30) not null,
|
||||||
project_id varchar(255) null,
|
project_id varchar(30) null,
|
||||||
swagger_url varchar(255) null,
|
swagger_url varchar(255) null,
|
||||||
module_id varchar(255) null,
|
module_id varchar(30) null,
|
||||||
module_path varchar(255) null,
|
module_path varchar(255) null,
|
||||||
mode_id varchar(255) null,
|
mode_id varchar(30) null,
|
||||||
primary key (id)
|
primary key (id)
|
||||||
) ENGINE = InnoDB
|
) ENGINE = InnoDB
|
||||||
DEFAULT CHARSET = utf8mb4;
|
DEFAULT CHARSET = utf8mb4;
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 355 KiB After Width: | Height: | Size: 169 KiB |
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
<ms-main-container>
|
<ms-main-container>
|
||||||
<el-tabs v-model="activeName" @tab-click="addTab" @tab-remove="removeTab">
|
<el-tabs v-model="activeName" @tab-click="addTab" @tab-remove="removeTab">
|
||||||
<el-tab-pane name="default" :label="$t('api_test.automation.scenario_test')">
|
<el-tab-pane name="default" :label="$t('api_test.automation.scenario_list')">
|
||||||
<ms-api-scenario-list
|
<ms-api-scenario-list
|
||||||
:module-tree="nodeTree"
|
:module-tree="nodeTree"
|
||||||
:module-options="moduleOptions"
|
:module-options="moduleOptions"
|
||||||
|
@ -97,6 +97,7 @@
|
||||||
renderComponent: true,
|
renderComponent: true,
|
||||||
isHide: true,
|
isHide: true,
|
||||||
activeName: 'default',
|
activeName: 'default',
|
||||||
|
redirectFlag: 'none',
|
||||||
currentModule: null,
|
currentModule: null,
|
||||||
moduleOptions: [],
|
moduleOptions: [],
|
||||||
tabs: [],
|
tabs: [],
|
||||||
|
@ -150,6 +151,15 @@
|
||||||
},
|
},
|
||||||
changeRedirectParam(redirectIDParam) {
|
changeRedirectParam(redirectIDParam) {
|
||||||
this.redirectID = redirectIDParam;
|
this.redirectID = redirectIDParam;
|
||||||
|
if(redirectIDParam!=null){
|
||||||
|
if(this.redirectFlag == "none"){
|
||||||
|
this.activeName = "default";
|
||||||
|
this.addListener();
|
||||||
|
this.redirectFlag = "redirected";
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
this.redirectFlag = "none";
|
||||||
|
}
|
||||||
},
|
},
|
||||||
addTab(tab) {
|
addTab(tab) {
|
||||||
if (!getCurrentProjectID()) {
|
if (!getCurrentProjectID()) {
|
||||||
|
@ -227,8 +237,18 @@
|
||||||
this.$refs.apiScenarioList.search(data);
|
this.$refs.apiScenarioList.search(data);
|
||||||
},
|
},
|
||||||
refresh(data) {
|
refresh(data) {
|
||||||
|
this.setTabTitle(data);
|
||||||
this.$refs.apiScenarioList.search(data);
|
this.$refs.apiScenarioList.search(data);
|
||||||
},
|
},
|
||||||
|
setTabTitle(data) {
|
||||||
|
for (let index in this.tabs) {
|
||||||
|
let tab = this.tabs[index];
|
||||||
|
if (tab.name === this.activeName) {
|
||||||
|
tab.label = data.name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
editScenario(row) {
|
editScenario(row) {
|
||||||
this.addTab({name: 'edit', currentScenario: row});
|
this.addTab({name: 'edit', currentScenario: row});
|
||||||
},
|
},
|
||||||
|
|
|
@ -118,6 +118,7 @@
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
this.getFails();
|
this.getFails();
|
||||||
|
this.computeTotalTime();
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
} else {
|
} else {
|
||||||
setTimeout(this.getReport, 2000)
|
setTimeout(this.getReport, 2000)
|
||||||
|
@ -146,12 +147,30 @@
|
||||||
failScenario.requestResults.push(failRequest);
|
failScenario.requestResults.push(failRequest);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computeTotalTime() {
|
||||||
|
if (this.content.scenarios) {
|
||||||
|
let startTime = 99991611737506593;
|
||||||
|
let endTime = 0;
|
||||||
|
this.content.scenarios.forEach((scenario) => {
|
||||||
|
scenario.requestResults.forEach((request) => {
|
||||||
|
if (request.startTime && Number(request.startTime) < startTime) {
|
||||||
|
startTime = request.startTime;
|
||||||
|
}
|
||||||
|
if (request.endTime && Number(request.endTime) > endTime) {
|
||||||
|
endTime = request.endTime;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
if (startTime < endTime) {
|
||||||
|
this.totalTime = endTime - startTime + 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
requestResult(requestResult) {
|
requestResult(requestResult) {
|
||||||
this.active();
|
this.active();
|
||||||
this.isRequestResult = false;
|
this.isRequestResult = false;
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="request-result">
|
<div class="request-result">
|
||||||
<div>
|
<div>
|
||||||
<el-row :gutter="10" type="flex" align="middle" class="info">
|
<el-row :gutter="8" type="flex" align="middle" class="info">
|
||||||
<el-col :span="2">
|
<el-col :span="2">
|
||||||
<div class="method">
|
<div class="method">
|
||||||
{{request.method}}
|
{{request.method}}
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
<el-col :span="8">
|
||||||
<el-tooltip effect="dark" :content="request.url" placement="bottom" :open-delay="800">
|
<el-tooltip effect="dark" :content="request.url" placement="bottom" :open-delay="800">
|
||||||
<div class="url">{{request.url}}</div>
|
<div class="url">{{request.url}}</div>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="url"> {{$t('api_report.start_time')}}:{{request.startTime | timestampFormatDate(true) }}
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
<el-collapse-transition>
|
<el-collapse-transition>
|
||||||
|
@ -19,7 +23,7 @@
|
||||||
<el-tabs v-model="activeName" v-show="isActive" v-if="hasSub">
|
<el-tabs v-model="activeName" v-show="isActive" v-if="hasSub">
|
||||||
<el-tab-pane :label="$t('api_report.sub_result')" name="sub">
|
<el-tab-pane :label="$t('api_report.sub_result')" name="sub">
|
||||||
<ms-request-sub-result class="sub-result" v-for="(sub, index) in request.subRequestResults"
|
<ms-request-sub-result class="sub-result" v-for="(sub, index) in request.subRequestResults"
|
||||||
:key="index" :indexNumber="index" :request="sub"/>
|
:key="index" :indexNumber="index" :request="sub"/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="$t('api_report.request_result')" name="result">
|
<el-tab-pane :label="$t('api_report.request_result')" name="result">
|
||||||
<ms-response-text :request-type="requestType" :response="request.responseResult" :request="request"/>
|
<ms-response-text :request-type="requestType" :response="request.responseResult" :request="request"/>
|
||||||
|
@ -43,7 +47,7 @@
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsRequestResultTail",
|
name: "MsRequestResultTail",
|
||||||
components: {MsResponseText, MsRequestText, MsAssertionResults, MsRequestMetric, MsRequestResult,MsRequestSubResult},
|
components: {MsResponseText, MsRequestText, MsAssertionResults, MsRequestMetric, MsRequestResult, MsRequestSubResult},
|
||||||
props: {
|
props: {
|
||||||
request: Object,
|
request: Object,
|
||||||
scenarioName: String,
|
scenarioName: String,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<el-card class="table-card" v-loading="loading">
|
<el-card class="table-card" v-loading="loading">
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
<ms-table-header :condition.sync="condition" @search="selectByParam" title=""
|
<ms-table-header :condition.sync="condition" @search="selectByParam" title=""
|
||||||
:show-create="false"/>
|
:show-create="false" :tip="$t('commons.search_by_id_name_tag')"/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table ref="scenarioTable" border :data="tableData" class="adjust-table ms-select-all-fixed"
|
<el-table ref="scenarioTable" border :data="tableData" class="adjust-table ms-select-all-fixed"
|
||||||
|
|
|
@ -137,7 +137,7 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- 场景步骤内容 -->
|
<!-- 场景步骤内容 -->
|
||||||
<div v-loading="loading">
|
<div v-loading="loading">
|
||||||
<el-tree node-key="resourceId" :props="props" :data="scenarioDefinition"
|
<el-tree node-key="resourceId" :props="props" :data="scenarioDefinition" class="ms-tree"
|
||||||
:default-expanded-keys="expandedNode"
|
:default-expanded-keys="expandedNode"
|
||||||
:expand-on-click-node="false"
|
:expand-on-click-node="false"
|
||||||
highlight-current
|
highlight-current
|
||||||
|
@ -286,8 +286,7 @@
|
||||||
},
|
},
|
||||||
response: {}
|
response: {}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
,
|
|
||||||
created() {
|
created() {
|
||||||
if (!this.currentScenario.apiScenarioModuleId) {
|
if (!this.currentScenario.apiScenarioModuleId) {
|
||||||
this.currentScenario.apiScenarioModuleId = "";
|
this.currentScenario.apiScenarioModuleId = "";
|
||||||
|
@ -848,7 +847,7 @@
|
||||||
if (this.currentScenario.tags instanceof String) {
|
if (this.currentScenario.tags instanceof String) {
|
||||||
this.currentScenario.tags = JSON.parse(this.currentScenario.tags);
|
this.currentScenario.tags = JSON.parse(this.currentScenario.tags);
|
||||||
}
|
}
|
||||||
this.$emit('refresh');
|
this.$emit('refresh', this.currentScenario);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -857,6 +856,9 @@
|
||||||
if (this.currentScenario.tags != undefined && !(this.currentScenario.tags instanceof Array)) {
|
if (this.currentScenario.tags != undefined && !(this.currentScenario.tags instanceof Array)) {
|
||||||
this.currentScenario.tags = JSON.parse(this.currentScenario.tags);
|
this.currentScenario.tags = JSON.parse(this.currentScenario.tags);
|
||||||
}
|
}
|
||||||
|
if (!this.currentScenario.variables) {
|
||||||
|
this.currentScenario.variables = [];
|
||||||
|
}
|
||||||
if (this.currentScenario.id) {
|
if (this.currentScenario.id) {
|
||||||
this.result = this.$get("/api/automation/getApiScenario/" + this.currentScenario.id, response => {
|
this.result = this.$get("/api/automation/getApiScenario/" + this.currentScenario.id, response => {
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
|
@ -1037,15 +1039,27 @@
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ms-expanded >>> .el-tree-node__expand-icon.expanded {
|
.ms-tree >>> .el-tree-node__expand-icon.expanded {
|
||||||
color: #7C3985;
|
-webkit-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ms-el-icon-caret-right .el-icon-caret-right {
|
.ms-tree >>> .el-icon-caret-right:before {
|
||||||
color: #7C3985;
|
content: '\e723';
|
||||||
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ms-is-leaf >>> .is-leaf {
|
.ms-tree >>> .el-tree-node__expand-icon.is-leaf {
|
||||||
color: transparent;
|
color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ms-tree >>> .el-tree-node__expand-icon {
|
||||||
|
color: #7C3985;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ms-tree >>> .el-tree-node__expand-icon.expanded.el-icon-caret-right:before {
|
||||||
|
color: #7C3985;
|
||||||
|
content: "\e722";
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -72,4 +72,11 @@
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-button--text .el-link.el-link--default {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #4b1980;
|
||||||
|
font-weight: 400;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -193,7 +193,10 @@ export default {
|
||||||
}
|
}
|
||||||
if (this.currentProtocol != null) {
|
if (this.currentProtocol != null) {
|
||||||
this.condition.protocol = this.currentProtocol;
|
this.condition.protocol = this.currentProtocol;
|
||||||
|
}else{
|
||||||
|
this.condition.protocol = "HTTP";
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = '/api/definition/list/';
|
let url = '/api/definition/list/';
|
||||||
if (this.isTestPlan) {
|
if (this.isTestPlan) {
|
||||||
url = '/api/definition/list/relevance/';
|
url = '/api/definition/list/relevance/';
|
||||||
|
|
|
@ -37,15 +37,17 @@
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="header">
|
||||||
|
<el-collapse-transition>
|
||||||
|
<div v-if="data.active && showCollapse" :draggable="draggable">
|
||||||
|
<fieldset :disabled="data.disabled" class="ms-fieldset">
|
||||||
|
<el-divider></el-divider>
|
||||||
|
<slot></slot>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
</el-collapse-transition>
|
||||||
|
</div>
|
||||||
|
|
||||||
<el-collapse-transition>
|
|
||||||
<div v-if="data.active && showCollapse" :draggable="draggable">
|
|
||||||
<fieldset :disabled="data.disabled" style="border: 0px">
|
|
||||||
<el-divider></el-divider>
|
|
||||||
<slot></slot>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
</el-collapse-transition>
|
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -148,5 +150,12 @@
|
||||||
.enable-switch {
|
.enable-switch {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
fieldset {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
min-width: 100%;
|
||||||
|
min-inline-size: 0px;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -76,18 +76,20 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-input size="small" v-model="controller.whileController.value" :placeholder="$t('api_test.value')" v-if="!hasEmptyOperator" style="width: 20%;margin-left: 20px"/>
|
<el-input size="small" v-model="controller.whileController.value" :placeholder="$t('api_test.value')" v-if="!hasEmptyOperator" style="width: 20%;margin-left: 20px"/>
|
||||||
<span class="ms-span ms-radio">{{$t('loop.timeout')}}</span>
|
<span class="ms-span ms-radio">{{$t('loop.timeout')}}</span>
|
||||||
<el-input-number size="small" v-model="controller.whileController.timeout" :placeholder="$t('commons.millisecond')" :max="1000*10000000" :min="1" :step="1000"/>
|
<el-input-number size="small" v-model="controller.whileController.timeout" :placeholder="$t('commons.millisecond')" :max="1000*10000000" :min="3000" :step="1000"/>
|
||||||
<span class="ms-span ms-radio">ms</span>
|
<span class="ms-span ms-radio">ms</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
|
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
|
||||||
<el-tabs v-model="activeName">
|
<div>
|
||||||
<el-tab-pane :label="item.name" :name="item.name" v-for="(item,index) in requestResult.scenarios" :key="index">
|
<el-tabs v-model="activeName" closable class="ms-tabs">
|
||||||
<div v-for="(result,i) in item.requestResults" :key="i" style="margin-bottom: 5px">
|
<el-tab-pane :label="item.name" :name="item.name" v-for="(item,index) in requestResult.scenarios" :key="index">
|
||||||
<api-response-component :result="result"/>
|
<div v-for="(result,i) in item.requestResults" :key="i" style="margin-bottom: 5px">
|
||||||
</div>
|
<api-response-component :result="result"/>
|
||||||
</el-tab-pane>
|
</div>
|
||||||
</el-tabs>
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</api-base-component>
|
</api-base-component>
|
||||||
|
|
||||||
|
@ -331,6 +333,11 @@
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ms-tabs >>> .el-icon-close:before {
|
||||||
|
content: "";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
.icon.is-active {
|
.icon.is-active {
|
||||||
transform: rotate(90deg);
|
transform: rotate(90deg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
this.$refs.nameInput.focus();
|
this.$refs.nameInput.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,22 @@
|
||||||
<el-form :model="form" :rules="rules" ref="from">
|
<el-form :model="form" :rules="rules" ref="from">
|
||||||
<el-form-item
|
<el-form-item
|
||||||
prop="cronValue">
|
prop="cronValue">
|
||||||
<el-input :disabled="isReadOnly" v-model="form.cronValue" class="inp"
|
<el-row>
|
||||||
:placeholder="$t('schedule.please_input_cron_expression')"/>
|
<el-col :span="18">
|
||||||
<el-button :disabled="isReadOnly" type="primary" @click="saveCron" v-tester>{{
|
<el-input :disabled="isReadOnly" v-model="form.cronValue" class="inp"
|
||||||
$t('commons.save')
|
:placeholder="$t('schedule.please_input_cron_expression')"/>
|
||||||
}}
|
<el-button :disabled="isReadOnly" type="primary" @click="saveCron" v-tester>{{
|
||||||
</el-button>
|
$t('commons.save')
|
||||||
|
}}
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<schedule-switch :schedule="schedule" @scheduleChange="scheduleChange"></schedule-switch>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-link :disabled="isReadOnly" type="primary" @click="showCronDialog">
|
<el-link :disabled="isReadOnly" type="primary" @click="showCronDialog">
|
||||||
|
@ -44,6 +54,7 @@ import Crontab from "@/business/components/common/cron/Crontab";
|
||||||
import CrontabResult from "@/business/components/common/cron/CrontabResult";
|
import CrontabResult from "@/business/components/common/cron/CrontabResult";
|
||||||
import {cronValidate} from "@/common/js/cron";
|
import {cronValidate} from "@/common/js/cron";
|
||||||
import MsScheduleNotification from "./ScheduleNotification";
|
import MsScheduleNotification from "./ScheduleNotification";
|
||||||
|
import ScheduleSwitch from "@/business/components/api/automation/schedule/ScheduleSwitch";
|
||||||
|
|
||||||
function defaultCustomValidate() {
|
function defaultCustomValidate() {
|
||||||
return {pass: true};
|
return {pass: true};
|
||||||
|
@ -55,7 +66,7 @@ const noticeTemplate = requireComponent.keys().length > 0 ? requireComponent("./
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsScheduleMaintain",
|
name: "MsScheduleMaintain",
|
||||||
components: {CrontabResult, Crontab, MsScheduleNotification, "NoticeTemplate": noticeTemplate.default},
|
components: {CrontabResult, ScheduleSwitch,Crontab, MsScheduleNotification, "NoticeTemplate": noticeTemplate.default},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
customValidate: {
|
customValidate: {
|
||||||
|
@ -100,6 +111,7 @@ export default {
|
||||||
form: {
|
form: {
|
||||||
cronValue: ""
|
cronValue: ""
|
||||||
},
|
},
|
||||||
|
paramRow:{},
|
||||||
activeName: 'first',
|
activeName: 'first',
|
||||||
rules: {
|
rules: {
|
||||||
cronValue: [{required: true, validator: validateCron, trigger: 'blur'}],
|
cronValue: [{required: true, validator: validateCron, trigger: 'blur'}],
|
||||||
|
@ -110,6 +122,35 @@ export default {
|
||||||
currentUser: () => {
|
currentUser: () => {
|
||||||
return getCurrentUser();
|
return getCurrentUser();
|
||||||
},
|
},
|
||||||
|
scheduleChange(){
|
||||||
|
let flag = this.schedule.enable;
|
||||||
|
this.$confirm(this.$t('api_test.home_page.running_task_list.confirm.close_title'), this.$t('commons.prompt'), {
|
||||||
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
|
cancelButtonText: this.$t('commons.cancel'),
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
let param = {};
|
||||||
|
param.taskID = this.schedule.id;
|
||||||
|
param.enable = flag;
|
||||||
|
this.updateTask(param);
|
||||||
|
}).catch(() => {
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
updateTask(param){
|
||||||
|
this.result = this.$post('/api/schedule/updateEnableByPrimyKey', param, response => {
|
||||||
|
let paramTestId = "";
|
||||||
|
if (this.paramRow.redirectFrom == 'testPlan') {
|
||||||
|
paramTestId = this.paramRow.id;
|
||||||
|
this.scheduleTaskType = "TEST_PLAN_TEST";
|
||||||
|
} else {
|
||||||
|
paramTestId = this.paramRow.id;
|
||||||
|
this.scheduleTaskType = "API_SCENARIO_TEST";
|
||||||
|
}
|
||||||
|
this.taskID = paramTestId;
|
||||||
|
this.findSchedule(paramTestId);
|
||||||
|
});
|
||||||
|
},
|
||||||
initUserList() {
|
initUserList() {
|
||||||
let param = {
|
let param = {
|
||||||
name: '',
|
name: '',
|
||||||
|
@ -132,6 +173,7 @@ export default {
|
||||||
open(row) {
|
open(row) {
|
||||||
//测试计划页面跳转来的
|
//测试计划页面跳转来的
|
||||||
let paramTestId = "";
|
let paramTestId = "";
|
||||||
|
this.paramRow = row;
|
||||||
if (row.redirectFrom == 'testPlan') {
|
if (row.redirectFrom == 'testPlan') {
|
||||||
paramTestId = row.id;
|
paramTestId = row.id;
|
||||||
this.scheduleTaskType = "TEST_PLAN_TEST";
|
this.scheduleTaskType = "TEST_PLAN_TEST";
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
<template>
|
||||||
|
<div class="schedule-config">
|
||||||
|
<div>
|
||||||
|
<span class="cron-ico">
|
||||||
|
<i class="el-icon-date" size="small"></i>
|
||||||
|
<span class="character">SCHEDULER</span>
|
||||||
|
</span>
|
||||||
|
<!-- <el-switch :disabled="!schedule.value || isReadOnly" v-model="schedule.enable" @change="scheduleChange"/>-->
|
||||||
|
<!-- <el-switch :disabled="!schedule.value || isReadOnly" v-model="schedule.enable" />-->
|
||||||
|
<el-switch :disabled="!schedule.value" v-model="schedule.enable" @change="scheduleChange"/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
{{ $t('schedule.next_execution_time') }}:
|
||||||
|
<span :class="{'disable-character': !schedule.enable}"
|
||||||
|
v-if="!schedule.enable">{{ $t('schedule.not_set') }}</span>
|
||||||
|
<crontab-result v-if="schedule.enable" :enable-simple-mode="true" :ex="schedule.value" ref="crontabResult"/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CrontabResult from "@/business/components/common/cron/CrontabResult";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "ScheduleSwitch",
|
||||||
|
components: {CrontabResult},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
testId: String,
|
||||||
|
schedule: Object,
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
scheduleChange() {
|
||||||
|
this.$emit('scheduleChange');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.schedule-config {
|
||||||
|
float: right;
|
||||||
|
width: 250px;
|
||||||
|
height: 15px;
|
||||||
|
line-height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon-date {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.character {
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disable-character {
|
||||||
|
color: #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-switch {
|
||||||
|
margin: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cron-ico {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -263,7 +263,6 @@
|
||||||
this.apiTabs = [];
|
this.apiTabs = [];
|
||||||
this.apiDefaultTab = tabs.name;
|
this.apiDefaultTab = tabs.name;
|
||||||
this.apiTabs.push(tabs);
|
this.apiTabs.push(tabs);
|
||||||
this.refresh();
|
|
||||||
},
|
},
|
||||||
handleTabRemove(targetName) {
|
handleTabRemove(targetName) {
|
||||||
let tabs = this.apiTabs;
|
let tabs = this.apiTabs;
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
</div>
|
</div>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-dialog :title="$t('api_test.request.assertions.script')" :visible.sync="visible" width="900px">
|
<el-dialog :title="$t('api_test.request.assertions.script')" :visible.sync="visible" width="900px" append-to-body>
|
||||||
<el-row type="flex" justify="space-between" align="middle" class="quick-script-block">
|
<el-row type="flex" justify="space-between" align="middle" class="quick-script-block">
|
||||||
<div class="assertion-item input">
|
<div class="assertion-item input">
|
||||||
<el-input size="small" v-model="assertion.variable"
|
<el-input size="small" v-model="assertion.variable"
|
||||||
|
@ -55,206 +55,206 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {AssertionJSR223} from "../../model/ApiTestModel";
|
import {AssertionJSR223} from "../../model/ApiTestModel";
|
||||||
import MsDialogFooter from "@/business/components/common/components/MsDialogFooter";
|
import MsDialogFooter from "@/business/components/common/components/MsDialogFooter";
|
||||||
import MsJsr233Processor from "../../../automation/scenario/component/Jsr233Processor";
|
import MsJsr233Processor from "../../../automation/scenario/common/Jsr233ProcessorContent";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsApiAssertionJsr223",
|
name: "MsApiAssertionJsr223",
|
||||||
components: {MsJsr233Processor, MsDialogFooter},
|
components: {MsJsr233Processor, MsDialogFooter},
|
||||||
props: {
|
props: {
|
||||||
assertion: {
|
assertion: {
|
||||||
default: () => {
|
default: () => {
|
||||||
return new AssertionJSR223();
|
return new AssertionJSR223();
|
||||||
}
|
|
||||||
},
|
|
||||||
edit: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
index: Number,
|
|
||||||
list: Array,
|
|
||||||
callback: Function,
|
|
||||||
isReadOnly: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
visible: false,
|
|
||||||
operators: {
|
|
||||||
EQ: {
|
|
||||||
label: "commons.adv_search.operators.equals",
|
|
||||||
value: "=="
|
|
||||||
},
|
|
||||||
NE: {
|
|
||||||
label: "commons.adv_search.operators.not_equals",
|
|
||||||
value: "!="
|
|
||||||
},
|
|
||||||
CONTAINS: {
|
|
||||||
label: "commons.adv_search.operators.like",
|
|
||||||
value: "contains"
|
|
||||||
},
|
|
||||||
NOT_CONTAINS: {
|
|
||||||
label: "commons.adv_search.operators.not_like",
|
|
||||||
value: "not contains"
|
|
||||||
},
|
|
||||||
GT: {
|
|
||||||
label: "commons.adv_search.operators.gt",
|
|
||||||
value: ">"
|
|
||||||
},
|
|
||||||
LT: {
|
|
||||||
label: "commons.adv_search.operators.lt",
|
|
||||||
value: "<"
|
|
||||||
},
|
|
||||||
IS_EMPTY: {
|
|
||||||
label: "commons.adv_search.operators.is_empty",
|
|
||||||
value: "is empty"
|
|
||||||
},
|
|
||||||
IS_NOT_EMPTY: {
|
|
||||||
label: "commons.adv_search.operators.is_not_empty",
|
|
||||||
value: "is not empty"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
templates: [
|
edit: {
|
||||||
{
|
type: Boolean,
|
||||||
title: this.$t('api_test.request.assertions.set_failure_status'),
|
default: false
|
||||||
value: 'AssertionResult.setFailure(true)',
|
},
|
||||||
|
index: Number,
|
||||||
|
list: Array,
|
||||||
|
callback: Function,
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
operators: {
|
||||||
|
EQ: {
|
||||||
|
label: "commons.adv_search.operators.equals",
|
||||||
|
value: "=="
|
||||||
|
},
|
||||||
|
NE: {
|
||||||
|
label: "commons.adv_search.operators.not_equals",
|
||||||
|
value: "!="
|
||||||
|
},
|
||||||
|
CONTAINS: {
|
||||||
|
label: "commons.adv_search.operators.like",
|
||||||
|
value: "contains"
|
||||||
|
},
|
||||||
|
NOT_CONTAINS: {
|
||||||
|
label: "commons.adv_search.operators.not_like",
|
||||||
|
value: "not contains"
|
||||||
|
},
|
||||||
|
GT: {
|
||||||
|
label: "commons.adv_search.operators.gt",
|
||||||
|
value: ">"
|
||||||
|
},
|
||||||
|
LT: {
|
||||||
|
label: "commons.adv_search.operators.lt",
|
||||||
|
value: "<"
|
||||||
|
},
|
||||||
|
IS_EMPTY: {
|
||||||
|
label: "commons.adv_search.operators.is_empty",
|
||||||
|
value: "is empty"
|
||||||
|
},
|
||||||
|
IS_NOT_EMPTY: {
|
||||||
|
label: "commons.adv_search.operators.is_not_empty",
|
||||||
|
value: "is not empty"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
templates: [
|
||||||
title: this.$t('api_test.request.assertions.set_failure_msg'),
|
{
|
||||||
value: 'AssertionResult.setFailureMessage("msg")',
|
title: this.$t('api_test.request.assertions.set_failure_status'),
|
||||||
|
value: 'AssertionResult.setFailure(true)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: this.$t('api_test.request.assertions.set_failure_msg'),
|
||||||
|
value: 'AssertionResult.setFailureMessage("msg")',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
add() {
|
||||||
|
this.list.push(new AssertionJSR223(this.assertion));
|
||||||
|
this.callback();
|
||||||
|
},
|
||||||
|
remove() {
|
||||||
|
this.list.splice(this.index, 1);
|
||||||
|
},
|
||||||
|
changeOperator(value) {
|
||||||
|
if (value.indexOf("empty") > 0 && !!this.assertion.value) {
|
||||||
|
this.assertion.value = "";
|
||||||
}
|
}
|
||||||
],
|
this.quickScript();
|
||||||
}
|
},
|
||||||
},
|
quickScript() {
|
||||||
|
if (this.assertion.variable && this.assertion.operator) {
|
||||||
|
let variable = this.assertion.variable;
|
||||||
|
let operator = this.assertion.operator;
|
||||||
|
let value = this.assertion.value || "";
|
||||||
|
let desc = "${" + variable + "} " + operator + " '" + value + "'";
|
||||||
|
let script = "value = vars.get(\"" + variable + "\");\n"
|
||||||
|
switch (this.assertion.operator) {
|
||||||
|
case "==":
|
||||||
|
script += "result = \"" + value + "\".equals(value);\n";
|
||||||
|
break;
|
||||||
|
case "!=":
|
||||||
|
script += "result = !\"" + value + "\".equals(value);\n";
|
||||||
|
break;
|
||||||
|
case "contains":
|
||||||
|
script += "result = value.contains(\"" + value + "\");\n";
|
||||||
|
break;
|
||||||
|
case "not contains":
|
||||||
|
script += "result = !value.contains(\"" + value + "\");\n";
|
||||||
|
break;
|
||||||
|
case ">":
|
||||||
|
desc = "${" + variable + "} " + operator + " " + value;
|
||||||
|
script += "number = Integer.parseInt(value);\n" +
|
||||||
|
"result = number > " + value + ";\n";
|
||||||
|
break;
|
||||||
|
case "<":
|
||||||
|
desc = "${" + variable + "} " + operator + " " + value;
|
||||||
|
script += "number = Integer.parseInt(value);\n" +
|
||||||
|
"result = number < " + value + ";\n";
|
||||||
|
break;
|
||||||
|
case "is empty":
|
||||||
|
desc = "${" + variable + "} " + operator
|
||||||
|
script += "result = value == void || value.length() == 0;\n";
|
||||||
|
break;
|
||||||
|
case "is not empty":
|
||||||
|
desc = "${" + variable + "} " + operator
|
||||||
|
script += "result = value != void && value.length() > 0;\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let msg = "assertion [" + desc + "]: false;"
|
||||||
|
script += "if (!result){\n" +
|
||||||
|
"\tmsg = \"" + msg + "\";\n" +
|
||||||
|
"\tAssertionResult.setFailureMessage(msg);\n" +
|
||||||
|
"\tAssertionResult.setFailure(true);\n" +
|
||||||
|
"}";
|
||||||
|
|
||||||
methods: {
|
this.assertion.desc = desc;
|
||||||
add() {
|
this.assertion.script = script;
|
||||||
this.list.push(new AssertionJSR223(this.assertion));
|
this.$refs.jsr233.reload();
|
||||||
this.callback();
|
|
||||||
},
|
|
||||||
remove() {
|
|
||||||
this.list.splice(this.index, 1);
|
|
||||||
},
|
|
||||||
changeOperator(value) {
|
|
||||||
if (value.indexOf("empty") > 0 && !!this.assertion.value) {
|
|
||||||
this.assertion.value = "";
|
|
||||||
}
|
|
||||||
this.quickScript();
|
|
||||||
},
|
|
||||||
quickScript() {
|
|
||||||
if (this.assertion.variable && this.assertion.operator) {
|
|
||||||
let variable = this.assertion.variable;
|
|
||||||
let operator = this.assertion.operator;
|
|
||||||
let value = this.assertion.value || "";
|
|
||||||
let desc = "${" + variable + "} " + operator + " '" + value + "'";
|
|
||||||
let script = "value = vars.get(\"" + variable + "\");\n"
|
|
||||||
switch (this.assertion.operator) {
|
|
||||||
case "==":
|
|
||||||
script += "result = \"" + value + "\".equals(value);\n";
|
|
||||||
break;
|
|
||||||
case "!=":
|
|
||||||
script += "result = !\"" + value + "\".equals(value);\n";
|
|
||||||
break;
|
|
||||||
case "contains":
|
|
||||||
script += "result = value.contains(\"" + value + "\");\n";
|
|
||||||
break;
|
|
||||||
case "not contains":
|
|
||||||
script += "result = !value.contains(\"" + value + "\");\n";
|
|
||||||
break;
|
|
||||||
case ">":
|
|
||||||
desc = "${" + variable + "} " + operator + " " + value;
|
|
||||||
script += "number = Integer.parseInt(value);\n" +
|
|
||||||
"result = number > " + value + ";\n";
|
|
||||||
break;
|
|
||||||
case "<":
|
|
||||||
desc = "${" + variable + "} " + operator + " " + value;
|
|
||||||
script += "number = Integer.parseInt(value);\n" +
|
|
||||||
"result = number < " + value + ";\n";
|
|
||||||
break;
|
|
||||||
case "is empty":
|
|
||||||
desc = "${" + variable + "} " + operator
|
|
||||||
script += "result = value == void || value.length() == 0;\n";
|
|
||||||
break;
|
|
||||||
case "is not empty":
|
|
||||||
desc = "${" + variable + "} " + operator
|
|
||||||
script += "result = value != void && value.length() > 0;\n";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
let msg = "assertion [" + desc + "]: false;"
|
|
||||||
script += "if (!result){\n" +
|
|
||||||
"\tmsg = \"" + msg + "\";\n" +
|
|
||||||
"\tAssertionResult.setFailureMessage(msg);\n" +
|
|
||||||
"\tAssertionResult.setFailure(true);\n" +
|
|
||||||
"}";
|
|
||||||
|
|
||||||
this.assertion.desc = desc;
|
},
|
||||||
this.assertion.script = script;
|
detail() {
|
||||||
this.$refs.jsr233.reload();
|
this.visible = true;
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
this.visible = false;
|
||||||
|
},
|
||||||
|
confirm() {
|
||||||
|
if (!this.edit) {
|
||||||
|
this.add();
|
||||||
|
}
|
||||||
|
if (!this.assertion.desc) {
|
||||||
|
this.assertion.desc = this.assertion.script;
|
||||||
|
}
|
||||||
|
this.close();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
},
|
computed: {
|
||||||
detail() {
|
hasEmptyOperator() {
|
||||||
this.visible = true;
|
return !!this.assertion.operator && this.assertion.operator.indexOf("empty") > 0;
|
||||||
},
|
|
||||||
close() {
|
|
||||||
this.visible = false;
|
|
||||||
},
|
|
||||||
confirm() {
|
|
||||||
if (!this.edit) {
|
|
||||||
this.add();
|
|
||||||
}
|
}
|
||||||
if (!this.assertion.desc) {
|
|
||||||
this.assertion.desc = this.assertion.script;
|
|
||||||
}
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
hasEmptyOperator() {
|
|
||||||
return !!this.assertion.operator && this.assertion.operator.indexOf("empty") > 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.assertion-item {
|
.assertion-item {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.assertion-item + .assertion-item {
|
.assertion-item + .assertion-item {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.assertion-item.input {
|
.assertion-item.input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.assertion-item.select {
|
.assertion-item.select {
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.assertion-item.label {
|
.assertion-item.label {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.assertion-item.btn {
|
.assertion-item.btn {
|
||||||
min-width: 130px;
|
min-width: 130px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.assertion-item.btn.circle {
|
.assertion-item.btn.circle {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
min-width: 80px;
|
min-width: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.quick-script-block {
|
.quick-script-block {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
<el-dialog
|
<el-dialog
|
||||||
:title="$t('api_test.environment.select_environment')"
|
:title="$t('api_test.environment.select_environment')"
|
||||||
:visible.sync="dialogVisible"
|
:visible.sync="dialogVisible"
|
||||||
width="25%"
|
width="15%"
|
||||||
:destroy-on-close="true"
|
:destroy-on-close="true"
|
||||||
@close="handleClose"
|
@close="handleClose"
|
||||||
>
|
>
|
||||||
<el-form label-position="right" label-width="150px" size="medium" ref="form">
|
<el-form ref="form">
|
||||||
<el-form-item prop="type">
|
<el-form-item prop="type">
|
||||||
<el-select v-model="environmentId" value-key="id" size="small" class="ms-htt-width"
|
<el-select v-model="environmentId" value-key="id" class="ms-htt-width"
|
||||||
: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"
|
||||||
|
@ -22,6 +22,7 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<!-- <el-button onclick="this.handleClose">{{ $t('commons.cancel') }}</el-button>-->
|
<!-- <el-button onclick="this.handleClose">{{ $t('commons.cancel') }}</el-button>-->
|
||||||
<el-button type="primary" @click="createPerformance" @keydown.enter.native.prevent>
|
<el-button type="primary" @click="createPerformance" @keydown.enter.native.prevent>
|
||||||
|
|
|
@ -212,7 +212,8 @@
|
||||||
this.$emit('singleRun', data);
|
this.$emit('singleRun', data);
|
||||||
},
|
},
|
||||||
copyCase(data) {
|
copyCase(data) {
|
||||||
let obj = {name: "copy_" + data.name, priority: data.priority, active: true, request: data.request};
|
let uuid = getUUID();
|
||||||
|
let obj = {name: "copy_" + data.name, priority: data.priority, active: true, tags: data.tags, request: data.request, uuid: uuid};
|
||||||
this.$emit('copyCase', obj);
|
this.$emit('copyCase', obj);
|
||||||
},
|
},
|
||||||
selectTestCase(item, $event) {
|
selectTestCase(item, $event) {
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
<el-container v-loading="result.loading">
|
<el-container v-loading="result.loading">
|
||||||
<el-main>
|
<el-main>
|
||||||
<div v-for="(item,index) in apiCaseList" :key="index">
|
<div v-for="(item,index) in apiCaseList" :key="item.id ? item.id : item.uuid">
|
||||||
<api-case-item v-loading="singleLoading && singleRunId === item.id || batchLoadingIds.indexOf(item.id) > -1"
|
<api-case-item v-loading="singleLoading && singleRunId === item.id || batchLoadingIds.indexOf(item.id) > -1"
|
||||||
@refresh="refresh"
|
@refresh="refresh"
|
||||||
@singleRun="singleRun"
|
@singleRun="singleRun"
|
||||||
|
@ -243,7 +243,8 @@
|
||||||
if (!request.hashTree) {
|
if (!request.hashTree) {
|
||||||
request.hashTree = [];
|
request.hashTree = [];
|
||||||
}
|
}
|
||||||
let obj = {apiDefinitionId: this.api.id, name: '', priority: 'P0', active: true, tags: []};
|
let uuid = getUUID();
|
||||||
|
let obj = {apiDefinitionId: this.api.id, name: '', priority: 'P0', active: true, tags: [], uuid: uuid};
|
||||||
obj.request = request;
|
obj.request = request;
|
||||||
this.apiCaseList.unshift(obj);
|
this.apiCaseList.unshift(obj);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,8 +50,9 @@
|
||||||
<el-switch
|
<el-switch
|
||||||
v-model="swaggerSynchronization"
|
v-model="swaggerSynchronization"
|
||||||
@click.native="scheduleEdit"
|
@click.native="scheduleEdit"
|
||||||
:active-text="$t('api_test.api_import.timing_synchronization')">
|
>
|
||||||
</el-switch>
|
</el-switch>
|
||||||
|
<span style="color: #6C317C;cursor: pointer;font-weight: bold;margin-left: 10px" @click="scheduleEditByText">{{$t('api_test.api_import.timing_synchronization')}}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12"
|
<el-col :span="12"
|
||||||
|
@ -188,6 +189,9 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
scheduleEditByText(){
|
||||||
|
this.$refs.scheduleEdit.open(this.buildParam());
|
||||||
|
},
|
||||||
open(module) {
|
open(module) {
|
||||||
this.currentModule = module;
|
this.currentModule = module;
|
||||||
this.visible = true;
|
this.visible = true;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
@isApiListEnableChange="isApiListEnableChange">
|
@isApiListEnableChange="isApiListEnableChange">
|
||||||
<el-link type="primary" style="float:right;margin-top: 5px" @click="open">{{$t('commons.adv_search.title')}}</el-link>
|
<el-link type="primary" style="float:right;margin-top: 5px" @click="open">{{$t('commons.adv_search.title')}}</el-link>
|
||||||
|
|
||||||
<el-input placeholder="搜索" @blur="search" @keyup.enter.native="search" class="search-input" size="small"
|
<el-input :placeholder="$t('commons.search_by_id_name_tag')" @blur="search" @keyup.enter.native="search" class="search-input" size="small"
|
||||||
v-model="condition.name"/>
|
v-model="condition.name"/>
|
||||||
|
|
||||||
<el-table v-loading="result.loading"
|
<el-table v-loading="result.loading"
|
||||||
|
@ -124,7 +124,7 @@ import MsContainer from "../../../../common/components/MsContainer";
|
||||||
import MsBottomContainer from "../BottomContainer";
|
import MsBottomContainer from "../BottomContainer";
|
||||||
import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn";
|
import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn";
|
||||||
import MsBatchEdit from "../basis/BatchEdit";
|
import MsBatchEdit from "../basis/BatchEdit";
|
||||||
import {API_METHOD_COLOUR, CASE_PRIORITY, REQ_METHOD} from "../../model/JsonData";
|
import {API_METHOD_COLOUR, CASE_PRIORITY, DUBBO_METHOD, REQ_METHOD, SQL_METHOD, TCP_METHOD} from "../../model/JsonData";
|
||||||
|
|
||||||
import {getBodyUploadFiles, getCurrentProjectID} from "@/common/js/utils";
|
import {getBodyUploadFiles, getCurrentProjectID} from "@/common/js/utils";
|
||||||
import ApiListContainer from "./ApiListContainer";
|
import ApiListContainer from "./ApiListContainer";
|
||||||
|
@ -409,6 +409,15 @@ export default {
|
||||||
// }
|
// }
|
||||||
},
|
},
|
||||||
handleEditBatch() {
|
handleEditBatch() {
|
||||||
|
if(this.currentProtocol =='HTTP'){
|
||||||
|
this.valueArr.method = REQ_METHOD;
|
||||||
|
}else if(this.currentProtocol =='TCP'){
|
||||||
|
this.valueArr.method = TCP_METHOD;
|
||||||
|
}else if(this.currentProtocol =='SQL'){
|
||||||
|
this.valueArr.method = SQL_METHOD;
|
||||||
|
}else if(this.currentProtocol =='DUBBO'){
|
||||||
|
this.valueArr.method = DUBBO_METHOD;
|
||||||
|
}
|
||||||
this.$refs.batchEdit.open();
|
this.$refs.batchEdit.open();
|
||||||
},
|
},
|
||||||
batchEdit(form) {
|
batchEdit(form) {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
@isApiListEnableChange="isApiListEnableChange">
|
@isApiListEnableChange="isApiListEnableChange">
|
||||||
|
|
||||||
<el-link type="primary" @click="open" style="float: right;margin-top: 5px">{{$t('commons.adv_search.title')}}</el-link>
|
<el-link type="primary" @click="open" style="float: right;margin-top: 5px">{{$t('commons.adv_search.title')}}</el-link>
|
||||||
<el-input :placeholder="$t('api_monitor.please_search')" @blur="search" class="search-input" size="small" @keyup.enter.native="search"
|
<el-input :placeholder="$t('commons.search_by_id_name_tag')" @blur="search" class="search-input" size="small" @keyup.enter.native="search"
|
||||||
v-model="condition.name"/>
|
v-model="condition.name"/>
|
||||||
|
|
||||||
<el-table v-loading="result.loading"
|
<el-table v-loading="result.loading"
|
||||||
|
@ -162,11 +162,10 @@
|
||||||
import MsBottomContainer from "../BottomContainer";
|
import MsBottomContainer from "../BottomContainer";
|
||||||
import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn";
|
import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn";
|
||||||
import MsBatchEdit from "../basis/BatchEdit";
|
import MsBatchEdit from "../basis/BatchEdit";
|
||||||
import {API_METHOD_COLOUR, API_STATUS, REQ_METHOD} from "../../model/JsonData";
|
import {API_METHOD_COLOUR, API_STATUS, REQ_METHOD,TCP_METHOD,SQL_METHOD,DUBBO_METHOD} from "../../model/JsonData";
|
||||||
import {_filter, _sort, getCurrentProjectID} from "@/common/js/utils";
|
import {_filter, _sort, getCurrentProjectID} from "@/common/js/utils";
|
||||||
import {WORKSPACE_ID} from '@/common/js/constants';
|
import {WORKSPACE_ID} from '@/common/js/constants';
|
||||||
import ApiListContainer from "./ApiListContainer";
|
import ApiListContainer from "./ApiListContainer";
|
||||||
// import MsTableSelectAll from "../../../../common/components/table/MsTableSelectAll";
|
|
||||||
import MsTableHeaderSelectPopover from "@/business/components/common/components/table/MsTableHeaderSelectPopover";
|
import MsTableHeaderSelectPopover from "@/business/components/common/components/table/MsTableHeaderSelectPopover";
|
||||||
import ApiStatus from "@/business/components/api/definition/components/list/ApiStatus";
|
import ApiStatus from "@/business/components/api/definition/components/list/ApiStatus";
|
||||||
import MsTableAdvSearchBar from "@/business/components/common/components/search/MsTableAdvSearchBar";
|
import MsTableAdvSearchBar from "@/business/components/common/components/search/MsTableAdvSearchBar";
|
||||||
|
@ -274,7 +273,12 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created: function () {
|
created: function () {
|
||||||
this.condition.filters = {status: ["Prepare", "Underway", "Completed"]};
|
if (this.trashEnable) {
|
||||||
|
this.condition.filters = {status: ["Trash"]};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.condition.filters = {status: ["Prepare", "Underway", "Completed"]};
|
||||||
|
}
|
||||||
this.initTable();
|
this.initTable();
|
||||||
this.getMaintainerOptions();
|
this.getMaintainerOptions();
|
||||||
},
|
},
|
||||||
|
@ -336,10 +340,10 @@
|
||||||
}
|
}
|
||||||
if (this.condition.projectId) {
|
if (this.condition.projectId) {
|
||||||
this.result = this.$post("/api/definition/list/" + this.currentPage + "/" + this.pageSize, this.condition, response => {
|
this.result = this.$post("/api/definition/list/" + this.currentPage + "/" + this.pageSize, this.condition, response => {
|
||||||
|
this.genProtocalFilter(this.condition.protocol);
|
||||||
this.total = response.data.itemCount;
|
this.total = response.data.itemCount;
|
||||||
this.tableData = response.data.listObject;
|
this.tableData = response.data.listObject;
|
||||||
this.unSelection = response.data.listObject.map(s => s.id);
|
this.unSelection = response.data.listObject.map(s => s.id);
|
||||||
|
|
||||||
this.tableData.forEach(item => {
|
this.tableData.forEach(item => {
|
||||||
if (item.tags && item.tags.length > 0) {
|
if (item.tags && item.tags.length > 0) {
|
||||||
item.tags = JSON.parse(item.tags);
|
item.tags = JSON.parse(item.tags);
|
||||||
|
@ -348,6 +352,48 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
genProtocalFilter(protocalType){
|
||||||
|
if(protocalType === "HTTP"){
|
||||||
|
this.methodFilters = [
|
||||||
|
{text: 'GET', value: 'GET'},
|
||||||
|
{text: 'POST', value: 'POST'},
|
||||||
|
{text: 'PUT', value: 'PUT'},
|
||||||
|
{text: 'PATCH', value: 'PATCH'},
|
||||||
|
{text: 'DELETE', value: 'DELETE'},
|
||||||
|
{text: 'OPTIONS', value: 'OPTIONS'},
|
||||||
|
{text: 'HEAD', value: 'HEAD'},
|
||||||
|
{text: 'CONNECT', value: 'CONNECT'},
|
||||||
|
];
|
||||||
|
}else if(protocalType === "TCP"){
|
||||||
|
this.methodFilters = [
|
||||||
|
{text: 'TCP', value: 'TCP'},
|
||||||
|
];
|
||||||
|
}else if(protocalType === "SQL"){
|
||||||
|
this.methodFilters = [
|
||||||
|
{text: 'SQL', value: 'SQL'},
|
||||||
|
];
|
||||||
|
}else if(protocalType === "DUBBO"){
|
||||||
|
this.methodFilters = [
|
||||||
|
{text: 'DUBBO', value: 'DUBBO'},
|
||||||
|
{text: 'dubbo://', value: 'dubbo://'},
|
||||||
|
];
|
||||||
|
}else{
|
||||||
|
this.methodFilters = [
|
||||||
|
{text: 'GET', value: 'GET'},
|
||||||
|
{text: 'POST', value: 'POST'},
|
||||||
|
{text: 'PUT', value: 'PUT'},
|
||||||
|
{text: 'PATCH', value: 'PATCH'},
|
||||||
|
{text: 'DELETE', value: 'DELETE'},
|
||||||
|
{text: 'OPTIONS', value: 'OPTIONS'},
|
||||||
|
{text: 'HEAD', value: 'HEAD'},
|
||||||
|
{text: 'CONNECT', value: 'CONNECT'},
|
||||||
|
{text: 'DUBBO', value: 'DUBBO'},
|
||||||
|
{text: 'dubbo://', value: 'dubbo://'},
|
||||||
|
{text: 'SQL', value: 'SQL'},
|
||||||
|
{text: 'TCP', value: 'TCP'},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
},
|
||||||
getMaintainerOptions() {
|
getMaintainerOptions() {
|
||||||
let workspaceId = localStorage.getItem(WORKSPACE_ID);
|
let workspaceId = localStorage.getItem(WORKSPACE_ID);
|
||||||
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
|
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
|
||||||
|
@ -466,6 +512,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleEditBatch() {
|
handleEditBatch() {
|
||||||
|
if(this.currentProtocol =='HTTP'){
|
||||||
|
this.valueArr.method = REQ_METHOD;
|
||||||
|
}else if(this.currentProtocol =='TCP'){
|
||||||
|
this.valueArr.method = TCP_METHOD;
|
||||||
|
}else if(this.currentProtocol =='SQL'){
|
||||||
|
this.valueArr.method = SQL_METHOD;
|
||||||
|
}else if(this.currentProtocol =='DUBBO'){
|
||||||
|
this.valueArr.method = DUBBO_METHOD;
|
||||||
|
}
|
||||||
this.$refs.batchEdit.open();
|
this.$refs.batchEdit.open();
|
||||||
},
|
},
|
||||||
batchEdit(form) {
|
batchEdit(form) {
|
||||||
|
|
|
@ -180,10 +180,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
//创建根目录的模块---供父类使用
|
//创建根目录的模块---供父类使用
|
||||||
createRootModel(){
|
createRootModel() {
|
||||||
let dataArr = this.$refs.nodeTree.extendTreeNodes;
|
let dataArr = this.$refs.nodeTree.extendTreeNodes;
|
||||||
if(dataArr.length>0){
|
if (dataArr.length > 0) {
|
||||||
this.$refs.nodeTree.append({},dataArr[0]);
|
this.$refs.nodeTree.append({}, dataArr[0]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
exportAPI() {
|
exportAPI() {
|
||||||
|
@ -197,7 +197,6 @@
|
||||||
},
|
},
|
||||||
refresh() {
|
refresh() {
|
||||||
this.list();
|
this.list();
|
||||||
this.$emit("refreshTable");
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,22 +64,22 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
<!--<div v-if="showScript">-->
|
<!--<div v-if="showScript">-->
|
||||||
<!--<div v-for="row in request.hashTree" :key="row.id" v-loading="isReloadData" style="margin-left: 20px;width: 100%">-->
|
<!--<div v-for="row in request.hashTree" :key="row.id" v-loading="isReloadData" style="margin-left: 20px;width: 100%">-->
|
||||||
<!--<!– 前置脚本 –>-->
|
<!--<!– 前置脚本 –>-->
|
||||||
<!--<ms-jsr233-processor v-if="row.label ==='JSR223 PreProcessor'" @copyRow="copyRow" @remove="remove" :is-read-only="false" :title="$t('api_test.definition.request.pre_script')" style-type="color: #B8741A;background-color: #F9F1EA"-->
|
<!--<ms-jsr233-processor v-if="row.label ==='JSR223 PreProcessor'" @copyRow="copyRow" @remove="remove" :is-read-only="false" :title="$t('api_test.definition.request.pre_script')" style-type="color: #B8741A;background-color: #F9F1EA"-->
|
||||||
<!--:jsr223-processor="row"/>-->
|
<!--:jsr223-processor="row"/>-->
|
||||||
<!--<!–后置脚本–>-->
|
<!--<!–后置脚本–>-->
|
||||||
<!--<ms-jsr233-processor v-if="row.label ==='JSR223 PostProcessor'" @copyRow="copyRow" @remove="remove" :is-read-only="false" :title="$t('api_test.definition.request.post_script')" style-type="color: #783887;background-color: #F2ECF3"-->
|
<!--<ms-jsr233-processor v-if="row.label ==='JSR223 PostProcessor'" @copyRow="copyRow" @remove="remove" :is-read-only="false" :title="$t('api_test.definition.request.post_script')" style-type="color: #783887;background-color: #F2ECF3"-->
|
||||||
<!--:jsr223-processor="row"/>-->
|
<!--:jsr223-processor="row"/>-->
|
||||||
<!--<!–断言规则–>-->
|
<!--<!–断言规则–>-->
|
||||||
<!--<div style="margin-top: 10px">-->
|
<!--<div style="margin-top: 10px">-->
|
||||||
<!--<ms-api-assertions v-if="row.type==='Assertions'" @copyRow="copyRow" @remove="remove" :is-read-only="isReadOnly" :assertions="row"/>-->
|
<!--<ms-api-assertions v-if="row.type==='Assertions'" @copyRow="copyRow" @remove="remove" :is-read-only="isReadOnly" :assertions="row"/>-->
|
||||||
<!--</div>-->
|
<!--</div>-->
|
||||||
<!--<!–提取规则–>-->
|
<!--<!–提取规则–>-->
|
||||||
<!--<div style="margin-top: 10px">-->
|
<!--<div style="margin-top: 10px">-->
|
||||||
<!--<ms-api-extract :is-read-only="isReadOnly" @copyRow="copyRow" @remove="remove" v-if="row.type==='Extract'" :extract="row"/>-->
|
<!--<ms-api-extract :is-read-only="isReadOnly" @copyRow="copyRow" @remove="remove" v-if="row.type==='Extract'" :extract="row"/>-->
|
||||||
<!--</div>-->
|
<!--</div>-->
|
||||||
<!--</div>-->
|
<!--</div>-->
|
||||||
<!--</div>-->
|
<!--</div>-->
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="3" class="ms-left-cell" v-if="showScript">
|
<el-col :span="3" class="ms-left-cell" v-if="showScript">
|
||||||
|
@ -225,6 +225,9 @@
|
||||||
if (!hasEnvironment) {
|
if (!hasEnvironment) {
|
||||||
this.request.environmentId = undefined;
|
this.request.environmentId = undefined;
|
||||||
}
|
}
|
||||||
|
if (!this.request.environmentId) {
|
||||||
|
this.request.dataSourceId = undefined;
|
||||||
|
}
|
||||||
this.initDataSource();
|
this.initDataSource();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -232,15 +235,22 @@
|
||||||
this.$refs.environmentConfig.open(getCurrentProjectID());
|
this.$refs.environmentConfig.open(getCurrentProjectID());
|
||||||
},
|
},
|
||||||
initDataSource() {
|
initDataSource() {
|
||||||
|
let flag = false;
|
||||||
for (let i in this.environments) {
|
for (let i in this.environments) {
|
||||||
if (this.environments[i].id === this.request.environmentId) {
|
if (this.environments[i].id === this.request.environmentId) {
|
||||||
this.databaseConfigsOptions = [];
|
this.databaseConfigsOptions = [];
|
||||||
this.environments[i].config.databaseConfigs.forEach(item => {
|
this.environments[i].config.databaseConfigs.forEach(item => {
|
||||||
|
if (item.id === this.request.dataSourceId) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
this.databaseConfigsOptions.push(item);
|
this.databaseConfigsOptions.push(item);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!flag) {
|
||||||
|
this.request.dataSourceId = undefined;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setDataSource() {
|
setDataSource() {
|
||||||
for (let item of this.databaseConfigsOptions) {
|
for (let item of this.databaseConfigsOptions) {
|
||||||
|
|
|
@ -86,10 +86,9 @@
|
||||||
import ApiRequestMethodSelect from "../../collapse/ApiRequestMethodSelect";
|
import ApiRequestMethodSelect from "../../collapse/ApiRequestMethodSelect";
|
||||||
import {REQUEST_HEADERS} from "@/common/js/constants";
|
import {REQUEST_HEADERS} from "@/common/js/constants";
|
||||||
import MsApiVariable from "../../ApiVariable";
|
import MsApiVariable from "../../ApiVariable";
|
||||||
import {createComponent} from "../../jmeter/components";
|
|
||||||
import MsApiAssertions from "../../assertion/ApiAssertions";
|
import MsApiAssertions from "../../assertion/ApiAssertions";
|
||||||
import MsApiExtract from "../../extract/ApiExtract";
|
import MsApiExtract from "../../extract/ApiExtract";
|
||||||
import {Assertions, Body, Extract, KeyValue} from "../../../model/ApiTestModel";
|
import {Body, KeyValue} from "../../../model/ApiTestModel";
|
||||||
import {getUUID} from "@/common/js/utils";
|
import {getUUID} from "@/common/js/utils";
|
||||||
import BatchAddParameter from "../../basis/BatchAddParameter";
|
import BatchAddParameter from "../../basis/BatchAddParameter";
|
||||||
import MsApiAdvancedConfig from "./ApiAdvancedConfig";
|
import MsApiAdvancedConfig from "./ApiAdvancedConfig";
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane :label="$t('api_test.definition.request.response_header')" name="headers" class="pane">
|
<el-tab-pane :label="$t('api_test.definition.request.response_header')" name="headers" class="pane">
|
||||||
<pre>{{ response.responseResult.headers }}</pre>
|
<div style="width: 400px">
|
||||||
|
<pre>{{ response.responseResult.headers }}</pre>
|
||||||
|
</div>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<!--<el-tab-pane label="Cookie" name="cookie" class="pane cookie">-->
|
<!--<el-tab-pane label="Cookie" name="cookie" class="pane cookie">-->
|
||||||
<!--<pre>{{response.cookies}}</pre>-->
|
<!--<pre>{{response.cookies}}</pre>-->
|
||||||
|
@ -25,7 +27,9 @@
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane :label="$t('api_test.request.extract.label')" name="label" class="pane">
|
<el-tab-pane :label="$t('api_test.request.extract.label')" name="label" class="pane">
|
||||||
<pre>{{response.responseResult.vars}}</pre>
|
<div style="width: 400px">
|
||||||
|
<pre>{{response.responseResult.vars}}</pre>
|
||||||
|
</div>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane :label="$t('api_report.request_body')" name="request_body" class="pane">
|
<el-tab-pane :label="$t('api_report.request_body')" name="request_body" class="pane">
|
||||||
|
|
|
@ -44,6 +44,15 @@ export const REQ_METHOD = [
|
||||||
{id: 'HEAD', label: 'HEAD'},
|
{id: 'HEAD', label: 'HEAD'},
|
||||||
{id: 'CONNECT', label: 'CONNECT'}
|
{id: 'CONNECT', label: 'CONNECT'}
|
||||||
]
|
]
|
||||||
|
export const TCP_METHOD = [
|
||||||
|
{id: 'TCP', label: 'TCP'}
|
||||||
|
]
|
||||||
|
export const SQL_METHOD = [
|
||||||
|
{id: 'SQL', label: 'SQL'}
|
||||||
|
]
|
||||||
|
export const DUBBO_METHOD = [
|
||||||
|
{id: 'dubbo://', label: 'dubbo://'},
|
||||||
|
]
|
||||||
|
|
||||||
export const CASE_PRIORITY = [
|
export const CASE_PRIORITY = [
|
||||||
{id: 'P0', label: 'P0'},
|
{id: 'P0', label: 'P0'},
|
||||||
|
|
|
@ -35,8 +35,8 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<el-button class="ht-btn-add" size="mini" p="$t('commons.add')" icon="el-icon-circle-plus-outline" @click="add">添加
|
<el-button class="ht-btn-add" size="mini" p="$t('commons.add')" icon="el-icon-circle-plus-outline" @click="add">{{$t("commons.add")}}</el-button>
|
||||||
</el-button>
|
<el-button class="ht-btn-add" size="mini" p="$t('commons.add')" icon="el-icon-files" @click="copy">{{$t("commons.copy")}}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -68,6 +68,16 @@
|
||||||
this.$emit('change', this.hostTable);
|
this.$emit('change', this.hostTable);
|
||||||
},
|
},
|
||||||
add: function (r) {
|
add: function (r) {
|
||||||
|
let row = {
|
||||||
|
ip: '',
|
||||||
|
domain: '',
|
||||||
|
status: 'edit',
|
||||||
|
annotation: '',
|
||||||
|
uuid: this.uuid(),
|
||||||
|
}
|
||||||
|
this.hostTable.push(row);
|
||||||
|
},
|
||||||
|
copy: function (r) {
|
||||||
let row = {
|
let row = {
|
||||||
ip: '',
|
ip: '',
|
||||||
domain: '',
|
domain: '',
|
||||||
|
|
|
@ -15,23 +15,6 @@
|
||||||
props: ['total', 'pageSize'],
|
props: ['total', 'pageSize'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
gridData: [{
|
|
||||||
date: '2016-05-02',
|
|
||||||
name: '王小虎',
|
|
||||||
address: '上海市普陀区金沙江路 1518 弄'
|
|
||||||
}, {
|
|
||||||
date: '2016-05-04',
|
|
||||||
name: '王小虎',
|
|
||||||
address: '上海市普陀区金沙江路 1518 弄'
|
|
||||||
}, {
|
|
||||||
date: '2016-05-01',
|
|
||||||
name: '王小虎',
|
|
||||||
address: '上海市普陀区金沙江路 1518 弄'
|
|
||||||
}, {
|
|
||||||
date: '2016-05-03',
|
|
||||||
name: '王小虎',
|
|
||||||
address: '上海市普陀区金沙江路 1518 弄'
|
|
||||||
}]
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<span v-if="triggerMode === 'SCHEDULE'">{{$t('commons.trigger_mode.schedule')}}</span>
|
<span v-if="triggerMode === 'SCHEDULE'">{{$t('commons.trigger_mode.schedule')}}</span>
|
||||||
<span v-if="triggerMode === 'TEST_PLAN_SCHEDULE'">{{$t('commons.trigger_mode.schedule')}}</span>
|
<span v-if="triggerMode === 'TEST_PLAN_SCHEDULE'">{{$t('commons.trigger_mode.schedule')}}</span>
|
||||||
<span v-if="triggerMode === 'API'">{{$t('commons.trigger_mode.api')}}</span>
|
<span v-if="triggerMode === 'API'">{{$t('commons.trigger_mode.api')}}</span>
|
||||||
<span v-if="triggerMode === 'CASE'">用例触发</span>
|
<span v-if="triggerMode === 'CASE'">{{$t('commons.trigger_mode.case')}}</span>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,7 @@ export default {
|
||||||
{text: this.$t('commons.trigger_mode.manual'), value: 'MANUAL'},
|
{text: this.$t('commons.trigger_mode.manual'), value: 'MANUAL'},
|
||||||
{text: this.$t('commons.trigger_mode.schedule'), value: 'SCHEDULE'},
|
{text: this.$t('commons.trigger_mode.schedule'), value: 'SCHEDULE'},
|
||||||
{text: this.$t('commons.trigger_mode.api'), value: 'API'},
|
{text: this.$t('commons.trigger_mode.api'), value: 'API'},
|
||||||
|
{text: this.$t('commons.trigger_mode.case'), value: 'CASE'},
|
||||||
],
|
],
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<el-tab-pane v-if="hasLicense()" :label="$t('display.title')" name="display">
|
<el-tab-pane v-if="hasLicense()" :label="$t('display.title')" name="display">
|
||||||
<ms-display/>
|
<ms-display/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane v-if="hasLicense()" :label="'认证设置'" name="auth">
|
<el-tab-pane v-if="hasLicense()" :label="$t('auth_source.title')" name="auth">
|
||||||
<ms-auth/>
|
<ms-auth/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
|
|
@ -81,7 +81,8 @@
|
||||||
if (size) {
|
if (size) {
|
||||||
this.size = size;
|
this.size = size;
|
||||||
} else {
|
} else {
|
||||||
this.size = this.$parent.selectRows.size;
|
// this.size = this.$parent.selectRows.size;
|
||||||
|
this.size = this.$parent.selectDataCounts;
|
||||||
}
|
}
|
||||||
listenGoBack(this.handleClose);
|
listenGoBack(this.handleClose);
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
:filter-node-method="filterNode"
|
:filter-node-method="filterNode"
|
||||||
:expand-on-click-node="false"
|
:expand-on-click-node="false"
|
||||||
highlight-current
|
highlight-current
|
||||||
|
style="overflow: auto"
|
||||||
@node-click="nodeClick"
|
@node-click="nodeClick"
|
||||||
ref="tree"
|
ref="tree"
|
||||||
>
|
>
|
||||||
|
|
|
@ -31,14 +31,14 @@
|
||||||
@select="handleSelect"
|
@select="handleSelect"
|
||||||
@cell-mouse-enter="showPopover"
|
@cell-mouse-enter="showPopover"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
class="test-content adjust-table ms-select-all"
|
class="test-content adjust-table ms-select-all-fixed"
|
||||||
ref="table" @row-click="handleEdit">
|
ref="table" @row-click="handleEdit">
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
width="50"
|
width="50"
|
||||||
type="selection"/>
|
type="selection"/>
|
||||||
|
|
||||||
<ms-table-select-all
|
<ms-table-header-select-popover v-show="total>0"
|
||||||
:page-size="pageSize > total ? total : pageSize"
|
:page-size="pageSize > total ? total : pageSize"
|
||||||
:total="total"
|
:total="total"
|
||||||
@selectPageAll="isSelectDataAll(false)"
|
@selectPageAll="isSelectDataAll(false)"
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
<el-table-column width="40" :resizable="false" align="center">
|
<el-table-column width="40" :resizable="false" align="center">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectRows.size"/>
|
<show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectDataCounts"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
|
@ -78,6 +78,7 @@
|
||||||
prop="priority"
|
prop="priority"
|
||||||
:filters="priorityFilters"
|
:filters="priorityFilters"
|
||||||
column-key="priority"
|
column-key="priority"
|
||||||
|
min-width="100px"
|
||||||
:label="$t('test_track.case.priority')"
|
:label="$t('test_track.case.priority')"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
|
@ -98,6 +99,7 @@
|
||||||
prop="method"
|
prop="method"
|
||||||
column-key="method"
|
column-key="method"
|
||||||
:filters="methodFilters"
|
:filters="methodFilters"
|
||||||
|
min-width="100px"
|
||||||
:label="$t('test_track.case.method')"
|
:label="$t('test_track.case.method')"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
|
@ -108,6 +110,7 @@
|
||||||
<el-table-column
|
<el-table-column
|
||||||
:filters="statusFilters"
|
:filters="statusFilters"
|
||||||
column-key="status"
|
column-key="status"
|
||||||
|
min-width="100px"
|
||||||
:label="$t('test_track.case.status')">
|
:label="$t('test_track.case.status')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<span class="el-dropdown-link">
|
<span class="el-dropdown-link">
|
||||||
|
@ -127,6 +130,7 @@
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="nodePath"
|
prop="nodePath"
|
||||||
:label="$t('test_track.case.module')"
|
:label="$t('test_track.case.module')"
|
||||||
|
min-width="150px"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
|
@ -134,12 +138,13 @@
|
||||||
prop="updateTime"
|
prop="updateTime"
|
||||||
sortable="custom"
|
sortable="custom"
|
||||||
:label="$t('commons.update_time')"
|
:label="$t('commons.update_time')"
|
||||||
|
min-width="150px"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column fixed="right"
|
||||||
:label="$t('commons.operating')" min-width="150">
|
:label="$t('commons.operating')" min-width="150">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<ms-table-operator :is-tester-permission="true" @editClick="handleEdit(scope.row)"
|
<ms-table-operator :is-tester-permission="true" @editClick="handleEdit(scope.row)"
|
||||||
|
@ -169,6 +174,7 @@
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import MsCreateBox from '../../../settings/CreateBox';
|
import MsCreateBox from '../../../settings/CreateBox';
|
||||||
|
import MsTableHeaderSelectPopover from "@/business/components/common/components/table/MsTableHeaderSelectPopover";
|
||||||
import TestCaseImport from '../components/TestCaseImport';
|
import TestCaseImport from '../components/TestCaseImport';
|
||||||
import TestCaseExport from '../components/TestCaseExport';
|
import TestCaseExport from '../components/TestCaseExport';
|
||||||
import MsTablePagination from '../../../../components/common/pagination/TablePagination';
|
import MsTablePagination from '../../../../components/common/pagination/TablePagination';
|
||||||
|
@ -191,7 +197,6 @@ import TestCaseDetail from "./TestCaseDetail";
|
||||||
import ReviewStatus from "@/business/components/track/case/components/ReviewStatus";
|
import ReviewStatus from "@/business/components/track/case/components/ReviewStatus";
|
||||||
import {getCurrentProjectID} from "../../../../../common/js/utils";
|
import {getCurrentProjectID} from "../../../../../common/js/utils";
|
||||||
import MsTag from "@/business/components/common/components/MsTag";
|
import MsTag from "@/business/components/common/components/MsTag";
|
||||||
import MsTableSelectAll from "../../../common/components/table/MsTableSelectAll";
|
|
||||||
import {_handleSelect, _handleSelectAll} from "../../../../../common/js/tableUtils";
|
import {_handleSelect, _handleSelectAll} from "../../../../../common/js/tableUtils";
|
||||||
import BatchMove from "./BatchMove";
|
import BatchMove from "./BatchMove";
|
||||||
|
|
||||||
|
@ -199,7 +204,7 @@ export default {
|
||||||
name: "TestCaseList",
|
name: "TestCaseList",
|
||||||
components: {
|
components: {
|
||||||
BatchMove,
|
BatchMove,
|
||||||
MsTableSelectAll,
|
MsTableHeaderSelectPopover,
|
||||||
MsTableButton,
|
MsTableButton,
|
||||||
MsTableOperatorButton,
|
MsTableOperatorButton,
|
||||||
MsTableOperator,
|
MsTableOperator,
|
||||||
|
@ -287,6 +292,7 @@ export default {
|
||||||
},
|
},
|
||||||
currentCaseId: null,
|
currentCaseId: null,
|
||||||
projectId: "",
|
projectId: "",
|
||||||
|
selectDataCounts: 0,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -323,6 +329,7 @@ export default {
|
||||||
this.condition.nodeIds = [];
|
this.condition.nodeIds = [];
|
||||||
this.condition.selectAll = false;
|
this.condition.selectAll = false;
|
||||||
this.condition.unSelectIds = [];
|
this.condition.unSelectIds = [];
|
||||||
|
this.selectDataCounts = 0;
|
||||||
if (this.planId) {
|
if (this.planId) {
|
||||||
// param.planId = this.planId;
|
// param.planId = this.planId;
|
||||||
this.condition.planId = this.planId;
|
this.condition.planId = this.planId;
|
||||||
|
@ -430,6 +437,7 @@ export default {
|
||||||
_handleSelect(this, selection, row, this.selectRows);
|
_handleSelect(this, selection, row, this.selectRows);
|
||||||
this.setUnSelectIds();
|
this.setUnSelectIds();
|
||||||
},
|
},
|
||||||
|
|
||||||
importTestCase() {
|
importTestCase() {
|
||||||
if (!getCurrentProjectID()) {
|
if (!getCurrentProjectID()) {
|
||||||
this.$warning(this.$t('commons.check_project_tip'));
|
this.$warning(this.$t('commons.check_project_tip'));
|
||||||
|
@ -548,6 +556,11 @@ export default {
|
||||||
this.condition.unSelectIds = allIDs.filter(function (val) {
|
this.condition.unSelectIds = allIDs.filter(function (val) {
|
||||||
return ids.indexOf(val) === -1
|
return ids.indexOf(val) === -1
|
||||||
});
|
});
|
||||||
|
if (this.condition.selectAll) {
|
||||||
|
this.selectDataCounts = this.total - this.condition.unSelectIds.length;
|
||||||
|
} else {
|
||||||
|
this.selectDataCounts = this.selectRows.size;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
moveSave(param) {
|
moveSave(param) {
|
||||||
param.condition = this.condition;
|
param.condition = this.condition;
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="tagNames" :label="$t('api_test.automation.tag')" width="200px">
|
<el-table-column prop="tagNames" :label="$t('api_test.automation.tag')" width="200px">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<div v-for="itemName in scope.row.tagNames" :key="itemName">
|
<div v-for="itemName in scope.row.tags" :key="itemName">
|
||||||
<ms-tag type="success" effect="plain" :content="itemName"/>
|
<ms-tag type="success" effect="plain" :content="itemName"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -89,9 +89,6 @@
|
||||||
selectRows: new Set()
|
selectRows: new Set()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
|
||||||
this.search();
|
|
||||||
},
|
|
||||||
watch: {
|
watch: {
|
||||||
selectNodeIds() {
|
selectNodeIds() {
|
||||||
this.search();
|
this.search();
|
||||||
|
@ -102,6 +99,9 @@
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
search() {
|
search() {
|
||||||
|
if (!this.projectId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.selectRows = new Set();
|
this.selectRows = new Set();
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
||||||
|
@ -122,6 +122,11 @@
|
||||||
let data = response.data;
|
let data = response.data;
|
||||||
this.total = data.itemCount;
|
this.total = data.itemCount;
|
||||||
this.tableData = data.listObject;
|
this.tableData = data.listObject;
|
||||||
|
this.tableData.forEach(item => {
|
||||||
|
if (item.tags && item.tags.length > 0) {
|
||||||
|
item.tags = JSON.parse(item.tags);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleSelectAll(selection) {
|
handleSelectAll(selection) {
|
||||||
|
|
|
@ -75,6 +75,9 @@
|
||||||
methods: {
|
methods: {
|
||||||
open() {
|
open() {
|
||||||
this.$refs.baseRelevance.open();
|
this.$refs.baseRelevance.open();
|
||||||
|
if (this.$refs.apiScenarioList) {
|
||||||
|
this.$refs.apiScenarioList.search();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setProject(projectId) {
|
setProject(projectId) {
|
||||||
this.projectId = projectId;
|
this.projectId = projectId;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
<show-more-btn :is-show="isSelect(row)" :buttons="buttons" :size="selectRows.length"/>
|
<show-more-btn :is-show="isSelect(row)" :buttons="buttons" :size="selectRows.length"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column prop="num" label="ID"/>
|
||||||
<el-table-column prop="name" :label="$t('api_test.automation.scenario_name')"
|
<el-table-column prop="name" :label="$t('api_test.automation.scenario_name')"
|
||||||
show-overflow-tooltip/>
|
show-overflow-tooltip/>
|
||||||
<el-table-column prop="level" :label="$t('api_test.automation.case_level')"
|
<el-table-column prop="level" :label="$t('api_test.automation.case_level')"
|
||||||
|
@ -29,7 +30,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="tagNames" :label="$t('api_test.automation.tag')" width="200px">
|
<el-table-column prop="tagNames" :label="$t('api_test.automation.tag')" width="200px">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<div v-for="itemName in scope.row.tagNames" :key="itemName">
|
<div v-for="(itemName,index) in scope.row.tags" :key="index">
|
||||||
<ms-tag type="success" effect="plain" :content="itemName"/>
|
<ms-tag type="success" effect="plain" :content="itemName"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -159,6 +160,11 @@
|
||||||
let data = response.data;
|
let data = response.data;
|
||||||
this.total = data.itemCount;
|
this.total = data.itemCount;
|
||||||
this.tableData = data.listObject;
|
this.tableData = data.listObject;
|
||||||
|
this.tableData.forEach(item => {
|
||||||
|
if (item.tags && item.tags.length > 0) {
|
||||||
|
item.tags = JSON.parse(item.tags);
|
||||||
|
}
|
||||||
|
});
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
:condition="condition"
|
:condition="condition"
|
||||||
@search="$emit('refresh')"
|
@search="$emit('refresh')"
|
||||||
:show-create="false"
|
:show-create="false"
|
||||||
:tip="$t('commons.search_by_name_or_id')">
|
:tip="$t('commons.search_by_id_name_tag')">
|
||||||
<template v-slot:title>
|
<template v-slot:title>
|
||||||
场景用例
|
场景用例
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -76,6 +76,14 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column prop="tags" :label="$t('commons.tag')">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<div v-for="(tag, index) in scope.row.showTags" :key="tag + '_' + index">
|
||||||
|
<ms-tag type="success" effect="plain" :content="tag"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="method"
|
prop="method"
|
||||||
:filters="methodFilters"
|
:filters="methodFilters"
|
||||||
|
@ -179,8 +187,9 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
min-width="100"
|
fixed="right"
|
||||||
:label="$t('commons.operating')">
|
min-width="100"
|
||||||
|
:label="$t('commons.operating')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<ms-table-operator-button :is-tester-permission="true" :tip="$t('commons.edit')" icon="el-icon-edit"
|
<ms-table-operator-button :is-tester-permission="true" :tip="$t('commons.edit')" icon="el-icon-edit"
|
||||||
@exec="handleEdit(scope.row)"/>
|
@exec="handleEdit(scope.row)"/>
|
||||||
|
@ -231,6 +240,7 @@ import ShowMoreBtn from "../../../../case/components/ShowMoreBtn";
|
||||||
import BatchEdit from "../../../../case/components/BatchEdit";
|
import BatchEdit from "../../../../case/components/BatchEdit";
|
||||||
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
|
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
|
||||||
import {hub} from "@/business/components/track/plan/event-bus";
|
import {hub} from "@/business/components/track/plan/event-bus";
|
||||||
|
import MsTag from "@/business/components/common/components/MsTag";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "FunctionalTestCaseList",
|
name: "FunctionalTestCaseList",
|
||||||
|
@ -243,7 +253,7 @@ export default {
|
||||||
StatusTableItem,
|
StatusTableItem,
|
||||||
PriorityTableItem, StatusEdit, ExecutorEdit, MsTipButton, MsTablePagination,
|
PriorityTableItem, StatusEdit, ExecutorEdit, MsTipButton, MsTablePagination,
|
||||||
MsTableHeader, NodeBreadcrumb, MsTableButton, ShowMoreBtn,
|
MsTableHeader, NodeBreadcrumb, MsTableButton, ShowMoreBtn,
|
||||||
BatchEdit
|
BatchEdit, MsTag
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -257,7 +267,7 @@ export default {
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 0,
|
total: 0,
|
||||||
status:'default',
|
status: 'default',
|
||||||
selectRows: new Set(),
|
selectRows: new Set(),
|
||||||
testPlan: {},
|
testPlan: {},
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
|
@ -319,7 +329,7 @@ export default {
|
||||||
planId: {
|
planId: {
|
||||||
type: String
|
type: String
|
||||||
},
|
},
|
||||||
clickType:String,
|
clickType: String,
|
||||||
selectNodeIds: {
|
selectNodeIds: {
|
||||||
type: Array
|
type: Array
|
||||||
},
|
},
|
||||||
|
@ -354,10 +364,10 @@ export default {
|
||||||
// param.planId = this.planId;
|
// param.planId = this.planId;
|
||||||
this.condition.planId = this.planId;
|
this.condition.planId = this.planId;
|
||||||
}
|
}
|
||||||
if(this.clickType){
|
if (this.clickType) {
|
||||||
if(this.status =='default'){
|
if (this.status == 'default') {
|
||||||
this.condition.status = this.clickType;
|
this.condition.status = this.clickType;
|
||||||
}else{
|
} else {
|
||||||
this.condition.status = null;
|
this.condition.status = null;
|
||||||
}
|
}
|
||||||
this.status = 'all';
|
this.status = 'all';
|
||||||
|
@ -373,6 +383,7 @@ export default {
|
||||||
this.tableData = data.listObject;
|
this.tableData = data.listObject;
|
||||||
for (let i = 0; i < this.tableData.length; i++) {
|
for (let i = 0; i < this.tableData.length; i++) {
|
||||||
if (this.tableData[i]) {
|
if (this.tableData[i]) {
|
||||||
|
this.$set(this.tableData[i], "showTags", JSON.parse(this.tableData[i].tags));
|
||||||
this.$set(this.tableData[i], "issuesSize", 0);
|
this.$set(this.tableData[i], "issuesSize", 0);
|
||||||
this.$get("/issues/get/" + this.tableData[i].caseId).then(response => {
|
this.$get("/issues/get/" + this.tableData[i].caseId).then(response => {
|
||||||
let issues = response.data.data;
|
let issues = response.data.data;
|
||||||
|
@ -381,7 +392,11 @@ export default {
|
||||||
this.$set(this.tableData[i], "issuesContent", issues);
|
this.$set(this.tableData[i], "issuesContent", issues);
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.$set(this.tableData[i], "issuesContent", [{title: '获取缺陷失败',description: '获取缺陷失败',platform: '获取缺陷失败' }]);
|
this.$set(this.tableData[i], "issuesContent", [{
|
||||||
|
title: '获取缺陷失败',
|
||||||
|
description: '获取缺陷失败',
|
||||||
|
platform: '获取缺陷失败'
|
||||||
|
}]);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -597,4 +612,7 @@ export default {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-tag {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -32,7 +32,7 @@ export default {
|
||||||
operating: 'Operating',
|
operating: 'Operating',
|
||||||
input_limit: 'Within {0} and {1} characters',
|
input_limit: 'Within {0} and {1} characters',
|
||||||
login: 'Sign In',
|
login: 'Sign In',
|
||||||
welcome: 'Welcome back, please enter username and password to log in',
|
welcome: 'One-stop open source continuous testing platform',
|
||||||
username: 'Username',
|
username: 'Username',
|
||||||
password: 'Password',
|
password: 'Password',
|
||||||
input_username: 'Please enter username',
|
input_username: 'Please enter username',
|
||||||
|
@ -150,7 +150,8 @@ export default {
|
||||||
name: "Trigger Mode",
|
name: "Trigger Mode",
|
||||||
manual: "Manual trigger",
|
manual: "Manual trigger",
|
||||||
schedule: "Scheduled Task",
|
schedule: "Scheduled Task",
|
||||||
api: "API call"
|
api: "API call",
|
||||||
|
case: "Case"
|
||||||
},
|
},
|
||||||
adv_search: {
|
adv_search: {
|
||||||
title: 'Advanced Search',
|
title: 'Advanced Search',
|
||||||
|
@ -602,6 +603,7 @@ export default {
|
||||||
customize_req: "Customize req",
|
customize_req: "Customize req",
|
||||||
reference_info: "Reference info",
|
reference_info: "Reference info",
|
||||||
scenario_test: "Scenario test",
|
scenario_test: "Scenario test",
|
||||||
|
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",
|
||||||
|
@ -1499,6 +1501,7 @@ export default {
|
||||||
format: "Output format",
|
format: "Output format",
|
||||||
},
|
},
|
||||||
auth_source: {
|
auth_source: {
|
||||||
delete_prompt: 'This operation will delete the authentication source, do you want to continue? '
|
delete_prompt: 'This operation will delete the authentication source, do you want to continue? ',
|
||||||
|
title: 'Auth Source'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,7 +33,7 @@ export default {
|
||||||
operating: '操作',
|
operating: '操作',
|
||||||
input_limit: '长度在 {0} 到 {1} 个字符',
|
input_limit: '长度在 {0} 到 {1} 个字符',
|
||||||
login: '登录',
|
login: '登录',
|
||||||
welcome: '欢迎回来,请输入用户名和密码登录',
|
welcome: '一站式开源持续测试平台',
|
||||||
username: '姓名',
|
username: '姓名',
|
||||||
password: '密码',
|
password: '密码',
|
||||||
input_username: '请输入用户姓名',
|
input_username: '请输入用户姓名',
|
||||||
|
@ -151,7 +151,8 @@ export default {
|
||||||
name: "触发方式",
|
name: "触发方式",
|
||||||
manual: "手动触发",
|
manual: "手动触发",
|
||||||
schedule: "定时任务",
|
schedule: "定时任务",
|
||||||
api: "API调用"
|
api: "API调用",
|
||||||
|
case: "用例触发"
|
||||||
},
|
},
|
||||||
adv_search: {
|
adv_search: {
|
||||||
title: '高级搜索',
|
title: '高级搜索',
|
||||||
|
@ -603,6 +604,7 @@ export default {
|
||||||
customize_req: "自定义请求",
|
customize_req: "自定义请求",
|
||||||
reference_info: "请选择接口或用例",
|
reference_info: "请选择接口或用例",
|
||||||
scenario_test: "场景",
|
scenario_test: "场景",
|
||||||
|
scenario_list: "场景列表",
|
||||||
add_scenario: "创建场景",
|
add_scenario: "创建场景",
|
||||||
scenario_name: "场景名称",
|
scenario_name: "场景名称",
|
||||||
case_level: "用例等级",
|
case_level: "用例等级",
|
||||||
|
@ -1502,6 +1504,7 @@ export default {
|
||||||
format: "输出格式",
|
format: "输出格式",
|
||||||
},
|
},
|
||||||
auth_source: {
|
auth_source: {
|
||||||
delete_prompt: '此操作会删除认证源,是否继续?'
|
delete_prompt: '此操作会删除认证源,是否继续?',
|
||||||
|
title: '认证设置'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,7 +33,7 @@ export default {
|
||||||
operating: '操作',
|
operating: '操作',
|
||||||
input_limit: '長度在 {0} 到 {1} 個字符',
|
input_limit: '長度在 {0} 到 {1} 個字符',
|
||||||
login: '登錄',
|
login: '登錄',
|
||||||
welcome: '歡迎回來,請輸入用戶名和密碼登錄',
|
welcome: '壹站式開源持續測試平臺',
|
||||||
username: '姓名',
|
username: '姓名',
|
||||||
password: '密碼',
|
password: '密碼',
|
||||||
input_username: '請輸入用戶姓名',
|
input_username: '請輸入用戶姓名',
|
||||||
|
@ -151,7 +151,8 @@ export default {
|
||||||
name: "觸發方式",
|
name: "觸發方式",
|
||||||
manual: "手動觸發",
|
manual: "手動觸發",
|
||||||
schedule: "定時任務",
|
schedule: "定時任務",
|
||||||
api: "API調用"
|
api: "API調用",
|
||||||
|
case: "用例觸發"
|
||||||
},
|
},
|
||||||
adv_search: {
|
adv_search: {
|
||||||
title: '高級搜索',
|
title: '高級搜索',
|
||||||
|
@ -602,6 +603,7 @@ export default {
|
||||||
customize_req: "自定義請求",
|
customize_req: "自定義請求",
|
||||||
reference_info: "請選擇接口或用例",
|
reference_info: "請選擇接口或用例",
|
||||||
scenario_test: "場景",
|
scenario_test: "場景",
|
||||||
|
scenario_list: "場景列表",
|
||||||
add_scenario: "創建場景",
|
add_scenario: "創建場景",
|
||||||
scenario_name: "場景名稱",
|
scenario_name: "場景名稱",
|
||||||
case_level: "用例等級",
|
case_level: "用例等級",
|
||||||
|
@ -1500,6 +1502,7 @@ export default {
|
||||||
format: "輸出格式",
|
format: "輸出格式",
|
||||||
},
|
},
|
||||||
auth_source: {
|
auth_source: {
|
||||||
delete_prompt: '此操作會刪除認證源,是否繼續? '
|
delete_prompt: '此操作會刪除認證源,是否繼續? ',
|
||||||
|
title: '認證設置'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,33 +2,36 @@
|
||||||
<div class="container" v-loading="result.loading" v-if="ready">
|
<div class="container" v-loading="result.loading" v-if="ready">
|
||||||
<el-row type="flex">
|
<el-row type="flex">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form :model="form" :rules="rules" ref="form">
|
|
||||||
<div class="logo">
|
<div class="title">
|
||||||
<img :src="'/display/file/loginLogo'" style="width: 224px;height: 45px;" alt="">
|
<div class="title-img">
|
||||||
|
<img :src="'/display/file/loginLogo'" alt="">
|
||||||
</div>
|
</div>
|
||||||
<div class="title">
|
|
||||||
<span id="s1">{{ loginTitle }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="border"></div>
|
|
||||||
<div class="welcome">
|
<div class="welcome">
|
||||||
{{ $t('commons.welcome') }}
|
<span>Metersphere</span>
|
||||||
|
<span>{{ $t('commons.welcome') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
<div class="form">
|
<div class="form">
|
||||||
<el-form-item v-slot:default>
|
<el-form :model="form" :rules="rules" ref="form">
|
||||||
<el-radio-group v-model="form.authenticate" @change="redirectAuth(form.authenticate)">
|
<el-form-item v-slot:default>
|
||||||
<el-radio label="LDAP" size="mini" v-if="openLdap">LDAP</el-radio>
|
<el-radio-group v-model="form.authenticate" @change="redirectAuth(form.authenticate)">
|
||||||
<el-radio label="LOCAL" size="mini" v-if="openLdap">普通登录</el-radio>
|
<el-radio label="LDAP" size="mini" v-if="openLdap">LDAP</el-radio>
|
||||||
<el-radio :label="auth.id" size="mini" v-for="auth in authSources" :key="auth.id">{{ auth.type }} {{ auth.name }}</el-radio>
|
<el-radio label="LOCAL" size="mini" v-if="openLdap">普通登录</el-radio>
|
||||||
</el-radio-group>
|
<el-radio :label="auth.id" size="mini" v-for="auth in authSources" :key="auth.id">{{ auth.type }} {{ auth.name }}</el-radio>
|
||||||
</el-form-item>
|
</el-radio-group>
|
||||||
<el-form-item prop="username">
|
</el-form-item>
|
||||||
<el-input v-model="form.username" :placeholder="$t('commons.login_username')" autofocus
|
<el-form-item prop="username">
|
||||||
autocomplete="off"/>
|
<el-input v-model="form.username" :placeholder="$t('commons.login_username')" autofocus
|
||||||
</el-form-item>
|
autocomplete="off"/>
|
||||||
<el-form-item prop="password">
|
</el-form-item>
|
||||||
<el-input v-model="form.password" :placeholder="$t('commons.password')" show-password autocomplete="off"
|
<el-form-item prop="password">
|
||||||
maxlength="30" show-word-limit/>
|
<el-input v-model="form.password" :placeholder="$t('commons.password')" show-password autocomplete="off"
|
||||||
</el-form-item>
|
maxlength="30" show-word-limit/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn">
|
<div class="btn">
|
||||||
<el-button type="primary" class="submit" @click="submit('form')">
|
<el-button type="primary" class="submit" @click="submit('form')">
|
||||||
|
@ -38,12 +41,17 @@
|
||||||
<div class="msg">
|
<div class="msg">
|
||||||
{{ msg }}
|
{{ msg }}
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
|
<div class="divider"/>
|
||||||
|
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<img :src="'/display/file/loginImage'" style="height: 560px; width: 100%">
|
<img class="login-image" :src="'/display/file/loginImage'">
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -54,19 +62,11 @@ import {DEFAULT_LANGUAGE} from "@/common/js/constants";
|
||||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||||
const display = requireComponent.keys().length > 0 ? requireComponent("./display/Display.vue") : {};
|
const display = requireComponent.keys().length > 0 ? requireComponent("./display/Display.vue") : {};
|
||||||
const auth = requireComponent.keys().length > 0 ? requireComponent("./auth/Auth.vue") : {};
|
const auth = requireComponent.keys().length > 0 ? requireComponent("./auth/Auth.vue") : {};
|
||||||
|
const license = requireComponent.keys().length > 0 ? requireComponent("./license/LicenseMessage.vue") : null;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Login",
|
name: "Login",
|
||||||
data() {
|
data() {
|
||||||
/*let validateEmail = (rule, value, callback) => {
|
|
||||||
// eslint-disable-next-line no-useless-escape
|
|
||||||
let EMAIL_REGEX = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
|
||||||
if (!EMAIL_REGEX.test(value)) {
|
|
||||||
callback(new Error('邮箱格式不正确'));
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};*/
|
|
||||||
return {
|
return {
|
||||||
result: {},
|
result: {},
|
||||||
form: {
|
form: {
|
||||||
|
@ -118,6 +118,10 @@ export default {
|
||||||
created: function () {
|
created: function () {
|
||||||
// 主页添加键盘事件,注意,不能直接在焦点事件上添加回车
|
// 主页添加键盘事件,注意,不能直接在焦点事件上添加回车
|
||||||
document.addEventListener("keydown", this.watchEnter);
|
document.addEventListener("keydown", this.watchEnter);
|
||||||
|
//
|
||||||
|
if (license.default) {
|
||||||
|
license.default.valid(this)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
destroyed() {
|
destroyed() {
|
||||||
|
@ -184,62 +188,51 @@ export default {
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.container {
|
.container {
|
||||||
min-width: 800px;
|
width: 1440px;
|
||||||
max-width: 1440px;
|
height: 810px;
|
||||||
height: 560px;
|
margin: calc((100vh - 810px) / 2) auto 0;
|
||||||
margin: calc((100vh - 560px) / 2) auto 0;
|
|
||||||
background-color: #FFFFFF;
|
background-color: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.el-col:nth-child(3) {
|
||||||
margin: 30px 30px 0;
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title img {
|
||||||
margin-top: 50px;
|
width: 293px;
|
||||||
font-size: 32px;
|
margin-top: 165px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-img {
|
||||||
letter-spacing: 0;
|
letter-spacing: 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title > #s1 {
|
.login-image {
|
||||||
color: #999999;
|
height: 365px;
|
||||||
}
|
width: 567px;
|
||||||
|
margin: auto;
|
||||||
.title > #s2 {
|
display: block;
|
||||||
color: #151515;
|
|
||||||
}
|
|
||||||
|
|
||||||
.border {
|
|
||||||
height: 2px;
|
|
||||||
margin: 20px auto 20px;
|
|
||||||
position: relative;
|
|
||||||
width: 80px;
|
|
||||||
background: #8B479B;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.welcome {
|
.welcome {
|
||||||
margin-top: 50px;
|
margin-top: 12px;
|
||||||
|
margin-bottom: 75px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #999999;
|
color: #843697;
|
||||||
letter-spacing: 0;
|
line-height: 14px;
|
||||||
line-height: 18px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form {
|
.form, .btn {
|
||||||
margin-top: 30px;
|
padding: 0;
|
||||||
padding: 0 40px;
|
width: 443px;
|
||||||
}
|
margin: auto;
|
||||||
|
|
||||||
.btn {
|
|
||||||
margin-top: 40px;
|
|
||||||
padding: 0 40px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn > .submit {
|
.btn > .submit {
|
||||||
width: 100%;
|
border-radius: 70px;
|
||||||
border-radius: 0;
|
|
||||||
border-color: #8B479B;
|
border-color: #8B479B;
|
||||||
background-color: #8B479B;
|
background-color: #8B479B;
|
||||||
}
|
}
|
||||||
|
@ -254,32 +247,54 @@ export default {
|
||||||
background-color: rgba(139, 71, 155, 0.8);
|
background-color: rgba(139, 71, 155, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
.msg {
|
.el-form-item:first-child {
|
||||||
margin-top: 10px;
|
margin-top: 60px;
|
||||||
padding: 0 40px;
|
|
||||||
color: red;
|
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.image {
|
/deep/ .el-radio__input.is-checked .el-radio__inner {
|
||||||
background: url(../assets/info.png);
|
background-color: #783887;
|
||||||
height: 560px;
|
background: #783887;
|
||||||
|
border-color: #783887;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-logo {
|
/deep/ .el-radio__input.is-checked + .el-radio__label {
|
||||||
background: url(../assets/logo-dark-MeterSphere.svg);
|
color: #783887;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-header {
|
/deep/ .el-input__inner {
|
||||||
background: url(../assets/logo-light-MeterSphere.svg);
|
border-radius: 70px !important;
|
||||||
|
background: #f6f3f8 !important;
|
||||||
|
border-color: #f6f3f8 !important;
|
||||||
|
/*谷歌浏览器默认填充的颜色无法替换,使用下列样式填充*/
|
||||||
|
box-shadow: inset 0 0 0 1000px #f6f3f8 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-input, .el-button {
|
||||||
|
width: 443px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .el-input__inner:focus {
|
||||||
|
border: 1px solid #783887 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
border: 1px solid #f6f3f8;
|
||||||
|
height: 480px;
|
||||||
|
margin: 165px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome span:first-child {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Neue Haas Grotesk Text Pro", "Arial Nova", "Segoe UI", "Helvetica Neue", ".PingFang SC", "PingFang SC", "Source Han Sans SC", "Noto Sans CJK SC", "Source Han Sans CN", "Noto Sans SC", "Source Han Sans TC", "Noto Sans CJK TC", "Hiragino Sans GB", sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, "Neue Haas Grotesk Text Pro", "Arial Nova", "Segoe UI", "Helvetica Neue", ".PingFang SC", "PingFang SC", "Source Han Sans SC", "Noto Sans CJK SC", "Source Han Sans CN", "Noto Sans SC", "Source Han Sans TC", "Noto Sans CJK TC", "Hiragino Sans GB", sans-serif;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
background-color: #F5F5F5;
|
/*background-color: #F5F5F5;*/
|
||||||
line-height: 26px;
|
line-height: 26px;
|
||||||
color: #2B415C;
|
color: #2B415C;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
|
|
|
@ -4,6 +4,10 @@ import 'element-ui/lib/theme-chalk/index.css';
|
||||||
import Login from "./Login.vue";
|
import Login from "./Login.vue";
|
||||||
import Ajax from "../common/js/ajax";
|
import Ajax from "../common/js/ajax";
|
||||||
import i18n from "../i18n/i18n";
|
import i18n from "../i18n/i18n";
|
||||||
|
// 引用静态资源,去掉打包将缺失图片
|
||||||
|
import infoImg from "../assets/info.png";
|
||||||
|
import loginLogo from "../assets/logo-dark-MeterSphere.svg";
|
||||||
|
import logoHeader from "../assets/logo-light-MeterSphere.svg";
|
||||||
|
|
||||||
Vue.config.productionTip = false;
|
Vue.config.productionTip = false;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue