Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
9f33d88d3a
|
@ -422,6 +422,12 @@
|
||||||
<version>${jmeter.version}</version>
|
<version>${jmeter.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- 添加jmeter包支持导入的jmx能正常执行 -->
|
<!-- 添加jmeter包支持导入的jmx能正常执行 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.jayway.jsonpath</groupId>
|
||||||
|
<artifactId>json-path</artifactId>
|
||||||
|
<version>2.5.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -34,4 +34,14 @@ public class SaveApiPlanRequest {
|
||||||
|
|
||||||
private String projectId;
|
private String projectId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目环境对应关系
|
||||||
|
*/
|
||||||
|
private Map<String, String> envMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用例的环境的对应关系
|
||||||
|
*/
|
||||||
|
private Map<String, List<String>> mapping;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -489,6 +489,7 @@ public class MsJmeterParser extends ApiImportAbstractParser<ScenarioImport> {
|
||||||
assertionJsonPath.setDescription(jsonPathAssertion.getName());
|
assertionJsonPath.setDescription(jsonPathAssertion.getName());
|
||||||
assertionJsonPath.setExpression(jsonPathAssertion.getJsonPath());
|
assertionJsonPath.setExpression(jsonPathAssertion.getJsonPath());
|
||||||
assertionJsonPath.setExpect(jsonPathAssertion.getExpectedValue());
|
assertionJsonPath.setExpect(jsonPathAssertion.getExpectedValue());
|
||||||
|
assertionJsonPath.setOption(jsonPathAssertion.getPropertyAsString("ASS_OPTION"));
|
||||||
assertions.setName(jsonPathAssertion.getName());
|
assertions.setName(jsonPathAssertion.getName());
|
||||||
assertions.getJsonPath().add(assertionJsonPath);
|
assertions.getJsonPath().add(assertionJsonPath);
|
||||||
} else if (key instanceof XPath2Assertion) {
|
} else if (key instanceof XPath2Assertion) {
|
||||||
|
|
|
@ -10,6 +10,7 @@ public class MsAssertionJsonPath extends MsAssertionType {
|
||||||
private String expect;
|
private String expect;
|
||||||
private String expression;
|
private String expression;
|
||||||
private String description;
|
private String description;
|
||||||
|
private String option = "REGEX";
|
||||||
|
|
||||||
public MsAssertionJsonPath() {
|
public MsAssertionJsonPath() {
|
||||||
setType(MsAssertionType.JSON_PATH);
|
setType(MsAssertionType.JSON_PATH);
|
||||||
|
|
|
@ -96,7 +96,12 @@ public class MsAssertions extends MsTestElement {
|
||||||
assertion.setJsonValidationBool(true);
|
assertion.setJsonValidationBool(true);
|
||||||
assertion.setExpectNull(false);
|
assertion.setExpectNull(false);
|
||||||
assertion.setInvert(false);
|
assertion.setInvert(false);
|
||||||
assertion.setIsRegex(true);
|
assertion.setProperty("ASS_OPTION",assertionJsonPath.getOption());
|
||||||
|
if (StringUtils.isEmpty(assertionJsonPath.getOption()) || "REGEX".equals(assertionJsonPath.getOption())) {
|
||||||
|
assertion.setIsRegex(true);
|
||||||
|
} else {
|
||||||
|
assertion.setIsRegex(false);
|
||||||
|
}
|
||||||
return assertion;
|
return assertion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,8 @@ public class MsJSR223Processor extends MsTestElement {
|
||||||
if (StringUtils.isNotEmpty(name) && !config.isOperating()) {
|
if (StringUtils.isNotEmpty(name) && !config.isOperating()) {
|
||||||
processor.setName(this.getName() + "<->" + name);
|
processor.setName(this.getName() + "<->" + name);
|
||||||
}
|
}
|
||||||
|
processor.setProperty("MS-ID", this.getId());
|
||||||
|
|
||||||
processor.setProperty(TestElement.TEST_CLASS, JSR223Sampler.class.getName());
|
processor.setProperty(TestElement.TEST_CLASS, JSR223Sampler.class.getName());
|
||||||
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
||||||
processor.setProperty("cacheKey", "true");
|
processor.setProperty("cacheKey", "true");
|
||||||
|
|
|
@ -82,6 +82,7 @@ public class MsDubboSampler extends MsTestElement {
|
||||||
}
|
}
|
||||||
sampler.setProperty(TestElement.TEST_CLASS, DubboSample.class.getName());
|
sampler.setProperty(TestElement.TEST_CLASS, DubboSample.class.getName());
|
||||||
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("DubboSampleGui"));
|
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("DubboSampleGui"));
|
||||||
|
sampler.setProperty("MS-ID", this.getId());
|
||||||
|
|
||||||
sampler.addTestElement(configCenter(this.getConfigCenter()));
|
sampler.addTestElement(configCenter(this.getConfigCenter()));
|
||||||
sampler.addTestElement(registryCenter(this.getRegistryCenter()));
|
sampler.addTestElement(registryCenter(this.getRegistryCenter()));
|
||||||
|
|
|
@ -106,6 +106,7 @@ public class MsHTTPSamplerProxy extends MsTestElement {
|
||||||
}
|
}
|
||||||
sampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
|
sampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
|
||||||
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("HttpTestSampleGui"));
|
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("HttpTestSampleGui"));
|
||||||
|
sampler.setProperty("MS-ID", this.getId());
|
||||||
sampler.setMethod(this.getMethod());
|
sampler.setMethod(this.getMethod());
|
||||||
sampler.setContentEncoding("UTF-8");
|
sampler.setContentEncoding("UTF-8");
|
||||||
sampler.setConnectTimeout(this.getConnectTimeout() == null ? "6000" : this.getConnectTimeout());
|
sampler.setConnectTimeout(this.getConnectTimeout() == null ? "6000" : this.getConnectTimeout());
|
||||||
|
|
|
@ -119,6 +119,8 @@ public class MsJDBCSampler extends MsTestElement {
|
||||||
}
|
}
|
||||||
sampler.setProperty(TestElement.TEST_CLASS, JDBCSampler.class.getName());
|
sampler.setProperty(TestElement.TEST_CLASS, JDBCSampler.class.getName());
|
||||||
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
||||||
|
sampler.setProperty("MS-ID", this.getId());
|
||||||
|
|
||||||
// request.getDataSource() 是ID,需要转换为Name
|
// request.getDataSource() 是ID,需要转换为Name
|
||||||
sampler.setProperty("dataSource", this.dataSource.getName());
|
sampler.setProperty("dataSource", this.dataSource.getName());
|
||||||
sampler.setProperty("query", this.getQuery());
|
sampler.setProperty("query", this.getQuery());
|
||||||
|
|
|
@ -117,6 +117,7 @@ public class MsTCPSampler extends MsTestElement {
|
||||||
if (StringUtils.isNotEmpty(name) && !config.isOperating()) {
|
if (StringUtils.isNotEmpty(name) && !config.isOperating()) {
|
||||||
tcpSampler.setName(this.getName() + "<->" + name);
|
tcpSampler.setName(this.getName() + "<->" + name);
|
||||||
}
|
}
|
||||||
|
tcpSampler.setProperty("MS-ID", this.getId());
|
||||||
|
|
||||||
tcpSampler.setProperty(TestElement.TEST_CLASS, TCPSampler.class.getName());
|
tcpSampler.setProperty(TestElement.TEST_CLASS, TCPSampler.class.getName());
|
||||||
tcpSampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TCPSamplerGui"));
|
tcpSampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TCPSamplerGui"));
|
||||||
|
|
|
@ -239,7 +239,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
LogUtil.error(e.getMessage(), e);
|
LogUtil.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendTask(report, reportUrl, testResult);
|
sendTask(report, reportUrl, testResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void sendTask(ApiTestReport report, String reportUrl, TestResult testResult) {
|
private static void sendTask(ApiTestReport report, String reportUrl, TestResult testResult) {
|
||||||
|
@ -303,6 +303,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
|
|
||||||
private RequestResult getRequestResult(SampleResult result) {
|
private RequestResult getRequestResult(SampleResult result) {
|
||||||
RequestResult requestResult = new RequestResult();
|
RequestResult requestResult = new RequestResult();
|
||||||
|
requestResult.setId(result.getSamplerId());
|
||||||
requestResult.setName(result.getSampleLabel());
|
requestResult.setName(result.getSampleLabel());
|
||||||
requestResult.setUrl(result.getUrlAsString());
|
requestResult.setUrl(result.getUrlAsString());
|
||||||
requestResult.setMethod(getMethod(result));
|
requestResult.setMethod(getMethod(result));
|
||||||
|
|
|
@ -7,6 +7,8 @@ import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class RequestResult {
|
public class RequestResult {
|
||||||
|
// 请求ID
|
||||||
|
private String id;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
|
|
@ -611,27 +611,38 @@ public class ApiAutomationService {
|
||||||
if (CollectionUtils.isEmpty(request.getPlanIds())) {
|
if (CollectionUtils.isEmpty(request.getPlanIds())) {
|
||||||
MSException.throwException(Translator.get("plan id is null "));
|
MSException.throwException(Translator.get("plan id is null "));
|
||||||
}
|
}
|
||||||
List<String> scenarioIds = request.getScenarioIds();
|
// List<String> scenarioIds = request.getScenarioIds();
|
||||||
if (request.isSelectAllDate()) {
|
// if (request.isSelectAllDate()) {
|
||||||
scenarioIds = this.getAllScenarioIdsByFontedSelect(
|
// scenarioIds = this.getAllScenarioIdsByFontedSelect(
|
||||||
request.getModuleIds(), request.getName(), request.getProjectId(), request.getFilters(), request.getUnSelectIds());
|
// request.getModuleIds(), request.getName(), request.getProjectId(), request.getFilters(), request.getUnSelectIds());
|
||||||
}
|
// }
|
||||||
|
Map<String, List<String>> mapping = request.getMapping();
|
||||||
|
Map<String, String> envMap = request.getEnvMap();
|
||||||
|
Set<String> set = mapping.keySet();
|
||||||
List<TestPlanDTO> list = extTestPlanMapper.selectByIds(request.getPlanIds());
|
List<TestPlanDTO> list = extTestPlanMapper.selectByIds(request.getPlanIds());
|
||||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||||
ExtTestPlanScenarioCaseMapper scenarioBatchMapper = sqlSession.getMapper(ExtTestPlanScenarioCaseMapper.class);
|
ExtTestPlanScenarioCaseMapper scenarioBatchMapper = sqlSession.getMapper(ExtTestPlanScenarioCaseMapper.class);
|
||||||
ExtTestPlanApiCaseMapper apiCaseBatchMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class);
|
ExtTestPlanApiCaseMapper apiCaseBatchMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class);
|
||||||
|
|
||||||
for (TestPlanDTO testPlan : list) {
|
for (TestPlanDTO testPlan : list) {
|
||||||
if (scenarioIds != null) {
|
if (!set.isEmpty()) {
|
||||||
for (String scenarioId : scenarioIds) {
|
set.forEach(id -> {
|
||||||
|
Map<String, String> newEnvMap = new HashMap<>(16);
|
||||||
|
if (envMap != null && !envMap.isEmpty()) {
|
||||||
|
List<String> lt = mapping.get(id);
|
||||||
|
lt.forEach(l -> {
|
||||||
|
newEnvMap.put(l, envMap.get(l));
|
||||||
|
});
|
||||||
|
}
|
||||||
TestPlanApiScenario testPlanApiScenario = new TestPlanApiScenario();
|
TestPlanApiScenario testPlanApiScenario = new TestPlanApiScenario();
|
||||||
testPlanApiScenario.setId(UUID.randomUUID().toString());
|
testPlanApiScenario.setId(UUID.randomUUID().toString());
|
||||||
testPlanApiScenario.setApiScenarioId(scenarioId);
|
testPlanApiScenario.setApiScenarioId(id);
|
||||||
testPlanApiScenario.setTestPlanId(testPlan.getId());
|
testPlanApiScenario.setTestPlanId(testPlan.getId());
|
||||||
testPlanApiScenario.setCreateTime(System.currentTimeMillis());
|
testPlanApiScenario.setCreateTime(System.currentTimeMillis());
|
||||||
testPlanApiScenario.setUpdateTime(System.currentTimeMillis());
|
testPlanApiScenario.setUpdateTime(System.currentTimeMillis());
|
||||||
|
testPlanApiScenario.setEnvironment(JSON.toJSONString(newEnvMap));
|
||||||
scenarioBatchMapper.insertIfNotExists(testPlanApiScenario);
|
scenarioBatchMapper.insertIfNotExists(testPlanApiScenario);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
if (request.getApiIds() != null) {
|
if (request.getApiIds() != null) {
|
||||||
for (String caseId : request.getApiIds()) {
|
for (String caseId : request.getApiIds()) {
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
package io.metersphere.base.domain;
|
package io.metersphere.base.domain;
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class ApiDefinition implements Serializable {
|
public class ApiDefinition implements Serializable {
|
||||||
|
@ -38,5 +37,7 @@ public class ApiDefinition implements Serializable {
|
||||||
|
|
||||||
private String tags;
|
private String tags;
|
||||||
|
|
||||||
|
private String originalState;
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
}
|
}
|
|
@ -1193,6 +1193,76 @@ public class ApiDefinitionExample {
|
||||||
addCriterion("tags not between", value1, value2, "tags");
|
addCriterion("tags not between", value1, value2, "tags");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateIsNull() {
|
||||||
|
addCriterion("original_state is null");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateIsNotNull() {
|
||||||
|
addCriterion("original_state is not null");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateEqualTo(String value) {
|
||||||
|
addCriterion("original_state =", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateNotEqualTo(String value) {
|
||||||
|
addCriterion("original_state <>", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateGreaterThan(String value) {
|
||||||
|
addCriterion("original_state >", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateGreaterThanOrEqualTo(String value) {
|
||||||
|
addCriterion("original_state >=", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateLessThan(String value) {
|
||||||
|
addCriterion("original_state <", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateLessThanOrEqualTo(String value) {
|
||||||
|
addCriterion("original_state <=", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateLike(String value) {
|
||||||
|
addCriterion("original_state like", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateNotLike(String value) {
|
||||||
|
addCriterion("original_state not like", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateIn(List<String> values) {
|
||||||
|
addCriterion("original_state in", values, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateNotIn(List<String> values) {
|
||||||
|
addCriterion("original_state not in", values, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateBetween(String value1, String value2) {
|
||||||
|
addCriterion("original_state between", value1, value2, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateNotBetween(String value1, String value2) {
|
||||||
|
addCriterion("original_state not between", value1, value2, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Criteria extends GeneratedCriteria {
|
public static class Criteria extends GeneratedCriteria {
|
||||||
|
|
|
@ -43,5 +43,7 @@ public class ApiScenario implements Serializable {
|
||||||
|
|
||||||
private Integer num;
|
private Integer num;
|
||||||
|
|
||||||
|
private String originalState;
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
}
|
}
|
|
@ -1393,6 +1393,76 @@ public class ApiScenarioExample {
|
||||||
addCriterion("num not between", value1, value2, "num");
|
addCriterion("num not between", value1, value2, "num");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateIsNull() {
|
||||||
|
addCriterion("original_state is null");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateIsNotNull() {
|
||||||
|
addCriterion("original_state is not null");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateEqualTo(String value) {
|
||||||
|
addCriterion("original_state =", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateNotEqualTo(String value) {
|
||||||
|
addCriterion("original_state <>", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateGreaterThan(String value) {
|
||||||
|
addCriterion("original_state >", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateGreaterThanOrEqualTo(String value) {
|
||||||
|
addCriterion("original_state >=", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateLessThan(String value) {
|
||||||
|
addCriterion("original_state <", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateLessThanOrEqualTo(String value) {
|
||||||
|
addCriterion("original_state <=", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateLike(String value) {
|
||||||
|
addCriterion("original_state like", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateNotLike(String value) {
|
||||||
|
addCriterion("original_state not like", value, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateIn(List<String> values) {
|
||||||
|
addCriterion("original_state in", values, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateNotIn(List<String> values) {
|
||||||
|
addCriterion("original_state not in", values, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateBetween(String value1, String value2) {
|
||||||
|
addCriterion("original_state between", value1, value2, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andOriginalStateNotBetween(String value1, String value2) {
|
||||||
|
addCriterion("original_state not between", value1, value2, "originalState");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Criteria extends GeneratedCriteria {
|
public static class Criteria extends GeneratedCriteria {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
<result column="path" jdbcType="VARCHAR" property="path" />
|
<result column="path" jdbcType="VARCHAR" property="path" />
|
||||||
<result column="num" jdbcType="INTEGER" property="num" />
|
<result column="num" jdbcType="INTEGER" property="num" />
|
||||||
<result column="tags" jdbcType="VARCHAR" property="tags" />
|
<result column="tags" jdbcType="VARCHAR" property="tags" />
|
||||||
|
<result column="original_state" jdbcType="VARCHAR" property="originalState" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiDefinitionWithBLOBs">
|
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiDefinitionWithBLOBs">
|
||||||
<result column="description" jdbcType="LONGVARCHAR" property="description" />
|
<result column="description" jdbcType="LONGVARCHAR" property="description" />
|
||||||
|
@ -84,7 +85,7 @@
|
||||||
</sql>
|
</sql>
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
id, project_id, `name`, `method`, module_path, environment_id, schedule, `status`,
|
id, project_id, `name`, `method`, module_path, environment_id, schedule, `status`,
|
||||||
module_id, user_id, create_time, update_time, protocol, `path`, num, tags
|
module_id, user_id, create_time, update_time, protocol, `path`, num, tags, original_state
|
||||||
</sql>
|
</sql>
|
||||||
<sql id="Blob_Column_List">
|
<sql id="Blob_Column_List">
|
||||||
description, request, response
|
description, request, response
|
||||||
|
@ -143,15 +144,15 @@
|
||||||
schedule, `status`, module_id,
|
schedule, `status`, module_id,
|
||||||
user_id, create_time, update_time,
|
user_id, create_time, update_time,
|
||||||
protocol, `path`, num,
|
protocol, `path`, num,
|
||||||
tags, description, request,
|
tags, original_state, description,
|
||||||
response)
|
request, response)
|
||||||
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
|
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
|
||||||
#{method,jdbcType=VARCHAR}, #{modulePath,jdbcType=VARCHAR}, #{environmentId,jdbcType=VARCHAR},
|
#{method,jdbcType=VARCHAR}, #{modulePath,jdbcType=VARCHAR}, #{environmentId,jdbcType=VARCHAR},
|
||||||
#{schedule,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{moduleId,jdbcType=VARCHAR},
|
#{schedule,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{moduleId,jdbcType=VARCHAR},
|
||||||
#{userId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
#{userId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
||||||
#{protocol,jdbcType=VARCHAR}, #{path,jdbcType=VARCHAR}, #{num,jdbcType=INTEGER},
|
#{protocol,jdbcType=VARCHAR}, #{path,jdbcType=VARCHAR}, #{num,jdbcType=INTEGER},
|
||||||
#{tags,jdbcType=VARCHAR}, #{description,jdbcType=LONGVARCHAR}, #{request,jdbcType=LONGVARCHAR},
|
#{tags,jdbcType=VARCHAR}, #{originalState,jdbcType=VARCHAR}, #{description,jdbcType=LONGVARCHAR},
|
||||||
#{response,jdbcType=LONGVARCHAR})
|
#{request,jdbcType=LONGVARCHAR}, #{response,jdbcType=LONGVARCHAR})
|
||||||
</insert>
|
</insert>
|
||||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiDefinitionWithBLOBs">
|
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiDefinitionWithBLOBs">
|
||||||
insert into api_definition
|
insert into api_definition
|
||||||
|
@ -204,6 +205,9 @@
|
||||||
<if test="tags != null">
|
<if test="tags != null">
|
||||||
tags,
|
tags,
|
||||||
</if>
|
</if>
|
||||||
|
<if test="originalState != null">
|
||||||
|
original_state,
|
||||||
|
</if>
|
||||||
<if test="description != null">
|
<if test="description != null">
|
||||||
description,
|
description,
|
||||||
</if>
|
</if>
|
||||||
|
@ -263,6 +267,9 @@
|
||||||
<if test="tags != null">
|
<if test="tags != null">
|
||||||
#{tags,jdbcType=VARCHAR},
|
#{tags,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="originalState != null">
|
||||||
|
#{originalState,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
<if test="description != null">
|
<if test="description != null">
|
||||||
#{description,jdbcType=LONGVARCHAR},
|
#{description,jdbcType=LONGVARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
@ -331,6 +338,9 @@
|
||||||
<if test="record.tags != null">
|
<if test="record.tags != null">
|
||||||
tags = #{record.tags,jdbcType=VARCHAR},
|
tags = #{record.tags,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="record.originalState != null">
|
||||||
|
original_state = #{record.originalState,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
<if test="record.description != null">
|
<if test="record.description != null">
|
||||||
description = #{record.description,jdbcType=LONGVARCHAR},
|
description = #{record.description,jdbcType=LONGVARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
@ -363,6 +373,7 @@
|
||||||
`path` = #{record.path,jdbcType=VARCHAR},
|
`path` = #{record.path,jdbcType=VARCHAR},
|
||||||
num = #{record.num,jdbcType=INTEGER},
|
num = #{record.num,jdbcType=INTEGER},
|
||||||
tags = #{record.tags,jdbcType=VARCHAR},
|
tags = #{record.tags,jdbcType=VARCHAR},
|
||||||
|
original_state = #{record.originalState,jdbcType=VARCHAR},
|
||||||
description = #{record.description,jdbcType=LONGVARCHAR},
|
description = #{record.description,jdbcType=LONGVARCHAR},
|
||||||
request = #{record.request,jdbcType=LONGVARCHAR},
|
request = #{record.request,jdbcType=LONGVARCHAR},
|
||||||
response = #{record.response,jdbcType=LONGVARCHAR}
|
response = #{record.response,jdbcType=LONGVARCHAR}
|
||||||
|
@ -387,7 +398,8 @@
|
||||||
protocol = #{record.protocol,jdbcType=VARCHAR},
|
protocol = #{record.protocol,jdbcType=VARCHAR},
|
||||||
`path` = #{record.path,jdbcType=VARCHAR},
|
`path` = #{record.path,jdbcType=VARCHAR},
|
||||||
num = #{record.num,jdbcType=INTEGER},
|
num = #{record.num,jdbcType=INTEGER},
|
||||||
tags = #{record.tags,jdbcType=VARCHAR}
|
tags = #{record.tags,jdbcType=VARCHAR},
|
||||||
|
original_state = #{record.originalState,jdbcType=VARCHAR}
|
||||||
<if test="_parameter != null">
|
<if test="_parameter != null">
|
||||||
<include refid="Update_By_Example_Where_Clause" />
|
<include refid="Update_By_Example_Where_Clause" />
|
||||||
</if>
|
</if>
|
||||||
|
@ -440,6 +452,9 @@
|
||||||
<if test="tags != null">
|
<if test="tags != null">
|
||||||
tags = #{tags,jdbcType=VARCHAR},
|
tags = #{tags,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="originalState != null">
|
||||||
|
original_state = #{originalState,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
<if test="description != null">
|
<if test="description != null">
|
||||||
description = #{description,jdbcType=LONGVARCHAR},
|
description = #{description,jdbcType=LONGVARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
@ -469,6 +484,7 @@
|
||||||
`path` = #{path,jdbcType=VARCHAR},
|
`path` = #{path,jdbcType=VARCHAR},
|
||||||
num = #{num,jdbcType=INTEGER},
|
num = #{num,jdbcType=INTEGER},
|
||||||
tags = #{tags,jdbcType=VARCHAR},
|
tags = #{tags,jdbcType=VARCHAR},
|
||||||
|
original_state = #{originalState,jdbcType=VARCHAR},
|
||||||
description = #{description,jdbcType=LONGVARCHAR},
|
description = #{description,jdbcType=LONGVARCHAR},
|
||||||
request = #{request,jdbcType=LONGVARCHAR},
|
request = #{request,jdbcType=LONGVARCHAR},
|
||||||
response = #{response,jdbcType=LONGVARCHAR}
|
response = #{response,jdbcType=LONGVARCHAR}
|
||||||
|
@ -490,7 +506,8 @@
|
||||||
protocol = #{protocol,jdbcType=VARCHAR},
|
protocol = #{protocol,jdbcType=VARCHAR},
|
||||||
`path` = #{path,jdbcType=VARCHAR},
|
`path` = #{path,jdbcType=VARCHAR},
|
||||||
num = #{num,jdbcType=INTEGER},
|
num = #{num,jdbcType=INTEGER},
|
||||||
tags = #{tags,jdbcType=VARCHAR}
|
tags = #{tags,jdbcType=VARCHAR},
|
||||||
|
original_state = #{originalState,jdbcType=VARCHAR}
|
||||||
where id = #{id,jdbcType=VARCHAR}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
</mapper>
|
</mapper>
|
|
@ -21,6 +21,7 @@
|
||||||
<result column="last_result" jdbcType="VARCHAR" property="lastResult" />
|
<result column="last_result" jdbcType="VARCHAR" property="lastResult" />
|
||||||
<result column="report_id" jdbcType="VARCHAR" property="reportId" />
|
<result column="report_id" jdbcType="VARCHAR" property="reportId" />
|
||||||
<result column="num" jdbcType="INTEGER" property="num" />
|
<result column="num" jdbcType="INTEGER" property="num" />
|
||||||
|
<result column="original_state" jdbcType="VARCHAR" property="originalState" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiScenarioWithBLOBs">
|
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiScenarioWithBLOBs">
|
||||||
<result column="scenario_definition" jdbcType="LONGVARCHAR" property="scenarioDefinition" />
|
<result column="scenario_definition" jdbcType="LONGVARCHAR" property="scenarioDefinition" />
|
||||||
|
@ -87,7 +88,7 @@
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
id, project_id, tags, user_id, api_scenario_module_id, module_path, `name`, `level`,
|
id, project_id, tags, user_id, api_scenario_module_id, module_path, `name`, `level`,
|
||||||
`status`, principal, step_total, follow_people, schedule, create_time, update_time,
|
`status`, principal, step_total, follow_people, schedule, create_time, update_time,
|
||||||
pass_rate, last_result, report_id, num
|
pass_rate, last_result, report_id, num, original_state
|
||||||
</sql>
|
</sql>
|
||||||
<sql id="Blob_Column_List">
|
<sql id="Blob_Column_List">
|
||||||
scenario_definition, description
|
scenario_definition, description
|
||||||
|
@ -147,16 +148,16 @@
|
||||||
principal, step_total, follow_people,
|
principal, step_total, follow_people,
|
||||||
schedule, create_time, update_time,
|
schedule, create_time, update_time,
|
||||||
pass_rate, last_result, report_id,
|
pass_rate, last_result, report_id,
|
||||||
num, scenario_definition, description
|
num, original_state, scenario_definition,
|
||||||
)
|
description)
|
||||||
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{tags,jdbcType=VARCHAR},
|
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{tags,jdbcType=VARCHAR},
|
||||||
#{userId,jdbcType=VARCHAR}, #{apiScenarioModuleId,jdbcType=VARCHAR}, #{modulePath,jdbcType=VARCHAR},
|
#{userId,jdbcType=VARCHAR}, #{apiScenarioModuleId,jdbcType=VARCHAR}, #{modulePath,jdbcType=VARCHAR},
|
||||||
#{name,jdbcType=VARCHAR}, #{level,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
|
#{name,jdbcType=VARCHAR}, #{level,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
|
||||||
#{principal,jdbcType=VARCHAR}, #{stepTotal,jdbcType=INTEGER}, #{followPeople,jdbcType=VARCHAR},
|
#{principal,jdbcType=VARCHAR}, #{stepTotal,jdbcType=INTEGER}, #{followPeople,jdbcType=VARCHAR},
|
||||||
#{schedule,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
#{schedule,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
||||||
#{passRate,jdbcType=VARCHAR}, #{lastResult,jdbcType=VARCHAR}, #{reportId,jdbcType=VARCHAR},
|
#{passRate,jdbcType=VARCHAR}, #{lastResult,jdbcType=VARCHAR}, #{reportId,jdbcType=VARCHAR},
|
||||||
#{num,jdbcType=INTEGER}, #{scenarioDefinition,jdbcType=LONGVARCHAR}, #{description,jdbcType=LONGVARCHAR}
|
#{num,jdbcType=INTEGER}, #{originalState,jdbcType=VARCHAR}, #{scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||||
)
|
#{description,jdbcType=LONGVARCHAR})
|
||||||
</insert>
|
</insert>
|
||||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiScenarioWithBLOBs">
|
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiScenarioWithBLOBs">
|
||||||
insert into api_scenario
|
insert into api_scenario
|
||||||
|
@ -218,6 +219,9 @@
|
||||||
<if test="num != null">
|
<if test="num != null">
|
||||||
num,
|
num,
|
||||||
</if>
|
</if>
|
||||||
|
<if test="originalState != null">
|
||||||
|
original_state,
|
||||||
|
</if>
|
||||||
<if test="scenarioDefinition != null">
|
<if test="scenarioDefinition != null">
|
||||||
scenario_definition,
|
scenario_definition,
|
||||||
</if>
|
</if>
|
||||||
|
@ -283,6 +287,9 @@
|
||||||
<if test="num != null">
|
<if test="num != null">
|
||||||
#{num,jdbcType=INTEGER},
|
#{num,jdbcType=INTEGER},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="originalState != null">
|
||||||
|
#{originalState,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
<if test="scenarioDefinition != null">
|
<if test="scenarioDefinition != null">
|
||||||
#{scenarioDefinition,jdbcType=LONGVARCHAR},
|
#{scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
@ -357,6 +364,9 @@
|
||||||
<if test="record.num != null">
|
<if test="record.num != null">
|
||||||
num = #{record.num,jdbcType=INTEGER},
|
num = #{record.num,jdbcType=INTEGER},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="record.originalState != null">
|
||||||
|
original_state = #{record.originalState,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
<if test="record.scenarioDefinition != null">
|
<if test="record.scenarioDefinition != null">
|
||||||
scenario_definition = #{record.scenarioDefinition,jdbcType=LONGVARCHAR},
|
scenario_definition = #{record.scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
@ -389,6 +399,7 @@
|
||||||
last_result = #{record.lastResult,jdbcType=VARCHAR},
|
last_result = #{record.lastResult,jdbcType=VARCHAR},
|
||||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||||
num = #{record.num,jdbcType=INTEGER},
|
num = #{record.num,jdbcType=INTEGER},
|
||||||
|
original_state = #{record.originalState,jdbcType=VARCHAR},
|
||||||
scenario_definition = #{record.scenarioDefinition,jdbcType=LONGVARCHAR},
|
scenario_definition = #{record.scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||||
description = #{record.description,jdbcType=LONGVARCHAR}
|
description = #{record.description,jdbcType=LONGVARCHAR}
|
||||||
<if test="_parameter != null">
|
<if test="_parameter != null">
|
||||||
|
@ -415,7 +426,8 @@
|
||||||
pass_rate = #{record.passRate,jdbcType=VARCHAR},
|
pass_rate = #{record.passRate,jdbcType=VARCHAR},
|
||||||
last_result = #{record.lastResult,jdbcType=VARCHAR},
|
last_result = #{record.lastResult,jdbcType=VARCHAR},
|
||||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||||
num = #{record.num,jdbcType=INTEGER}
|
num = #{record.num,jdbcType=INTEGER},
|
||||||
|
original_state = #{record.originalState,jdbcType=VARCHAR}
|
||||||
<if test="_parameter != null">
|
<if test="_parameter != null">
|
||||||
<include refid="Update_By_Example_Where_Clause" />
|
<include refid="Update_By_Example_Where_Clause" />
|
||||||
</if>
|
</if>
|
||||||
|
@ -477,6 +489,9 @@
|
||||||
<if test="num != null">
|
<if test="num != null">
|
||||||
num = #{num,jdbcType=INTEGER},
|
num = #{num,jdbcType=INTEGER},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="originalState != null">
|
||||||
|
original_state = #{originalState,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
<if test="scenarioDefinition != null">
|
<if test="scenarioDefinition != null">
|
||||||
scenario_definition = #{scenarioDefinition,jdbcType=LONGVARCHAR},
|
scenario_definition = #{scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||||
</if>
|
</if>
|
||||||
|
@ -506,6 +521,7 @@
|
||||||
last_result = #{lastResult,jdbcType=VARCHAR},
|
last_result = #{lastResult,jdbcType=VARCHAR},
|
||||||
report_id = #{reportId,jdbcType=VARCHAR},
|
report_id = #{reportId,jdbcType=VARCHAR},
|
||||||
num = #{num,jdbcType=INTEGER},
|
num = #{num,jdbcType=INTEGER},
|
||||||
|
original_state = #{originalState,jdbcType=VARCHAR},
|
||||||
scenario_definition = #{scenarioDefinition,jdbcType=LONGVARCHAR},
|
scenario_definition = #{scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||||
description = #{description,jdbcType=LONGVARCHAR}
|
description = #{description,jdbcType=LONGVARCHAR}
|
||||||
where id = #{id,jdbcType=VARCHAR}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
|
@ -529,7 +545,8 @@
|
||||||
pass_rate = #{passRate,jdbcType=VARCHAR},
|
pass_rate = #{passRate,jdbcType=VARCHAR},
|
||||||
last_result = #{lastResult,jdbcType=VARCHAR},
|
last_result = #{lastResult,jdbcType=VARCHAR},
|
||||||
report_id = #{reportId,jdbcType=VARCHAR},
|
report_id = #{reportId,jdbcType=VARCHAR},
|
||||||
num = #{num,jdbcType=INTEGER}
|
num = #{num,jdbcType=INTEGER},
|
||||||
|
original_state = #{originalState,jdbcType=VARCHAR}
|
||||||
where id = #{id,jdbcType=VARCHAR}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
</mapper>
|
</mapper>
|
|
@ -235,7 +235,7 @@
|
||||||
|
|
||||||
<update id="removeToGc">
|
<update id="removeToGc">
|
||||||
update api_definition
|
update api_definition
|
||||||
set
|
set original_state=status,
|
||||||
status = 'Trash'
|
status = 'Trash'
|
||||||
where id in
|
where id in
|
||||||
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
||||||
|
@ -245,7 +245,7 @@
|
||||||
|
|
||||||
<update id="removeToGcByExample" parameterType="io.metersphere.base.domain.ApiDefinitionExample">
|
<update id="removeToGcByExample" parameterType="io.metersphere.base.domain.ApiDefinitionExample">
|
||||||
update api_definition
|
update api_definition
|
||||||
set
|
set original_state=status,
|
||||||
status = 'Trash', module_path = null, module_id = null
|
status = 'Trash', module_path = null, module_id = null
|
||||||
<if test="_parameter != null">
|
<if test="_parameter != null">
|
||||||
<include refid="Example_Where_Clause" />
|
<include refid="Example_Where_Clause" />
|
||||||
|
@ -255,7 +255,7 @@
|
||||||
<update id="reduction">
|
<update id="reduction">
|
||||||
update api_definition
|
update api_definition
|
||||||
set
|
set
|
||||||
status = 'Underway'
|
status = original_state
|
||||||
where id in
|
where id in
|
||||||
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
||||||
#{v}
|
#{v}
|
||||||
|
|
|
@ -275,7 +275,7 @@
|
||||||
|
|
||||||
<update id="removeToGc">
|
<update id="removeToGc">
|
||||||
update api_scenario
|
update api_scenario
|
||||||
set
|
set original_state=status,
|
||||||
status = 'Trash'
|
status = 'Trash'
|
||||||
where id in
|
where id in
|
||||||
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
||||||
|
@ -285,7 +285,7 @@
|
||||||
|
|
||||||
<update id="removeToGcByExample" parameterType="io.metersphere.base.domain.ApiScenarioExample">
|
<update id="removeToGcByExample" parameterType="io.metersphere.base.domain.ApiScenarioExample">
|
||||||
update api_scenario
|
update api_scenario
|
||||||
set
|
set original_state=status,
|
||||||
status = 'Trash', module_path = null, api_scenario_module_id = null
|
status = 'Trash', module_path = null, api_scenario_module_id = null
|
||||||
<if test="_parameter != null">
|
<if test="_parameter != null">
|
||||||
<include refid="Example_Where_Clause" />
|
<include refid="Example_Where_Clause" />
|
||||||
|
@ -295,7 +295,7 @@
|
||||||
<update id="reduction">
|
<update id="reduction">
|
||||||
update api_scenario
|
update api_scenario
|
||||||
set
|
set
|
||||||
status = 'Underway'
|
status = original_state
|
||||||
where id in
|
where id in
|
||||||
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
||||||
#{v}
|
#{v}
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
<insert id="insertIfNotExists" parameterType="io.metersphere.base.domain.TestPlanApiScenario">
|
<insert id="insertIfNotExists" parameterType="io.metersphere.base.domain.TestPlanApiScenario">
|
||||||
-- 查询没有数据再插入
|
-- 查询没有数据再插入
|
||||||
INSERT INTO test_plan_api_scenario(id, test_plan_id, api_scenario_id, create_time, update_time)
|
INSERT INTO test_plan_api_scenario(id, test_plan_id, api_scenario_id, create_time, update_time, environment)
|
||||||
SELECT #{request.id}, #{request.testPlanId}, #{request.apiScenarioId}, #{request.createTime}, #{request.updateTime}
|
SELECT #{request.id}, #{request.testPlanId}, #{request.apiScenarioId}, #{request.createTime}, #{request.updateTime}, #{request.environment}
|
||||||
FROM DUAL
|
FROM DUAL
|
||||||
WHERE NOT EXISTS(
|
WHERE NOT EXISTS(
|
||||||
SELECT id FROM
|
SELECT id FROM
|
||||||
|
|
|
@ -1,18 +1,35 @@
|
||||||
package io.metersphere.commons.user;
|
package io.metersphere.commons.user;
|
||||||
|
|
||||||
|
import io.metersphere.commons.utils.CodingUtil;
|
||||||
import io.metersphere.dto.UserDTO;
|
import io.metersphere.dto.UserDTO;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
public class SessionUser extends UserDTO implements Serializable {
|
public class SessionUser extends UserDTO implements Serializable {
|
||||||
|
public static final String secret = "9a9rdqPlTqhpZzkq";
|
||||||
|
public static final String iv = "1Av7hf9PgHusUHRm";
|
||||||
|
|
||||||
private static final long serialVersionUID = -7149638440406959033L;
|
private static final long serialVersionUID = -7149638440406959033L;
|
||||||
|
private String csrfToken;
|
||||||
|
|
||||||
|
private SessionUser() {
|
||||||
|
}
|
||||||
|
|
||||||
public static SessionUser fromUser(UserDTO user) {
|
public static SessionUser fromUser(UserDTO user) {
|
||||||
SessionUser sessionUser = new SessionUser();
|
SessionUser sessionUser = new SessionUser();
|
||||||
BeanUtils.copyProperties(user, sessionUser);
|
BeanUtils.copyProperties(user, sessionUser);
|
||||||
|
|
||||||
|
List<String> infos = Arrays.asList(user.getId(), RandomStringUtils.random(6), "" + System.currentTimeMillis());
|
||||||
|
sessionUser.csrfToken = CodingUtil.aesEncrypt(StringUtils.join(infos, "|"), secret, iv);
|
||||||
return sessionUser;
|
return sessionUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,14 +62,14 @@ public class SessionUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getCurrentWorkspaceId() {
|
public static String getCurrentWorkspaceId() {
|
||||||
return Optional.ofNullable(getUser()).orElse(new SessionUser()).getLastWorkspaceId();
|
return getUser().getLastWorkspaceId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getCurrentOrganizationId() {
|
public static String getCurrentOrganizationId() {
|
||||||
return Optional.ofNullable(getUser()).orElse(new SessionUser()).getLastOrganizationId();
|
return getUser().getLastOrganizationId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getCurrentProjectId() {
|
public static String getCurrentProjectId() {
|
||||||
return Optional.ofNullable(getUser()).orElse(new SessionUser()).getLastProjectId();
|
return getUser().getLastProjectId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,10 @@ public class ShiroUtils {
|
||||||
// filterChainDefinitionMap.put("/document/**", "anon");
|
// filterChainDefinitionMap.put("/document/**", "anon");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ignoreCsrfFilter(Map<String, String> filterChainDefinitionMap) {
|
||||||
|
filterChainDefinitionMap.put("/", "apikey, authc"); // 跳转到 / 不用校验 csrf
|
||||||
|
}
|
||||||
|
|
||||||
public static Cookie getSessionIdCookie(){
|
public static Cookie getSessionIdCookie(){
|
||||||
SimpleCookie sessionIdCookie = new SimpleCookie();
|
SimpleCookie sessionIdCookie = new SimpleCookie();
|
||||||
sessionIdCookie.setPath("/");
|
sessionIdCookie.setPath("/");
|
||||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.config;
|
||||||
|
|
||||||
import io.metersphere.commons.utils.ShiroUtils;
|
import io.metersphere.commons.utils.ShiroUtils;
|
||||||
import io.metersphere.security.ApiKeyFilter;
|
import io.metersphere.security.ApiKeyFilter;
|
||||||
|
import io.metersphere.security.CsrfFilter;
|
||||||
import io.metersphere.security.UserModularRealmAuthenticator;
|
import io.metersphere.security.UserModularRealmAuthenticator;
|
||||||
import io.metersphere.security.realm.LdapRealm;
|
import io.metersphere.security.realm.LdapRealm;
|
||||||
import io.metersphere.security.realm.ShiroDBRealm;
|
import io.metersphere.security.realm.ShiroDBRealm;
|
||||||
|
@ -44,10 +45,14 @@ public class ShiroConfig implements EnvironmentAware {
|
||||||
shiroFilterFactoryBean.setSuccessUrl("/");
|
shiroFilterFactoryBean.setSuccessUrl("/");
|
||||||
|
|
||||||
shiroFilterFactoryBean.getFilters().put("apikey", new ApiKeyFilter());
|
shiroFilterFactoryBean.getFilters().put("apikey", new ApiKeyFilter());
|
||||||
|
shiroFilterFactoryBean.getFilters().put("csrf", new CsrfFilter());
|
||||||
Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap();
|
Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap();
|
||||||
|
|
||||||
ShiroUtils.loadBaseFilterChain(filterChainDefinitionMap);
|
ShiroUtils.loadBaseFilterChain(filterChainDefinitionMap);
|
||||||
|
|
||||||
filterChainDefinitionMap.put("/**", "apikey, authc");
|
ShiroUtils.ignoreCsrfFilter(filterChainDefinitionMap);
|
||||||
|
|
||||||
|
filterChainDefinitionMap.put("/**", "apikey, csrf, authc");
|
||||||
return shiroFilterFactoryBean;
|
return shiroFilterFactoryBean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package io.metersphere.controller;
|
package io.metersphere.controller;
|
||||||
|
|
||||||
import io.metersphere.commons.constants.SsoMode;
|
|
||||||
import io.metersphere.commons.constants.UserSource;
|
import io.metersphere.commons.constants.UserSource;
|
||||||
import io.metersphere.commons.user.SessionUser;
|
import io.metersphere.commons.user.SessionUser;
|
||||||
import io.metersphere.commons.utils.SessionUtils;
|
import io.metersphere.commons.utils.SessionUtils;
|
||||||
|
@ -10,7 +9,6 @@ import io.metersphere.service.UserService;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
import org.springframework.core.env.Environment;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
@ -24,8 +22,6 @@ public class LoginController {
|
||||||
@Resource
|
@Resource
|
||||||
private UserService userService;
|
private UserService userService;
|
||||||
@Resource
|
@Resource
|
||||||
private Environment env;
|
|
||||||
@Resource
|
|
||||||
private BaseDisplayService baseDisplayService;
|
private BaseDisplayService baseDisplayService;
|
||||||
|
|
||||||
@GetMapping(value = "/isLogin")
|
@GetMapping(value = "/isLogin")
|
||||||
|
@ -37,10 +33,6 @@ public class LoginController {
|
||||||
}
|
}
|
||||||
return ResultHolder.success(user);
|
return ResultHolder.success(user);
|
||||||
}
|
}
|
||||||
String ssoMode = env.getProperty("sso.mode");
|
|
||||||
if (ssoMode != null && StringUtils.equalsIgnoreCase(SsoMode.CAS.name(), ssoMode)) {
|
|
||||||
return ResultHolder.error("sso");
|
|
||||||
}
|
|
||||||
return ResultHolder.error("");
|
return ResultHolder.error("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
package io.metersphere.controller;
|
package io.metersphere.controller;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.github.pagehelper.Page;
|
import com.github.pagehelper.Page;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import io.metersphere.base.domain.Organization;
|
|
||||||
import io.metersphere.base.domain.User;
|
import io.metersphere.base.domain.User;
|
||||||
import io.metersphere.base.domain.Workspace;
|
|
||||||
import io.metersphere.commons.constants.RoleConstants;
|
import io.metersphere.commons.constants.RoleConstants;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.commons.user.SessionUser;
|
import io.metersphere.commons.user.SessionUser;
|
||||||
|
@ -29,7 +26,6 @@ import io.metersphere.service.WorkspaceService;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
import org.checkerframework.checker.units.qual.C;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,7 @@ public class EngineContext {
|
||||||
private String reportId;
|
private String reportId;
|
||||||
private Integer resourceIndex;
|
private Integer resourceIndex;
|
||||||
private Map<String, Object> properties = new HashMap<>();
|
private Map<String, Object> properties = new HashMap<>();
|
||||||
private Map<String, String> testData = new HashMap<>();
|
private Map<String, byte[]> testResourceFiles = new HashMap<>();
|
||||||
private Map<String, byte[]> testJars = new HashMap<>();
|
|
||||||
|
|
||||||
public String getTestId() {
|
public String getTestId() {
|
||||||
return testId;
|
return testId;
|
||||||
|
@ -69,14 +68,6 @@ public class EngineContext {
|
||||||
this.fileType = fileType;
|
this.fileType = fileType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getTestData() {
|
|
||||||
return testData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTestData(Map<String, String> testData) {
|
|
||||||
this.testData = testData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getResourcePoolId() {
|
public String getResourcePoolId() {
|
||||||
return resourcePoolId;
|
return resourcePoolId;
|
||||||
}
|
}
|
||||||
|
@ -111,11 +102,11 @@ public class EngineContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Map<String, byte[]> getTestJars() {
|
public Map<String, byte[]> getTestResourceFiles() {
|
||||||
return testJars;
|
return testResourceFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTestJars(Map<String, byte[]> testJars) {
|
public void setTestResourceFiles(Map<String, byte[]> testResourceFiles) {
|
||||||
this.testJars = testJars;
|
this.testResourceFiles = testResourceFiles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,8 @@ import io.metersphere.service.FileService;
|
||||||
import io.metersphere.service.KubernetesTestEngine;
|
import io.metersphere.service.KubernetesTestEngine;
|
||||||
import io.metersphere.service.TestResourcePoolService;
|
import io.metersphere.service.TestResourcePoolService;
|
||||||
import org.apache.commons.beanutils.ConstructorUtils;
|
import org.apache.commons.beanutils.ConstructorUtils;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.collections4.ListUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.reflections8.Reflections;
|
import org.reflections8.Reflections;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
@ -92,8 +93,7 @@ public class EngineFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<FileMetadata> jmxFiles = fileMetadataList.stream().filter(f -> StringUtils.equalsIgnoreCase(f.getType(), FileType.JMX.name())).collect(Collectors.toList());
|
List<FileMetadata> jmxFiles = fileMetadataList.stream().filter(f -> StringUtils.equalsIgnoreCase(f.getType(), FileType.JMX.name())).collect(Collectors.toList());
|
||||||
List<FileMetadata> csvFiles = fileMetadataList.stream().filter(f -> StringUtils.equalsIgnoreCase(f.getType(), FileType.CSV.name())).collect(Collectors.toList());
|
List<FileMetadata> resourceFiles = ListUtils.subtract(fileMetadataList, jmxFiles);
|
||||||
List<FileMetadata> jarFiles = fileMetadataList.stream().filter(f -> StringUtils.equalsIgnoreCase(f.getType(), FileType.JAR.name())).collect(Collectors.toList());
|
|
||||||
// 合并上传的jmx
|
// 合并上传的jmx
|
||||||
byte[] jmxBytes = mergeJmx(jmxFiles);
|
byte[] jmxBytes = mergeJmx(jmxFiles);
|
||||||
final EngineContext engineContext = new EngineContext();
|
final EngineContext engineContext = new EngineContext();
|
||||||
|
@ -156,22 +156,13 @@ public class EngineFactory {
|
||||||
MSException.throwException(e);
|
MSException.throwException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CollectionUtils.isNotEmpty(csvFiles)) {
|
if (CollectionUtils.isNotEmpty(resourceFiles)) {
|
||||||
Map<String, String> data = new HashMap<>();
|
|
||||||
csvFiles.forEach(cf -> {
|
|
||||||
FileContent csvContent = fileService.getFileContent(cf.getId());
|
|
||||||
data.put(cf.getName(), new String(csvContent.getFile()));
|
|
||||||
});
|
|
||||||
engineContext.setTestData(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CollectionUtils.isNotEmpty(jarFiles)) {
|
|
||||||
Map<String, byte[]> data = new HashMap<>();
|
Map<String, byte[]> data = new HashMap<>();
|
||||||
jarFiles.forEach(jf -> {
|
resourceFiles.forEach(cf -> {
|
||||||
FileContent content = fileService.getFileContent(jf.getId());
|
FileContent csvContent = fileService.getFileContent(cf.getId());
|
||||||
data.put(jf.getName(), content.getFile());
|
data.put(cf.getName(), csvContent.getFile());
|
||||||
});
|
});
|
||||||
engineContext.setTestJars(data);
|
engineContext.setTestResourceFiles(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return engineContext;
|
return engineContext;
|
||||||
|
|
|
@ -51,17 +51,9 @@ public class JmeterFileService {
|
||||||
|
|
||||||
// 每个测试生成一个文件夹
|
// 每个测试生成一个文件夹
|
||||||
files.put(fileName, context.getContent().getBytes(StandardCharsets.UTF_8));
|
files.put(fileName, context.getContent().getBytes(StandardCharsets.UTF_8));
|
||||||
// 保存测试数据文件
|
|
||||||
Map<String, String> testData = context.getTestData();
|
|
||||||
if (!CollectionUtils.isEmpty(testData)) {
|
|
||||||
for (String k : testData.keySet()) {
|
|
||||||
String v = testData.get(k);
|
|
||||||
files.put(k, v.getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存 byte[] jar
|
// 保存 byte[]
|
||||||
Map<String, byte[]> jarFiles = context.getTestJars();
|
Map<String, byte[]> jarFiles = context.getTestResourceFiles();
|
||||||
if (!CollectionUtils.isEmpty(jarFiles)) {
|
if (!CollectionUtils.isEmpty(jarFiles)) {
|
||||||
for (String k : jarFiles.keySet()) {
|
for (String k : jarFiles.keySet()) {
|
||||||
byte[] v = jarFiles.get(k);
|
byte[] v = jarFiles.get(k);
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
package io.metersphere.security;
|
||||||
|
|
||||||
|
import io.metersphere.commons.user.SessionUser;
|
||||||
|
import io.metersphere.commons.utils.CodingUtil;
|
||||||
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
|
import io.metersphere.commons.utils.SessionUtils;
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
import org.apache.shiro.web.filter.authc.AnonymousFilter;
|
||||||
|
import org.apache.shiro.web.util.WebUtils;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
public class CsrfFilter extends AnonymousFilter {
|
||||||
|
private static final String TOKEN_NAME = "CSRF-TOKEN";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) {
|
||||||
|
HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
|
||||||
|
|
||||||
|
if (!SecurityUtils.getSubject().isAuthenticated()) {
|
||||||
|
((HttpServletResponse) response).setHeader("Authentication-Status", "invalid");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// api 过来的请求
|
||||||
|
if (ApiKeyHandler.isApiKeyCall(WebUtils.toHttp(request))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// websocket 不需要csrf
|
||||||
|
String websocketKey = httpServletRequest.getHeader("Sec-WebSocket-Key");
|
||||||
|
if (StringUtils.isNotBlank(websocketKey)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 请求头取出的token value
|
||||||
|
String csrfToken = httpServletRequest.getHeader(TOKEN_NAME);
|
||||||
|
// 校验 token
|
||||||
|
validateToken(csrfToken);
|
||||||
|
// 校验 referer
|
||||||
|
validateReferer(httpServletRequest);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateReferer(HttpServletRequest request) {
|
||||||
|
Environment env = CommonBeanFactory.getBean(Environment.class);
|
||||||
|
String domains = env.getProperty("referer.urls");
|
||||||
|
if (StringUtils.isBlank(domains)) {
|
||||||
|
// 没有配置不校验
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] split = StringUtils.split(domains, ",");
|
||||||
|
String referer = request.getHeader(HttpHeaders.REFERER);
|
||||||
|
if (split != null) {
|
||||||
|
if (!ArrayUtils.contains(split, referer)) {
|
||||||
|
throw new RuntimeException("csrf error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateToken(String csrfToken) {
|
||||||
|
if (StringUtils.isBlank(csrfToken)) {
|
||||||
|
throw new RuntimeException("csrf token is empty");
|
||||||
|
}
|
||||||
|
csrfToken = CodingUtil.aesDecrypt(csrfToken, SessionUser.secret, SessionUser.iv);
|
||||||
|
|
||||||
|
String[] signatureArray = StringUtils.split(StringUtils.trimToNull(csrfToken), "|");
|
||||||
|
if (signatureArray.length != 3) {
|
||||||
|
throw new RuntimeException("invalid token");
|
||||||
|
}
|
||||||
|
|
||||||
|
long signatureTime;
|
||||||
|
try {
|
||||||
|
signatureTime = Long.parseLong(signatureArray[2]);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
Environment env = CommonBeanFactory.getBean(Environment.class);
|
||||||
|
long timeout = env.getProperty("session.timeout", Long.class, 43200L);
|
||||||
|
if (Math.abs(System.currentTimeMillis() - signatureTime) > timeout * 1000) {
|
||||||
|
throw new RuntimeException("expired token");
|
||||||
|
}
|
||||||
|
if (!StringUtils.equals(SessionUtils.getUserId(), signatureArray[0])) {
|
||||||
|
throw new RuntimeException("Please check csrf token.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -136,8 +136,8 @@ public class XmindCaseParser {
|
||||||
data.setNodePath(nodePath);
|
data.setNodePath(nodePath);
|
||||||
|
|
||||||
|
|
||||||
if (data.getName().length() > 50) {
|
if (data.getName().length() > 200) {
|
||||||
process.add(Translator.get("test_case") + Translator.get("test_track.length_less_than") + "50", nodePath + data.getName());
|
process.add(Translator.get("test_case") + Translator.get("test_track.length_less_than") + "200", nodePath + data.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!StringUtils.isEmpty(nodePath)) {
|
if (!StringUtils.isEmpty(nodePath)) {
|
||||||
|
|
|
@ -0,0 +1,252 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.jmeter.assertions;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.jayway.jsonpath.JsonPath;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.jmeter.samplers.SampleResult;
|
||||||
|
import org.apache.jmeter.testelement.AbstractTestElement;
|
||||||
|
import org.apache.jmeter.testelement.ThreadListener;
|
||||||
|
import org.apache.jmeter.util.JMeterUtils;
|
||||||
|
import org.apache.oro.text.regex.Pattern;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is main class for JSONPath Assertion which verifies assertion on
|
||||||
|
* previous sample result using JSON path expression
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class JSONPathAssertion extends AbstractTestElement implements Serializable, Assertion, ThreadListener {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(JSONPathAssertion.class);
|
||||||
|
private static final long serialVersionUID = 2L;
|
||||||
|
public static final String JSONPATH = "JSON_PATH";
|
||||||
|
public static final String EXPECTEDVALUE = "EXPECTED_VALUE";
|
||||||
|
public static final String JSONVALIDATION = "JSONVALIDATION";
|
||||||
|
public static final String EXPECT_NULL = "EXPECT_NULL";
|
||||||
|
public static final String INVERT = "INVERT";
|
||||||
|
public static final String ISREGEX = "ISREGEX";
|
||||||
|
|
||||||
|
private static ThreadLocal<DecimalFormat> decimalFormatter =
|
||||||
|
ThreadLocal.withInitial(JSONPathAssertion::createDecimalFormat);
|
||||||
|
|
||||||
|
public String getOption() {
|
||||||
|
return getPropertyAsString("ASS_OPTION");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DecimalFormat createDecimalFormat() {
|
||||||
|
DecimalFormat decimalFormatter = new DecimalFormat("#.#");
|
||||||
|
decimalFormatter.setMaximumFractionDigits(340); // java.text.DecimalFormat.DOUBLE_FRACTION_DIGITS == 340
|
||||||
|
decimalFormatter.setMinimumFractionDigits(1);
|
||||||
|
return decimalFormatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJsonPath() {
|
||||||
|
return getPropertyAsString(JSONPATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJsonPath(String jsonPath) {
|
||||||
|
setProperty(JSONPATH, jsonPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExpectedValue() {
|
||||||
|
return getPropertyAsString(EXPECTEDVALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpectedValue(String expectedValue) {
|
||||||
|
setProperty(EXPECTEDVALUE, expectedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJsonValidationBool(boolean jsonValidation) {
|
||||||
|
setProperty(JSONVALIDATION, jsonValidation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpectNull(boolean val) {
|
||||||
|
setProperty(EXPECT_NULL, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExpectNull() {
|
||||||
|
return getPropertyAsBoolean(EXPECT_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isJsonValidationBool() {
|
||||||
|
return getPropertyAsBoolean(JSONVALIDATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInvert(boolean invert) {
|
||||||
|
setProperty(INVERT, invert);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInvert() {
|
||||||
|
return getPropertyAsBoolean(INVERT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsRegex(boolean flag) {
|
||||||
|
setProperty(ISREGEX, flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUseRegex() {
|
||||||
|
return getPropertyAsBoolean(ISREGEX, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doAssert(String jsonString) {
|
||||||
|
Object value = JsonPath.read(jsonString, getJsonPath());
|
||||||
|
|
||||||
|
if (!isJsonValidationBool()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value instanceof JSONArray) {
|
||||||
|
if (arrayMatched((JSONArray) value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((isExpectNull() && value == null)
|
||||||
|
|| isEquals(value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isExpectNull()) {
|
||||||
|
throw new IllegalStateException(String.format("Value expected to be null, but found '%s'", value));
|
||||||
|
} else {
|
||||||
|
String msg;
|
||||||
|
if (isUseRegex()) {
|
||||||
|
msg = "Value expected to match regexp '%s', but it did not match: '%s'";
|
||||||
|
} else {
|
||||||
|
msg = "Value expected to be '%s', but found '%s'";
|
||||||
|
}
|
||||||
|
throw new IllegalStateException(String.format(msg, getExpectedValue(), objectToString(value)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean arrayMatched(JSONArray value) {
|
||||||
|
if (value.isEmpty() && "[]".equals(getExpectedValue())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Object subj : value.toArray()) {
|
||||||
|
if ((subj == null && isExpectNull())
|
||||||
|
|| isEquals(subj)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isEquals(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isEquals(Object subj) {
|
||||||
|
String str = objectToString(subj);
|
||||||
|
if (isUseRegex()) {
|
||||||
|
Pattern pattern = JMeterUtils.getPatternCache().getPattern(getExpectedValue());
|
||||||
|
return JMeterUtils.getMatcher().matches(str, pattern);
|
||||||
|
} else {
|
||||||
|
if (StringUtils.isNotEmpty(getOption())) {
|
||||||
|
boolean refFlag = false;
|
||||||
|
switch (getOption()) {
|
||||||
|
case "CONTAINS":
|
||||||
|
refFlag = str.contains(getExpectedValue());
|
||||||
|
break;
|
||||||
|
case "NOT_CONTAINS":
|
||||||
|
refFlag = !str.contains(getExpectedValue());
|
||||||
|
break;
|
||||||
|
case "EQUALS":
|
||||||
|
refFlag = str.equals(getExpectedValue());
|
||||||
|
break;
|
||||||
|
case "NOT_EQUALS":
|
||||||
|
refFlag = !str.contains(getExpectedValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return refFlag;
|
||||||
|
}
|
||||||
|
return str.equals(getExpectedValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AssertionResult getResult(SampleResult samplerResult) {
|
||||||
|
AssertionResult result = new AssertionResult(getName());
|
||||||
|
String responseData = samplerResult.getResponseDataAsString();
|
||||||
|
if (responseData.isEmpty()) {
|
||||||
|
return result.setResultForNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.setFailure(false);
|
||||||
|
result.setFailureMessage("");
|
||||||
|
|
||||||
|
if (!isInvert()) {
|
||||||
|
try {
|
||||||
|
doAssert(responseData);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("Assertion failed", e);
|
||||||
|
result.setFailure(true);
|
||||||
|
result.setFailureMessage(e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
doAssert(responseData);
|
||||||
|
result.setFailure(true);
|
||||||
|
if (isJsonValidationBool()) {
|
||||||
|
if (isExpectNull()) {
|
||||||
|
result.setFailureMessage("Failed that JSONPath " + getJsonPath() + " not matches null");
|
||||||
|
} else {
|
||||||
|
result.setFailureMessage("Failed that JSONPath " + getJsonPath() + " not matches " + getExpectedValue());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.setFailureMessage("Failed that JSONPath not exists: " + getJsonPath());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("Assertion failed, as expected", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String objectToString(Object subj) {
|
||||||
|
String str;
|
||||||
|
if (subj == null) {
|
||||||
|
str = "null";
|
||||||
|
} else if (subj instanceof Map) {
|
||||||
|
//noinspection unchecked
|
||||||
|
str = new JSONObject((Map<String, Object>) subj).toJSONString();
|
||||||
|
} else if (subj instanceof Double || subj instanceof Float) {
|
||||||
|
str = decimalFormatter.get().format(subj);
|
||||||
|
} else {
|
||||||
|
str = subj.toString();
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void threadStarted() {
|
||||||
|
// nothing to do on thread start
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void threadFinished() {
|
||||||
|
decimalFormatter.remove();
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -45,3 +45,9 @@ alter table test_plan_api_scenario change environment_id environment longtext nu
|
||||||
|
|
||||||
-- file add sort column
|
-- file add sort column
|
||||||
alter table file_metadata add sort int default 0;
|
alter table file_metadata add sort int default 0;
|
||||||
|
|
||||||
|
-- add Original state
|
||||||
|
alter table api_definition add original_state varchar(64);
|
||||||
|
alter table api_scenario add original_state varchar(64);
|
||||||
|
update api_definition set original_state='Underway';
|
||||||
|
update api_scenario set original_state='Underway';
|
|
@ -17,7 +17,6 @@
|
||||||
"@fortawesome/vue-fontawesome": "^0.1.9",
|
"@fortawesome/vue-fontawesome": "^0.1.9",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"core-js": "^3.4.3",
|
"core-js": "^3.4.3",
|
||||||
"default-passive-events": "^2.0.0",
|
|
||||||
"diffable-html": "^4.0.0",
|
"diffable-html": "^4.0.0",
|
||||||
"echarts": "^4.6.0",
|
"echarts": "^4.6.0",
|
||||||
"el-table-infinite-scroll": "^1.0.10",
|
"el-table-infinite-scroll": "^1.0.10",
|
||||||
|
|
|
@ -30,6 +30,7 @@ import MsUser from "./components/common/head/HeaderUser";
|
||||||
import MsHeaderOrgWs from "./components/common/head/HeaderOrgWs";
|
import MsHeaderOrgWs from "./components/common/head/HeaderOrgWs";
|
||||||
import MsLanguageSwitch from "./components/common/head/LanguageSwitch";
|
import MsLanguageSwitch from "./components/common/head/LanguageSwitch";
|
||||||
import {saveLocalStorage} from "@/common/js/utils";
|
import {saveLocalStorage} from "@/common/js/utils";
|
||||||
|
import {registerRequestHeaders} from "@/common/js/ajax";
|
||||||
|
|
||||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||||
const header = requireComponent.keys().length > 0 ? requireComponent("./license/LicenseMessage.vue") : {};
|
const header = requireComponent.keys().length > 0 ? requireComponent("./license/LicenseMessage.vue") : {};
|
||||||
|
@ -53,6 +54,7 @@ export default {
|
||||||
window.addEventListener("beforeunload", () => {
|
window.addEventListener("beforeunload", () => {
|
||||||
localStorage.setItem("store", JSON.stringify(this.$store.state))
|
localStorage.setItem("store", JSON.stringify(this.$store.state))
|
||||||
})
|
})
|
||||||
|
registerRequestHeaders();
|
||||||
},
|
},
|
||||||
beforeCreate() {
|
beforeCreate() {
|
||||||
this.$get("/isLogin").then(response => {
|
this.$get("/isLogin").then(response => {
|
||||||
|
|
|
@ -100,6 +100,19 @@
|
||||||
active() {
|
active() {
|
||||||
this.isActive = !this.isActive;
|
this.isActive = !this.isActive;
|
||||||
},
|
},
|
||||||
|
formatResult(res) {
|
||||||
|
let resMap = new Map;
|
||||||
|
if (res && res.scenarios) {
|
||||||
|
res.scenarios.forEach(item => {
|
||||||
|
if (item && item.requestResults) {
|
||||||
|
item.requestResults.forEach(req => {
|
||||||
|
resMap.set(req.id, req);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.$emit('refresh', resMap);
|
||||||
|
},
|
||||||
getReport() {
|
getReport() {
|
||||||
this.init();
|
this.init();
|
||||||
if (this.reportId) {
|
if (this.reportId) {
|
||||||
|
@ -113,7 +126,7 @@
|
||||||
if (!this.content) {
|
if (!this.content) {
|
||||||
this.content = {scenarios: []};
|
this.content = {scenarios: []};
|
||||||
}
|
}
|
||||||
this.$emit('refresh');
|
this.formatResult(this.content);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,7 @@
|
||||||
<!--测试计划-->
|
<!--测试计划-->
|
||||||
<el-drawer :visible.sync="planVisible" :destroy-on-close="true" direction="ltr" :withHeader="false"
|
<el-drawer :visible.sync="planVisible" :destroy-on-close="true" direction="ltr" :withHeader="false"
|
||||||
:title="$t('test_track.plan_view.test_result')" :modal="false" size="90%">
|
:title="$t('test_track.plan_view.test_result')" :modal="false" size="90%">
|
||||||
<ms-test-plan-list @addTestPlan="addTestPlan" @cancel="cancel"/>
|
<ms-test-plan-list @addTestPlan="addTestPlan(arguments)" @cancel="cancel" ref="testPlanList" :row="selectRows"/>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
@ -276,7 +276,9 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: this.$t('test_track.case.batch_move_case'), handleClick: this.handleBatchMove
|
name: this.$t('test_track.case.batch_move_case'), handleClick: this.handleBatchMove
|
||||||
}
|
},
|
||||||
|
{name: this.$t('api_test.definition.request.batch_delete'), handleClick: this.handleDeleteBatch},
|
||||||
|
|
||||||
],
|
],
|
||||||
isSelectAllDate: false,
|
isSelectAllDate: false,
|
||||||
selectRows: new Set(),
|
selectRows: new Set(),
|
||||||
|
@ -318,7 +320,7 @@
|
||||||
],
|
],
|
||||||
principal: [],
|
principal: [],
|
||||||
environmentId: [],
|
environmentId: [],
|
||||||
projectEnv: []
|
projectEnv: [],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -496,17 +498,31 @@
|
||||||
cancel() {
|
cancel() {
|
||||||
this.planVisible = false;
|
this.planVisible = false;
|
||||||
},
|
},
|
||||||
addTestPlan(plans) {
|
addTestPlan(params) {
|
||||||
let obj = {planIds: plans, scenarioIds: this.selection};
|
let obj = {planIds: params[0], scenarioIds: this.selection};
|
||||||
|
|
||||||
obj.projectId = getCurrentProjectID();
|
// obj.projectId = getCurrentProjectID();
|
||||||
obj.selectAllDate = this.isSelectAllDate;
|
// obj.selectAllDate = this.isSelectAllDate;
|
||||||
obj.unSelectIds = this.unSelection;
|
// obj.unSelectIds = this.unSelection;
|
||||||
obj = Object.assign(obj, this.condition);
|
// obj = Object.assign(obj, this.condition);
|
||||||
|
|
||||||
|
// todo 选取全部数据
|
||||||
|
if (this.isSelectAllDate) {
|
||||||
|
this.$warning("暂不支持批量添加所有场景到测试计划!");
|
||||||
|
}
|
||||||
|
|
||||||
this.planVisible = false;
|
this.planVisible = false;
|
||||||
|
|
||||||
|
let map = new Map();
|
||||||
|
this.selectRows.forEach(row => {
|
||||||
|
map.set(row.id, row.projectIds);
|
||||||
|
})
|
||||||
|
obj.mapping = strMapToObj(map);
|
||||||
|
obj.envMap = strMapToObj(params[1]);
|
||||||
|
|
||||||
this.$post("/api/automation/scenario/plan", obj, response => {
|
this.$post("/api/automation/scenario/plan", obj, response => {
|
||||||
this.$success(this.$t("commons.save_success"));
|
this.$success(this.$t("commons.save_success"));
|
||||||
|
this.search();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getReport() {
|
getReport() {
|
||||||
|
@ -582,6 +598,29 @@
|
||||||
this.search();
|
this.search();
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
handleDeleteBatch(row) {
|
||||||
|
if (this.trashEnable) {
|
||||||
|
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||||
|
this.$post('/api/automation/deleteBatch/', ids, () => {
|
||||||
|
this.$success(this.$t('commons.delete_success'));
|
||||||
|
this.search();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$alert(this.$t('api_test.definition.request.delete_confirm') + " ?", '', {
|
||||||
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
|
callback: (action) => {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||||
|
this.$post('/api/automation/removeToGc/', ids, () => {
|
||||||
|
this.$success(this.$t('commons.delete_success'));
|
||||||
|
this.search();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
execute(row) {
|
execute(row) {
|
||||||
this.infoDb = false;
|
this.infoDb = false;
|
||||||
let url = "/api/automation/run";
|
let url = "/api/automation/run";
|
||||||
|
|
|
@ -184,7 +184,7 @@
|
||||||
<!-- 调试结果 -->
|
<!-- 调试结果 -->
|
||||||
<el-drawer v-if="type!=='detail'" :visible.sync="debugVisible" :destroy-on-close="true" direction="ltr"
|
<el-drawer v-if="type!=='detail'" :visible.sync="debugVisible" :destroy-on-close="true" direction="ltr"
|
||||||
:withHeader="true" :modal="false" size="90%">
|
:withHeader="true" :modal="false" size="90%">
|
||||||
<ms-api-report-detail :report-id="reportId" :debug="true" :currentProjectId="projectId"/>
|
<ms-api-report-detail :report-id="reportId" :debug="true" :currentProjectId="projectId" @refresh="detailRefresh"/>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
|
|
||||||
<!--场景公共参数-->
|
<!--场景公共参数-->
|
||||||
|
@ -224,6 +224,7 @@
|
||||||
import MsComponentConfig from "./component/ComponentConfig";
|
import MsComponentConfig from "./component/ComponentConfig";
|
||||||
import {handleCtrlSEvent} from "../../../../../common/js/utils";
|
import {handleCtrlSEvent} from "../../../../../common/js/utils";
|
||||||
import EnvPopover from "@/business/components/api/automation/scenario/EnvPopover";
|
import EnvPopover from "@/business/components/api/automation/scenario/EnvPopover";
|
||||||
|
|
||||||
let jsonPath = require('jsonpath');
|
let jsonPath = require('jsonpath');
|
||||||
export default {
|
export default {
|
||||||
name: "EditApiScenario",
|
name: "EditApiScenario",
|
||||||
|
@ -290,7 +291,8 @@
|
||||||
response: {},
|
response: {},
|
||||||
projectIds: new Set,
|
projectIds: new Set,
|
||||||
projectEnvMap: new Map,
|
projectEnvMap: new Map,
|
||||||
projectList: []
|
projectList: [],
|
||||||
|
debugResult: new Map,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
@ -400,7 +402,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: this.$t('api_test.automation.scenario_import'),
|
title: this.$t('api_test.automation.scenario_import'),
|
||||||
show:this.showButton("scenario"),
|
show: this.showButton("scenario"),
|
||||||
titleColor: "#606266",
|
titleColor: "#606266",
|
||||||
titleBgColor: "#F4F4F5",
|
titleBgColor: "#F4F4F5",
|
||||||
icon: "movie",
|
icon: "movie",
|
||||||
|
@ -547,21 +549,32 @@
|
||||||
if (arr[i].hashTree != undefined && arr[i].hashTree.length > 0) {
|
if (arr[i].hashTree != undefined && arr[i].hashTree.length > 0) {
|
||||||
this.recursiveSorting(arr[i].hashTree);
|
this.recursiveSorting(arr[i].hashTree);
|
||||||
}
|
}
|
||||||
|
// 添加debug结果
|
||||||
|
if (this.debugResult && this.debugResult.get(arr[i].id)) {
|
||||||
|
arr[i].requestResult = this.debugResult.get(arr[i].id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sort() {
|
sort() {
|
||||||
for (let i in this.scenarioDefinition) {
|
for (let i in this.scenarioDefinition) {
|
||||||
|
// 排序
|
||||||
this.scenarioDefinition[i].index = Number(i) + 1;
|
this.scenarioDefinition[i].index = Number(i) + 1;
|
||||||
|
// 设置循环控制
|
||||||
if (this.scenarioDefinition[i].type === ELEMENT_TYPE.LoopController && this.scenarioDefinition[i].hashTree
|
if (this.scenarioDefinition[i].type === ELEMENT_TYPE.LoopController && this.scenarioDefinition[i].hashTree
|
||||||
&& this.scenarioDefinition[i].hashTree.length > 1) {
|
&& this.scenarioDefinition[i].hashTree.length > 1) {
|
||||||
this.scenarioDefinition[i].countController.proceed = true;
|
this.scenarioDefinition[i].countController.proceed = true;
|
||||||
}
|
}
|
||||||
|
// 设置项目ID
|
||||||
if (!this.scenarioDefinition[i].projectId) {
|
if (!this.scenarioDefinition[i].projectId) {
|
||||||
this.scenarioDefinition.projectId = getCurrentProjectID();
|
this.scenarioDefinition[i].projectId = getCurrentProjectID();
|
||||||
}
|
}
|
||||||
if (this.scenarioDefinition[i].hashTree != undefined && this.scenarioDefinition[i].hashTree.length > 0) {
|
if (this.scenarioDefinition[i].hashTree != undefined && this.scenarioDefinition[i].hashTree.length > 0) {
|
||||||
this.recursiveSorting(this.scenarioDefinition[i].hashTree);
|
this.recursiveSorting(this.scenarioDefinition[i].hashTree);
|
||||||
}
|
}
|
||||||
|
// 添加debug结果
|
||||||
|
if (this.debugResult && this.debugResult.get(this.scenarioDefinition[i].id)) {
|
||||||
|
this.scenarioDefinition[i].requestResult = this.debugResult.get(this.scenarioDefinition[i].id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addCustomizeApi(request) {
|
addCustomizeApi(request) {
|
||||||
|
@ -575,6 +588,7 @@
|
||||||
this.customizeRequest = {};
|
this.customizeRequest = {};
|
||||||
this.sort();
|
this.sort();
|
||||||
this.reload();
|
this.reload();
|
||||||
|
this.initProjectIds();
|
||||||
},
|
},
|
||||||
addScenario(arr) {
|
addScenario(arr) {
|
||||||
if (arr && arr.length > 0) {
|
if (arr && arr.length > 0) {
|
||||||
|
@ -677,7 +691,7 @@
|
||||||
}
|
}
|
||||||
const index = hashTree.findIndex(d => d.resourceId === row.resourceId);
|
const index = hashTree.findIndex(d => d.resourceId === row.resourceId);
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
hashTree.splice(index+1, 0, obj);
|
hashTree.splice(index + 1, 0, obj);
|
||||||
} else {
|
} else {
|
||||||
hashTree.push(obj);
|
hashTree.push(obj);
|
||||||
}
|
}
|
||||||
|
@ -1019,11 +1033,16 @@
|
||||||
// 加载环境配置
|
// 加载环境配置
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.projectIds.clear();
|
this.projectIds.clear();
|
||||||
this.scenarioDefinition.forEach(data=>{
|
this.scenarioDefinition.forEach(data => {
|
||||||
let arr = jsonPath.query(data, "$..projectId");
|
let arr = jsonPath.query(data, "$..projectId");
|
||||||
arr.forEach(a => this.projectIds.add(a));
|
arr.forEach(a => this.projectIds.add(a));
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
detailRefresh(result) {
|
||||||
|
// 把执行结果分发给各个请求
|
||||||
|
this.debugResult = result;
|
||||||
|
this.sort()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,17 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
sign = false;
|
// 如果有环境,检查环境
|
||||||
|
if (this.envMap && this.envMap.size > 0) {
|
||||||
|
this.projectIds.forEach(id => {
|
||||||
|
if (!this.envMap.get(id)) {
|
||||||
|
sign = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
sign = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sign) {
|
if (!sign) {
|
||||||
|
|
|
@ -6,8 +6,8 @@ export const ELEMENTS = new Map([
|
||||||
['JDBCSampler', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],
|
['JDBCSampler', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],
|
||||||
['TCPSampler', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],
|
['TCPSampler', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],
|
||||||
['OT_IMPORT', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],
|
['OT_IMPORT', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],
|
||||||
['IfController', ["IfController","scenario", "HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "OT_IMPORT", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract", "CustomizeReq"]],
|
['IfController', ["IfController", "scenario", "HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "OT_IMPORT", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract", "CustomizeReq"]],
|
||||||
['LoopController', ["IfController", "HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "OT_IMPORT", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract", "CustomizeReq"]],
|
['LoopController', ["IfController", "scenario", "HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "OT_IMPORT", "ConstantTimer", "JSR223Processor", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract", "CustomizeReq"]],
|
||||||
['ConstantTimer', []],
|
['ConstantTimer', []],
|
||||||
['JSR223Processor', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],
|
['JSR223Processor', ["ConstantTimer", "JSR223PreProcessor", "JSR223PostProcessor", "Assertions", "Extract"]],
|
||||||
['JSR223PreProcessor', []],
|
['JSR223PreProcessor', []],
|
||||||
|
|
|
@ -3,9 +3,11 @@
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
<ms-table-header :is-tester-permission="true" :condition.sync="condition"
|
<ms-table-header :is-tester-permission="true" :condition.sync="condition"
|
||||||
@search="initTableData" :showCreate="false"
|
@search="initTableData" :showCreate="false"
|
||||||
:title="$t('test_track.plan.test_plan')"/>
|
:title="$t('test_track.plan.test_plan')">
|
||||||
|
</ms-table-header>
|
||||||
</template>
|
</template>
|
||||||
|
<env-popover :env-map="projectEnvMap" :project-ids="projectIds" @setProjectEnvMap="setProjectEnvMap"
|
||||||
|
:project-list="projectList" ref="envPopover" class="env-popover" style="float: right; margin-top: 4px;"/>
|
||||||
<el-table
|
<el-table
|
||||||
border
|
border
|
||||||
class="adjust-table"
|
class="adjust-table"
|
||||||
|
@ -142,7 +144,7 @@ import MsTableOperatorButton from "../../../../common/components/MsTableOperator
|
||||||
import MsTableOperator from "../../../../common/components/MsTableOperator";
|
import MsTableOperator from "../../../../common/components/MsTableOperator";
|
||||||
import PlanStatusTableItem from "../../../../track/common/tableItems/plan/PlanStatusTableItem";
|
import PlanStatusTableItem from "../../../../track/common/tableItems/plan/PlanStatusTableItem";
|
||||||
import PlanStageTableItem from "../../../../track/common/tableItems/plan/PlanStageTableItem";
|
import PlanStageTableItem from "../../../../track/common/tableItems/plan/PlanStageTableItem";
|
||||||
import {checkoutTestManagerOrTestUser} from "@/common/js/utils";
|
import {checkoutTestManagerOrTestUser, strMapToObj} from "@/common/js/utils";
|
||||||
import TestReportTemplateList from "../../../../track/plan/view/comonents/TestReportTemplateList";
|
import TestReportTemplateList from "../../../../track/plan/view/comonents/TestReportTemplateList";
|
||||||
import TestCaseReportView from "../../../../track/plan/view/comonents/report/TestCaseReportView";
|
import TestCaseReportView from "../../../../track/plan/view/comonents/report/TestCaseReportView";
|
||||||
import MsDeleteConfirm from "../../../../common/components/MsDeleteConfirm";
|
import MsDeleteConfirm from "../../../../common/components/MsDeleteConfirm";
|
||||||
|
@ -150,6 +152,7 @@ import {TEST_PLAN_CONFIGS} from "../../../../common/components/search/search-com
|
||||||
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
|
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
|
||||||
import {getCurrentProjectID} from "../../../../../../common/js/utils";
|
import {getCurrentProjectID} from "../../../../../../common/js/utils";
|
||||||
import {_filter, _sort} from "@/common/js/tableUtils";
|
import {_filter, _sort} from "@/common/js/tableUtils";
|
||||||
|
import EnvPopover from "@/business/components/api/automation/scenario/EnvPopover";
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -160,7 +163,10 @@ export default {
|
||||||
TestReportTemplateList,
|
TestReportTemplateList,
|
||||||
PlanStageTableItem,
|
PlanStageTableItem,
|
||||||
PlanStatusTableItem,
|
PlanStatusTableItem,
|
||||||
MsTableOperator, MsTableOperatorButton, MsDialogFooter, MsTableHeader, MsCreateBox, MsTablePagination
|
MsTableOperator, MsTableOperatorButton, MsDialogFooter, MsTableHeader, MsCreateBox, MsTablePagination, EnvPopover
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
row: Set
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -187,6 +193,9 @@ export default {
|
||||||
{text: this.$t('test_track.plan.system_test'), value: 'system'},
|
{text: this.$t('test_track.plan.system_test'), value: 'system'},
|
||||||
{text: this.$t('test_track.plan.regression_test'), value: 'regression'},
|
{text: this.$t('test_track.plan.regression_test'), value: 'regression'},
|
||||||
],
|
],
|
||||||
|
projectEnvMap: new Map(),
|
||||||
|
projectList: [],
|
||||||
|
projectIds: new Set()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -200,22 +209,37 @@ export default {
|
||||||
this.projectId = this.$route.params.projectId;
|
this.projectId = this.$route.params.projectId;
|
||||||
this.isTestManagerOrTestUser = checkoutTestManagerOrTestUser();
|
this.isTestManagerOrTestUser = checkoutTestManagerOrTestUser();
|
||||||
this.initTableData();
|
this.initTableData();
|
||||||
|
this.setScenarioSelectRows(this.row);
|
||||||
|
this.getWsProjects();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
confirm() {
|
confirm() {
|
||||||
if (this.selection.length==0) {
|
if (this.selection.length==0) {
|
||||||
this.$warning(this.$t("api_test.definition.request.test_plan_select"));
|
this.$warning(this.$t("api_test.definition.request.test_plan_select"));
|
||||||
}else{
|
}else{
|
||||||
this.$emit('addTestPlan', this.selection);
|
const sign = this.checkEnv();
|
||||||
|
if (!sign) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.$emit('addTestPlan', this.selection, this.projectEnvMap);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
cancel(){
|
cancel(){
|
||||||
this.$emit('cancel');
|
this.$emit('cancel');
|
||||||
},
|
},
|
||||||
|
setProjectEnvMap(projectEnvMap) {
|
||||||
|
this.projectEnvMap = projectEnvMap;
|
||||||
|
},
|
||||||
select(selection) {
|
select(selection) {
|
||||||
this.selection = selection.map(s => s.id);
|
this.selection = selection.map(s => s.id);
|
||||||
this.$emit('selection', selection);
|
this.$emit('selection', selection);
|
||||||
},
|
},
|
||||||
|
setScenarioSelectRows(rows) {
|
||||||
|
this.projectIds.clear();
|
||||||
|
rows.forEach(row => {
|
||||||
|
row.projectIds.forEach(id => this.projectIds.add(id));
|
||||||
|
})
|
||||||
|
},
|
||||||
initTableData() {
|
initTableData() {
|
||||||
if (this.planId) {
|
if (this.planId) {
|
||||||
this.condition.planId = this.planId;
|
this.condition.planId = this.planId;
|
||||||
|
@ -284,6 +308,14 @@ export default {
|
||||||
this.$refs.testCaseReportView.open(planId, reportId);
|
this.$refs.testCaseReportView.open(planId, reportId);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
checkEnv() {
|
||||||
|
return this.$refs.envPopover.checkEnv();
|
||||||
|
},
|
||||||
|
getWsProjects() {
|
||||||
|
this.$get("/project/listAll", res => {
|
||||||
|
this.projectList = res.data;
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,13 +1,24 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div v-loading="loading">
|
||||||
<el-row :gutter="10" type="flex" justify="space-between" align="middle">
|
<el-row :gutter="10" type="flex" justify="space-between" align="middle">
|
||||||
<el-col>
|
<el-col>
|
||||||
<el-input :disabled="isReadOnly" v-model="jsonPath.expression" maxlength="200" size="small" show-word-limit
|
<el-input :disabled="isReadOnly" v-model="jsonPath.expression" maxlength="200" size="small" show-word-limit
|
||||||
:placeholder="$t('api_test.request.extract.json_path_expression')"/>
|
:placeholder="$t('api_test.request.extract.json_path_expression')"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col>
|
<el-col>
|
||||||
|
<el-select v-model="jsonPath.option" class="ms-col-type" size="small" style="width:40%;margin-right: 10px" @change="reload">
|
||||||
|
<el-option :label="$t('api_test.request.assertions.contains')" value="CONTAINS"/>
|
||||||
|
<el-option :label="$t('api_test.request.assertions.not_contains')" value="NOT_CONTAINS"/>
|
||||||
|
<el-option :label="$t('api_test.request.assertions.equals')" value="EQUALS"/>
|
||||||
|
<el-option :label="$t('commons.adv_search.operators.not_equals')" value="NOT_EQUALS"/>
|
||||||
|
<el-option label="正则匹配" value="REGEX"/>
|
||||||
|
</el-select>
|
||||||
<el-input :disabled="isReadOnly" v-model="jsonPath.expect" size="small" show-word-limit
|
<el-input :disabled="isReadOnly" v-model="jsonPath.expect" size="small" show-word-limit
|
||||||
:placeholder="$t('api_test.request.assertions.expect')"/>
|
:placeholder="$t('api_test.request.assertions.expect')" style="width: 50%"/>
|
||||||
|
<el-tooltip placement="top" v-if="jsonPath.option === 'REGEX'">
|
||||||
|
<div slot="content">特殊字符"$ ( ) * + . [ ] \ ^ { } |"需转义为"\ "+"特殊字符",如"\$"</div>
|
||||||
|
<i class="el-icon-question" style="cursor: pointer"/>
|
||||||
|
</el-tooltip>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col class="assertion-btn">
|
<el-col class="assertion-btn">
|
||||||
<el-button :disabled="isReadOnly" type="danger" size="mini" icon="el-icon-delete" circle @click="remove" v-if="edit"/>
|
<el-button :disabled="isReadOnly" type="danger" size="mini" icon="el-icon-delete" circle @click="remove" v-if="edit"/>
|
||||||
|
@ -44,8 +55,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
if (!this.jsonPath.option) {
|
||||||
|
this.jsonPath.option = "REGEX";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
loading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -71,6 +89,12 @@
|
||||||
jsonPath.description = jsonPath.expression + " expect: " + (jsonPath.expect ? jsonPath.expect : '');
|
jsonPath.description = jsonPath.expression + " expect: " + (jsonPath.expect ? jsonPath.expect : '');
|
||||||
return jsonPath;
|
return jsonPath;
|
||||||
},
|
},
|
||||||
|
reload() {
|
||||||
|
this.loading = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
setJSONPathDescription() {
|
setJSONPathDescription() {
|
||||||
this.jsonPath.description = this.jsonPath.expression + " expect: " + (this.jsonPath.expect ? this.jsonPath.expect : '');
|
this.jsonPath.description = this.jsonPath.expression + " expect: " + (this.jsonPath.expect ? this.jsonPath.expect : '');
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,31 +56,31 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import MsApiAssertionText from "./ApiAssertionText";
|
import MsApiAssertionText from "./ApiAssertionText";
|
||||||
import MsApiAssertionRegex from "./ApiAssertionRegex";
|
import MsApiAssertionRegex from "./ApiAssertionRegex";
|
||||||
import MsApiAssertionDuration from "./ApiAssertionDuration";
|
import MsApiAssertionDuration from "./ApiAssertionDuration";
|
||||||
import {ASSERTION_TYPE, JSONPath} from "../../model/ApiTestModel";
|
import {ASSERTION_TYPE, JSONPath} from "../../model/ApiTestModel";
|
||||||
import MsApiAssertionsEdit from "./ApiAssertionsEdit";
|
import MsApiAssertionsEdit from "./ApiAssertionsEdit";
|
||||||
import MsApiAssertionJsonPath from "./ApiAssertionJsonPath";
|
import MsApiAssertionJsonPath from "./ApiAssertionJsonPath";
|
||||||
import MsApiAssertionJsr223 from "./ApiAssertionJsr223";
|
import MsApiAssertionJsr223 from "./ApiAssertionJsr223";
|
||||||
import MsApiJsonpathSuggestList from "./ApiJsonpathSuggestList";
|
import MsApiJsonpathSuggestList from "./ApiJsonpathSuggestList";
|
||||||
import MsApiAssertionXPath2 from "./ApiAssertionXPath2";
|
import MsApiAssertionXPath2 from "./ApiAssertionXPath2";
|
||||||
import {getUUID} from "@/common/js/utils";
|
import {getUUID} from "@/common/js/utils";
|
||||||
import ApiJsonPathSuggestButton from "./ApiJsonPathSuggestButton";
|
import ApiJsonPathSuggestButton from "./ApiJsonPathSuggestButton";
|
||||||
import MsApiJsonpathSuggest from "./ApiJsonpathSuggest";
|
import MsApiJsonpathSuggest from "./ApiJsonpathSuggest";
|
||||||
import ApiBaseComponent from "../../../automation/scenario/common/ApiBaseComponent";
|
import ApiBaseComponent from "../../../automation/scenario/common/ApiBaseComponent";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsApiAssertions",
|
name: "MsApiAssertions",
|
||||||
components: {
|
components: {
|
||||||
ApiBaseComponent,
|
ApiBaseComponent,
|
||||||
MsApiJsonpathSuggest,
|
MsApiJsonpathSuggest,
|
||||||
ApiJsonPathSuggestButton,
|
ApiJsonPathSuggestButton,
|
||||||
MsApiAssertionXPath2,
|
MsApiAssertionXPath2,
|
||||||
MsApiAssertionJsr223,
|
MsApiAssertionJsr223,
|
||||||
MsApiJsonpathSuggestList,
|
MsApiJsonpathSuggestList,
|
||||||
MsApiAssertionJsonPath,
|
MsApiAssertionJsonPath,
|
||||||
MsApiAssertionsEdit, MsApiAssertionDuration, MsApiAssertionRegex, MsApiAssertionText
|
MsApiAssertionsEdit, MsApiAssertionDuration, MsApiAssertionRegex, MsApiAssertionText
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
draggable: {
|
draggable: {
|
||||||
|
@ -146,6 +146,11 @@ export default {
|
||||||
jsonItem.expression = data.path;
|
jsonItem.expression = data.path;
|
||||||
jsonItem.expect = data.value;
|
jsonItem.expect = data.value;
|
||||||
jsonItem.setJSONPathDescription();
|
jsonItem.setJSONPathDescription();
|
||||||
|
let expect = jsonItem.expect.replaceAll('\\', "\\\\").replaceAll('(', "\\(").replaceAll(')', "\\)")
|
||||||
|
.replaceAll('+', "\\+").replaceAll('.', "\\.").replaceAll('[', "\\[").replaceAll(']', "\\]")
|
||||||
|
.replaceAll('?', "\\?").replaceAll('/', "\\/").replaceAll('*', "\\*")
|
||||||
|
.replaceAll('^', "\\^").replaceAll('{', "\\{").replaceAll('}', "\\}").replaceAll('$', "\\$");
|
||||||
|
jsonItem.expect = expect;
|
||||||
this.assertions.jsonPath.push(jsonItem);
|
this.assertions.jsonPath.push(jsonItem);
|
||||||
},
|
},
|
||||||
clearJson() {
|
clearJson() {
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
v-permission="['test_manager','test_user','test_viewer']">
|
v-permission="['test_manager','test_user','test_viewer']">
|
||||||
{{ $t('commons.performance') }}
|
{{ $t('commons.performance') }}
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
<el-menu-item index="/reportForm" v-permission="['test_manager','test_user','test_viewer']" v-if="isReport">
|
<el-menu-item index="/report" v-permission="['test_manager','test_user','test_viewer']" v-if="isReport">
|
||||||
{{ $t('commons.report_statistics.title') }}
|
{{ $t('commons.report_statistics.title') }}
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -178,8 +178,11 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
calculateLoadConfiguration: function (data) {
|
calculateLoadConfiguration: function (data) {
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < this.threadGroups.length; i++) {
|
||||||
let d = data[i];
|
let d = data[i];
|
||||||
|
if (!d) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
d.forEach(item => {
|
d.forEach(item => {
|
||||||
switch (item.key) {
|
switch (item.key) {
|
||||||
case TARGET_LEVEL:
|
case TARGET_LEVEL:
|
||||||
|
@ -225,7 +228,7 @@ export default {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
this.calculateChart(this.threadGroups[i]);
|
this.calculateChart(this.threadGroups[i]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,36 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-form :inline="true">
|
||||||
|
<el-form-item>
|
||||||
|
<div>
|
||||||
|
{{ $t('load_test.granularity') }}
|
||||||
|
<el-popover
|
||||||
|
placement="bottom"
|
||||||
|
width="400"
|
||||||
|
trigger="hover">
|
||||||
|
<el-table :data="granularityData">
|
||||||
|
<el-table-column property="start" :label="$t('load_test.duration')">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>{{ scope.row.start }} - {{ scope.row.end }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column property="granularity" :label="$t('load_test.granularity')"/>
|
||||||
|
</el-table>
|
||||||
|
<i slot="reference" class="el-icon-info pointer"/>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-select v-model="granularity" :placeholder="$t('commons.please_select')" size="mini" clearable>
|
||||||
|
<el-option v-for="op in granularityData" :key="op.granularity" :label="op.granularity" :value="op.granularity"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -134,6 +164,18 @@ export default {
|
||||||
domains: [],
|
domains: [],
|
||||||
params: [],
|
params: [],
|
||||||
statusCodeStr: '',
|
statusCodeStr: '',
|
||||||
|
granularity: undefined,
|
||||||
|
granularityData: [
|
||||||
|
{start: 0, end: 100, granularity: 1},
|
||||||
|
{start: 101, end: 500, granularity: 5},
|
||||||
|
{start: 501, end: 1000, granularity: 10},
|
||||||
|
{start: 1001, end: 3000, granularity: 30},
|
||||||
|
{start: 3001, end: 6000, granularity: 60},
|
||||||
|
{start: 6001, end: 30000, granularity: 300},
|
||||||
|
{start: 30001, end: 60000, granularity: 600},
|
||||||
|
{start: 60001, end: 180000, granularity: 1800},
|
||||||
|
{start: 180001, end: 360000, granularity: 3600},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -166,6 +208,7 @@ export default {
|
||||||
this.statusCodeStr = this.statusCode.join(',');
|
this.statusCodeStr = this.statusCode.join(',');
|
||||||
this.domains = data.domains || [];
|
this.domains = data.domains || [];
|
||||||
this.params = data.params || [];
|
this.params = data.params || [];
|
||||||
|
this.granularity = data.granularity;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -252,6 +295,7 @@ export default {
|
||||||
statusCode: statusCode,
|
statusCode: statusCode,
|
||||||
params: this.params,
|
params: this.params,
|
||||||
domains: this.domains,
|
domains: this.domains,
|
||||||
|
granularity: this.granularity,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -287,4 +331,8 @@ export default {
|
||||||
align: center;
|
align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
<el-row type="flex" justify="start" align="middle">
|
<el-row type="flex" justify="start" align="middle">
|
||||||
<el-upload
|
<el-upload
|
||||||
style="padding-right: 10px;"
|
style="padding-right: 10px;"
|
||||||
accept=".jar,.csv"
|
accept=".jar,.csv,.json,.pdf,.jpg,.png,.jpeg,.doc,.docx,.xlsx"
|
||||||
action=""
|
action=""
|
||||||
:limit="fileNumLimit"
|
:limit="fileNumLimit"
|
||||||
multiple
|
multiple
|
||||||
|
@ -170,7 +170,7 @@ export default {
|
||||||
fileList: [],
|
fileList: [],
|
||||||
tableData: [],
|
tableData: [],
|
||||||
uploadList: [],
|
uploadList: [],
|
||||||
metadataIdList:[],
|
metadataIdList: [],
|
||||||
fileNumLimit: 10,
|
fileNumLimit: 10,
|
||||||
threadGroups: [],
|
threadGroups: [],
|
||||||
loadFileVisible: false,
|
loadFileVisible: false,
|
||||||
|
@ -276,7 +276,10 @@ export default {
|
||||||
let self = this;
|
let self = this;
|
||||||
let file = uploadResources.file;
|
let file = uploadResources.file;
|
||||||
self.uploadList.push(file);
|
self.uploadList.push(file);
|
||||||
|
let type = file.name.substring(file.name.lastIndexOf(".") + 1);
|
||||||
|
if (type.toLowerCase() !== 'jmx') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let jmxReader = new FileReader();
|
let jmxReader = new FileReader();
|
||||||
jmxReader.onload = (event) => {
|
jmxReader.onload = (event) => {
|
||||||
self.threadGroups = self.threadGroups.concat(findThreadGroup(event.target.result, file.name));
|
self.threadGroups = self.threadGroups.concat(findThreadGroup(event.target.result, file.name));
|
||||||
|
|
|
@ -22,7 +22,6 @@ import {left2RightDrag, bottom2TopDrag, right2LeftDrag} from "../common/js/direc
|
||||||
import JsonSchemaEditor from './components/common/json-schema/schema/index';
|
import JsonSchemaEditor from './components/common/json-schema/schema/index';
|
||||||
import JSONPathPicker from 'vue-jsonpath-picker';
|
import JSONPathPicker from 'vue-jsonpath-picker';
|
||||||
import VueClipboard from 'vue-clipboard2'
|
import VueClipboard from 'vue-clipboard2'
|
||||||
|
|
||||||
Vue.use(JsonSchemaEditor);
|
Vue.use(JsonSchemaEditor);
|
||||||
import VuePapaParse from 'vue-papa-parse'
|
import VuePapaParse from 'vue-papa-parse'
|
||||||
Vue.use(VuePapaParse)
|
Vue.use(VuePapaParse)
|
||||||
|
|
|
@ -1,13 +1,23 @@
|
||||||
import {Message, MessageBox} from 'element-ui';
|
import {Message, MessageBox} from 'element-ui';
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import i18n from '../../i18n/i18n'
|
import i18n from '../../i18n/i18n'
|
||||||
|
import {TokenKey} from "@/common/js/constants";
|
||||||
|
|
||||||
|
export function registerRequestHeaders() {
|
||||||
|
axios.interceptors.request.use(config => {
|
||||||
|
let user = JSON.parse(localStorage.getItem(TokenKey));
|
||||||
|
if (user && user.csrfToken) {
|
||||||
|
config.headers['CSRF-TOKEN'] = user.csrfToken;
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
install(Vue) {
|
install(Vue) {
|
||||||
|
|
||||||
// 登入请求不重定向
|
// 登入请求不重定向
|
||||||
let unRedirectUrls = new Set(['signin','ldap/signin','/signin', '/ldap/signin']);
|
let unRedirectUrls = new Set(['signin', 'ldap/signin', '/signin', '/ldap/signin']);
|
||||||
|
|
||||||
if (!axios) {
|
if (!axios) {
|
||||||
window.console.error('You have to install axios');
|
window.console.error('You have to install axios');
|
||||||
|
|
|
@ -478,7 +478,8 @@ export default {
|
||||||
delete_file: "The file already exists, please delete the file with the same name first!",
|
delete_file: "The file already exists, please delete the file with the same name first!",
|
||||||
thread_num: 'Concurrent users:',
|
thread_num: 'Concurrent users:',
|
||||||
input_thread_num: 'Please enter the number of threads',
|
input_thread_num: 'Please enter the number of threads',
|
||||||
duration: 'Duration time (seconds):',
|
duration: 'Duration time (seconds)',
|
||||||
|
granularity: 'Aggregation time (seconds)',
|
||||||
input_duration: 'Please enter a duration',
|
input_duration: 'Please enter a duration',
|
||||||
rps_limit: 'RPS Limit:',
|
rps_limit: 'RPS Limit:',
|
||||||
input_rps_limit: 'Please enter a limit',
|
input_rps_limit: 'Please enter a limit',
|
||||||
|
|
|
@ -475,7 +475,8 @@ export default {
|
||||||
delete_file: "文件已存在,请先删除同名文件!",
|
delete_file: "文件已存在,请先删除同名文件!",
|
||||||
thread_num: '并发用户数:',
|
thread_num: '并发用户数:',
|
||||||
input_thread_num: '请输入线程数',
|
input_thread_num: '请输入线程数',
|
||||||
duration: '压测时长(秒):',
|
duration: '压测时长(秒)',
|
||||||
|
granularity: '聚合时间(秒)',
|
||||||
input_duration: '请输入时长',
|
input_duration: '请输入时长',
|
||||||
rps_limit: 'RPS上限:',
|
rps_limit: 'RPS上限:',
|
||||||
input_rps_limit: '请输入限制',
|
input_rps_limit: '请输入限制',
|
||||||
|
|
|
@ -475,7 +475,8 @@ export default {
|
||||||
delete_file: "文件已存在,請先刪除同名文件!",
|
delete_file: "文件已存在,請先刪除同名文件!",
|
||||||
thread_num: '並發用戶數:',
|
thread_num: '並發用戶數:',
|
||||||
input_thread_num: '請輸入線程數',
|
input_thread_num: '請輸入線程數',
|
||||||
duration: '壓測時長(秒):',
|
duration: '壓測時長(秒)',
|
||||||
|
granularity: '聚合時間(秒)',
|
||||||
input_duration: '請輸入時長',
|
input_duration: '請輸入時長',
|
||||||
rps_limit: 'RPS上限:',
|
rps_limit: 'RPS上限:',
|
||||||
input_rps_limit: '請輸入限制',
|
input_rps_limit: '請輸入限制',
|
||||||
|
|
Loading…
Reference in New Issue