Merge remote-tracking branch 'origin/master'
# Conflicts: # backend/pom.xml
This commit is contained in:
commit
95b44e7fd0
|
@ -165,6 +165,12 @@
|
||||||
<version>${jmeter.version}</version>
|
<version>${jmeter.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.jmeter</groupId>
|
||||||
|
<artifactId>ApacheJMeter_jdbc</artifactId>
|
||||||
|
<version>${jmeter.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Zookeeper -->
|
<!-- Zookeeper -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.dubbo</groupId>
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package io.metersphere.api.dto.scenario;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DatabaseConfig {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private long poolMax;
|
||||||
|
private long timeout;
|
||||||
|
private String driver;
|
||||||
|
private String dbUrl;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
}
|
|
@ -16,5 +16,6 @@ public class Scenario {
|
||||||
private List<KeyValue> headers;
|
private List<KeyValue> headers;
|
||||||
private List<Request> requests;
|
private List<Request> requests;
|
||||||
private DubboConfig dubboConfig;
|
private DubboConfig dubboConfig;
|
||||||
|
private List<DatabaseConfig> databaseConfigs;
|
||||||
private Boolean enable;
|
private Boolean enable;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,9 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
|
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
|
||||||
@JsonSubTypes({
|
@JsonSubTypes({
|
||||||
@JsonSubTypes.Type(value = HttpRequest.class, name = RequestType.HTTP),
|
@JsonSubTypes.Type(value = HttpRequest.class, name = RequestType.HTTP),
|
||||||
@JsonSubTypes.Type(value = DubboRequest.class, name = RequestType.DUBBO)
|
@JsonSubTypes.Type(value = DubboRequest.class, name = RequestType.DUBBO),
|
||||||
|
@JsonSubTypes.Type(value = SqlRequest.class, name = RequestType.SQL)
|
||||||
})
|
})
|
||||||
@JSONType(seeAlso = {HttpRequest.class, DubboRequest.class}, typeKey = "type")
|
@JSONType(seeAlso = {HttpRequest.class, DubboRequest.class, SqlRequest.class}, typeKey = "type")
|
||||||
public interface Request {
|
public interface Request {
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,4 +5,6 @@ public class RequestType {
|
||||||
public static final String HTTP = "HTTP";
|
public static final String HTTP = "HTTP";
|
||||||
|
|
||||||
public static final String DUBBO = "DUBBO";
|
public static final String DUBBO = "DUBBO";
|
||||||
|
|
||||||
|
public static final String SQL = "SQL";
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package io.metersphere.api.dto.scenario.request;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import com.alibaba.fastjson.annotation.JSONType;
|
||||||
|
import io.metersphere.api.dto.scenario.assertions.Assertions;
|
||||||
|
import io.metersphere.api.dto.scenario.extract.Extract;
|
||||||
|
import io.metersphere.api.dto.scenario.processor.JSR223PostProcessor;
|
||||||
|
import io.metersphere.api.dto.scenario.processor.JSR223PreProcessor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@JSONType(typeName = RequestType.SQL)
|
||||||
|
public class SqlRequest implements Request {
|
||||||
|
// type 必须放最前面,以便能够转换正确的类
|
||||||
|
private String type = RequestType.SQL;
|
||||||
|
@JSONField(ordinal = 1)
|
||||||
|
private String id;
|
||||||
|
@JSONField(ordinal = 2)
|
||||||
|
private String name;
|
||||||
|
@JSONField(ordinal = 3)
|
||||||
|
private String dataSource;
|
||||||
|
@JSONField(ordinal = 4)
|
||||||
|
private String query;
|
||||||
|
@JSONField(ordinal = 5)
|
||||||
|
private long queryTimeout;
|
||||||
|
@JSONField(ordinal = 6)
|
||||||
|
private Boolean useEnvironment;
|
||||||
|
@JSONField(ordinal = 7)
|
||||||
|
private Assertions assertions;
|
||||||
|
@JSONField(ordinal = 8)
|
||||||
|
private Extract extract;
|
||||||
|
@JSONField(ordinal = 9)
|
||||||
|
private Boolean enable;
|
||||||
|
@JSONField(ordinal = 10)
|
||||||
|
private Boolean followRedirects;
|
||||||
|
@JSONField(ordinal = 11)
|
||||||
|
private JSR223PreProcessor jsr223PreProcessor;
|
||||||
|
@JSONField(ordinal = 12)
|
||||||
|
private JSR223PostProcessor jsr223PostProcessor;
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ import io.metersphere.api.parse.JmeterDocumentParser;
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
import io.metersphere.base.mapper.ApiTestFileMapper;
|
import io.metersphere.base.mapper.ApiTestFileMapper;
|
||||||
import io.metersphere.base.mapper.ApiTestMapper;
|
import io.metersphere.base.mapper.ApiTestMapper;
|
||||||
|
import io.metersphere.base.mapper.UserMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtApiTestMapper;
|
import io.metersphere.base.mapper.ext.ExtApiTestMapper;
|
||||||
import io.metersphere.commons.constants.APITestStatus;
|
import io.metersphere.commons.constants.APITestStatus;
|
||||||
import io.metersphere.commons.constants.FileType;
|
import io.metersphere.commons.constants.FileType;
|
||||||
|
@ -23,9 +24,12 @@ import io.metersphere.controller.request.QueryScheduleRequest;
|
||||||
import io.metersphere.dto.ScheduleDao;
|
import io.metersphere.dto.ScheduleDao;
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.job.sechedule.ApiTestJob;
|
import io.metersphere.job.sechedule.ApiTestJob;
|
||||||
|
import io.metersphere.notice.service.MailService;
|
||||||
|
import io.metersphere.notice.service.NoticeService;
|
||||||
import io.metersphere.service.FileService;
|
import io.metersphere.service.FileService;
|
||||||
import io.metersphere.service.QuotaService;
|
import io.metersphere.service.QuotaService;
|
||||||
import io.metersphere.service.ScheduleService;
|
import io.metersphere.service.ScheduleService;
|
||||||
|
import io.metersphere.service.UserService;
|
||||||
import io.metersphere.track.service.TestCaseService;
|
import io.metersphere.track.service.TestCaseService;
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.constants.CommonConstants;
|
import org.apache.dubbo.common.constants.CommonConstants;
|
||||||
|
@ -44,7 +48,8 @@ import java.util.stream.Collectors;
|
||||||
@Service
|
@Service
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public class APITestService {
|
public class APITestService {
|
||||||
|
@Resource
|
||||||
|
private UserService userService;
|
||||||
@Resource
|
@Resource
|
||||||
private ApiTestMapper apiTestMapper;
|
private ApiTestMapper apiTestMapper;
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -61,6 +66,10 @@ public class APITestService {
|
||||||
private ScheduleService scheduleService;
|
private ScheduleService scheduleService;
|
||||||
@Resource
|
@Resource
|
||||||
private TestCaseService testCaseService;
|
private TestCaseService testCaseService;
|
||||||
|
@Resource
|
||||||
|
private MailService mailService;
|
||||||
|
@Resource
|
||||||
|
private NoticeService noticeService;
|
||||||
|
|
||||||
private static final String BODY_FILE_DIR = "/opt/metersphere/data/body";
|
private static final String BODY_FILE_DIR = "/opt/metersphere/data/body";
|
||||||
|
|
||||||
|
@ -214,8 +223,11 @@ public class APITestService {
|
||||||
apiTest.setUserId(request.getUserId());
|
apiTest.setUserId(request.getUserId());
|
||||||
}
|
}
|
||||||
String reportId = apiReportService.create(apiTest, request.getTriggerMode());
|
String reportId = apiReportService.create(apiTest, request.getTriggerMode());
|
||||||
|
if (request.getTriggerMode().equals("SCHEDULE")) {
|
||||||
|
List<Notice> notice = noticeService.queryNotice(request.getId());
|
||||||
|
mailService.sendHtml(reportId,notice,"api");
|
||||||
|
}
|
||||||
changeStatus(request.getId(), APITestStatus.Running);
|
changeStatus(request.getId(), APITestStatus.Running);
|
||||||
|
|
||||||
jMeterService.run(request.getId(), null, is);
|
jMeterService.run(request.getId(), null, is);
|
||||||
return reportId;
|
return reportId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,5 +15,9 @@ public class Notice implements Serializable {
|
||||||
|
|
||||||
private String enable;
|
private String enable;
|
||||||
|
|
||||||
|
private String[] names;
|
||||||
|
|
||||||
|
private String[] emails;
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
}
|
}
|
|
@ -7,8 +7,6 @@ import lombok.Data;
|
||||||
public class TestPlan implements Serializable {
|
public class TestPlan implements Serializable {
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
private String projectId;
|
|
||||||
|
|
||||||
private String workspaceId;
|
private String workspaceId;
|
||||||
|
|
||||||
private String reportId;
|
private String reportId;
|
||||||
|
|
|
@ -174,76 +174,6 @@ public class TestPlanExample {
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andProjectIdIsNull() {
|
|
||||||
addCriterion("project_id is null");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andProjectIdIsNotNull() {
|
|
||||||
addCriterion("project_id is not null");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andProjectIdEqualTo(String value) {
|
|
||||||
addCriterion("project_id =", value, "projectId");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andProjectIdNotEqualTo(String value) {
|
|
||||||
addCriterion("project_id <>", value, "projectId");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andProjectIdGreaterThan(String value) {
|
|
||||||
addCriterion("project_id >", value, "projectId");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andProjectIdGreaterThanOrEqualTo(String value) {
|
|
||||||
addCriterion("project_id >=", value, "projectId");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andProjectIdLessThan(String value) {
|
|
||||||
addCriterion("project_id <", value, "projectId");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andProjectIdLessThanOrEqualTo(String value) {
|
|
||||||
addCriterion("project_id <=", value, "projectId");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andProjectIdLike(String value) {
|
|
||||||
addCriterion("project_id like", value, "projectId");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andProjectIdNotLike(String value) {
|
|
||||||
addCriterion("project_id not like", value, "projectId");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andProjectIdIn(List<String> values) {
|
|
||||||
addCriterion("project_id in", values, "projectId");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andProjectIdNotIn(List<String> values) {
|
|
||||||
addCriterion("project_id not in", values, "projectId");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andProjectIdBetween(String value1, String value2) {
|
|
||||||
addCriterion("project_id between", value1, value2, "projectId");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andProjectIdNotBetween(String value1, String value2) {
|
|
||||||
addCriterion("project_id not between", value1, value2, "projectId");
|
|
||||||
return (Criteria) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Criteria andWorkspaceIdIsNull() {
|
public Criteria andWorkspaceIdIsNull() {
|
||||||
addCriterion("workspace_id is null");
|
addCriterion("workspace_id is null");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
|
@ -385,72 +315,72 @@ public class TestPlanExample {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andNameIsNull() {
|
public Criteria andNameIsNull() {
|
||||||
addCriterion("name is null");
|
addCriterion("`name` is null");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andNameIsNotNull() {
|
public Criteria andNameIsNotNull() {
|
||||||
addCriterion("name is not null");
|
addCriterion("`name` is not null");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andNameEqualTo(String value) {
|
public Criteria andNameEqualTo(String value) {
|
||||||
addCriterion("name =", value, "name");
|
addCriterion("`name` =", value, "name");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andNameNotEqualTo(String value) {
|
public Criteria andNameNotEqualTo(String value) {
|
||||||
addCriterion("name <>", value, "name");
|
addCriterion("`name` <>", value, "name");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andNameGreaterThan(String value) {
|
public Criteria andNameGreaterThan(String value) {
|
||||||
addCriterion("name >", value, "name");
|
addCriterion("`name` >", value, "name");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andNameGreaterThanOrEqualTo(String value) {
|
public Criteria andNameGreaterThanOrEqualTo(String value) {
|
||||||
addCriterion("name >=", value, "name");
|
addCriterion("`name` >=", value, "name");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andNameLessThan(String value) {
|
public Criteria andNameLessThan(String value) {
|
||||||
addCriterion("name <", value, "name");
|
addCriterion("`name` <", value, "name");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andNameLessThanOrEqualTo(String value) {
|
public Criteria andNameLessThanOrEqualTo(String value) {
|
||||||
addCriterion("name <=", value, "name");
|
addCriterion("`name` <=", value, "name");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andNameLike(String value) {
|
public Criteria andNameLike(String value) {
|
||||||
addCriterion("name like", value, "name");
|
addCriterion("`name` like", value, "name");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andNameNotLike(String value) {
|
public Criteria andNameNotLike(String value) {
|
||||||
addCriterion("name not like", value, "name");
|
addCriterion("`name` not like", value, "name");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andNameIn(List<String> values) {
|
public Criteria andNameIn(List<String> values) {
|
||||||
addCriterion("name in", values, "name");
|
addCriterion("`name` in", values, "name");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andNameNotIn(List<String> values) {
|
public Criteria andNameNotIn(List<String> values) {
|
||||||
addCriterion("name not in", values, "name");
|
addCriterion("`name` not in", values, "name");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andNameBetween(String value1, String value2) {
|
public Criteria andNameBetween(String value1, String value2) {
|
||||||
addCriterion("name between", value1, value2, "name");
|
addCriterion("`name` between", value1, value2, "name");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andNameNotBetween(String value1, String value2) {
|
public Criteria andNameNotBetween(String value1, String value2) {
|
||||||
addCriterion("name not between", value1, value2, "name");
|
addCriterion("`name` not between", value1, value2, "name");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,72 +455,72 @@ public class TestPlanExample {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andStatusIsNull() {
|
public Criteria andStatusIsNull() {
|
||||||
addCriterion("status is null");
|
addCriterion("`status` is null");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andStatusIsNotNull() {
|
public Criteria andStatusIsNotNull() {
|
||||||
addCriterion("status is not null");
|
addCriterion("`status` is not null");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andStatusEqualTo(String value) {
|
public Criteria andStatusEqualTo(String value) {
|
||||||
addCriterion("status =", value, "status");
|
addCriterion("`status` =", value, "status");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andStatusNotEqualTo(String value) {
|
public Criteria andStatusNotEqualTo(String value) {
|
||||||
addCriterion("status <>", value, "status");
|
addCriterion("`status` <>", value, "status");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andStatusGreaterThan(String value) {
|
public Criteria andStatusGreaterThan(String value) {
|
||||||
addCriterion("status >", value, "status");
|
addCriterion("`status` >", value, "status");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andStatusGreaterThanOrEqualTo(String value) {
|
public Criteria andStatusGreaterThanOrEqualTo(String value) {
|
||||||
addCriterion("status >=", value, "status");
|
addCriterion("`status` >=", value, "status");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andStatusLessThan(String value) {
|
public Criteria andStatusLessThan(String value) {
|
||||||
addCriterion("status <", value, "status");
|
addCriterion("`status` <", value, "status");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andStatusLessThanOrEqualTo(String value) {
|
public Criteria andStatusLessThanOrEqualTo(String value) {
|
||||||
addCriterion("status <=", value, "status");
|
addCriterion("`status` <=", value, "status");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andStatusLike(String value) {
|
public Criteria andStatusLike(String value) {
|
||||||
addCriterion("status like", value, "status");
|
addCriterion("`status` like", value, "status");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andStatusNotLike(String value) {
|
public Criteria andStatusNotLike(String value) {
|
||||||
addCriterion("status not like", value, "status");
|
addCriterion("`status` not like", value, "status");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andStatusIn(List<String> values) {
|
public Criteria andStatusIn(List<String> values) {
|
||||||
addCriterion("status in", values, "status");
|
addCriterion("`status` in", values, "status");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andStatusNotIn(List<String> values) {
|
public Criteria andStatusNotIn(List<String> values) {
|
||||||
addCriterion("status not in", values, "status");
|
addCriterion("`status` not in", values, "status");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andStatusBetween(String value1, String value2) {
|
public Criteria andStatusBetween(String value1, String value2) {
|
||||||
addCriterion("status between", value1, value2, "status");
|
addCriterion("`status` between", value1, value2, "status");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andStatusNotBetween(String value1, String value2) {
|
public Criteria andStatusNotBetween(String value1, String value2) {
|
||||||
addCriterion("status not between", value1, value2, "status");
|
addCriterion("`status` not between", value1, value2, "status");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
<mapper namespace="io.metersphere.base.mapper.TestPlanMapper">
|
<mapper namespace="io.metersphere.base.mapper.TestPlanMapper">
|
||||||
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.TestPlan">
|
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.TestPlan">
|
||||||
<id column="id" jdbcType="VARCHAR" property="id" />
|
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||||
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
|
|
||||||
<result column="workspace_id" jdbcType="VARCHAR" property="workspaceId" />
|
<result column="workspace_id" jdbcType="VARCHAR" property="workspaceId" />
|
||||||
<result column="report_id" jdbcType="VARCHAR" property="reportId" />
|
<result column="report_id" jdbcType="VARCHAR" property="reportId" />
|
||||||
<result column="name" jdbcType="VARCHAR" property="name" />
|
<result column="name" jdbcType="VARCHAR" property="name" />
|
||||||
|
@ -78,8 +77,8 @@
|
||||||
</where>
|
</where>
|
||||||
</sql>
|
</sql>
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
id, project_id, workspace_id, report_id, name, description, status, stage, principal,
|
id, workspace_id, report_id, `name`, description, `status`, stage, principal, test_case_match_rule,
|
||||||
test_case_match_rule, executor_match_rule, create_time, update_time
|
executor_match_rule, create_time, update_time
|
||||||
</sql>
|
</sql>
|
||||||
<sql id="Blob_Column_List">
|
<sql id="Blob_Column_List">
|
||||||
tags
|
tags
|
||||||
|
@ -133,16 +132,16 @@
|
||||||
</if>
|
</if>
|
||||||
</delete>
|
</delete>
|
||||||
<insert id="insert" parameterType="io.metersphere.base.domain.TestPlan">
|
<insert id="insert" parameterType="io.metersphere.base.domain.TestPlan">
|
||||||
insert into test_plan (id, project_id, workspace_id,
|
insert into test_plan (id, workspace_id, report_id,
|
||||||
report_id, name, description,
|
`name`, description, `status`,
|
||||||
status, stage, principal,
|
stage, principal, test_case_match_rule,
|
||||||
test_case_match_rule, executor_match_rule, create_time,
|
executor_match_rule, create_time, update_time,
|
||||||
update_time, tags)
|
tags)
|
||||||
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{workspaceId,jdbcType=VARCHAR},
|
values (#{id,jdbcType=VARCHAR}, #{workspaceId,jdbcType=VARCHAR}, #{reportId,jdbcType=VARCHAR},
|
||||||
#{reportId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR},
|
#{name,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
|
||||||
#{status,jdbcType=VARCHAR}, #{stage,jdbcType=VARCHAR}, #{principal,jdbcType=VARCHAR},
|
#{stage,jdbcType=VARCHAR}, #{principal,jdbcType=VARCHAR}, #{testCaseMatchRule,jdbcType=VARCHAR},
|
||||||
#{testCaseMatchRule,jdbcType=VARCHAR}, #{executorMatchRule,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
|
#{executorMatchRule,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
||||||
#{updateTime,jdbcType=BIGINT}, #{tags,jdbcType=LONGVARCHAR})
|
#{tags,jdbcType=LONGVARCHAR})
|
||||||
</insert>
|
</insert>
|
||||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestPlan">
|
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestPlan">
|
||||||
insert into test_plan
|
insert into test_plan
|
||||||
|
@ -150,9 +149,6 @@
|
||||||
<if test="id != null">
|
<if test="id != null">
|
||||||
id,
|
id,
|
||||||
</if>
|
</if>
|
||||||
<if test="projectId != null">
|
|
||||||
project_id,
|
|
||||||
</if>
|
|
||||||
<if test="workspaceId != null">
|
<if test="workspaceId != null">
|
||||||
workspace_id,
|
workspace_id,
|
||||||
</if>
|
</if>
|
||||||
|
@ -160,13 +156,13 @@
|
||||||
report_id,
|
report_id,
|
||||||
</if>
|
</if>
|
||||||
<if test="name != null">
|
<if test="name != null">
|
||||||
name,
|
`name`,
|
||||||
</if>
|
</if>
|
||||||
<if test="description != null">
|
<if test="description != null">
|
||||||
description,
|
description,
|
||||||
</if>
|
</if>
|
||||||
<if test="status != null">
|
<if test="status != null">
|
||||||
status,
|
`status`,
|
||||||
</if>
|
</if>
|
||||||
<if test="stage != null">
|
<if test="stage != null">
|
||||||
stage,
|
stage,
|
||||||
|
@ -194,9 +190,6 @@
|
||||||
<if test="id != null">
|
<if test="id != null">
|
||||||
#{id,jdbcType=VARCHAR},
|
#{id,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="projectId != null">
|
|
||||||
#{projectId,jdbcType=VARCHAR},
|
|
||||||
</if>
|
|
||||||
<if test="workspaceId != null">
|
<if test="workspaceId != null">
|
||||||
#{workspaceId,jdbcType=VARCHAR},
|
#{workspaceId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
@ -247,9 +240,6 @@
|
||||||
<if test="record.id != null">
|
<if test="record.id != null">
|
||||||
id = #{record.id,jdbcType=VARCHAR},
|
id = #{record.id,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="record.projectId != null">
|
|
||||||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
|
||||||
</if>
|
|
||||||
<if test="record.workspaceId != null">
|
<if test="record.workspaceId != null">
|
||||||
workspace_id = #{record.workspaceId,jdbcType=VARCHAR},
|
workspace_id = #{record.workspaceId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
@ -257,13 +247,13 @@
|
||||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="record.name != null">
|
<if test="record.name != null">
|
||||||
name = #{record.name,jdbcType=VARCHAR},
|
`name` = #{record.name,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="record.description != null">
|
<if test="record.description != null">
|
||||||
description = #{record.description,jdbcType=VARCHAR},
|
description = #{record.description,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="record.status != null">
|
<if test="record.status != null">
|
||||||
status = #{record.status,jdbcType=VARCHAR},
|
`status` = #{record.status,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="record.stage != null">
|
<if test="record.stage != null">
|
||||||
stage = #{record.stage,jdbcType=VARCHAR},
|
stage = #{record.stage,jdbcType=VARCHAR},
|
||||||
|
@ -294,12 +284,11 @@
|
||||||
<update id="updateByExampleWithBLOBs" parameterType="map">
|
<update id="updateByExampleWithBLOBs" parameterType="map">
|
||||||
update test_plan
|
update test_plan
|
||||||
set id = #{record.id,jdbcType=VARCHAR},
|
set id = #{record.id,jdbcType=VARCHAR},
|
||||||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
|
||||||
workspace_id = #{record.workspaceId,jdbcType=VARCHAR},
|
workspace_id = #{record.workspaceId,jdbcType=VARCHAR},
|
||||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||||
name = #{record.name,jdbcType=VARCHAR},
|
`name` = #{record.name,jdbcType=VARCHAR},
|
||||||
description = #{record.description,jdbcType=VARCHAR},
|
description = #{record.description,jdbcType=VARCHAR},
|
||||||
status = #{record.status,jdbcType=VARCHAR},
|
`status` = #{record.status,jdbcType=VARCHAR},
|
||||||
stage = #{record.stage,jdbcType=VARCHAR},
|
stage = #{record.stage,jdbcType=VARCHAR},
|
||||||
principal = #{record.principal,jdbcType=VARCHAR},
|
principal = #{record.principal,jdbcType=VARCHAR},
|
||||||
test_case_match_rule = #{record.testCaseMatchRule,jdbcType=VARCHAR},
|
test_case_match_rule = #{record.testCaseMatchRule,jdbcType=VARCHAR},
|
||||||
|
@ -314,12 +303,11 @@
|
||||||
<update id="updateByExample" parameterType="map">
|
<update id="updateByExample" parameterType="map">
|
||||||
update test_plan
|
update test_plan
|
||||||
set id = #{record.id,jdbcType=VARCHAR},
|
set id = #{record.id,jdbcType=VARCHAR},
|
||||||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
|
||||||
workspace_id = #{record.workspaceId,jdbcType=VARCHAR},
|
workspace_id = #{record.workspaceId,jdbcType=VARCHAR},
|
||||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||||
name = #{record.name,jdbcType=VARCHAR},
|
`name` = #{record.name,jdbcType=VARCHAR},
|
||||||
description = #{record.description,jdbcType=VARCHAR},
|
description = #{record.description,jdbcType=VARCHAR},
|
||||||
status = #{record.status,jdbcType=VARCHAR},
|
`status` = #{record.status,jdbcType=VARCHAR},
|
||||||
stage = #{record.stage,jdbcType=VARCHAR},
|
stage = #{record.stage,jdbcType=VARCHAR},
|
||||||
principal = #{record.principal,jdbcType=VARCHAR},
|
principal = #{record.principal,jdbcType=VARCHAR},
|
||||||
test_case_match_rule = #{record.testCaseMatchRule,jdbcType=VARCHAR},
|
test_case_match_rule = #{record.testCaseMatchRule,jdbcType=VARCHAR},
|
||||||
|
@ -333,9 +321,6 @@
|
||||||
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.TestPlan">
|
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.TestPlan">
|
||||||
update test_plan
|
update test_plan
|
||||||
<set>
|
<set>
|
||||||
<if test="projectId != null">
|
|
||||||
project_id = #{projectId,jdbcType=VARCHAR},
|
|
||||||
</if>
|
|
||||||
<if test="workspaceId != null">
|
<if test="workspaceId != null">
|
||||||
workspace_id = #{workspaceId,jdbcType=VARCHAR},
|
workspace_id = #{workspaceId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
@ -343,13 +328,13 @@
|
||||||
report_id = #{reportId,jdbcType=VARCHAR},
|
report_id = #{reportId,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="name != null">
|
<if test="name != null">
|
||||||
name = #{name,jdbcType=VARCHAR},
|
`name` = #{name,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="description != null">
|
<if test="description != null">
|
||||||
description = #{description,jdbcType=VARCHAR},
|
description = #{description,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="status != null">
|
<if test="status != null">
|
||||||
status = #{status,jdbcType=VARCHAR},
|
`status` = #{status,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="stage != null">
|
<if test="stage != null">
|
||||||
stage = #{stage,jdbcType=VARCHAR},
|
stage = #{stage,jdbcType=VARCHAR},
|
||||||
|
@ -377,12 +362,11 @@
|
||||||
</update>
|
</update>
|
||||||
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.TestPlan">
|
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.TestPlan">
|
||||||
update test_plan
|
update test_plan
|
||||||
set project_id = #{projectId,jdbcType=VARCHAR},
|
set workspace_id = #{workspaceId,jdbcType=VARCHAR},
|
||||||
workspace_id = #{workspaceId,jdbcType=VARCHAR},
|
|
||||||
report_id = #{reportId,jdbcType=VARCHAR},
|
report_id = #{reportId,jdbcType=VARCHAR},
|
||||||
name = #{name,jdbcType=VARCHAR},
|
`name` = #{name,jdbcType=VARCHAR},
|
||||||
description = #{description,jdbcType=VARCHAR},
|
description = #{description,jdbcType=VARCHAR},
|
||||||
status = #{status,jdbcType=VARCHAR},
|
`status` = #{status,jdbcType=VARCHAR},
|
||||||
stage = #{stage,jdbcType=VARCHAR},
|
stage = #{stage,jdbcType=VARCHAR},
|
||||||
principal = #{principal,jdbcType=VARCHAR},
|
principal = #{principal,jdbcType=VARCHAR},
|
||||||
test_case_match_rule = #{testCaseMatchRule,jdbcType=VARCHAR},
|
test_case_match_rule = #{testCaseMatchRule,jdbcType=VARCHAR},
|
||||||
|
@ -394,12 +378,11 @@
|
||||||
</update>
|
</update>
|
||||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.TestPlan">
|
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.TestPlan">
|
||||||
update test_plan
|
update test_plan
|
||||||
set project_id = #{projectId,jdbcType=VARCHAR},
|
set workspace_id = #{workspaceId,jdbcType=VARCHAR},
|
||||||
workspace_id = #{workspaceId,jdbcType=VARCHAR},
|
|
||||||
report_id = #{reportId,jdbcType=VARCHAR},
|
report_id = #{reportId,jdbcType=VARCHAR},
|
||||||
name = #{name,jdbcType=VARCHAR},
|
`name` = #{name,jdbcType=VARCHAR},
|
||||||
description = #{description,jdbcType=VARCHAR},
|
description = #{description,jdbcType=VARCHAR},
|
||||||
status = #{status,jdbcType=VARCHAR},
|
`status` = #{status,jdbcType=VARCHAR},
|
||||||
stage = #{stage,jdbcType=VARCHAR},
|
stage = #{stage,jdbcType=VARCHAR},
|
||||||
principal = #{principal,jdbcType=VARCHAR},
|
principal = #{principal,jdbcType=VARCHAR},
|
||||||
test_case_match_rule = #{testCaseMatchRule,jdbcType=VARCHAR},
|
test_case_match_rule = #{testCaseMatchRule,jdbcType=VARCHAR},
|
||||||
|
|
|
@ -57,7 +57,16 @@
|
||||||
</include>
|
</include>
|
||||||
</if>
|
</if>
|
||||||
</sql>
|
</sql>
|
||||||
|
<select id="get" resultMap="BaseResultMap">
|
||||||
|
SELECT r.*, t.name AS test_name, project.name AS project_name, user.name AS user_name
|
||||||
|
FROM api_test_report r JOIN api_test t ON r.test_id = t.id
|
||||||
|
LEFT JOIN project ON project.id = t.project_id
|
||||||
|
LEFT JOIN user ON user.id = r.user_id
|
||||||
|
<where>
|
||||||
|
r.id = #{id}
|
||||||
|
</where>
|
||||||
|
ORDER BY r.update_time DESC
|
||||||
|
</select>
|
||||||
<select id="list" resultMap="BaseResultMap">
|
<select id="list" resultMap="BaseResultMap">
|
||||||
SELECT t.name AS test_name,
|
SELECT t.name AS test_name,
|
||||||
r.name, r.description, r.id, r.test_id, r.create_time, r.update_time, r.status, r.trigger_mode,
|
r.name, r.description, r.id, r.test_id, r.create_time, r.update_time, r.status, r.trigger_mode,
|
||||||
|
@ -125,16 +134,7 @@
|
||||||
ORDER BY r.update_time DESC
|
ORDER BY r.update_time DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="get" resultMap="BaseResultMap">
|
|
||||||
SELECT r.*, t.name AS test_name, project.name AS project_name, user.name AS user_name
|
|
||||||
FROM api_test_report r JOIN api_test t ON r.test_id = t.id
|
|
||||||
LEFT JOIN project ON project.id = t.project_id
|
|
||||||
LEFT JOIN user ON user.id = r.user_id
|
|
||||||
<where>
|
|
||||||
r.id = #{id}
|
|
||||||
</where>
|
|
||||||
ORDER BY r.update_time DESC
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectDashboardTests" resultType="io.metersphere.dto.DashboardTestDTO">
|
<select id="selectDashboardTests" resultType="io.metersphere.dto.DashboardTestDTO">
|
||||||
SELECT min(create_time) AS date, count(api_test_report.id) AS count,
|
SELECT min(create_time) AS date, count(api_test_report.id) AS count,
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package io.metersphere.base.mapper.ext;
|
||||||
|
|
||||||
|
public interface ExtSystemParameterMapper {
|
||||||
|
String email();
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||||
|
<mapper namespace="io.metersphere.base.mapper.ext.ExtSystemParameterMapper">
|
||||||
|
|
||||||
|
<select id="email" resultType="string">
|
||||||
|
select param_value from system_parameter where param_key=#{smtp.account}
|
||||||
|
</select>
|
||||||
|
</mapper>
|
|
@ -11,4 +11,6 @@ public interface ExtTestPlanMapper {
|
||||||
List<TestPlanDTO> list(@Param("request") QueryTestPlanRequest params);
|
List<TestPlanDTO> list(@Param("request") QueryTestPlanRequest params);
|
||||||
|
|
||||||
List<TestPlanDTOWithMetric> listRelate(@Param("request") QueryTestPlanRequest params);
|
List<TestPlanDTOWithMetric> listRelate(@Param("request") QueryTestPlanRequest params);
|
||||||
|
|
||||||
|
List<TestPlanDTO> planList(@Param("request") QueryTestPlanRequest params);
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,6 +143,18 @@
|
||||||
</foreach>
|
</foreach>
|
||||||
</if>
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
<select id="planList" resultMap="BaseResultMap"
|
||||||
|
parameterType="io.metersphere.track.request.testcase.QueryTestPlanRequest">
|
||||||
|
SELECT * FROM TEST_PLAN p LEFT JOIN test_plan_project t ON t.test_plan_id=p.ID
|
||||||
|
<where>
|
||||||
|
<if test="request.workspaceId != null">
|
||||||
|
AND p.workspace_id = #{request.workspaceId}
|
||||||
|
</if>
|
||||||
|
<if test="request.projectId != null">
|
||||||
|
AND t.project_id = #{request.projectId}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="listRelate" resultType="io.metersphere.track.dto.TestPlanDTOWithMetric">
|
<select id="listRelate" resultType="io.metersphere.track.dto.TestPlanDTOWithMetric">
|
||||||
select test_plan.* from test_plan
|
select test_plan.* from test_plan
|
||||||
|
|
|
@ -16,4 +16,6 @@ public interface ExtUserMapper {
|
||||||
|
|
||||||
List<User> searchUser(String condition);
|
List<User> searchUser(String condition);
|
||||||
|
|
||||||
|
List<String> queryEmails(String[] names);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,18 @@
|
||||||
</where>
|
</where>
|
||||||
order by u.update_time desc
|
order by u.update_time desc
|
||||||
</select>
|
</select>
|
||||||
|
<!--查询邮箱-->
|
||||||
|
<select id="queryEmails" parameterType="java.lang.String" resultType="java.lang.String">
|
||||||
|
SELECT
|
||||||
|
email
|
||||||
|
from user
|
||||||
|
WHERE name IN
|
||||||
|
<foreach collection="array" item="id" index="index"
|
||||||
|
open="(" close=")" separator=",">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
|
||||||
|
</select>
|
||||||
|
|
||||||
<!--修改密码-->
|
<!--修改密码-->
|
||||||
<update id="updatePassword" parameterType="io.metersphere.base.domain.User">
|
<update id="updatePassword" parameterType="io.metersphere.base.domain.User">
|
||||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.job.sechedule;
|
||||||
|
|
||||||
import io.metersphere.api.dto.SaveAPITestRequest;
|
import io.metersphere.api.dto.SaveAPITestRequest;
|
||||||
import io.metersphere.api.service.APITestService;
|
import io.metersphere.api.service.APITestService;
|
||||||
|
import io.metersphere.notice.service.MailService;
|
||||||
import io.metersphere.commons.constants.ReportTriggerMode;
|
import io.metersphere.commons.constants.ReportTriggerMode;
|
||||||
import io.metersphere.commons.constants.ScheduleGroup;
|
import io.metersphere.commons.constants.ScheduleGroup;
|
||||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
|
@ -13,7 +14,7 @@ import org.quartz.TriggerKey;
|
||||||
public class ApiTestJob extends MsScheduleJob {
|
public class ApiTestJob extends MsScheduleJob {
|
||||||
|
|
||||||
private APITestService apiTestService;
|
private APITestService apiTestService;
|
||||||
|
private MailService mailService;
|
||||||
public ApiTestJob() {
|
public ApiTestJob() {
|
||||||
apiTestService = (APITestService) CommonBeanFactory.getBean(APITestService.class);
|
apiTestService = (APITestService) CommonBeanFactory.getBean(APITestService.class);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package io.metersphere.notice.controller;
|
||||||
|
|
||||||
|
import io.metersphere.base.domain.Notice;
|
||||||
|
import io.metersphere.notice.controller.request.NoticeRequest;
|
||||||
|
import io.metersphere.notice.service.MailService;
|
||||||
|
import io.metersphere.notice.service.NoticeService;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("notice")
|
||||||
|
public class NoticeController {
|
||||||
|
@Resource
|
||||||
|
private NoticeService noticeService;
|
||||||
|
|
||||||
|
@PostMapping("/save")
|
||||||
|
public void saveNotice(@RequestBody NoticeRequest noticeRequest) {
|
||||||
|
noticeService.saveNotice(noticeRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/query/{testId}")
|
||||||
|
public List<Notice> queryNotice(@PathVariable String testId) {
|
||||||
|
return noticeService.queryNotice(testId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package io.metersphere.notice.controller.request;
|
||||||
|
|
||||||
|
import io.metersphere.base.domain.Notice;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class NoticeRequest extends Notice {
|
||||||
|
private String testId;
|
||||||
|
private List<Notice> notices;
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package io.metersphere.notice.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class Mail {
|
||||||
|
// 发送给谁
|
||||||
|
private String to;
|
||||||
|
|
||||||
|
// 发送主题
|
||||||
|
private String subject;
|
||||||
|
|
||||||
|
// 发送内容
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
// 附件地址
|
||||||
|
private String filePath;
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package io.metersphere.notice.service;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.APIReportResult;
|
||||||
|
import io.metersphere.base.domain.ApiTestReportDetail;
|
||||||
|
import io.metersphere.base.domain.Schedule;
|
||||||
|
import io.metersphere.base.mapper.ApiTestReportDetailMapper;
|
||||||
|
import io.metersphere.base.mapper.ext.ExtApiTestReportMapper;
|
||||||
|
import io.metersphere.base.mapper.ext.ExtLoadTestMapper;
|
||||||
|
import io.metersphere.commons.constants.ScheduleGroup;
|
||||||
|
import io.metersphere.dto.LoadTestDTO;
|
||||||
|
import io.metersphere.service.ScheduleService;
|
||||||
|
import io.metersphere.track.request.testplan.QueryTestPlanRequest;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ApiAndPerformanceHelper {
|
||||||
|
@Resource
|
||||||
|
private ExtLoadTestMapper extLoadTestMapper;
|
||||||
|
@Resource
|
||||||
|
private ExtApiTestReportMapper extApiTestReportMapper;
|
||||||
|
@Resource
|
||||||
|
private ApiTestReportDetailMapper apiTestReportDetailMapper;
|
||||||
|
@Resource
|
||||||
|
private ScheduleService scheduleService;
|
||||||
|
|
||||||
|
public APIReportResult getApi(String reportId) {
|
||||||
|
APIReportResult result = extApiTestReportMapper.get(reportId);
|
||||||
|
ApiTestReportDetail detail = apiTestReportDetailMapper.selectByPrimaryKey(reportId);
|
||||||
|
if (detail != null) {
|
||||||
|
result.setContent(new String(detail.getContent(), StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoadTestDTO getPerformance(String testId) {
|
||||||
|
QueryTestPlanRequest request = new QueryTestPlanRequest();
|
||||||
|
request.setId(testId);
|
||||||
|
List<LoadTestDTO> testDTOS = extLoadTestMapper.list(request);
|
||||||
|
if (!CollectionUtils.isEmpty(testDTOS)) {
|
||||||
|
LoadTestDTO loadTestDTO = testDTOS.get(0);
|
||||||
|
Schedule schedule = scheduleService.getScheduleByResource(loadTestDTO.getId(), ScheduleGroup.PERFORMANCE_TEST.name());
|
||||||
|
loadTestDTO.setSchedule(schedule);
|
||||||
|
return loadTestDTO;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
package io.metersphere.notice.service;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.APIReportResult;
|
||||||
|
import io.metersphere.base.domain.Notice;
|
||||||
|
import io.metersphere.base.domain.SystemParameter;
|
||||||
|
import io.metersphere.commons.constants.ParamConstants;
|
||||||
|
import io.metersphere.commons.utils.EncryptUtils;
|
||||||
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
|
import io.metersphere.dto.LoadTestDTO;
|
||||||
|
import io.metersphere.service.SystemParameterService;
|
||||||
|
import io.metersphere.service.UserService;
|
||||||
|
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||||
|
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.mail.MessagingException;
|
||||||
|
import javax.mail.internet.MimeMessage;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class MailService {
|
||||||
|
@Resource
|
||||||
|
private ApiAndPerformanceHelper apiAndPerformanceHelper;
|
||||||
|
@Resource
|
||||||
|
private UserService userService;
|
||||||
|
@Resource
|
||||||
|
private SystemParameterService systemParameterService;
|
||||||
|
|
||||||
|
public void sendHtml(String id, List<Notice> notice,String type) {
|
||||||
|
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
|
||||||
|
List<SystemParameter> paramList=systemParameterService.getParamList(ParamConstants.Classify.MAIL.getValue());
|
||||||
|
javaMailSender.setDefaultEncoding("UTF-8");
|
||||||
|
javaMailSender.setProtocol("smtps");
|
||||||
|
for(SystemParameter p:paramList){
|
||||||
|
if(p.getParamKey().equals("smtp.host")){
|
||||||
|
javaMailSender.setHost(p.getParamValue());
|
||||||
|
}
|
||||||
|
if(p.getParamKey().equals("smtp.port")){
|
||||||
|
javaMailSender.setPort(Integer.parseInt(p.getParamValue()));
|
||||||
|
}
|
||||||
|
if(p.getParamKey().equals("smtp.account")){
|
||||||
|
javaMailSender.setUsername(p.getParamValue());
|
||||||
|
}
|
||||||
|
if(p.getParamKey().equals("smtp.password")){
|
||||||
|
javaMailSender.setPassword(EncryptUtils.aesDecrypt(p.getParamValue()).toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.put("mail.smtp.auth", "true");
|
||||||
|
props.put("mail.smtp.starttls.enable", "true");
|
||||||
|
props.put("mail.smtp.starttls.required", "true");
|
||||||
|
props.put("mail.smtp.timeout", "30000");
|
||||||
|
props.put("mail.smtp.connectiontimeout", "5000");
|
||||||
|
javaMailSender.setJavaMailProperties(props);
|
||||||
|
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
|
||||||
|
String testName = "";
|
||||||
|
String state = "";
|
||||||
|
if (type.equals("api")) {
|
||||||
|
APIReportResult reportResult = apiAndPerformanceHelper.getApi(id);
|
||||||
|
testName = reportResult.getTestName();
|
||||||
|
state = reportResult.getStatus();
|
||||||
|
} else if (type.equals("performance")) {
|
||||||
|
LoadTestDTO performanceResult = apiAndPerformanceHelper.getPerformance(id);
|
||||||
|
testName = performanceResult.getName();
|
||||||
|
state = performanceResult.getStatus();
|
||||||
|
}
|
||||||
|
String html1 = "<!DOCTYPE html>\n" +
|
||||||
|
"<html lang=\"en\">\n" +
|
||||||
|
"<head>\n" +
|
||||||
|
" <meta charset=\"UTF-8\">\n" +
|
||||||
|
" <title>MeterSphere</title>\n" +
|
||||||
|
"</head>\n" +
|
||||||
|
"<body style=\"text-align: left\">\n" +
|
||||||
|
" <div>\n" +
|
||||||
|
" <h3>"+type+"定时任务结果通知</h3>\n" +
|
||||||
|
" <p> 尊敬的用户:您好,您所执行的"+testName+"运行失败,请点击报告链接查看</p>\n" +
|
||||||
|
" </div>\n" +
|
||||||
|
"</body>\n" +
|
||||||
|
"</html>";
|
||||||
|
String html2="<!DOCTYPE html>\n" +
|
||||||
|
"<html lang=\"en\">\n" +
|
||||||
|
"<head>\n" +
|
||||||
|
" <meta charset=\"UTF-8\">\n" +
|
||||||
|
" <title>MeterSphere</title>\n" +
|
||||||
|
"</head>\n" +
|
||||||
|
"<body style=\"text-align: left\">\n" +
|
||||||
|
" <div>\n" +
|
||||||
|
" <h3>"+type+"定时任务结果通知</h3>\n" +
|
||||||
|
" <p> 尊敬的用户:您好,"+testName+"运行成功,请点击报告链接查看</p>\n" +
|
||||||
|
" </div>\n" +
|
||||||
|
"</body>\n" +
|
||||||
|
"</html>";
|
||||||
|
try {
|
||||||
|
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
|
||||||
|
helper.setFrom(javaMailSender.getUsername());
|
||||||
|
helper.setSubject("MeterSphere定时任务结果通知");
|
||||||
|
String users[] = {};
|
||||||
|
List<String> successEmailList=new ArrayList<>();
|
||||||
|
List<String> failEmailList=new ArrayList<>();
|
||||||
|
if(notice.size()>0){
|
||||||
|
for(Notice n:notice){
|
||||||
|
if (n.getEnable().equals("true")&&n.getEvent().equals("执行成功")) {
|
||||||
|
successEmailList=userService.queryEmail(n.getNames());
|
||||||
|
}
|
||||||
|
if (n.getEnable().equals("true")&&n.getEvent().equals("执行失败")) {
|
||||||
|
failEmailList=userService.queryEmail(n.getNames());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
LogUtil.error("Recipient information is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state.equals("success")){
|
||||||
|
users=successEmailList.toArray(new String[successEmailList.size()]);
|
||||||
|
helper.setText(html2,true);
|
||||||
|
}else{
|
||||||
|
users=failEmailList.toArray(new String[failEmailList.size()]);
|
||||||
|
helper.setText(html1,true);
|
||||||
|
|
||||||
|
}
|
||||||
|
helper.setTo(users);
|
||||||
|
javaMailSender.send(mimeMessage);
|
||||||
|
|
||||||
|
} catch (MessagingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
package io.metersphere.notice.service;
|
||||||
|
|
||||||
|
import io.metersphere.base.domain.Notice;
|
||||||
|
import io.metersphere.base.domain.NoticeExample;
|
||||||
|
import io.metersphere.base.mapper.NoticeMapper;
|
||||||
|
import io.metersphere.notice.controller.request.NoticeRequest;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class NoticeService {
|
||||||
|
@Resource
|
||||||
|
private NoticeMapper noticeMapper;
|
||||||
|
public void saveNotice(NoticeRequest noticeRequest) {
|
||||||
|
NoticeExample example = new NoticeExample();
|
||||||
|
example.createCriteria().andTestIdEqualTo(noticeRequest.getTestId());
|
||||||
|
List<Notice> notices = noticeMapper.selectByExample(example);
|
||||||
|
if (notices != null) {
|
||||||
|
noticeMapper.deleteByExample(example);
|
||||||
|
noticeRequest.getNotices().forEach(notice -> {
|
||||||
|
for(String x:notice.getNames()){
|
||||||
|
notice.setEvent(notice.getEvent());
|
||||||
|
notice.setEmail(notice.getEmail());
|
||||||
|
notice.setEnable(notice.getEnable());
|
||||||
|
notice.setTestId(noticeRequest.getTestId());
|
||||||
|
notice.setName(x);
|
||||||
|
noticeMapper.insert(notice);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
noticeRequest.getNotices().forEach(notice -> {
|
||||||
|
notice.setEvent(noticeRequest.getEvent());
|
||||||
|
notice.setTestId(noticeRequest.getTestId());
|
||||||
|
noticeMapper.insert(notice);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Notice> queryNotice(String id) {
|
||||||
|
NoticeExample example = new NoticeExample();
|
||||||
|
example.createCriteria().andTestIdEqualTo(id);
|
||||||
|
List<Notice> notices=noticeMapper.selectByExample(example);
|
||||||
|
List<Notice> notice=new ArrayList<>();
|
||||||
|
List<String> success=new ArrayList<>();
|
||||||
|
List<String> fail=new ArrayList<>();
|
||||||
|
String[] successArray=new String[success.size()];
|
||||||
|
String[] failArray=new String[fail.size()];
|
||||||
|
Notice notice1=new Notice();
|
||||||
|
Notice notice2=new Notice();
|
||||||
|
if(notices.size()>0){
|
||||||
|
for(Notice n:notices){
|
||||||
|
if(n.getEvent().equals("执行成功")){
|
||||||
|
success.add(n.getName());
|
||||||
|
notice1.setEnable(n.getEnable());
|
||||||
|
notice1.setTestId(id);
|
||||||
|
notice1.setEvent(n.getEvent());
|
||||||
|
notice1.setEmail(n.getEmail());
|
||||||
|
}
|
||||||
|
if(n.getEvent().equals("执行失败")){
|
||||||
|
fail.add(n.getName());
|
||||||
|
notice2.setEnable(n.getEnable());
|
||||||
|
notice2.setTestId(id);
|
||||||
|
notice2.setEvent(n.getEvent());
|
||||||
|
notice2.setEmail(n.getEmail());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
successArray=success.toArray(new String[success.size()]);
|
||||||
|
failArray=fail.toArray(new String[fail.size()]);
|
||||||
|
notice1.setNames(successArray);
|
||||||
|
notice2.setNames(failArray);
|
||||||
|
notice.add(notice1);
|
||||||
|
notice.add(notice2);
|
||||||
|
}
|
||||||
|
return notice;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -19,6 +19,8 @@ import io.metersphere.dto.LoadTestDTO;
|
||||||
import io.metersphere.dto.ScheduleDao;
|
import io.metersphere.dto.ScheduleDao;
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.job.sechedule.PerformanceTestJob;
|
import io.metersphere.job.sechedule.PerformanceTestJob;
|
||||||
|
import io.metersphere.notice.service.MailService;
|
||||||
|
import io.metersphere.notice.service.NoticeService;
|
||||||
import io.metersphere.performance.engine.Engine;
|
import io.metersphere.performance.engine.Engine;
|
||||||
import io.metersphere.performance.engine.EngineFactory;
|
import io.metersphere.performance.engine.EngineFactory;
|
||||||
import io.metersphere.service.FileService;
|
import io.metersphere.service.FileService;
|
||||||
|
@ -80,6 +82,10 @@ public class PerformanceTestService {
|
||||||
private TestCaseMapper testCaseMapper;
|
private TestCaseMapper testCaseMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private TestCaseService testCaseService;
|
private TestCaseService testCaseService;
|
||||||
|
@Resource
|
||||||
|
private NoticeService noticeService;
|
||||||
|
@Resource
|
||||||
|
private MailService mailService;
|
||||||
|
|
||||||
public List<LoadTestDTO> list(QueryTestPlanRequest request) {
|
public List<LoadTestDTO> list(QueryTestPlanRequest request) {
|
||||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||||
|
@ -231,7 +237,10 @@ public class PerformanceTestService {
|
||||||
}
|
}
|
||||||
|
|
||||||
startEngine(loadTest, engine, request.getTriggerMode());
|
startEngine(loadTest, engine, request.getTriggerMode());
|
||||||
|
if (request.getTriggerMode().equals("SCHEDULE")) {
|
||||||
|
List<Notice> notice = noticeService.queryNotice(request.getId());
|
||||||
|
mailService.sendHtml(engine.getReportId(),notice,"performance");
|
||||||
|
}
|
||||||
return engine.getReportId();
|
return engine.getReportId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package io.metersphere.service;
|
||||||
import io.metersphere.base.domain.SystemParameter;
|
import io.metersphere.base.domain.SystemParameter;
|
||||||
import io.metersphere.base.domain.SystemParameterExample;
|
import io.metersphere.base.domain.SystemParameterExample;
|
||||||
import io.metersphere.base.mapper.SystemParameterMapper;
|
import io.metersphere.base.mapper.SystemParameterMapper;
|
||||||
|
import io.metersphere.base.mapper.ext.ExtSystemParameterMapper;
|
||||||
import io.metersphere.commons.constants.ParamConstants;
|
import io.metersphere.commons.constants.ParamConstants;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.commons.utils.EncryptUtils;
|
import io.metersphere.commons.utils.EncryptUtils;
|
||||||
|
@ -24,7 +25,12 @@ public class SystemParameterService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SystemParameterMapper systemParameterMapper;
|
private SystemParameterMapper systemParameterMapper;
|
||||||
|
@Resource
|
||||||
|
private ExtSystemParameterMapper extSystemParameterMapper;
|
||||||
|
|
||||||
|
public String searchEmail(){
|
||||||
|
return extSystemParameterMapper.email();
|
||||||
|
}
|
||||||
public String getSystemLanguage() {
|
public String getSystemLanguage() {
|
||||||
String result = StringUtils.EMPTY;
|
String result = StringUtils.EMPTY;
|
||||||
SystemParameterExample example = new SystemParameterExample();
|
SystemParameterExample example = new SystemParameterExample();
|
||||||
|
|
|
@ -61,6 +61,9 @@ public class UserService {
|
||||||
@Resource
|
@Resource
|
||||||
private WorkspaceService workspaceService;
|
private WorkspaceService workspaceService;
|
||||||
|
|
||||||
|
public List<String> queryEmail(String[] names){
|
||||||
|
return extUserMapper.queryEmails(names);
|
||||||
|
}
|
||||||
public UserDTO insert(UserRequest user) {
|
public UserDTO insert(UserRequest user) {
|
||||||
checkUserParam(user);
|
checkUserParam(user);
|
||||||
//
|
//
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.track.controller;
|
package io.metersphere.track.controller;
|
||||||
|
|
||||||
import io.metersphere.base.domain.Issues;
|
import io.metersphere.base.domain.Issues;
|
||||||
|
import io.metersphere.track.domain.TapdUser;
|
||||||
import io.metersphere.track.service.IssuesService;
|
import io.metersphere.track.service.IssuesService;
|
||||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
@ -35,4 +36,9 @@ public class TestCaseIssuesController {
|
||||||
issuesService.closeLocalIssue(id);
|
issuesService.closeLocalIssue(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/tapd/user/{caseId}")
|
||||||
|
public List<TapdUser> getTapdUsers(@PathVariable String caseId) {
|
||||||
|
return issuesService.getTapdProjectUsers(caseId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class TestPlanController {
|
||||||
QueryTestPlanRequest request = new QueryTestPlanRequest();
|
QueryTestPlanRequest request = new QueryTestPlanRequest();
|
||||||
request.setWorkspaceId(workspaceId);
|
request.setWorkspaceId(workspaceId);
|
||||||
request.setProjectId(projectId);
|
request.setProjectId(projectId);
|
||||||
return testPlanService.listTestPlan(request);
|
return testPlanService.listTestPlanByProject(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/list/all")
|
@PostMapping("/list/all")
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package io.metersphere.track.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class TapdUser implements Serializable {
|
||||||
|
private List<String> roleId;
|
||||||
|
private String name;
|
||||||
|
private String user;
|
||||||
|
}
|
|
@ -3,6 +3,8 @@ package io.metersphere.track.request.testcase;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class IssuesRequest {
|
public class IssuesRequest {
|
||||||
|
@ -10,4 +12,5 @@ public class IssuesRequest {
|
||||||
private String content;
|
private String content;
|
||||||
private String projectId;
|
private String projectId;
|
||||||
private String testCaseId;
|
private String testCaseId;
|
||||||
|
private List<String> tapdUsers;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,4 +21,6 @@ public class QueryTestPlanRequest extends TestPlan {
|
||||||
private Map<String, List<String>> filters;
|
private Map<String, List<String>> filters;
|
||||||
|
|
||||||
private Map<String, Object> combine;
|
private Map<String, Object> combine;
|
||||||
|
|
||||||
|
private String projectId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.track.service;
|
package io.metersphere.track.service;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
import io.metersphere.base.mapper.IssuesMapper;
|
import io.metersphere.base.mapper.IssuesMapper;
|
||||||
|
@ -17,6 +18,7 @@ import io.metersphere.controller.ResultHolder;
|
||||||
import io.metersphere.controller.request.IntegrationRequest;
|
import io.metersphere.controller.request.IntegrationRequest;
|
||||||
import io.metersphere.service.IntegrationService;
|
import io.metersphere.service.IntegrationService;
|
||||||
import io.metersphere.service.ProjectService;
|
import io.metersphere.service.ProjectService;
|
||||||
|
import io.metersphere.track.domain.TapdUser;
|
||||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
|
@ -188,10 +190,17 @@ public class IssuesService {
|
||||||
MSException.throwException("未关联Tapd 项目ID");
|
MSException.throwException("未关联Tapd 项目ID");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> tapdUsers = issuesRequest.getTapdUsers();
|
||||||
|
String usersStr = String.join(";", tapdUsers);
|
||||||
|
|
||||||
|
String username = SessionUtils.getUser().getName();
|
||||||
|
|
||||||
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
|
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
|
||||||
paramMap.add("title", issuesRequest.getTitle());
|
paramMap.add("title", issuesRequest.getTitle());
|
||||||
paramMap.add("workspace_id", tapdId);
|
paramMap.add("workspace_id", tapdId);
|
||||||
paramMap.add("description", issuesRequest.getContent());
|
paramMap.add("description", issuesRequest.getContent());
|
||||||
|
paramMap.add("reporter", username);
|
||||||
|
paramMap.add("current_owner", usersStr);
|
||||||
|
|
||||||
ResultHolder result = call(url, HttpMethod.POST, paramMap);
|
ResultHolder result = call(url, HttpMethod.POST, paramMap);
|
||||||
|
|
||||||
|
@ -535,4 +544,19 @@ public class IssuesService {
|
||||||
issuesMapper.updateByPrimaryKeySelective(issues);
|
issuesMapper.updateByPrimaryKeySelective(issues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<TapdUser> getTapdProjectUsers(String caseId) {
|
||||||
|
List<TapdUser> users = new ArrayList<>();
|
||||||
|
String projectId = getTapdProjectId(caseId);
|
||||||
|
String url = "https://api.tapd.cn/workspaces/users?workspace_id=" + projectId;
|
||||||
|
ResultHolder call = call(url);
|
||||||
|
String listJson = JSON.toJSONString(call.getData());
|
||||||
|
JSONArray jsonArray = JSON.parseArray(listJson);
|
||||||
|
for (int i = 0; i < jsonArray.size(); i++) {
|
||||||
|
JSONObject o = jsonArray.getJSONObject(i);
|
||||||
|
TapdUser user = o.getObject("UserWorkspace", TapdUser.class);
|
||||||
|
users.add(user);
|
||||||
|
}
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,6 +146,10 @@ public class TestPlanService {
|
||||||
return extTestPlanMapper.list(request);
|
return extTestPlanMapper.list(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<TestPlanDTO> listTestPlanByProject(QueryTestPlanRequest request) {
|
||||||
|
return extTestPlanMapper.planList(request);
|
||||||
|
}
|
||||||
|
|
||||||
public void testPlanRelevance(PlanCaseRelevanceRequest request) {
|
public void testPlanRelevance(PlanCaseRelevanceRequest request) {
|
||||||
|
|
||||||
List<String> testCaseIds = request.getTestCaseIds();
|
List<String> testCaseIds = request.getTestCaseIds();
|
||||||
|
|
|
@ -69,13 +69,13 @@ jmeter.home=/opt/jmeter
|
||||||
# quartz
|
# quartz
|
||||||
quartz.enabled=true
|
quartz.enabled=true
|
||||||
quartz.scheduler-name=msServerJob
|
quartz.scheduler-name=msServerJob
|
||||||
|
|
||||||
# file upload
|
# file upload
|
||||||
spring.servlet.multipart.max-file-size=500MB
|
spring.servlet.multipart.max-file-size=500MB
|
||||||
spring.servlet.multipart.max-request-size=500MB
|
spring.servlet.multipart.max-request-size=500MB
|
||||||
|
|
||||||
# actuator
|
# actuator
|
||||||
management.server.port=8083
|
management.server.port=8083
|
||||||
management.endpoints.web.exposure.include=*
|
management.endpoints.web.exposure.include=*
|
||||||
|
#spring.freemarker.checkTemplateLocation=false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
spring.freemarker.checkTemplateLocation=false
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
alter table test_plan drop column project_id;
|
|
@ -22,7 +22,7 @@ user_already_exists=The user already exists in the current member list
|
||||||
cannot_remove_current=Unable to remove the currently logged in user
|
cannot_remove_current=Unable to remove the currently logged in user
|
||||||
password_is_incorrect=Incorrect password
|
password_is_incorrect=Incorrect password
|
||||||
user_not_exist=user does not exist:
|
user_not_exist=user does not exist:
|
||||||
user_has_been_disabled=the user has been disabled.
|
user_has_been_disabled=the user has been disabled.
|
||||||
excessive_attempts=Excessive attempts
|
excessive_attempts=Excessive attempts
|
||||||
user_locked=the user has been locked.
|
user_locked=the user has been locked.
|
||||||
user_expires=user expires.
|
user_expires=user expires.
|
||||||
|
@ -151,5 +151,5 @@ quota_max_threads_excess_workspace=The maximum number of concurrent threads exce
|
||||||
quota_max_threads_excess_organization=The maximum number of concurrent threads exceeds the organization quota
|
quota_max_threads_excess_organization=The maximum number of concurrent threads exceeds the organization quota
|
||||||
quota_duration_excess_workspace=The stress test duration exceeds the work space quota
|
quota_duration_excess_workspace=The stress test duration exceeds the work space quota
|
||||||
quota_duration_excess_organization=The stress test duration exceeds the organization quota
|
quota_duration_excess_organization=The stress test duration exceeds the organization quota
|
||||||
license_valid_license_error=valid license error
|
|
||||||
license_valid_license_code=The authorization code already exists
|
email_subject=Metersphere timing task result notification
|
||||||
|
|
|
@ -151,7 +151,7 @@ quota_max_threads_excess_workspace=最大并发数超过工作空间限额
|
||||||
quota_max_threads_excess_organization=最大并发数超过组织限额
|
quota_max_threads_excess_organization=最大并发数超过组织限额
|
||||||
quota_duration_excess_workspace=压测时长超过工作空间限额
|
quota_duration_excess_workspace=压测时长超过工作空间限额
|
||||||
quota_duration_excess_organization=压测时长超过组织限额
|
quota_duration_excess_organization=压测时长超过组织限额
|
||||||
license_valid_license_error=授权验证失败
|
email_subject=MeterSphere定时任务结果通知
|
||||||
license_valid_license_code=授权码已经存在
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -154,3 +154,5 @@ quota_duration_excess_organization=壓測時長超過組織限額
|
||||||
license_valid_license_error=授權驗證失敗
|
license_valid_license_error=授權驗證失敗
|
||||||
license_valid_license_code=授權碼已經存在
|
license_valid_license_code=授權碼已經存在
|
||||||
|
|
||||||
|
|
||||||
|
email_subject=MeterSphere定時任務結果通知
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
LABEL maintainer="support@fit2cloud.com"
|
LABEL maintainer="support@fit2cloud.com"
|
||||||
|
|
||||||
ENV JMETER_VERSION "5.2.1"
|
ENV JMETER_VERSION "5.3"
|
||||||
|
ENV KAFKA_BACKEND_LISTENER_VERSION "1.0.4"
|
||||||
#定义时区参数
|
#定义时区参数
|
||||||
ENV TZ=Asia/Shanghai
|
ENV TZ=Asia/Shanghai
|
||||||
|
|
||||||
RUN apk update && \
|
RUN apk update && \
|
||||||
apk upgrade && \
|
apk upgrade && \
|
||||||
apk add --update openjdk8-jre wget tar bash && \
|
apk add --update openjdk8 wget tar bash && \
|
||||||
wget https://mirrors.tuna.tsinghua.edu.cn/apache/jmeter/binaries/apache-jmeter-${JMETER_VERSION}.tgz && \
|
wget https://mirrors.tuna.tsinghua.edu.cn/apache/jmeter/binaries/apache-jmeter-${JMETER_VERSION}.tgz && \
|
||||||
wget https://jmeter-plugins.org/files/packages/jpgc-casutg-2.9.zip && \
|
wget https://jmeter-plugins.org/files/packages/jpgc-casutg-2.9.zip && \
|
||||||
wget https://jmeter-plugins.org/files/packages/jpgc-tst-2.5.zip && \
|
wget https://jmeter-plugins.org/files/packages/jpgc-tst-2.5.zip && \
|
||||||
wget https://github.com/metersphere/jmeter-backend-listener-kafka/releases/download/v1.0.2/jmeter.backendlistener.kafka-1.0.2.jar && \
|
wget https://github.com/metersphere/jmeter-backend-listener-kafka/releases/download/v${KAFKA_BACKEND_LISTENER_VERSION}/jmeter.backendlistener.kafka-${KAFKA_BACKEND_LISTENER_VERSION}.jar && \
|
||||||
wget https://github.com/metersphere/jmeter-plugins-for-apache-dubbo/releases/download/2.7.7/jmeter-plugins-dubbo-2.7.7-jar-with-dependencies.jar && \
|
wget https://github.com/metersphere/jmeter-plugins-for-apache-dubbo/releases/download/2.7.7/jmeter-plugins-dubbo-2.7.7-jar-with-dependencies.jar && \
|
||||||
mkdir -p /opt/jmeter && \
|
mkdir -p /opt/jmeter && \
|
||||||
tar -zxf apache-jmeter-${JMETER_VERSION}.tgz -C /opt/jmeter/ --strip-components=1 && \
|
tar -zxf apache-jmeter-${JMETER_VERSION}.tgz -C /opt/jmeter/ --strip-components=1 && \
|
||||||
unzip -o jpgc-casutg-2.9.zip -d /tmp/ && mv /tmp/lib/ext/jmeter-plugins-casutg-2.9.jar /opt/jmeter/lib/ext && \
|
unzip -o jpgc-casutg-2.9.zip -d /tmp/ && mv /tmp/lib/ext/jmeter-plugins-casutg-2.9.jar /opt/jmeter/lib/ext && \
|
||||||
unzip -o jpgc-tst-2.5.zip -d /tmp/ && mv /tmp/lib/ext/jmeter-plugins-tst-2.5.jar /opt/jmeter/lib/ext && \
|
unzip -o jpgc-tst-2.5.zip -d /tmp/ && mv /tmp/lib/ext/jmeter-plugins-tst-2.5.jar /opt/jmeter/lib/ext && \
|
||||||
mv jmeter.backendlistener.kafka-1.0.2.jar /opt/jmeter/lib/ext && \
|
mv jmeter.backendlistener.kafka-${KAFKA_BACKEND_LISTENER_VERSION}.jar /opt/jmeter/lib/ext && \
|
||||||
mv jmeter-plugins-dubbo-2.7.7-jar-with-dependencies.jar /opt/jmeter/lib/ext && \
|
mv jmeter-plugins-dubbo-2.7.7-jar-with-dependencies.jar /opt/jmeter/lib/ext && \
|
||||||
rm -rf apache-jmeter-${JMETER_VERSION}.tgz && \
|
rm -rf apache-jmeter-${JMETER_VERSION}.tgz && \
|
||||||
rm -rf jpgc-casutg-2.9.zip && \
|
rm -rf jpgc-casutg-2.9.zip && \
|
||||||
rm -rf jpgc-tst-2.5.zip && \
|
rm -rf jpgc-tst-2.5.zip && \
|
||||||
rm -rf jmeter.backendlistener.kafka-1.0.2.jar && \
|
rm -rf jmeter.backendlistener.kafka-${KAFKA_BACKEND_LISTENER_VERSION}.jar && \
|
||||||
rm -rf jmeter-plugins-dubbo-2.7.7-jar-with-dependencies.jar && \
|
rm -rf jmeter-plugins-dubbo-2.7.7-jar-with-dependencies.jar && \
|
||||||
rm -rf /var/cache/apk/* && \
|
rm -rf /var/cache/apk/* && \
|
||||||
wget -O /usr/bin/tpl https://github.com/schneidexe/tpl/releases/download/v0.5.0/tpl-linux-amd64 && \
|
wget -O /usr/bin/tpl https://github.com/schneidexe/tpl/releases/download/v0.5.0/tpl-linux-amd64 && \
|
||||||
|
@ -31,7 +31,7 @@ RUN apk update && \
|
||||||
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo "$TZ" > /etc/timezone
|
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo "$TZ" > /etc/timezone
|
||||||
|
|
||||||
ENV JMETER_HOME /opt/jmeter
|
ENV JMETER_HOME /opt/jmeter
|
||||||
ENV PATH $PATH:$JMETER_HOME/bin
|
ENV PATH $PATH:$JMETER_HOME/bin:/usr/lib/jvm/java-1.8-openjdk/bin
|
||||||
|
|
||||||
ADD log4j2.xml $JMETER_HOME/bin/log4j2.xml
|
ADD log4j2.xml $JMETER_HOME/bin/log4j2.xml
|
||||||
ADD jmeter.properties $JMETER_HOME/bin/jmeter.properties
|
ADD jmeter.properties $JMETER_HOME/bin/jmeter.properties
|
|
@ -1,4 +1,4 @@
|
||||||
FROM registry.fit2cloud.com/metersphere/jmeter-base:latest
|
FROM registry.fit2cloud.com/metersphere/jmeter-base:0.0.1
|
||||||
LABEL maintainer="support@fit2cloud.com"
|
LABEL maintainer="support@fit2cloud.com"
|
||||||
|
|
||||||
EXPOSE 60000
|
EXPOSE 60000
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
<ms-api-report-dialog :test-id="id" ref="reportDialog"/>
|
<ms-api-report-dialog :test-id="id" ref="reportDialog"/>
|
||||||
|
|
||||||
<ms-schedule-config :schedule="test.schedule" :is-read-only="isReadOnly" :save="saveCronExpression"
|
<ms-schedule-config :schedule="test.schedule" :is-read-only="isReadOnly" :save="saveCronExpression"
|
||||||
@scheduleChange="saveSchedule" :check-open="checkScheduleEdit"/>
|
@scheduleChange="saveSchedule" :test-id="id" :check-open="checkScheduleEdit"/>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-header>
|
</el-header>
|
||||||
<ms-api-scenario-config :debug-report-id="debugReportId" @runDebug="runDebug" :is-read-only="isReadOnly"
|
<ms-api-scenario-config :debug-report-id="debugReportId" @runDebug="runDebug" :is-read-only="isReadOnly"
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
<el-radio-group v-model="type" @change="createRequest">
|
<el-radio-group v-model="type" @change="createRequest">
|
||||||
<el-radio :label="types.HTTP">HTTP</el-radio>
|
<el-radio :label="types.HTTP">HTTP</el-radio>
|
||||||
<el-radio :label="types.DUBBO">DUBBO</el-radio>
|
<el-radio :label="types.DUBBO">DUBBO</el-radio>
|
||||||
|
<el-radio :label="types.SQL">SQL</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
<el-button slot="reference" :disabled="isReadOnly"
|
<el-button slot="reference" :disabled="isReadOnly"
|
||||||
class="request-create" type="primary" size="mini" icon="el-icon-plus" plain/>
|
class="request-create" type="primary" size="mini" icon="el-icon-plus" plain/>
|
||||||
|
|
|
@ -9,14 +9,15 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {JSR223Processor, Request, RequestFactory, Scenario} from "../../model/ScenarioModel";
|
import {JSR223Processor, Request, RequestFactory, Scenario} from "../../model/ScenarioModel";
|
||||||
import MsApiHttpRequestForm from "./ApiHttpRequestForm";
|
import MsApiHttpRequestForm from "./ApiHttpRequestForm";
|
||||||
import MsApiDubboRequestForm from "./ApiDubboRequestForm";
|
import MsApiDubboRequestForm from "./ApiDubboRequestForm";
|
||||||
import MsScenarioResults from "../../../report/components/ScenarioResults";
|
import MsScenarioResults from "../../../report/components/ScenarioResults";
|
||||||
import MsRequestResultTail from "../../../report/components/RequestResultTail";
|
import MsRequestResultTail from "../../../report/components/RequestResultTail";
|
||||||
|
import MsApiSqlRequestForm from "./ApiSqlRequestForm";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsApiRequestForm",
|
name: "MsApiRequestForm",
|
||||||
components: {MsRequestResultTail, MsScenarioResults, MsApiDubboRequestForm, MsApiHttpRequestForm},
|
components: {MsApiSqlRequestForm, MsRequestResultTail, MsScenarioResults, MsApiDubboRequestForm, MsApiHttpRequestForm},
|
||||||
props: {
|
props: {
|
||||||
scenario: Scenario,
|
scenario: Scenario,
|
||||||
request: Request,
|
request: Request,
|
||||||
|
@ -41,6 +42,9 @@ export default {
|
||||||
case RequestFactory.TYPES.DUBBO:
|
case RequestFactory.TYPES.DUBBO:
|
||||||
name = "MsApiDubboRequestForm";
|
name = "MsApiDubboRequestForm";
|
||||||
break;
|
break;
|
||||||
|
case RequestFactory.TYPES.SQL:
|
||||||
|
name = "MsApiSqlRequestForm";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
name = "MsApiHttpRequestForm";
|
name = "MsApiHttpRequestForm";
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
<template>
|
||||||
|
<el-form :model="request" :rules="rules" ref="request" label-width="100px" :disabled="isReadOnly">
|
||||||
|
|
||||||
|
<el-form-item :label="$t('api_test.request.name')" prop="name">
|
||||||
|
<el-input v-model="request.name" maxlength="300" show-word-limit/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="'连接池'" prop="dataSource">
|
||||||
|
<el-select v-model="request.dataSource">
|
||||||
|
<el-option v-for="(item, index) in scenario.databaseConfigs" :key="index" :value="item.name" :label="item.name"/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!--<el-form-item :label="'查询类型'" prop="protocol">-->
|
||||||
|
<!--<el-select v-model="request.queryType">-->
|
||||||
|
<!--<el-option label="dubbo://" :value="protocols.DUBBO"/>-->
|
||||||
|
<!--</el-select>-->
|
||||||
|
<!--</el-form-item>-->
|
||||||
|
|
||||||
|
<el-form-item :label="'超时时间'" prop="queryTimeout">
|
||||||
|
<el-input-number :disabled="isReadOnly" size="mini" v-model="request.queryTimeout" :placeholder="$t('commons.millisecond')" :max="1000*10000000" :min="0"/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-button :disabled="!request.enable || !scenario.enable || isReadOnly" class="debug-button" size="small" type="primary" @click="runDebug">{{$t('api_test.request.debug')}}</el-button>
|
||||||
|
|
||||||
|
<el-tabs v-model="activeName">
|
||||||
|
<el-tab-pane :label="'sql脚本'" name="sql">
|
||||||
|
<div class="sql-content" >
|
||||||
|
<ms-code-edit mode="sql" :read-only="isReadOnly" :modes="['sql']" :data.sync="request.query" theme="eclipse" ref="codeEdit"/>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="$t('api_test.request.assertions.label')" name="assertions">
|
||||||
|
<ms-api-assertions :is-read-only="isReadOnly" :assertions="request.assertions"/>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="$t('api_test.request.extract.label')" name="extract">
|
||||||
|
<ms-api-extract :is-read-only="isReadOnly" :extract="request.extract"/>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="$t('api_test.request.processor.pre_exec_script')" name="beanShellPreProcessor">
|
||||||
|
<ms-jsr233-processor :is-read-only="isReadOnly" :jsr223-processor="request.jsr223PreProcessor"/>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="$t('api_test.request.processor.post_exec_script')" name="beanShellPostProcessor">
|
||||||
|
<ms-jsr233-processor :is-read-only="isReadOnly" :jsr223-processor="request.jsr223PostProcessor"/>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsApiKeyValue from "../ApiKeyValue";
|
||||||
|
import MsApiAssertions from "../assertion/ApiAssertions";
|
||||||
|
import {DubboRequest, Scenario, SqlRequest} from "../../model/ScenarioModel";
|
||||||
|
import MsApiExtract from "../extract/ApiExtract";
|
||||||
|
import ApiRequestMethodSelect from "../collapse/ApiRequestMethodSelect";
|
||||||
|
import MsDubboInterface from "@/business/components/api/test/components/request/dubbo/Interface";
|
||||||
|
import MsDubboRegistryCenter from "@/business/components/api/test/components/request/dubbo/RegistryCenter";
|
||||||
|
import MsDubboConfigCenter from "@/business/components/api/test/components/request/dubbo/ConfigCenter";
|
||||||
|
import MsDubboConsumerService from "@/business/components/api/test/components/request/dubbo/ConsumerAndService";
|
||||||
|
import MsJsr233Processor from "../processor/Jsr233Processor";
|
||||||
|
import MsCodeEdit from "../../../../common/components/MsCodeEdit";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MsApiSqlRequestForm",
|
||||||
|
components: {
|
||||||
|
MsCodeEdit,
|
||||||
|
MsJsr233Processor,
|
||||||
|
MsDubboConsumerService,
|
||||||
|
MsDubboConfigCenter,
|
||||||
|
MsDubboRegistryCenter,
|
||||||
|
MsDubboInterface, ApiRequestMethodSelect, MsApiExtract, MsApiAssertions, MsApiKeyValue
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
request: SqlRequest,
|
||||||
|
scenario: Scenario,
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeName: "sql",
|
||||||
|
rules: {
|
||||||
|
name: [
|
||||||
|
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
|
||||||
|
{max: 300, message: this.$t('commons.input_limit', [1, 300]), trigger: 'blur'},
|
||||||
|
],
|
||||||
|
dataSource: [
|
||||||
|
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
useEnvironmentChange(value) {
|
||||||
|
if (value && !this.request.environment) {
|
||||||
|
this.$error(this.$t('api_test.request.please_add_environment_to_scenario'), 2000);
|
||||||
|
this.request.useEnvironment = false;
|
||||||
|
}
|
||||||
|
this.$refs["request"].clearValidate();
|
||||||
|
},
|
||||||
|
runDebug() {
|
||||||
|
this.$emit('runDebug');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.sql-content {
|
||||||
|
height: calc(100vh - 570px);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -8,7 +8,7 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="'数据库连接URL'" prop="dbUrl">
|
<el-form-item :label="'数据库连接URL'" prop="dbUrl">
|
||||||
<el-input v-model="config.dbUrl" maxlength="300" show-word-limit
|
<el-input v-model="config.dbUrl" maxlength="500" show-word-limit
|
||||||
:placeholder="$t('commons.input_content')"/>
|
:placeholder="$t('commons.input_content')"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="'密码'" prop="password">
|
<el-form-item :label="'密码'" prop="password">
|
||||||
<el-input v-model="config.password" maxlength="300" show-word-limit
|
<el-input v-model="config.password" maxlength="200" show-word-limit
|
||||||
:placeholder="$t('commons.input_content')"/>
|
:placeholder="$t('commons.input_content')"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
@ -67,7 +67,6 @@
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
drivers: DatabaseConfig.DRIVER_CLASS,
|
drivers: DatabaseConfig.DRIVER_CLASS,
|
||||||
// config: new DatabaseConfig(),
|
|
||||||
rules: {
|
rules: {
|
||||||
name: [
|
name: [
|
||||||
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
|
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
|
||||||
|
@ -95,7 +94,6 @@
|
||||||
this.$refs['databaseFrom'].validate((valid) => {
|
this.$refs['databaseFrom'].validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.$emit('save', this.config);
|
this.$emit('save', this.config);
|
||||||
// this.config = new DatabaseConfig();
|
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,6 +274,38 @@ export class DubboSample extends DefaultTestElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class JDBCSampler extends DefaultTestElement {
|
||||||
|
constructor(testName, request = {}) {
|
||||||
|
super('JDBCSampler', 'TestBeanGUI', 'JDBCSampler', testName);
|
||||||
|
|
||||||
|
this.stringProp("dataSource", request.dataSource);
|
||||||
|
this.stringProp("query", request.query);
|
||||||
|
this.stringProp("queryTimeout", request.queryTimeout);
|
||||||
|
this.stringProp("queryArguments");
|
||||||
|
this.stringProp("queryArgumentsTypes");
|
||||||
|
this.stringProp("resultSetMaxRows");
|
||||||
|
this.stringProp("resultVariable");
|
||||||
|
this.stringProp("variableNames");
|
||||||
|
this.stringProp("resultSetHandler", 'Store as String');
|
||||||
|
this.stringProp("queryType", 'Callable Statement');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// <JDBCSampler guiclass="TestBeanGUI" testclass="JDBCSampler" testname="JDBC Request" enabled="true">
|
||||||
|
// <stringProp name="dataSource">test</stringProp>
|
||||||
|
// <stringProp name="query">select id from test_plan;
|
||||||
|
// select name from test_plan;
|
||||||
|
// </stringProp>
|
||||||
|
// <stringProp name="queryArguments"></stringProp>
|
||||||
|
// <stringProp name="queryArgumentsTypes"></stringProp>
|
||||||
|
// <stringProp name="queryTimeout"></stringProp>
|
||||||
|
// <stringProp name="queryType">Callable Statement</stringProp>
|
||||||
|
// <stringProp name="resultSetHandler">Store as String</stringProp>
|
||||||
|
// <stringProp name="resultSetMaxRows"></stringProp>
|
||||||
|
// <stringProp name="resultVariable"></stringProp>
|
||||||
|
// <stringProp name="variableNames"></stringProp>
|
||||||
|
// </JDBCSampler>
|
||||||
|
|
||||||
export class HTTPSamplerProxy extends DefaultTestElement {
|
export class HTTPSamplerProxy extends DefaultTestElement {
|
||||||
constructor(testName, options = {}) {
|
constructor(testName, options = {}) {
|
||||||
super('HTTPSamplerProxy', 'HttpTestSampleGui', 'HTTPSamplerProxy', testName);
|
super('HTTPSamplerProxy', 'HttpTestSampleGui', 'HTTPSamplerProxy', testName);
|
||||||
|
@ -515,6 +547,29 @@ export class DNSCacheManager extends DefaultTestElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class JDBCDataSource extends DefaultTestElement {
|
||||||
|
constructor(testName, datasource) {
|
||||||
|
super('JDBCDataSource', 'TestBeanGUI', 'JDBCDataSource', testName);
|
||||||
|
|
||||||
|
this.boolProp('autocommit', true);
|
||||||
|
this.boolProp('keepAlive', true);
|
||||||
|
this.boolProp('preinit', false);
|
||||||
|
this.stringProp('dataSource', datasource.name);
|
||||||
|
this.stringProp('dbUrl', datasource.dbUrl);
|
||||||
|
this.stringProp('driver', datasource.driver);
|
||||||
|
this.stringProp('username', datasource.username);
|
||||||
|
this.stringProp('password', datasource.password);
|
||||||
|
this.stringProp('poolMax', datasource.poolMax);
|
||||||
|
this.stringProp('timeout', datasource.timeout);
|
||||||
|
this.stringProp('connectionAge', '5000');
|
||||||
|
this.stringProp('trimInterval', '60000');
|
||||||
|
this.stringProp('transactionIsolation', 'DEFAULT');
|
||||||
|
this.stringProp('checkQuery');
|
||||||
|
this.stringProp('initQuery');
|
||||||
|
this.stringProp('connectionProperties');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class Arguments extends DefaultTestElement {
|
export class Arguments extends DefaultTestElement {
|
||||||
constructor(testName, args) {
|
constructor(testName, args) {
|
||||||
super('Arguments', 'ArgumentsPanel', 'Arguments', testName);
|
super('Arguments', 'ArgumentsPanel', 'Arguments', testName);
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
HashTree,
|
HashTree,
|
||||||
HeaderManager,
|
HeaderManager,
|
||||||
HTTPSamplerArguments, HTTPsamplerFiles,
|
HTTPSamplerArguments, HTTPsamplerFiles,
|
||||||
HTTPSamplerProxy,
|
HTTPSamplerProxy, JDBCDataSource, JDBCSampler,
|
||||||
JSONPathAssertion,
|
JSONPathAssertion,
|
||||||
JSONPostProcessor, JSR223PostProcessor, JSR223PreProcessor,
|
JSONPostProcessor, JSR223PostProcessor, JSR223PreProcessor,
|
||||||
RegexExtractor,
|
RegexExtractor,
|
||||||
|
@ -211,7 +211,7 @@ export class Scenario extends BaseConfig {
|
||||||
this.environment = undefined;
|
this.environment = undefined;
|
||||||
this.enableCookieShare = false;
|
this.enableCookieShare = false;
|
||||||
this.enable = true;
|
this.enable = true;
|
||||||
this.databaseConfigs = undefined;
|
this.databaseConfigs = [];
|
||||||
|
|
||||||
this.set(options);
|
this.set(options);
|
||||||
this.sets({variables: KeyValue, headers: KeyValue, requests: RequestFactory, databaseConfigs: DatabaseConfig}, options);
|
this.sets({variables: KeyValue, headers: KeyValue, requests: RequestFactory, databaseConfigs: DatabaseConfig}, options);
|
||||||
|
@ -273,6 +273,7 @@ export class RequestFactory {
|
||||||
static TYPES = {
|
static TYPES = {
|
||||||
HTTP: "HTTP",
|
HTTP: "HTTP",
|
||||||
DUBBO: "DUBBO",
|
DUBBO: "DUBBO",
|
||||||
|
SQL: "SQL",
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(options = {}) {
|
constructor(options = {}) {
|
||||||
|
@ -280,6 +281,8 @@ export class RequestFactory {
|
||||||
switch (options.type) {
|
switch (options.type) {
|
||||||
case RequestFactory.TYPES.DUBBO:
|
case RequestFactory.TYPES.DUBBO:
|
||||||
return new DubboRequest(options);
|
return new DubboRequest(options);
|
||||||
|
case RequestFactory.TYPES.SQL:
|
||||||
|
return new SqlRequest(options);
|
||||||
default:
|
default:
|
||||||
return new HttpRequest(options);
|
return new HttpRequest(options);
|
||||||
}
|
}
|
||||||
|
@ -460,6 +463,60 @@ export class DubboRequest extends Request {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class SqlRequest extends Request {
|
||||||
|
|
||||||
|
constructor(options = {}) {
|
||||||
|
super(RequestFactory.TYPES.SQL);
|
||||||
|
this.id = options.id || uuid();
|
||||||
|
this.name = options.name;
|
||||||
|
this.dataSource = options.dataSource;
|
||||||
|
this.query = options.query;
|
||||||
|
// this.queryType = options.queryType;
|
||||||
|
this.queryTimeout = options.queryTimeout;
|
||||||
|
this.enable = options.enable === undefined ? true : options.enable;
|
||||||
|
this.assertions = new Assertions(options.assertions);
|
||||||
|
this.extract = new Extract(options.extract);
|
||||||
|
this.jsr223PreProcessor = new JSR223Processor(options.jsr223PreProcessor);
|
||||||
|
this.jsr223PostProcessor = new JSR223Processor(options.jsr223PostProcessor);
|
||||||
|
|
||||||
|
this.sets({args: KeyValue, attachmentArgs: KeyValue}, options);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
isValid() {
|
||||||
|
if (this.enable) {
|
||||||
|
if (!this.name) {
|
||||||
|
return {
|
||||||
|
isValid: false,
|
||||||
|
info: 'name'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.dataSource) {
|
||||||
|
return {
|
||||||
|
isValid: false,
|
||||||
|
info: 'dataSource'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
isValid: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showType() {
|
||||||
|
return "SQL";
|
||||||
|
}
|
||||||
|
|
||||||
|
showMethod() {
|
||||||
|
return "SQL";
|
||||||
|
}
|
||||||
|
|
||||||
|
clone() {
|
||||||
|
return new SqlRequest(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export class ConfigCenter extends BaseConfig {
|
export class ConfigCenter extends BaseConfig {
|
||||||
static PROTOCOLS = ["zookeeper", "nacos", "apollo"];
|
static PROTOCOLS = ["zookeeper", "nacos", "apollo"];
|
||||||
|
|
||||||
|
@ -502,24 +559,6 @@ export class DatabaseConfig extends BaseConfig {
|
||||||
// options.id = options.id || uuid();
|
// options.id = options.id || uuid();
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
// <JDBCDataSource guiclass="TestBeanGUI" testclass="JDBCDataSource" testname="JDBC Connection Configurationqqq" enabled="true">
|
|
||||||
// <boolProp name="autocommit">true</boolProp>
|
|
||||||
// <stringProp name="checkQuery"></stringProp>
|
|
||||||
// <stringProp name="connectionAge">5000</stringProp>
|
|
||||||
// <stringProp name="connectionProperties"></stringProp>
|
|
||||||
// <stringProp name="dataSource">test</stringProp>
|
|
||||||
// <stringProp name="dbUrl">jdbc:mysql://localhost:3306/metersphere?autoReconnect=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true</stringProp>
|
|
||||||
// <stringProp name="driver">com.mysql.jdbc.Driver</stringProp>
|
|
||||||
// <stringProp name="initQuery"></stringProp>
|
|
||||||
// <boolProp name="keepAlive">true</boolProp>
|
|
||||||
// <stringProp name="password">root</stringProp>
|
|
||||||
// <stringProp name="poolMax">10</stringProp>
|
|
||||||
// <boolProp name="preinit">false</boolProp>
|
|
||||||
// <stringProp name="timeout">10000</stringProp>
|
|
||||||
// <stringProp name="transactionIsolation">DEFAULT</stringProp>
|
|
||||||
// <stringProp name="trimInterval">60000</stringProp>
|
|
||||||
// <stringProp name="username">root</stringProp>
|
|
||||||
// </JDBCDataSource>
|
|
||||||
|
|
||||||
isValid() {
|
isValid() {
|
||||||
return !!this.name || !!this.poolMax || !!this.timeout || !!this.driver || !!this.dbUrl || !!this.username || !!this.password;
|
return !!this.name || !!this.poolMax || !!this.timeout || !!this.driver || !!this.dbUrl || !!this.username || !!this.password;
|
||||||
|
@ -929,6 +968,8 @@ class JMXGenerator {
|
||||||
// 放在计划或线程组中,不建议放具体某个请求中
|
// 放在计划或线程组中,不建议放具体某个请求中
|
||||||
this.addDNSCacheManager(threadGroup, scenario.requests[0]);
|
this.addDNSCacheManager(threadGroup, scenario.requests[0]);
|
||||||
|
|
||||||
|
this.addJDBCDataSource(threadGroup, scenario);
|
||||||
|
|
||||||
scenario.requests.forEach(request => {
|
scenario.requests.forEach(request => {
|
||||||
if (request.enable) {
|
if (request.enable) {
|
||||||
if (!request.isValid()) return;
|
if (!request.isValid()) return;
|
||||||
|
@ -936,9 +977,7 @@ class JMXGenerator {
|
||||||
|
|
||||||
if (request instanceof DubboRequest) {
|
if (request instanceof DubboRequest) {
|
||||||
sampler = new DubboSample(request.name || "", new JMXDubboRequest(request, scenario.dubboConfig));
|
sampler = new DubboSample(request.name || "", new JMXDubboRequest(request, scenario.dubboConfig));
|
||||||
}
|
} else if (request instanceof HttpRequest) {
|
||||||
|
|
||||||
if (request instanceof HttpRequest) {
|
|
||||||
sampler = new HTTPSamplerProxy(request.name || "", new JMXHttpRequest(request, scenario.environment));
|
sampler = new HTTPSamplerProxy(request.name || "", new JMXHttpRequest(request, scenario.environment));
|
||||||
this.addRequestHeader(sampler, request);
|
this.addRequestHeader(sampler, request);
|
||||||
if (request.method.toUpperCase() === 'GET') {
|
if (request.method.toUpperCase() === 'GET') {
|
||||||
|
@ -946,6 +985,8 @@ class JMXGenerator {
|
||||||
} else {
|
} else {
|
||||||
this.addRequestBody(sampler, request, testId);
|
this.addRequestBody(sampler, request, testId);
|
||||||
}
|
}
|
||||||
|
} else if (request instanceof SqlRequest) {
|
||||||
|
sampler = new JDBCSampler(request.name || "", request);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addRequestExtractor(sampler, request);
|
this.addRequestExtractor(sampler, request);
|
||||||
|
@ -1009,6 +1050,13 @@ class JMXGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addJDBCDataSource(threadGroup, scenario) {
|
||||||
|
scenario.databaseConfigs.forEach(config => {
|
||||||
|
let name = config.name + "JDBCDataSource";
|
||||||
|
threadGroup.put(new JDBCDataSource(name, config));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
addScenarioHeaders(threadGroup, scenario) {
|
addScenarioHeaders(threadGroup, scenario) {
|
||||||
let environment = scenario.environment;
|
let environment = scenario.environment;
|
||||||
if (environment) {
|
if (environment) {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<span class="character">SCHEDULER</span>
|
<span class="character">SCHEDULER</span>
|
||||||
</span>
|
</span>
|
||||||
<el-switch :disabled="!schedule.value || isReadOnly" v-model="schedule.enable" @change="scheduleChange"/>
|
<el-switch :disabled="!schedule.value || isReadOnly" v-model="schedule.enable" @change="scheduleChange"/>
|
||||||
<ms-schedule-edit :is-read-only="isReadOnly" :schedule="schedule" :save="save" :custom-validate="customValidate"
|
<ms-schedule-edit :is-read-only="isReadOnly" :schedule="schedule" :test-id="testId" :save="save" :custom-validate="customValidate"
|
||||||
ref="scheduleEdit"/>
|
ref="scheduleEdit"/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -38,6 +38,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
testId:String,
|
||||||
save: Function,
|
save: Function,
|
||||||
schedule: {},
|
schedule: {},
|
||||||
checkOpen: {
|
checkOpen: {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||||
|
|
||||||
<el-tab-pane :label="$t('schedule.edit_timer_task')" name="first">
|
<el-tab-pane :label="$t('schedule.edit_timer_task')" name="first">
|
||||||
<el-form :model="form" :rules="rules" ref="from">
|
<el-form :model="form" :rules="rules" ref="from">
|
||||||
<el-form-item
|
<el-form-item
|
||||||
|
@ -26,81 +27,50 @@
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="$t('schedule.task_notification')" name="second">
|
<el-tab-pane :label="$t('schedule.task_notification')" name="second">
|
||||||
<template>
|
<template>
|
||||||
<el-select v-model="value" :placeholder="$t('commons.please_select')">
|
|
||||||
<el-option
|
|
||||||
v-for="item in options"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
<el-table
|
<el-table
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
style="width: 100%">
|
style="width: 100%">
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="receiver"
|
prop="event"
|
||||||
|
:label="$t('schedule.event')"
|
||||||
|
|
||||||
|
>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="name"
|
||||||
:label="$t('schedule.receiver')"
|
:label="$t('schedule.receiver')"
|
||||||
|
width="200"
|
||||||
>
|
>
|
||||||
<template v-slot:default="{row}">
|
<template v-slot:default="{row}">
|
||||||
<el-input
|
<el-select v-model="row.names" filterable multiple placeholder="请选择" @click.native="userList()">
|
||||||
size="mini"
|
<el-option
|
||||||
type="textarea"
|
v-for="item in options"
|
||||||
:rows="1"
|
:key="item.id"
|
||||||
class="edit-input"
|
:label="item.name"
|
||||||
v-model="row.receiver"
|
:value="item.name">
|
||||||
:placeholder="$t('schedule.receiver')"
|
</el-option>
|
||||||
clearable>
|
</el-select>
|
||||||
</el-input>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="email"
|
prop="email"
|
||||||
:label="$t('schedule.receiving_mode')"
|
:label="$t('schedule.receiving_mode')"
|
||||||
width="200"
|
>
|
||||||
>
|
|
||||||
<template v-slot:default="{row}">
|
|
||||||
<el-input
|
|
||||||
size="mini"
|
|
||||||
type="textarea"
|
|
||||||
:rows="1"
|
|
||||||
class="edit-input"
|
|
||||||
v-model="row.email"
|
|
||||||
:placeholder="$t('schedule.input_email')"
|
|
||||||
clearable>
|
|
||||||
</el-input>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
align="center"
|
|
||||||
prop="enable"
|
|
||||||
:label="$t('test_resource_pool.enable_disable')"
|
:label="$t('test_resource_pool.enable_disable')"
|
||||||
>
|
prop="enable"
|
||||||
<template slot-scope="scope">
|
>
|
||||||
|
<template v-slot:default="{row}">
|
||||||
<el-switch
|
<el-switch
|
||||||
v-model="scope.row.enable"
|
v-model="row.enable"
|
||||||
:active-value="true"
|
active-value="true"
|
||||||
:inactive-value="false"
|
inactive-value="false"
|
||||||
active-color="#13ce66"
|
|
||||||
inactive-color="#ff4949"
|
inactive-color="#ff4949"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('schedule.operation')">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
icon="el-icon-plus"
|
|
||||||
circle size="mini"
|
|
||||||
@click="handleAddStep(scope.$index)"></el-button>
|
|
||||||
<el-button
|
|
||||||
type="danger"
|
|
||||||
icon="el-icon-delete"
|
|
||||||
circle size="mini"
|
|
||||||
@click="handleDeleteStep(scope.$index)"></el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
</el-table>
|
||||||
<el-button type="primary" @click="saveNotice">{{$t('commons.save')}}</el-button>
|
|
||||||
</template>
|
</template>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
@ -111,19 +81,20 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import Crontab from "../cron/Crontab";
|
import Crontab from "../cron/Crontab";
|
||||||
import CrontabResult from "../cron/CrontabResult";
|
import CrontabResult from "../cron/CrontabResult";
|
||||||
import {cronValidate} from "@/common/js/cron";
|
import {cronValidate} from "@/common/js/cron";
|
||||||
import {listenGoBack, removeGoBackListener} from "@/common/js/utils";
|
import {listenGoBack, removeGoBackListener} from "@/common/js/utils";
|
||||||
|
|
||||||
function defaultCustomValidate() {
|
function defaultCustomValidate() {
|
||||||
return {pass: true};
|
return {pass: true};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsScheduleEdit",
|
name: "MsScheduleEdit",
|
||||||
components: {CrontabResult, Crontab},
|
components: {CrontabResult, Crontab},
|
||||||
props: {
|
props: {
|
||||||
|
testId: String,
|
||||||
save: Function,
|
save: Function,
|
||||||
schedule: {},
|
schedule: {},
|
||||||
customValidate: {
|
customValidate: {
|
||||||
|
@ -133,8 +104,10 @@ function defaultCustomValidate() {
|
||||||
isReadOnly: {
|
isReadOnly: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
'schedule.value'() {
|
'schedule.value'() {
|
||||||
this.form.cronValue = this.schedule.value;
|
this.form.cronValue = this.schedule.value;
|
||||||
|
@ -164,25 +137,22 @@ function defaultCustomValidate() {
|
||||||
form: {
|
form: {
|
||||||
cronValue: ""
|
cronValue: ""
|
||||||
},
|
},
|
||||||
options: [{
|
|
||||||
value: 'success',
|
|
||||||
label: '执行成功通知'
|
|
||||||
}, {
|
|
||||||
value: 'fail',
|
|
||||||
label: '执行失败通知'
|
|
||||||
}, {
|
|
||||||
value: 'all',
|
|
||||||
label: '全部通知'
|
|
||||||
}],
|
|
||||||
value: '',
|
|
||||||
tableData: [
|
tableData: [
|
||||||
{
|
{
|
||||||
receiver: "",
|
event: "执行成功",
|
||||||
email: "",
|
names: [],
|
||||||
|
email: "邮箱",
|
||||||
|
enable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
event: "执行失败",
|
||||||
|
names: [],
|
||||||
|
email: "邮箱",
|
||||||
enable: false
|
enable: false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
enable: false,
|
options: [{}],
|
||||||
|
enable: true,
|
||||||
email: "",
|
email: "",
|
||||||
activeName: 'first',
|
activeName: 'first',
|
||||||
rules: {
|
rules: {
|
||||||
|
@ -191,37 +161,31 @@ function defaultCustomValidate() {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleClick() {
|
userList() {
|
||||||
|
this.result = this.$get('user/list', response => {
|
||||||
|
this.options = response.data
|
||||||
|
})
|
||||||
},
|
},
|
||||||
saveNotice(){
|
handleClick() {
|
||||||
let param = this.buildParam();
|
if (this.activeName == "second") {
|
||||||
/* this.result=this.$post("notice/save",param,()=>{
|
this.result = this.$get('notice/query/' + this.testId, response => {
|
||||||
|
if (response.data.length > 0) {
|
||||||
})*/
|
this.tableData = response.data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
buildParam() {
|
buildParam() {
|
||||||
let param = {};
|
let param = {};
|
||||||
param.form = this.tableData
|
param.notices = this.tableData
|
||||||
param.testId = ""
|
param.testId = this.testId
|
||||||
param.event = this.value
|
|
||||||
return param;
|
return param;
|
||||||
},
|
},
|
||||||
handleAddStep(index) {
|
|
||||||
let form = {}
|
|
||||||
form.receiver = null;
|
|
||||||
form.email = null;
|
|
||||||
form.enable = null
|
|
||||||
this.tableData.splice(index + 1, 0, form);
|
|
||||||
},
|
|
||||||
handleDeleteStep(index) {
|
|
||||||
this.tableData.splice(index, 1);
|
|
||||||
},
|
|
||||||
open() {
|
open() {
|
||||||
this.dialogVisible = true;
|
this.dialogVisible = true;
|
||||||
this.form.cronValue = this.schedule.value;
|
this.form.cronValue = this.schedule.value;
|
||||||
listenGoBack(this.close);
|
listenGoBack(this.close);
|
||||||
|
this.handleClick()
|
||||||
},
|
},
|
||||||
crontabFill(value, resultList) {
|
crontabFill(value, resultList) {
|
||||||
//确定后回传的值
|
//确定后回传的值
|
||||||
|
@ -242,6 +206,10 @@ function defaultCustomValidate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
let param = this.buildParam();
|
||||||
|
this.result = this.$post("notice/save", param, () => {
|
||||||
|
|
||||||
|
})
|
||||||
},
|
},
|
||||||
close() {
|
close() {
|
||||||
this.dialogVisible = false;
|
this.dialogVisible = false;
|
||||||
|
@ -274,13 +242,13 @@ function defaultCustomValidate() {
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
.inp {
|
.inp {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-form-item {
|
.el-form-item {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<ms-schedule-config :schedule="testPlan.schedule" :save="saveCronExpression" @scheduleChange="saveSchedule"
|
<ms-schedule-config :schedule="testPlan.schedule" :save="saveCronExpression" @scheduleChange="saveSchedule"
|
||||||
:check-open="checkScheduleEdit" :custom-validate="durationValidate"/>
|
:check-open="checkScheduleEdit" :test-id="testId" :custom-validate="durationValidate"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
|
|
|
@ -218,6 +218,12 @@
|
||||||
/>
|
/>
|
||||||
<ckeditor :editor="editor" :disabled="isReadOnly" :config="editorConfig"
|
<ckeditor :editor="editor" :disabled="isReadOnly" :config="editorConfig"
|
||||||
v-model="testCase.issues.content"/>
|
v-model="testCase.issues.content"/>
|
||||||
|
<el-row v-if="hasTapdId">
|
||||||
|
Tapd平台处理人:
|
||||||
|
<el-select v-model="testCase.tapdUsers" placeholder="请选择处理人" style="width: 20%" multiple collapse-tags>
|
||||||
|
<el-option v-for="(userInfo, index) in users" :key="index" :label="userInfo.user" :value="userInfo.user"/>
|
||||||
|
</el-select>
|
||||||
|
</el-row>
|
||||||
<el-button type="primary" size="small" @click="saveIssues">{{$t('commons.save')}}</el-button>
|
<el-button type="primary" size="small" @click="saveIssues">{{$t('commons.save')}}</el-button>
|
||||||
<el-button size="small" @click="issuesSwitch=false">{{$t('commons.cancel')}}</el-button>
|
<el-button size="small" @click="issuesSwitch=false">{{$t('commons.cancel')}}</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
@ -323,6 +329,8 @@
|
||||||
test: {},
|
test: {},
|
||||||
activeTab: 'detail',
|
activeTab: 'detail',
|
||||||
isFailure: true,
|
isFailure: true,
|
||||||
|
users: [],
|
||||||
|
hasTapdId: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -490,6 +498,17 @@
|
||||||
executeResult += this.addPLabel(stepPrefix + (step.executeResult == undefined ? '' : step.executeResult));
|
executeResult += this.addPLabel(stepPrefix + (step.executeResult == undefined ? '' : step.executeResult));
|
||||||
});
|
});
|
||||||
this.testCase.issues.content = desc + this.addPLabel('') + result + this.addPLabel('') + executeResult + this.addPLabel('');
|
this.testCase.issues.content = desc + this.addPLabel('') + result + this.addPLabel('') + executeResult + this.addPLabel('');
|
||||||
|
|
||||||
|
this.$get("/test/case/project/" + this.testCase.caseId, res => {
|
||||||
|
const project = res.data;
|
||||||
|
if (project.tapdId) {
|
||||||
|
this.hasTapdId = true;
|
||||||
|
this.result = this.$get("/issues/tapd/user/" + this.testCase.caseId, response => {
|
||||||
|
let data = response.data;
|
||||||
|
this.users = data;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addPLabel(str) {
|
addPLabel(str) {
|
||||||
|
@ -515,6 +534,7 @@
|
||||||
param.title = this.testCase.issues.title;
|
param.title = this.testCase.issues.title;
|
||||||
param.content = this.testCase.issues.content;
|
param.content = this.testCase.issues.content;
|
||||||
param.testCaseId = this.testCase.caseId;
|
param.testCaseId = this.testCase.caseId;
|
||||||
|
param.tapdUsers = this.testCase.tapdUsers;
|
||||||
this.result = this.$post("/issues/add", param, () => {
|
this.result = this.$post("/issues/add", param, () => {
|
||||||
this.$success(this.$t('commons.save_success'));
|
this.$success(this.$t('commons.save_success'));
|
||||||
this.getIssues(param.testCaseId);
|
this.getIssues(param.testCaseId);
|
||||||
|
@ -522,6 +542,7 @@
|
||||||
this.issuesSwitch = false;
|
this.issuesSwitch = false;
|
||||||
this.testCase.issues.title = "";
|
this.testCase.issues.title = "";
|
||||||
this.testCase.issues.content = "";
|
this.testCase.issues.content = "";
|
||||||
|
this.testCase.tapdUsers = [];
|
||||||
},
|
},
|
||||||
getIssues(caseId) {
|
getIssues(caseId) {
|
||||||
this.result = this.$get("/issues/get/" + caseId, response => {
|
this.result = this.$get("/issues/get/" + caseId, response => {
|
||||||
|
|
|
@ -855,7 +855,7 @@ export default {
|
||||||
schedule: {
|
schedule: {
|
||||||
input_email: "请输入邮箱账号",
|
input_email: "请输入邮箱账号",
|
||||||
event: "事件",
|
event: "事件",
|
||||||
receiving_mode: "邮箱",
|
receiving_mode: "接收方式",
|
||||||
receiver: "接收人",
|
receiver: "接收人",
|
||||||
operation: "操作",
|
operation: "操作",
|
||||||
task_notification: "任务通知",
|
task_notification: "任务通知",
|
||||||
|
|
Loading…
Reference in New Issue