Merge remote-tracking branch 'origin/v1.8' into v1.8
This commit is contained in:
commit
cc99108e28
|
@ -14,7 +14,8 @@ yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.idea
|
.idea/*
|
||||||
|
!.idea/icon.png
|
||||||
**/*.iml
|
**/*.iml
|
||||||
.vscode
|
.vscode
|
||||||
*.suo
|
*.suo
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 104 KiB |
|
@ -13,6 +13,9 @@ pipeline {
|
||||||
stage('Build/Test') {
|
stage('Build/Test') {
|
||||||
steps {
|
steps {
|
||||||
configFileProvider([configFile(fileId: 'metersphere-maven', targetLocation: 'settings.xml')]) {
|
configFileProvider([configFile(fileId: 'metersphere-maven', targetLocation: 'settings.xml')]) {
|
||||||
|
sh "cd frontend"
|
||||||
|
sh "yarn install"
|
||||||
|
sh "cd .."
|
||||||
sh "mvn clean package --settings ./settings.xml"
|
sh "mvn clean package --settings ./settings.xml"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,6 +283,13 @@
|
||||||
<version>2.0.22</version>
|
<version>2.0.22</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- ApacheJMeter_core scope 是 runtime,这里去掉scope -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.codehaus.groovy</groupId>
|
||||||
|
<artifactId>groovy-jsr223</artifactId>
|
||||||
|
<version>2.5.10</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 执行 js 代码依赖 -->
|
<!-- 执行 js 代码依赖 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.graalvm.sdk</groupId>
|
<groupId>org.graalvm.sdk</groupId>
|
||||||
|
|
|
@ -149,6 +149,14 @@ public class Swagger2Parser extends SwaggerAbstractParser {
|
||||||
return getBodyType(contentType);
|
return getBodyType(contentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getResponseBodyType(Operation operation) {
|
||||||
|
if (CollectionUtils.isEmpty(operation.getProduces())) {
|
||||||
|
return Body.JSON;
|
||||||
|
}
|
||||||
|
String contentType = operation.getProduces().get(0);
|
||||||
|
return getBodyType(contentType);
|
||||||
|
}
|
||||||
|
|
||||||
private void parsePathParameters(Parameter parameter, List<KeyValue> rests) {
|
private void parsePathParameters(Parameter parameter, List<KeyValue> rests) {
|
||||||
PathParameter pathParameter = (PathParameter) parameter;
|
PathParameter pathParameter = (PathParameter) parameter;
|
||||||
rests.add(new KeyValue(pathParameter.getName(), "", getDefaultStringValue(parameter.getDescription())));
|
rests.add(new KeyValue(pathParameter.getName(), "", getDefaultStringValue(parameter.getDescription())));
|
||||||
|
@ -175,14 +183,17 @@ public class Swagger2Parser extends SwaggerAbstractParser {
|
||||||
msResponse.getBody().setKvs(new ArrayList<>());
|
msResponse.getBody().setKvs(new ArrayList<>());
|
||||||
msResponse.setHeaders(new ArrayList<>());
|
msResponse.setHeaders(new ArrayList<>());
|
||||||
msResponse.setType(RequestType.HTTP);
|
msResponse.setType(RequestType.HTTP);
|
||||||
msResponse.getBody().setType(getBodyType(operation));
|
msResponse.getBody().setType(getResponseBodyType(operation));
|
||||||
// todo 状态码要调整?
|
// todo 状态码要调整?
|
||||||
msResponse.setStatusCode(new ArrayList<>());
|
msResponse.setStatusCode(new ArrayList<>());
|
||||||
if (responses != null) {
|
if (responses != null && responses.size() > 0) {
|
||||||
responses.forEach((responseCode, response) -> {
|
responses.forEach((responseCode, response) -> {
|
||||||
msResponse.getStatusCode().add(new KeyValue(responseCode, responseCode));
|
msResponse.getStatusCode().add(new KeyValue(responseCode, responseCode));
|
||||||
|
String body = parseSchema(response.getResponseSchema());
|
||||||
|
if (StringUtils.isNotBlank(body)) {
|
||||||
|
msResponse.getBody().setRaw(body);
|
||||||
|
}
|
||||||
parseResponseHeader(response, msResponse.getHeaders());
|
parseResponseHeader(response, msResponse.getHeaders());
|
||||||
parseResponseBodyParameters(response, msResponse.getBody());
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return msResponse;
|
return msResponse;
|
||||||
|
@ -197,10 +208,6 @@ public class Swagger2Parser extends SwaggerAbstractParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseResponseBodyParameters(Response response, Body body) {
|
|
||||||
body.setRaw(parseSchema(response.getResponseSchema()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseRequestBodyParameters(Parameter parameter, Body body) {
|
private void parseRequestBodyParameters(Parameter parameter, Body body) {
|
||||||
BodyParameter bodyParameter = (BodyParameter) parameter;
|
BodyParameter bodyParameter = (BodyParameter) parameter;
|
||||||
body.setRaw(parseSchema(bodyParameter.getSchema()));
|
body.setRaw(parseSchema(bodyParameter.getSchema()));
|
||||||
|
|
|
@ -26,12 +26,15 @@ import io.swagger.v3.oas.models.parameters.*;
|
||||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||||
import io.swagger.v3.oas.models.responses.ApiResponses;
|
import io.swagger.v3.oas.models.responses.ApiResponses;
|
||||||
import io.swagger.v3.parser.core.models.SwaggerParseResult;
|
import io.swagger.v3.parser.core.models.SwaggerParseResult;
|
||||||
|
import net.sf.saxon.ma.json.XMLToJsonFn;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.collections.MapUtils;
|
import org.apache.commons.collections.MapUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.fife.ui.rsyntaxtextarea.parser.XmlParser;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
@ -334,6 +337,16 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
||||||
} else if (schema instanceof BinarySchema) {
|
} else if (schema instanceof BinarySchema) {
|
||||||
return getDefaultValueByPropertyType(schema);
|
return getDefaultValueByPropertyType(schema);
|
||||||
} else {
|
} else {
|
||||||
|
if(schema.getType() != null) { // 特判属性不是对象的情况,直接将基本类型赋值进去
|
||||||
|
if(StringUtils.equals(schema.getType(), "string")) {
|
||||||
|
String example = (String) schema.getExample();
|
||||||
|
return example == null ? "" : example;
|
||||||
|
} else if(StringUtils.equals(schema.getType(), "boolean")) {
|
||||||
|
return schema.getExample();
|
||||||
|
} else if(StringUtils.equals(schema.getType(), "double")) {
|
||||||
|
return schema.getExample();
|
||||||
|
}
|
||||||
|
}
|
||||||
Object propertiesResult = parseSchemaProperties(schema, refSet, infoMap);
|
Object propertiesResult = parseSchemaProperties(schema, refSet, infoMap);
|
||||||
return propertiesResult == null ? getDefaultValueByPropertyType(schema) : propertiesResult;
|
return propertiesResult == null ? getDefaultValueByPropertyType(schema) : propertiesResult;
|
||||||
}
|
}
|
||||||
|
@ -432,7 +445,9 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
||||||
JSONObject requestBody = buildRequestBody(requestObject);
|
JSONObject requestBody = buildRequestBody(requestObject);
|
||||||
swaggerApiInfo.setRequestBody(requestBody);
|
swaggerApiInfo.setRequestBody(requestBody);
|
||||||
// 设置响应体
|
// 设置响应体
|
||||||
swaggerApiInfo.setResponses(new JSONObject());
|
// JSONObject reponseObject = JSON.parseObject(apiDefinition.getResponse());
|
||||||
|
// swaggerApiInfo.setResponses(buildResponseBody(reponseObject));
|
||||||
|
//.....
|
||||||
// 设置请求参数列表
|
// 设置请求参数列表
|
||||||
List<JSONObject> paramsList = buildParameters(requestObject);
|
List<JSONObject> paramsList = buildParameters(requestObject);
|
||||||
swaggerApiInfo.setParameters(paramsList);
|
swaggerApiInfo.setParameters(paramsList);
|
||||||
|
@ -459,6 +474,9 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
||||||
if(params != null) {
|
if(params != null) {
|
||||||
for(int i = 0; i < params.size(); ++i) {
|
for(int i = 0; i < params.size(); ++i) {
|
||||||
JSONObject param = params.getJSONObject(i); // 对于每个参数:
|
JSONObject param = params.getJSONObject(i); // 对于每个参数:
|
||||||
|
if(param.get("name") == null || StringUtils.isEmpty(((String) param.get("name")))) {
|
||||||
|
continue;
|
||||||
|
} // 否则无参数的情况,可能多出一行空行
|
||||||
SwaggerParams swaggerParam = new SwaggerParams();
|
SwaggerParams swaggerParam = new SwaggerParams();
|
||||||
swaggerParam.setIn(typeMap.get(type)); // 利用 map,根据 request 的 key 设置对应的参数类型
|
swaggerParam.setIn(typeMap.get(type)); // 利用 map,根据 request 的 key 设置对应的参数类型
|
||||||
swaggerParam.setDescription((String) param.get("description"));
|
swaggerParam.setDescription((String) param.get("description"));
|
||||||
|
@ -480,9 +498,20 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
||||||
put("Form Data", org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE);
|
put("Form Data", org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE);
|
||||||
put("WWW_FORM", org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE);
|
put("WWW_FORM", org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE);
|
||||||
}};
|
}};
|
||||||
|
JSONObject bodyInfo = new JSONObject();
|
||||||
|
if(request.getJSONObject("body") != null && request.getJSONObject("body").containsKey("raw")) {
|
||||||
|
String bodyType = request.getJSONObject("body").getString("type");
|
||||||
|
if(bodyType.equals("JSON")) {
|
||||||
|
bodyInfo = buildRequestBodyJsonInfo(request.getJSONObject("body").getJSONObject("raw"));
|
||||||
|
} else if(bodyType.equals("XML")) {
|
||||||
|
String xmlText = request.getJSONObject("body").getString("raw");
|
||||||
|
JSONObject xmlToJson = XMLUtils.XmlToJson(xmlText);
|
||||||
|
bodyInfo = buildRequestBodyJsonInfo(xmlToJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
String type = request.getJSONObject("body").getString("type");
|
String type = request.getJSONObject("body").getString("type");
|
||||||
JSONObject requestBody = new JSONObject();
|
JSONObject requestBody = new JSONObject();
|
||||||
JSONObject schema = new JSONObject();
|
JSONObject schema = bodyInfo; // 需要转换导出
|
||||||
JSONObject typeName = new JSONObject();
|
JSONObject typeName = new JSONObject();
|
||||||
schema.put("type", null);
|
schema.put("type", null);
|
||||||
schema.put("format", null);
|
schema.put("format", null);
|
||||||
|
@ -494,4 +523,55 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
||||||
requestBody.put("content", content);
|
requestBody.put("content", content);
|
||||||
return requestBody;
|
return requestBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将请求体中的一个 json 对象转换成 swagger 格式的 json 对象返回
|
||||||
|
private JSONObject buildRequestBodyJsonInfo(JSONObject requestBody) {
|
||||||
|
JSONObject schema = new JSONObject();
|
||||||
|
schema.put("type", "object");
|
||||||
|
JSONObject properties = buildSchema(requestBody);
|
||||||
|
schema.put("properties", properties);
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置一个 json 对象的属性在 swagger 格式中的类型、值
|
||||||
|
private JSONObject buildSchema(JSONObject requestBody) {
|
||||||
|
JSONObject schema = new JSONObject();
|
||||||
|
for(String key : requestBody.keySet()) {
|
||||||
|
Object param = requestBody.get(key);
|
||||||
|
JSONObject parsedParam = new JSONObject();
|
||||||
|
if(param instanceof java.lang.String) {
|
||||||
|
parsedParam.put("type", "string");
|
||||||
|
parsedParam.put("example", param == null? "" : param);
|
||||||
|
} else if(param instanceof java.lang.Integer) {
|
||||||
|
parsedParam.put("type", "integer");
|
||||||
|
parsedParam.put("format", "int64");
|
||||||
|
parsedParam.put("example", param);
|
||||||
|
} else if(param instanceof JSONObject) {
|
||||||
|
parsedParam = buildRequestBodyJsonInfo((JSONObject) param);
|
||||||
|
} else if(param instanceof java.lang.Boolean) {
|
||||||
|
parsedParam.put("type", "boolean");
|
||||||
|
parsedParam.put("example", param);
|
||||||
|
} else if(param instanceof java.math.BigDecimal) { // double 类型会被 fastJson 转换为 BigDecimal
|
||||||
|
parsedParam.put("type", "double");
|
||||||
|
parsedParam.put("example", param);
|
||||||
|
} else { // JSONOArray
|
||||||
|
parsedParam.put("type", "array");
|
||||||
|
JSONObject item = new JSONObject();
|
||||||
|
if(((JSONArray) param).size() > 0) {
|
||||||
|
if(((JSONArray) param).get(0) instanceof JSONObject) { ///
|
||||||
|
item = buildRequestBodyJsonInfo((JSONObject) ((JSONArray) param).get(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parsedParam.put("items", item);
|
||||||
|
}
|
||||||
|
schema.put(key, parsedParam);
|
||||||
|
}
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JSONObject buildResponseBody(JSONObject reponse) {
|
||||||
|
JSONObject responseBody = new JSONObject();
|
||||||
|
|
||||||
|
return responseBody;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,7 @@ public class MsHTTPSamplerProxy extends MsTestElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.8 之前历史数据
|
// 1.8 之前历史数据
|
||||||
if(StringUtils.isEmpty(this.getProjectId()) && config.getConfig()!= null && !config.getConfig().isEmpty()){
|
if (StringUtils.isEmpty(this.getProjectId()) && config.getConfig() != null && !config.getConfig().isEmpty()) {
|
||||||
this.setProjectId("historyProjectID");
|
this.setProjectId("historyProjectID");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,10 +154,11 @@ public class MsHTTPSamplerProxy extends MsTestElement {
|
||||||
}
|
}
|
||||||
URL urlObject = new URL(url);
|
URL urlObject = new URL(url);
|
||||||
sampler.setDomain(URLDecoder.decode(urlObject.getHost(), "UTF-8"));
|
sampler.setDomain(URLDecoder.decode(urlObject.getHost(), "UTF-8"));
|
||||||
if (urlObject.getPort() > 0 && urlObject.getPort() != 10990 && StringUtils.isNotEmpty(this.getPort()) && this.getPort().startsWith("${")) {
|
|
||||||
sampler.setPort(urlObject.getPort());
|
if (urlObject.getPort() > 0 && urlObject.getPort() == 10990 && StringUtils.isNotEmpty(this.getPort()) && this.getPort().startsWith("${")) {
|
||||||
} else {
|
|
||||||
sampler.setProperty("HTTPSampler.port", this.getPort());
|
sampler.setProperty("HTTPSampler.port", this.getPort());
|
||||||
|
} else {
|
||||||
|
sampler.setPort(urlObject.getPort());
|
||||||
}
|
}
|
||||||
sampler.setProtocol(urlObject.getProtocol());
|
sampler.setProtocol(urlObject.getProtocol());
|
||||||
sampler.setPath(urlObject.getPath());
|
sampler.setPath(urlObject.getPath());
|
||||||
|
|
|
@ -21,10 +21,7 @@ import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
||||||
import io.metersphere.api.jmeter.JMeterService;
|
import io.metersphere.api.jmeter.JMeterService;
|
||||||
import io.metersphere.api.parse.ApiImportParser;
|
import io.metersphere.api.parse.ApiImportParser;
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
import io.metersphere.base.mapper.ApiScenarioMapper;
|
import io.metersphere.base.mapper.*;
|
||||||
import io.metersphere.base.mapper.ApiScenarioReportMapper;
|
|
||||||
import io.metersphere.base.mapper.TestCaseReviewScenarioMapper;
|
|
||||||
import io.metersphere.base.mapper.TestPlanApiScenarioMapper;
|
|
||||||
import io.metersphere.base.mapper.ext.*;
|
import io.metersphere.base.mapper.ext.*;
|
||||||
import io.metersphere.commons.constants.*;
|
import io.metersphere.commons.constants.*;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
|
@ -61,6 +58,8 @@ import java.util.stream.Collectors;
|
||||||
@Service
|
@Service
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public class ApiAutomationService {
|
public class ApiAutomationService {
|
||||||
|
@Resource
|
||||||
|
ApiScenarioModuleMapper apiScenarioModuleMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private ExtScheduleMapper extScheduleMapper;
|
private ExtScheduleMapper extScheduleMapper;
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -242,9 +241,14 @@ public class ApiAutomationService {
|
||||||
} else {
|
} else {
|
||||||
scenario.setUserId(request.getUserId());
|
scenario.setUserId(request.getUserId());
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(request.getApiScenarioModuleId())) {
|
if (StringUtils.isEmpty(request.getApiScenarioModuleId()) || StringUtils.isEmpty(request.getModulePath()) || "default-module".equals(request.getApiScenarioModuleId())) {
|
||||||
scenario.setApiScenarioModuleId("root");
|
ApiScenarioModuleExample example = new ApiScenarioModuleExample();
|
||||||
scenario.setModulePath("/默认模块");
|
example.createCriteria().andProjectIdEqualTo(request.getProjectId()).andNameEqualTo("默认模块");
|
||||||
|
List<ApiScenarioModule> modules = apiScenarioModuleMapper.selectByExample(example);
|
||||||
|
if (CollectionUtils.isNotEmpty(modules)) {
|
||||||
|
scenario.setApiScenarioModuleId(modules.get(0).getId());
|
||||||
|
scenario.setModulePath(modules.get(0).getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return scenario;
|
return scenario;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,8 @@ public class ApiDefinitionService {
|
||||||
private ApiTestEnvironmentService environmentService;
|
private ApiTestEnvironmentService environmentService;
|
||||||
@Resource
|
@Resource
|
||||||
private EsbApiParamService esbApiParamService;
|
private EsbApiParamService esbApiParamService;
|
||||||
|
@Resource
|
||||||
|
ApiModuleMapper apiModuleMapper;
|
||||||
|
|
||||||
private static Cache cache = Cache.newHardMemoryCache(0, 3600 * 24);
|
private static Cache cache = Cache.newHardMemoryCache(0, 3600 * 24);
|
||||||
|
|
||||||
|
@ -262,9 +264,14 @@ public class ApiDefinitionService {
|
||||||
test.setEnvironmentId(request.getEnvironmentId());
|
test.setEnvironmentId(request.getEnvironmentId());
|
||||||
test.setUserId(request.getUserId());
|
test.setUserId(request.getUserId());
|
||||||
test.setTags(request.getTags());
|
test.setTags(request.getTags());
|
||||||
if (StringUtils.isEmpty(request.getModuleId())) {
|
if (StringUtils.isEmpty(request.getModulePath()) || StringUtils.isEmpty(request.getModuleId()) || "default-module".equals(request.getModuleId())) {
|
||||||
test.setModulePath("/默认模块");
|
ApiModuleExample example = new ApiModuleExample();
|
||||||
test.setModuleId("root");
|
example.createCriteria().andProjectIdEqualTo(test.getProjectId()).andProtocolEqualTo(test.getProtocol()).andNameEqualTo("默认模块");
|
||||||
|
List<ApiModule> modules = apiModuleMapper.selectByExample(example);
|
||||||
|
if (CollectionUtils.isNotEmpty(modules)) {
|
||||||
|
test.setModuleId(modules.get(0).getId());
|
||||||
|
test.setModulePath(modules.get(0).getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
apiDefinitionMapper.updateByPrimaryKeySelective(test);
|
apiDefinitionMapper.updateByPrimaryKeySelective(test);
|
||||||
return test;
|
return test;
|
||||||
|
@ -290,9 +297,14 @@ public class ApiDefinitionService {
|
||||||
test.setStatus(APITestStatus.Underway.name());
|
test.setStatus(APITestStatus.Underway.name());
|
||||||
test.setModulePath(request.getModulePath());
|
test.setModulePath(request.getModulePath());
|
||||||
test.setModuleId(request.getModuleId());
|
test.setModuleId(request.getModuleId());
|
||||||
if (StringUtils.isEmpty(request.getModuleId())) {
|
if (StringUtils.isEmpty(request.getModulePath()) || StringUtils.isEmpty(request.getModuleId()) || "default-module".equals(request.getModuleId())) {
|
||||||
test.setModulePath("/默认模块");
|
ApiModuleExample example = new ApiModuleExample();
|
||||||
test.setModuleId("root");
|
example.createCriteria().andProjectIdEqualTo(test.getProjectId()).andProtocolEqualTo(test.getProtocol()).andNameEqualTo("默认模块");
|
||||||
|
List<ApiModule> modules = apiModuleMapper.selectByExample(example);
|
||||||
|
if (CollectionUtils.isNotEmpty(modules)) {
|
||||||
|
test.setModuleId(modules.get(0).getId());
|
||||||
|
test.setModulePath("/默认模块");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
test.setResponse(JSONObject.toJSONString(request.getResponse()));
|
test.setResponse(JSONObject.toJSONString(request.getResponse()));
|
||||||
test.setEnvironmentId(request.getEnvironmentId());
|
test.setEnvironmentId(request.getEnvironmentId());
|
||||||
|
@ -604,9 +616,14 @@ public class ApiDefinitionService {
|
||||||
}
|
}
|
||||||
for (int i = 0; i < data.size(); i++) {
|
for (int i = 0; i < data.size(); i++) {
|
||||||
ApiDefinitionWithBLOBs item = data.get(i);
|
ApiDefinitionWithBLOBs item = data.get(i);
|
||||||
if (StringUtils.isEmpty(item.getModuleId())) {
|
if (StringUtils.isEmpty(item.getModuleId()) || StringUtils.isEmpty(item.getModulePath()) || "default-module".equals(item.getModuleId())) {
|
||||||
item.setModuleId("root");
|
ApiModuleExample example = new ApiModuleExample();
|
||||||
item.setModulePath("/默认模块");
|
example.createCriteria().andProjectIdEqualTo(item.getProjectId()).andProtocolEqualTo(item.getProtocol()).andNameEqualTo("默认模块");
|
||||||
|
List<ApiModule> modules = apiModuleMapper.selectByExample(example);
|
||||||
|
if (CollectionUtils.isNotEmpty(modules)) {
|
||||||
|
item.setModuleId(modules.get(0).getId());
|
||||||
|
item.setModulePath(modules.get(0).getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (item.getName().length() > 255) {
|
if (item.getName().length() > 255) {
|
||||||
item.setName(item.getName().substring(0, 255));
|
item.setName(item.getName().substring(0, 255));
|
||||||
|
|
|
@ -39,8 +39,6 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
|
||||||
@Resource
|
@Resource
|
||||||
ExtApiModuleMapper extApiModuleMapper;
|
ExtApiModuleMapper extApiModuleMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private ApiDefinitionMapper apiDefinitionMapper;
|
|
||||||
@Resource
|
|
||||||
private ExtApiDefinitionMapper extApiDefinitionMapper;
|
private ExtApiDefinitionMapper extApiDefinitionMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private TestPlanProjectService testPlanProjectService;
|
private TestPlanProjectService testPlanProjectService;
|
||||||
|
@ -61,6 +59,22 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ApiModuleDTO> getNodeTreeByProjectId(String projectId, String protocol) {
|
public List<ApiModuleDTO> getNodeTreeByProjectId(String projectId, String protocol) {
|
||||||
|
// 判断当前项目下是否有默认模块,没有添加默认模块
|
||||||
|
ApiModuleExample example = new ApiModuleExample();
|
||||||
|
example.createCriteria().andProjectIdEqualTo(projectId).andProtocolEqualTo(protocol).andNameEqualTo("默认模块");
|
||||||
|
long count = apiModuleMapper.countByExample(example);
|
||||||
|
if (count <= 0) {
|
||||||
|
ApiModule record = new ApiModule();
|
||||||
|
record.setId(UUID.randomUUID().toString());
|
||||||
|
record.setName("默认模块");
|
||||||
|
record.setProtocol(protocol);
|
||||||
|
record.setPos(1.0);
|
||||||
|
record.setLevel(1);
|
||||||
|
record.setCreateTime(System.currentTimeMillis());
|
||||||
|
record.setUpdateTime(System.currentTimeMillis());
|
||||||
|
record.setProjectId(projectId);
|
||||||
|
apiModuleMapper.insert(record);
|
||||||
|
}
|
||||||
List<ApiModuleDTO> apiModules = extApiModuleMapper.getNodeTreeByProjectId(projectId, protocol);
|
List<ApiModuleDTO> apiModules = extApiModuleMapper.getNodeTreeByProjectId(projectId, protocol);
|
||||||
return getNodeTrees(apiModules);
|
return getNodeTrees(apiModules);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,22 @@ public class ApiScenarioModuleService extends NodeTreeService<ApiScenarioModuleD
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ApiScenarioModuleDTO> getNodeTreeByProjectId(String projectId) {
|
public List<ApiScenarioModuleDTO> getNodeTreeByProjectId(String projectId) {
|
||||||
|
// 判断当前项目下是否有默认模块,没有添加默认模块
|
||||||
|
ApiScenarioModuleExample example = new ApiScenarioModuleExample();
|
||||||
|
example.createCriteria().andProjectIdEqualTo(projectId).andNameEqualTo("默认模块");
|
||||||
|
long count = apiScenarioModuleMapper.countByExample(example);
|
||||||
|
if (count <= 0) {
|
||||||
|
ApiScenarioModule record = new ApiScenarioModule();
|
||||||
|
record.setId(UUID.randomUUID().toString());
|
||||||
|
record.setName("默认模块");
|
||||||
|
record.setPos(1.0);
|
||||||
|
record.setLevel(1);
|
||||||
|
record.setCreateTime(System.currentTimeMillis());
|
||||||
|
record.setUpdateTime(System.currentTimeMillis());
|
||||||
|
record.setProjectId(projectId);
|
||||||
|
apiScenarioModuleMapper.insert(record);
|
||||||
|
}
|
||||||
|
|
||||||
List<ApiScenarioModuleDTO> nodes = extApiScenarioModuleMapper.getNodeTreeByProjectId(projectId);
|
List<ApiScenarioModuleDTO> nodes = extApiScenarioModuleMapper.getNodeTreeByProjectId(projectId);
|
||||||
return getNodeTrees(nodes);
|
return getNodeTrees(nodes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,46 +2,140 @@ package io.metersphere.commons.utils;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import io.metersphere.commons.exception.MSException;
|
||||||
|
import io.metersphere.i18n.Translator;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
import java.util.Set;
|
import java.util.regex.*;
|
||||||
|
|
||||||
public class XMLUtils {
|
public class XMLUtils {
|
||||||
|
|
||||||
private static void jsonToXmlStr(JSONObject jObj, StringBuffer buffer) {
|
private static void jsonToXmlStr(JSONObject jObj, StringBuffer buffer, StringBuffer tab) {
|
||||||
Set<Map.Entry<String, Object>> se = jObj.entrySet();
|
Set<Map.Entry<String, Object>> se = jObj.entrySet();
|
||||||
|
StringBuffer nowTab = new StringBuffer(tab.toString());
|
||||||
for (Map.Entry<String, Object> en : se) {
|
for (Map.Entry<String, Object> en : se) {
|
||||||
if ("com.alibaba.fastjson.JSONObject".equals(en.getValue().getClass().getName())) {
|
if ("com.alibaba.fastjson.JSONObject".equals(en.getValue().getClass().getName())) {
|
||||||
buffer.append("<").append(en.getKey()).append(">");
|
buffer.append(tab).append("<").append(en.getKey()).append(">\n");
|
||||||
JSONObject jo = jObj.getJSONObject(en.getKey());
|
JSONObject jo = jObj.getJSONObject(en.getKey());
|
||||||
jsonToXmlStr(jo, buffer);
|
jsonToXmlStr(jo, buffer, nowTab.append("\t"));
|
||||||
buffer.append("</").append(en.getKey()).append(">");
|
buffer.append(tab).append("</").append(en.getKey()).append(">\n");
|
||||||
} else if ("com.alibaba.fastjson.JSONArray".equals(en.getValue().getClass().getName())) {
|
} else if ("com.alibaba.fastjson.JSONArray".equals(en.getValue().getClass().getName())) {
|
||||||
JSONArray jarray = jObj.getJSONArray(en.getKey());
|
JSONArray jarray = jObj.getJSONArray(en.getKey());
|
||||||
for (int i = 0; i < jarray.size(); i++) {
|
for (int i = 0; i < jarray.size(); i++) {
|
||||||
buffer.append("<").append(en.getKey()).append(">");
|
buffer.append(tab).append("<").append(en.getKey()).append(">\n");
|
||||||
if (StringUtils.isNotBlank(jarray.getString(i))) {
|
if (StringUtils.isNotBlank(jarray.getString(i))) {
|
||||||
JSONObject jsonobject = jarray.getJSONObject(i);
|
JSONObject jsonobject = jarray.getJSONObject(i);
|
||||||
jsonToXmlStr(jsonobject, buffer);
|
jsonToXmlStr(jsonobject, buffer, nowTab.append("\t"));
|
||||||
buffer.append("</").append(en.getKey()).append(">");
|
buffer.append(tab).append("</").append(en.getKey()).append(">\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ("java.lang.String".equals(en.getValue().getClass().getName())) {
|
} else if ("java.lang.String".equals(en.getValue().getClass().getName())) {
|
||||||
buffer.append("<").append(en.getKey()).append(">").append(en.getValue());
|
buffer.append(tab).append("<").append(en.getKey()).append(">").append(en.getValue());
|
||||||
buffer.append("</").append(en.getKey()).append(">");
|
buffer.append("</").append(en.getKey()).append(">\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String jsonToXmlStr(JSONObject jObj) {
|
public static String jsonToXmlStr(JSONObject jObj) {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer buffer = new StringBuffer();
|
||||||
buffer.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
|
buffer.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
|
||||||
try {
|
try {
|
||||||
jsonToXmlStr(jObj, buffer);
|
jsonToXmlStr(jObj, buffer, new StringBuffer(""));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtil.error(e.getMessage(), e);
|
LogUtil.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 传入完整的 xml 文本,转换成 json 对象
|
||||||
|
public static JSONObject XmlToJson(String xml) {
|
||||||
|
JSONObject result = new JSONObject();
|
||||||
|
List<String> list = preProcessXml(xml);
|
||||||
|
try {
|
||||||
|
result = (JSONObject) XmlTagToJsonObject(list);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.error(e.getMessage(), e);
|
||||||
|
MSException.throwException(Translator.get("illegal_xml_format"));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预处理 xml 文本,转换成 tag + data 的列表
|
||||||
|
private static List<String> preProcessXml(String xml) {
|
||||||
|
int begin = xml.indexOf("?>");
|
||||||
|
if(begin != -1) {
|
||||||
|
if(begin + 2 >= xml.length()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
xml = xml.substring(begin + 2);
|
||||||
|
} // <?xml version="1.0" encoding="utf-8"?> 若存在,则去除
|
||||||
|
String rgex = "\\s*";
|
||||||
|
Pattern pattern = Pattern.compile(rgex);
|
||||||
|
Matcher m = pattern.matcher(xml);
|
||||||
|
xml = m.replaceAll("");
|
||||||
|
rgex = ">";
|
||||||
|
pattern = Pattern.compile(rgex);
|
||||||
|
m = pattern.matcher(xml);
|
||||||
|
xml = m.replaceAll("> ");
|
||||||
|
rgex = "\\s*</";
|
||||||
|
pattern = Pattern.compile(rgex);
|
||||||
|
m = pattern.matcher(xml);
|
||||||
|
xml = m.replaceAll(" </");
|
||||||
|
return Arrays.asList(xml.split(" "));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 传入预处理的列表,返回转换成功的 json 对象
|
||||||
|
private static Object XmlTagToJsonObject(List<String> list) {
|
||||||
|
if(list == null || list.size() == 0)
|
||||||
|
return null;
|
||||||
|
Stack<String> tagStack = new Stack<>(); // tag 栈
|
||||||
|
Stack<Object> valueStack = new Stack<>(); // 数据栈
|
||||||
|
valueStack.push(new JSONObject()); // 最终结果将存放在第一个入栈的元素中
|
||||||
|
for(String item : list) {
|
||||||
|
String beginTag = isBeginTag(item), endTag = isEndTag(item); // 判断当前 tag 是开始还是结尾
|
||||||
|
if(beginTag != null) {
|
||||||
|
tagStack.push(beginTag);
|
||||||
|
valueStack.push(new JSONObject());
|
||||||
|
} else if(endTag != null) {
|
||||||
|
if(endTag.equals(tagStack.peek())) { // 是一对 tag
|
||||||
|
Object topValue = valueStack.peek();
|
||||||
|
if(topValue instanceof String) { // 栈顶是纯数据 xml 节点
|
||||||
|
valueStack.pop();
|
||||||
|
}
|
||||||
|
valueStack.pop();
|
||||||
|
if(valueStack.peek() instanceof JSONObject) {
|
||||||
|
((JSONObject) valueStack.peek()).put(tagStack.peek(), topValue);
|
||||||
|
}
|
||||||
|
tagStack.pop();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
valueStack.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(valueStack.empty())
|
||||||
|
return null;
|
||||||
|
return valueStack.peek();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String isEndTag(String tagLine) {
|
||||||
|
String rgex = "</(\\w*)>";
|
||||||
|
Pattern pattern = Pattern.compile(rgex);// 匹配的模式
|
||||||
|
Matcher m = pattern.matcher(tagLine);
|
||||||
|
if (m.find()) {
|
||||||
|
return m.group(1);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String isBeginTag(String tagLine) {
|
||||||
|
String rgex = "<(\\w*)>";
|
||||||
|
Pattern pattern = Pattern.compile(rgex);// 匹配的模式
|
||||||
|
Matcher m = pattern.matcher(tagLine);
|
||||||
|
if (m.find()) {
|
||||||
|
return m.group(1);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -701,9 +701,11 @@ public class JmeterDocumentParser implements DocumentParser {
|
||||||
switch (unit) {
|
switch (unit) {
|
||||||
case "M":
|
case "M":
|
||||||
duration = String.valueOf(Long.parseLong(duration) * 60);
|
duration = String.valueOf(Long.parseLong(duration) * 60);
|
||||||
|
rampUp = String.valueOf(Long.parseLong(rampUp) * 60);
|
||||||
break;
|
break;
|
||||||
case "H":
|
case "H":
|
||||||
duration = String.valueOf(Long.parseLong(duration) * 60 * 60);
|
duration = String.valueOf(Long.parseLong(duration) * 60 * 60);
|
||||||
|
rampUp = String.valueOf(Long.parseLong(rampUp) * 60 * 60);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -804,9 +806,11 @@ public class JmeterDocumentParser implements DocumentParser {
|
||||||
switch (unit) {
|
switch (unit) {
|
||||||
case "M":
|
case "M":
|
||||||
hold = String.valueOf(Long.parseLong(hold) * 60);
|
hold = String.valueOf(Long.parseLong(hold) * 60);
|
||||||
|
rampUp = String.valueOf(Long.parseLong(rampUp) * 60);
|
||||||
break;
|
break;
|
||||||
case "H":
|
case "H":
|
||||||
hold = String.valueOf(Long.parseLong(hold) * 60 * 60);
|
hold = String.valueOf(Long.parseLong(hold) * 60 * 60);
|
||||||
|
rampUp = String.valueOf(Long.parseLong(rampUp) * 60 * 60);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -107,6 +107,21 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TestCaseNodeDTO> getNodeTreeByProjectId(String projectId) {
|
public List<TestCaseNodeDTO> getNodeTreeByProjectId(String projectId) {
|
||||||
|
// 判断当前项目下是否有默认模块,没有添加默认模块
|
||||||
|
TestCaseNodeExample example = new TestCaseNodeExample();
|
||||||
|
example.createCriteria().andProjectIdEqualTo(projectId).andNameEqualTo("默认模块");
|
||||||
|
long count = testCaseNodeMapper.countByExample(example);
|
||||||
|
if (count <= 0) {
|
||||||
|
TestCaseNode record = new TestCaseNode();
|
||||||
|
record.setId(UUID.randomUUID().toString());
|
||||||
|
record.setName("默认模块");
|
||||||
|
record.setPos(1.0);
|
||||||
|
record.setLevel(1);
|
||||||
|
record.setCreateTime(System.currentTimeMillis());
|
||||||
|
record.setUpdateTime(System.currentTimeMillis());
|
||||||
|
record.setProjectId(projectId);
|
||||||
|
testCaseNodeMapper.insert(record);
|
||||||
|
}
|
||||||
List<TestCaseNodeDTO> testCaseNodes = extTestCaseNodeMapper.getNodeTreeByProjectId(projectId);
|
List<TestCaseNodeDTO> testCaseNodes = extTestCaseNodeMapper.getNodeTreeByProjectId(projectId);
|
||||||
return getNodeTrees(testCaseNodes);
|
return getNodeTrees(testCaseNodes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,8 @@ import java.util.stream.Collectors;
|
||||||
@Service
|
@Service
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public class TestCaseService {
|
public class TestCaseService {
|
||||||
|
@Resource
|
||||||
|
TestCaseNodeMapper testCaseNodeMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
TestCaseMapper testCaseMapper;
|
TestCaseMapper testCaseMapper;
|
||||||
|
@ -90,6 +92,18 @@ public class TestCaseService {
|
||||||
@Resource
|
@Resource
|
||||||
TestCaseTestMapper testCaseTestMapper;
|
TestCaseTestMapper testCaseTestMapper;
|
||||||
|
|
||||||
|
private void setNode(TestCaseWithBLOBs testCase){
|
||||||
|
if (StringUtils.isEmpty(testCase.getNodeId()) || StringUtils.isEmpty(testCase.getNodePath()) || "default-module".equals(testCase.getNodeId())) {
|
||||||
|
TestCaseNodeExample example = new TestCaseNodeExample();
|
||||||
|
example.createCriteria().andProjectIdEqualTo(testCase.getProjectId()).andNameEqualTo("默认模块");
|
||||||
|
List<TestCaseNode> nodes = testCaseNodeMapper.selectByExample(example);
|
||||||
|
if (CollectionUtils.isNotEmpty(nodes)) {
|
||||||
|
testCase.setNodeId(nodes.get(0).getId());
|
||||||
|
testCase.setNodePath("/" + nodes.get(0).getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public TestCaseWithBLOBs addTestCase(TestCaseWithBLOBs testCase) {
|
public TestCaseWithBLOBs addTestCase(TestCaseWithBLOBs testCase) {
|
||||||
testCase.setName(testCase.getName());
|
testCase.setName(testCase.getName());
|
||||||
checkTestCaseExist(testCase);
|
checkTestCaseExist(testCase);
|
||||||
|
@ -100,7 +114,7 @@ public class TestCaseService {
|
||||||
testCase.setReviewStatus(TestCaseReviewStatus.Prepare.name());
|
testCase.setReviewStatus(TestCaseReviewStatus.Prepare.name());
|
||||||
testCase.setDemandId(testCase.getDemandId());
|
testCase.setDemandId(testCase.getDemandId());
|
||||||
testCase.setDemandName(testCase.getDemandName());
|
testCase.setDemandName(testCase.getDemandName());
|
||||||
|
this.setNode(testCase);
|
||||||
testCaseMapper.insert(testCase);
|
testCaseMapper.insert(testCase);
|
||||||
return testCase;
|
return testCase;
|
||||||
}
|
}
|
||||||
|
@ -179,7 +193,7 @@ public class TestCaseService {
|
||||||
String steps = tc.getSteps();
|
String steps = tc.getSteps();
|
||||||
String remark = tc.getRemark();
|
String remark = tc.getRemark();
|
||||||
if (StringUtils.equals(steps, testCase.getSteps()) && StringUtils.equals(remark, caseRemark)) {
|
if (StringUtils.equals(steps, testCase.getSteps()) && StringUtils.equals(remark, caseRemark)) {
|
||||||
//MSException.throwException(Translator.get("test_case_already_exists"));
|
//MSException.throwException(Translator.get("test_case_already_exists"));
|
||||||
isExt = true;
|
isExt = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,16 +209,16 @@ public class TestCaseService {
|
||||||
* 根据id和pojectId查询id是否在数据库中存在。
|
* 根据id和pojectId查询id是否在数据库中存在。
|
||||||
* 在数据库中单id的话是可重复的,id与projectId的组合是唯一的
|
* 在数据库中单id的话是可重复的,id与projectId的组合是唯一的
|
||||||
*/
|
*/
|
||||||
public Integer checkIdExist(Integer id, String projectId){
|
public Integer checkIdExist(Integer id, String projectId) {
|
||||||
TestCaseExample example = new TestCaseExample();
|
TestCaseExample example = new TestCaseExample();
|
||||||
TestCaseExample.Criteria criteria = example.createCriteria();
|
TestCaseExample.Criteria criteria = example.createCriteria();
|
||||||
if (null != id) {
|
if (null != id) {
|
||||||
criteria.andNumEqualTo(id);
|
criteria.andNumEqualTo(id);
|
||||||
criteria.andProjectIdEqualTo(projectId);
|
criteria.andProjectIdEqualTo(projectId);
|
||||||
long count = testCaseMapper.countByExample(example); //查询是否有包含此ID的数据
|
long count = testCaseMapper.countByExample(example); //查询是否有包含此ID的数据
|
||||||
if(count == 0){ //如果ID不存在
|
if (count == 0) { //如果ID不存在
|
||||||
return null;
|
return null;
|
||||||
}else { //有对应ID的数据
|
} else { //有对应ID的数据
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -415,7 +429,7 @@ public class TestCaseService {
|
||||||
testcase.setSort(sort.getAndIncrement());
|
testcase.setSort(sort.getAndIncrement());
|
||||||
testcase.setNum(num.decrementAndGet());
|
testcase.setNum(num.decrementAndGet());
|
||||||
testcase.setReviewStatus(TestCaseReviewStatus.Prepare.name());
|
testcase.setReviewStatus(TestCaseReviewStatus.Prepare.name());
|
||||||
mapper.insert(testcase);
|
mapper.insert(testcase);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
sqlSession.flushStatements();
|
sqlSession.flushStatements();
|
||||||
|
@ -443,6 +457,7 @@ public class TestCaseService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 把Excel中带ID的数据更新到数据库
|
* 把Excel中带ID的数据更新到数据库
|
||||||
|
*
|
||||||
* @param testCases
|
* @param testCases
|
||||||
* @param projectId
|
* @param projectId
|
||||||
*/
|
*/
|
||||||
|
@ -820,14 +835,14 @@ public class TestCaseService {
|
||||||
|
|
||||||
if (files != null) {
|
if (files != null) {
|
||||||
files.forEach(file -> {
|
files.forEach(file -> {
|
||||||
final FileMetadata fileMetadata = fileService.saveFile(file,testCaseWithBLOBs.getProjectId());
|
final FileMetadata fileMetadata = fileService.saveFile(file, testCaseWithBLOBs.getProjectId());
|
||||||
TestCaseFile testCaseFile = new TestCaseFile();
|
TestCaseFile testCaseFile = new TestCaseFile();
|
||||||
testCaseFile.setFileId(fileMetadata.getId());
|
testCaseFile.setFileId(fileMetadata.getId());
|
||||||
testCaseFile.setCaseId(request.getId());
|
testCaseFile.setCaseId(request.getId());
|
||||||
testCaseFileMapper.insert(testCaseFile);
|
testCaseFileMapper.insert(testCaseFile);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
this.setNode(request);
|
||||||
editTestCase(request);
|
editTestCase(request);
|
||||||
return request.getId();
|
return request.getId();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
@ -34,6 +35,10 @@ import javax.script.ScriptEngine;
|
||||||
import javax.script.ScriptEngineManager;
|
import javax.script.ScriptEngineManager;
|
||||||
import javax.script.ScriptException;
|
import javax.script.ScriptException;
|
||||||
|
|
||||||
|
import io.metersphere.base.domain.JarConfig;
|
||||||
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
|
import io.metersphere.service.JarConfigService;
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.apache.commons.collections.map.LRUMap;
|
import org.apache.commons.collections.map.LRUMap;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -45,9 +50,11 @@ import org.apache.jmeter.threads.JMeterContext;
|
||||||
import org.apache.jmeter.threads.JMeterContextService;
|
import org.apache.jmeter.threads.JMeterContextService;
|
||||||
import org.apache.jmeter.threads.JMeterVariables;
|
import org.apache.jmeter.threads.JMeterVariables;
|
||||||
import org.apache.jorphan.util.JOrphanUtils;
|
import org.apache.jorphan.util.JOrphanUtils;
|
||||||
|
import org.codehaus.groovy.jsr223.GroovyScriptEngineImpl;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for JSR223 Test elements
|
* Base class for JSR223 Test elements
|
||||||
*
|
*
|
||||||
|
@ -166,6 +173,9 @@ public abstract class JSR223TestElement extends ScriptingTestElement
|
||||||
*/
|
*/
|
||||||
protected Object processFileOrScript(ScriptEngine scriptEngine, final Bindings pBindings)
|
protected Object processFileOrScript(ScriptEngine scriptEngine, final Bindings pBindings)
|
||||||
throws IOException, ScriptException {
|
throws IOException, ScriptException {
|
||||||
|
|
||||||
|
this.loadGroovyJar(scriptEngine);
|
||||||
|
|
||||||
Bindings bindings = pBindings;
|
Bindings bindings = pBindings;
|
||||||
if (bindings == null) {
|
if (bindings == null) {
|
||||||
bindings = scriptEngine.createBindings();
|
bindings = scriptEngine.createBindings();
|
||||||
|
@ -250,6 +260,37 @@ public abstract class JSR223TestElement extends ScriptingTestElement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* groovy 使用的是自己的类加载器,
|
||||||
|
* 这里再执行脚本前,使用 groovy的加载器加载jar包,
|
||||||
|
* 解决groovy脚本无法使用jar包的问题
|
||||||
|
* @Auth jianxing
|
||||||
|
* @param scriptEngine
|
||||||
|
*/
|
||||||
|
public static void loadGroovyJar(ScriptEngine scriptEngine) {
|
||||||
|
if (scriptEngine instanceof GroovyScriptEngineImpl) {
|
||||||
|
GroovyScriptEngineImpl groovyScriptEngine = (GroovyScriptEngineImpl) scriptEngine;
|
||||||
|
|
||||||
|
JarConfigService jarConfigService = CommonBeanFactory.getBean(JarConfigService.class);
|
||||||
|
List<JarConfig> jars = jarConfigService.list();
|
||||||
|
|
||||||
|
jars.forEach(jarConfig -> {
|
||||||
|
try {
|
||||||
|
String path = jarConfig.getPath();
|
||||||
|
File file = new File(path);
|
||||||
|
if (file.isDirectory() && !path.endsWith("/")) {
|
||||||
|
file = new File(path + "/");
|
||||||
|
}
|
||||||
|
groovyScriptEngine.getClassLoader().addURL(file.toURI().toURL());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
LogUtil.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return boolean true if element is not compilable or if compilation succeeds
|
* @return boolean true if element is not compilable or if compilation succeeds
|
||||||
* @throws IOException if script is missing
|
* @throws IOException if script is missing
|
||||||
|
@ -351,4 +392,4 @@ public abstract class JSR223TestElement extends ScriptingTestElement
|
||||||
public void setScriptLanguage(String s) {
|
public void setScriptLanguage(String s) {
|
||||||
scriptLanguage = s;
|
scriptLanguage = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
-- file name length change
|
||||||
|
ALTER TABLE file_metadata
|
||||||
|
MODIFY name VARCHAR(250) NOT NULL COMMENT 'File name';
|
||||||
|
-- api_scenario_report modify column length
|
||||||
|
ALTER TABLE api_scenario_report MODIFY COLUMN name VARCHAR(300);
|
|
@ -75,6 +75,7 @@ organization_does_not_belong_to_user=The current organization does not belong to
|
||||||
organization_id_is_null=Organization ID cannot be null
|
organization_id_is_null=Organization ID cannot be null
|
||||||
#api
|
#api
|
||||||
api_load_script_error=Load script error
|
api_load_script_error=Load script error
|
||||||
|
illegal_xml_format=illegal XML format
|
||||||
api_report_is_null="Report is null, can't update"
|
api_report_is_null="Report is null, can't update"
|
||||||
api_test_environment_already_exists="Api test environment already exists"
|
api_test_environment_already_exists="Api test environment already exists"
|
||||||
api_test=API Test
|
api_test=API Test
|
||||||
|
|
|
@ -75,6 +75,7 @@ organization_does_not_belong_to_user=当前组织不属于当前用户
|
||||||
organization_id_is_null=组织 ID 不能为空
|
organization_id_is_null=组织 ID 不能为空
|
||||||
#api
|
#api
|
||||||
api_load_script_error=读取脚本失败
|
api_load_script_error=读取脚本失败
|
||||||
|
illegal_xml_format=不合法的 XML 格式
|
||||||
api_report_is_null="测试报告是未生成,无法更新"
|
api_report_is_null="测试报告是未生成,无法更新"
|
||||||
api_test_environment_already_exists="已存在该名称的环境配置"
|
api_test_environment_already_exists="已存在该名称的环境配置"
|
||||||
api_test=接口测试
|
api_test=接口测试
|
||||||
|
|
|
@ -75,6 +75,7 @@ organization_does_not_belong_to_user=當前組織不屬於當前用戶
|
||||||
organization_id_is_null=組織 ID 不能為空
|
organization_id_is_null=組織 ID 不能為空
|
||||||
#api
|
#api
|
||||||
api_load_script_error=讀取腳本失敗
|
api_load_script_error=讀取腳本失敗
|
||||||
|
illegal_xml_format=不合法的 XML 格式
|
||||||
api_report_is_null="測試報告是未生成,無法更新"
|
api_report_is_null="測試報告是未生成,無法更新"
|
||||||
api_test_environment_already_exists="已存在該名稱的環境配置"
|
api_test_environment_already_exists="已存在該名稱的環境配置"
|
||||||
api_test=接口測試
|
api_test=接口測試
|
||||||
|
|
|
@ -190,13 +190,17 @@
|
||||||
this.activeName = name;
|
this.activeName = name;
|
||||||
let currentScenario = {
|
let currentScenario = {
|
||||||
status: "Underway", principal: getCurrentUser().id,
|
status: "Underway", principal: getCurrentUser().id,
|
||||||
apiScenarioModuleId: "root", id: getUUID(),
|
apiScenarioModuleId: "default-module", id: getUUID(),
|
||||||
modulePath: "/" + this.$t("commons.module_title")
|
modulePath: "/" + this.$t("commons.module_title")
|
||||||
};
|
};
|
||||||
if (this.nodeTree && this.nodeTree.length > 0) {
|
if (this.nodeTree && this.nodeTree.length > 0) {
|
||||||
currentScenario.apiScenarioModuleId = this.nodeTree[0].id;
|
currentScenario.apiScenarioModuleId = this.nodeTree[0].id;
|
||||||
currentScenario.modulePath = this.nodeTree[0].path;
|
currentScenario.modulePath = this.nodeTree[0].path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.selectNodeIds && this.selectNodeIds.length > 0) {
|
||||||
|
currentScenario.apiScenarioModuleId = this.selectNodeIds[0];
|
||||||
|
}
|
||||||
this.tabs.push({label: label, name: name, currentScenario: currentScenario});
|
this.tabs.push({label: label, name: name, currentScenario: currentScenario});
|
||||||
}
|
}
|
||||||
if (tab.name === 'edit') {
|
if (tab.name === 'edit') {
|
||||||
|
|
|
@ -117,6 +117,9 @@
|
||||||
if (this.currentModule && this.currentModule.id != "root") {
|
if (this.currentModule && this.currentModule.id != "root") {
|
||||||
this.scenarioForm.modulePath = this.currentModule.method !== undefined ? this.currentModule.method : null;
|
this.scenarioForm.modulePath = this.currentModule.method !== undefined ? this.currentModule.method : null;
|
||||||
this.scenarioForm.apiScenarioModuleId = this.currentModule.id;
|
this.scenarioForm.apiScenarioModuleId = this.currentModule.id;
|
||||||
|
}else{
|
||||||
|
this.scenarioForm.modulePath = this.$t("commons.module_title");
|
||||||
|
this.scenarioForm.apiScenarioModuleId = "default-module";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getMaintainerOptions() {
|
getMaintainerOptions() {
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
@refresh="refresh"
|
@refresh="refresh"
|
||||||
ref="basisScenario"/>
|
ref="basisScenario"/>
|
||||||
|
|
||||||
<api-import ref="apiImport" :moduleOptions="extendTreeNodes" @refreshAll="$emit('refreshAll')"/>
|
<api-import ref="apiImport" :moduleOptions="data" @refreshAll="$emit('refreshAll')"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
@ -82,9 +82,7 @@
|
||||||
trashEnable: false
|
trashEnable: false
|
||||||
},
|
},
|
||||||
data: [],
|
data: [],
|
||||||
extendTreeNodes: [],
|
|
||||||
currentModule: undefined,
|
currentModule: undefined,
|
||||||
moduleOptions: [],
|
|
||||||
operators: [
|
operators: [
|
||||||
{
|
{
|
||||||
label: this.$t('api_test.automation.add_scenario'),
|
label: this.$t('api_test.automation.add_scenario'),
|
||||||
|
@ -141,11 +139,9 @@
|
||||||
this.result = this.$get("/api/automation/module/list/" + this.projectId, response => {
|
this.result = this.$get("/api/automation/module/list/" + this.projectId, response => {
|
||||||
if (response.data != undefined && response.data != null) {
|
if (response.data != undefined && response.data != null) {
|
||||||
this.data = response.data;
|
this.data = response.data;
|
||||||
let moduleOptions = [];
|
|
||||||
this.data.forEach(node => {
|
this.data.forEach(node => {
|
||||||
buildNodePath(node, {path: ''}, moduleOptions);
|
buildTree(node, {path: ''});
|
||||||
});
|
});
|
||||||
this.moduleOptions = moduleOptions
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.$refs.apiImport.open(this.currentModule);
|
this.$refs.apiImport.open(this.currentModule);
|
||||||
|
@ -163,11 +159,9 @@
|
||||||
this.result = this.$get("/api/automation/module/list/" + this.projectId, response => {
|
this.result = this.$get("/api/automation/module/list/" + this.projectId, response => {
|
||||||
if (response.data != undefined && response.data != null) {
|
if (response.data != undefined && response.data != null) {
|
||||||
this.data = response.data;
|
this.data = response.data;
|
||||||
let moduleOptions = [];
|
|
||||||
this.data.forEach(node => {
|
this.data.forEach(node => {
|
||||||
buildNodePath(node, {path: ''}, moduleOptions);
|
buildTree(node, {path: ''});
|
||||||
});
|
});
|
||||||
this.moduleOptions = moduleOptions
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.$refs.apiImport.open(this.currentModule);
|
this.$refs.apiImport.open(this.currentModule);
|
||||||
|
@ -188,17 +182,10 @@
|
||||||
this.result = this.$get(url, response => {
|
this.result = this.$get(url, response => {
|
||||||
if (response.data != undefined && response.data != null) {
|
if (response.data != undefined && response.data != null) {
|
||||||
this.data = response.data;
|
this.data = response.data;
|
||||||
this.extendTreeNodes = [];
|
this.data.forEach(node => {
|
||||||
this.extendTreeNodes.unshift({
|
|
||||||
"id": "root",
|
|
||||||
"name": this.$t('commons.module_title'),
|
|
||||||
"level": 0,
|
|
||||||
"children": this.data,
|
|
||||||
});
|
|
||||||
this.extendTreeNodes.forEach(node => {
|
|
||||||
buildTree(node, {path: ''});
|
buildTree(node, {path: ''});
|
||||||
});
|
});
|
||||||
this.$emit('setModuleOptions', this.extendTreeNodes);
|
this.$emit('setModuleOptions', this.data);
|
||||||
this.$emit('setNodeTree', this.data);
|
this.$emit('setNodeTree', this.data);
|
||||||
if (this.$refs.nodeTree) {
|
if (this.$refs.nodeTree) {
|
||||||
this.$refs.nodeTree.filter(this.condition.filterText);
|
this.$refs.nodeTree.filter(this.condition.filterText);
|
||||||
|
|
|
@ -84,7 +84,7 @@
|
||||||
callback();
|
callback();
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
httpForm: {environmentId: "", moduleId: "root"},
|
httpForm: {environmentId: "", moduleId: "default-module"},
|
||||||
moduleOptions: [],
|
moduleOptions: [],
|
||||||
httpVisible: false,
|
httpVisible: false,
|
||||||
currentModule: {},
|
currentModule: {},
|
||||||
|
@ -251,14 +251,7 @@
|
||||||
let url = "/api/module/list/" + getCurrentProjectID() + "/" + data.protocol;
|
let url = "/api/module/list/" + getCurrentProjectID() + "/" + data.protocol;
|
||||||
this.result = this.$get(url, response => {
|
this.result = this.$get(url, response => {
|
||||||
if (response.data != undefined && response.data != null) {
|
if (response.data != undefined && response.data != null) {
|
||||||
let data = response.data;
|
this.moduleOptions = response.data;
|
||||||
this.moduleOptions = [];
|
|
||||||
this.moduleOptions.unshift({
|
|
||||||
"id": "root",
|
|
||||||
"name": this.$t('commons.module_title'),
|
|
||||||
"level": 0,
|
|
||||||
"children": data,
|
|
||||||
});
|
|
||||||
this.moduleOptions.forEach(node => {
|
this.moduleOptions.forEach(node => {
|
||||||
buildTree(node, {path: ''});
|
buildTree(node, {path: ''});
|
||||||
});
|
});
|
||||||
|
@ -282,7 +275,7 @@
|
||||||
data.protocol = "DUBBO";
|
data.protocol = "DUBBO";
|
||||||
}
|
}
|
||||||
data.id = getUUID();
|
data.id = getUUID();
|
||||||
this.httpForm = {id: data.id, name: data.name, protocol: data.protocol, path: data.path, method: api.method, userId: getCurrentUser().id, request: data, moduleId: "root"};
|
this.httpForm = {id: data.id, name: data.name, protocol: data.protocol, path: data.path, method: api.method, userId: getCurrentUser().id, request: data, moduleId: "default-module"};
|
||||||
this.getMaintainerOptions();
|
this.getMaintainerOptions();
|
||||||
this.list(data);
|
this.list(data);
|
||||||
this.httpVisible = true;
|
this.httpVisible = true;
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<slot name="button"></slot>
|
<slot name="button"></slot>
|
||||||
<el-tooltip content="Copy" placement="top">
|
<el-tooltip content="Copy" placement="top">
|
||||||
<el-button size="mini" icon="el-icon-copy-document" circle @click="copyRow" style="padding: 5px"/>
|
<el-button size="mini" icon="el-icon-copy-document" circle @click="copyRow" style="padding: 5px" :disabled="data.disabled && !data.root"/>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<step-extend-btns style="display: contents" :data="data" @copy="copyRow" @remove="remove" @openScenario="openScenario" v-if="showBtn && (!data.disabled || data.root)"/>
|
<step-extend-btns style="display: contents" :data="data" @copy="copyRow" @remove="remove" @openScenario="openScenario" v-if="showBtn && (!data.disabled || data.root)"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -296,12 +296,15 @@
|
||||||
}
|
}
|
||||||
let api = {
|
let api = {
|
||||||
status: "Underway", method: "GET", userId: getCurrentUser().id,
|
status: "Underway", method: "GET", userId: getCurrentUser().id,
|
||||||
url: "", protocol: this.currentProtocol, environmentId: "", moduleId: 'root', modulePath: "/" + this.$t("commons.module_title")
|
url: "", protocol: this.currentProtocol, environmentId: "", moduleId: 'default-module', modulePath: "/" + this.$t("commons.module_title")
|
||||||
};
|
};
|
||||||
if (this.nodeTree && this.nodeTree.length > 0) {
|
if (this.nodeTree && this.nodeTree.length > 0) {
|
||||||
api.moduleId = this.nodeTree[0].id;
|
api.moduleId = this.nodeTree[0].id;
|
||||||
api.modulePath = this.nodeTree[0].path;
|
api.modulePath = this.nodeTree[0].path;
|
||||||
}
|
}
|
||||||
|
if (this.selectNodeIds && this.selectNodeIds.length > 0) {
|
||||||
|
api.moduleId = this.selectNodeIds[0];
|
||||||
|
}
|
||||||
this.handleTabsEdit(this.$t('api_test.definition.request.title'), e, api);
|
this.handleTabsEdit(this.$t('api_test.definition.request.title'), e, api);
|
||||||
},
|
},
|
||||||
handleTabClose() {
|
handleTabClose() {
|
||||||
|
|
|
@ -154,6 +154,9 @@
|
||||||
if (this.currentModule != null) {
|
if (this.currentModule != null) {
|
||||||
this.httpForm.modulePath = this.currentModule.method != undefined ? this.currentModule.method : null;
|
this.httpForm.modulePath = this.currentModule.method != undefined ? this.currentModule.method : null;
|
||||||
this.httpForm.moduleId = this.currentModule.id;
|
this.httpForm.moduleId = this.currentModule.id;
|
||||||
|
} else {
|
||||||
|
this.httpForm.modulePath = this.$t("commons.module_title");
|
||||||
|
this.httpForm.moduleId = "default-module";
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
|
@ -275,7 +275,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addModule(row) {
|
addModule(row) {
|
||||||
this.saveApi(row, "root");
|
this.saveApi(row, "default-module");
|
||||||
},
|
},
|
||||||
saveApi(row, module) {
|
saveApi(row, module) {
|
||||||
let data = this.api;
|
let data = this.api;
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
:condition="condition"
|
:condition="condition"
|
||||||
:current-module="currentModule"
|
:current-module="currentModule"
|
||||||
:is-read-only="isReadOnly"
|
:is-read-only="isReadOnly"
|
||||||
:moduleOptions="extendTreeNodes"
|
:moduleOptions="data"
|
||||||
@exportAPI="exportAPI"
|
@exportAPI="exportAPI"
|
||||||
@saveAsEdit="saveAsEdit"
|
@saveAsEdit="saveAsEdit"
|
||||||
@refreshTable="$emit('refreshTable')"
|
@refreshTable="$emit('refreshTable')"
|
||||||
|
@ -62,7 +62,6 @@
|
||||||
},
|
},
|
||||||
data: [],
|
data: [],
|
||||||
currentModule: {},
|
currentModule: {},
|
||||||
extendTreeNodes: [],
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -131,17 +130,10 @@
|
||||||
this.result = this.$get(url, response => {
|
this.result = this.$get(url, response => {
|
||||||
if (response.data != undefined && response.data != null) {
|
if (response.data != undefined && response.data != null) {
|
||||||
this.data = response.data;
|
this.data = response.data;
|
||||||
this.extendTreeNodes = [];
|
this.data.forEach(node => {
|
||||||
this.extendTreeNodes.unshift({
|
|
||||||
"id": "root",
|
|
||||||
"name": this.$t('commons.module_title'),
|
|
||||||
"level": 0,
|
|
||||||
"children": this.data,
|
|
||||||
});
|
|
||||||
this.extendTreeNodes.forEach(node => {
|
|
||||||
buildTree(node, {path: ''});
|
buildTree(node, {path: ''});
|
||||||
});
|
});
|
||||||
this.$emit('setModuleOptions', this.extendTreeNodes);
|
this.$emit('setModuleOptions', this.data);
|
||||||
this.$emit('setNodeTree', this.data);
|
this.$emit('setNodeTree', this.data);
|
||||||
if (this.$refs.nodeTree) {
|
if (this.$refs.nodeTree) {
|
||||||
this.$refs.nodeTree.filter(this.condition.filterText);
|
this.$refs.nodeTree.filter(this.condition.filterText);
|
||||||
|
|
|
@ -154,35 +154,39 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
let rows = this.existFiles.filter(f => this.selectIds.has(f.id));
|
let rows = this.existFiles.filter(f => this.selectIds.has(f.id));
|
||||||
|
let jmxIds = [];
|
||||||
for (let i = 0; i < rows.length; i++) {
|
for (let i = 0; i < rows.length; i++) {
|
||||||
let row = rows[i];
|
let row = rows[i];
|
||||||
if (this.tableData.filter(f => f.name === row.name).length > 0) {
|
if (this.tableData.filter(f => f.name === row.name).length > 0) {
|
||||||
this.$error(this.$t('load_test.delete_file') + ', name: ' + row.name);
|
setTimeout(() => {
|
||||||
this.selectIds.clear();
|
this.$warning(this.$t('load_test.delete_file') + 'name: ' + row.name);
|
||||||
return;
|
}, 100);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
if (row.type.toUpperCase() === 'JMX') {
|
||||||
|
jmxIds.push(row.id);
|
||||||
|
}
|
||||||
|
this.tableData.push({
|
||||||
|
name: row.name,
|
||||||
|
size: (row.size / 1024).toFixed(2) + ' KB',
|
||||||
|
type: row.type.toUpperCase(),
|
||||||
|
updateTime: row.lastModified,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.loadType === 'resource') {
|
if (this.loadType === 'resource') {
|
||||||
rows.forEach(row => {
|
rows.forEach(row => {
|
||||||
this.fileList.push(row);
|
this.fileList.push(row);
|
||||||
this.tableData.push({
|
|
||||||
name: row.name,
|
|
||||||
size: (row.size / 1024).toFixed(2) + ' KB',
|
|
||||||
type: row.type.toUpperCase(),
|
|
||||||
updateTime: row.lastModified,
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
this.$success(this.$t('test_track.case.import.success'));
|
this.$success(this.$t('test_track.case.import.success'));
|
||||||
this.loadFileVisible = false;
|
this.close();
|
||||||
this.selectIds.clear();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getJmxContents();
|
this.getJmxContents(jmxIds);
|
||||||
},
|
},
|
||||||
getJmxContents() {
|
getJmxContents(jmxIds) {
|
||||||
this.projectLoadingResult = this.$post('/performance/export/jmx', [...this.selectIds], (response) => {
|
this.projectLoadingResult = this.$post('/performance/export/jmx', jmxIds, (response) => {
|
||||||
let data = response.data;
|
let data = response.data;
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return;
|
return;
|
||||||
|
@ -195,18 +199,11 @@ export default {
|
||||||
});
|
});
|
||||||
let file = new File([d.jmx], d.name);
|
let file = new File([d.jmx], d.name);
|
||||||
this.uploadList.push(file);
|
this.uploadList.push(file);
|
||||||
this.tableData.push({
|
|
||||||
name: file.name,
|
|
||||||
size: (file.size / 1024).toFixed(2) + ' KB',
|
|
||||||
type: 'JMX',
|
|
||||||
updateTime: file.lastModified,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$emit('fileChange', this.scenarios);
|
this.$emit('fileChange', this.scenarios);
|
||||||
this.$success(this.$t('test_track.case.import.success'));
|
this.$success(this.$t('test_track.case.import.success'));
|
||||||
this.loadFileVisible = false;
|
this.close();
|
||||||
this.selectIds.clear();
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
beforeUploadFile(file) {
|
beforeUploadFile(file) {
|
||||||
|
|
|
@ -114,8 +114,8 @@ export default {
|
||||||
this.testCaseForm.nodePath = this.currentModule.path;
|
this.testCaseForm.nodePath = this.currentModule.path;
|
||||||
this.testCaseForm.nodeId = this.currentModule.id;
|
this.testCaseForm.nodeId = this.currentModule.id;
|
||||||
} else {
|
} else {
|
||||||
this.testCaseForm.nodePath = "/全部用例"
|
this.testCaseForm.nodePath = "/默认模块"
|
||||||
this.testCaseForm.nodeId = "root"
|
this.testCaseForm.nodeId = "default-module"
|
||||||
}
|
}
|
||||||
this.result = this.$post(path, this.testCaseForm, response => {
|
this.result = this.$post(path, this.testCaseForm, response => {
|
||||||
this.testCaseForm.id = response.data.id
|
this.testCaseForm.id = response.data.id
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
<el-col :span="7">
|
<el-col :span="7">
|
||||||
<el-form-item :label="$t('test_track.case.module')" :label-width="formLabelWidth" prop="module">
|
<el-form-item :label="$t('test_track.case.module')" :label-width="formLabelWidth" prop="module">
|
||||||
<ms-select-tree :disabled="readOnly" :data="moduleOptions" :defaultKey="form.module" :obj="moduleObj"
|
<ms-select-tree :disabled="readOnly" :data="treeNodes" :defaultKey="form.module" :obj="moduleObj"
|
||||||
@getValue="setModule" clearable checkStrictly size="small" />
|
@getValue="setModule" clearable checkStrictly size="small" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
@ -314,8 +314,8 @@ export default {
|
||||||
dialogFormVisible: false,
|
dialogFormVisible: false,
|
||||||
form: {
|
form: {
|
||||||
name: '',
|
name: '',
|
||||||
module: 'root',
|
module: 'default-module',
|
||||||
nodePath:'',
|
nodePath:'/默认模块',
|
||||||
maintainer: getCurrentUser().id,
|
maintainer: getCurrentUser().id,
|
||||||
priority: 'P0',
|
priority: 'P0',
|
||||||
type: '',
|
type: '',
|
||||||
|
@ -416,7 +416,7 @@ export default {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}, 1000);
|
}, 1000);
|
||||||
if(this.selectNode && this.selectNode.data){
|
if(this.selectNode && this.selectNode.data && !this.form.id){
|
||||||
this.form.module = this.selectNode.data.id;
|
this.form.module = this.selectNode.data.id;
|
||||||
this.form.nodePath = this.selectNode.data.path;
|
this.form.nodePath = this.selectNode.data.path;
|
||||||
}
|
}
|
||||||
|
@ -432,7 +432,16 @@ export default {
|
||||||
created() {
|
created() {
|
||||||
this.loadOptions();
|
this.loadOptions();
|
||||||
this.addListener(); // 添加 ctrl s 监听
|
this.addListener(); // 添加 ctrl s 监听
|
||||||
|
if(this.selectNode && this.selectNode.data && !this.form.id){
|
||||||
|
this.form.module = this.selectNode.data.id;
|
||||||
|
this.form.nodePath = this.selectNode.data.path;
|
||||||
|
}else{
|
||||||
|
this.form.module =this.treeNodes && this.length>0? this.treeNodes[0].id:"";
|
||||||
|
}
|
||||||
|
if (this.type === 'edit' || this.type === 'copy') {
|
||||||
|
this.form.module = this.currentTestCaseInfo.nodeId;
|
||||||
|
this.form.nodePath = this.currentTestCaseInfo.nodePath;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setModule(id,data) {
|
setModule(id,data) {
|
||||||
|
@ -836,16 +845,11 @@ export default {
|
||||||
this.getTestOptions()
|
this.getTestOptions()
|
||||||
},
|
},
|
||||||
getModuleOptions() {
|
getModuleOptions() {
|
||||||
this.moduleOptions = [];
|
let moduleOptions = [];
|
||||||
this.moduleOptions.unshift({
|
this.treeNodes.forEach(node => {
|
||||||
"id": "root",
|
buildNodePath(node, {path: ''}, moduleOptions);
|
||||||
"name": this.$t('commons.module_title'),
|
|
||||||
"level": 0,
|
|
||||||
"children": this.treeNodes,
|
|
||||||
});
|
|
||||||
this.moduleOptions.forEach(node => {
|
|
||||||
buildTree(node, {path: ''});
|
|
||||||
});
|
});
|
||||||
|
this.moduleOptions = moduleOptions;
|
||||||
},
|
},
|
||||||
getMaintainerOptions() {
|
getMaintainerOptions() {
|
||||||
let workspaceId = localStorage.getItem(WORKSPACE_ID);
|
let workspaceId = localStorage.getItem(WORKSPACE_ID);
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
<span v-if="!disabled" class="node-operate child">
|
<span v-if="!disabled" class="node-operate child">
|
||||||
<el-tooltip
|
<el-tooltip
|
||||||
v-if="data.id != 'root'"
|
v-if="data.id != 'root' && data.name !='默认模块'"
|
||||||
class="item"
|
class="item"
|
||||||
effect="dark"
|
effect="dark"
|
||||||
:open-delay="200"
|
:open-delay="200"
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
<i @click.stop="append(node, data)" class="el-icon-circle-plus-outline"></i>
|
<i @click.stop="append(node, data)" class="el-icon-circle-plus-outline"></i>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip
|
<el-tooltip
|
||||||
v-if="data.id != 'root'"
|
v-if="data.id != 'root' && data.name !='默认模块'"
|
||||||
class="item" effect="dark"
|
class="item" effect="dark"
|
||||||
:open-delay="200"
|
:open-delay="200"
|
||||||
:content="$t('commons.delete')"
|
:content="$t('commons.delete')"
|
||||||
|
@ -92,7 +92,7 @@ export default {
|
||||||
allLabel: {
|
allLabel: {
|
||||||
type: String,
|
type: String,
|
||||||
default() {
|
default() {
|
||||||
return this.$t('commons.module_title');
|
return this.$t("commons.all_label.case");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
nameLimit: {
|
nameLimit: {
|
||||||
|
@ -230,7 +230,7 @@ export default {
|
||||||
if (dropType === "none" || dropType === undefined) {
|
if (dropType === "none" || dropType === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (dropNode.data.id === 'root' && dropType === 'before') {
|
if (dropNode.data.id === 'root' && dropType === 'before' || draggingNode.data.name==='默认模块') {
|
||||||
this.$emit('refresh');
|
this.$emit('refresh');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import MsNodeTree from "./NodeTree";
|
||||||
import TestCaseCreate from "@/business/components/track/case/components/TestCaseCreate";
|
import TestCaseCreate from "@/business/components/track/case/components/TestCaseCreate";
|
||||||
import TestCaseImport from "@/business/components/track/case/components/TestCaseImport";
|
import TestCaseImport from "@/business/components/track/case/components/TestCaseImport";
|
||||||
import MsSearchBar from "@/business/components/common/components/search/MsSearchBar";
|
import MsSearchBar from "@/business/components/common/components/search/MsSearchBar";
|
||||||
|
import {buildTree} from "../../api/definition/model/NodeTree";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TestCaseNodeTree",
|
name: "TestCaseNodeTree",
|
||||||
|
@ -115,6 +116,9 @@ export default {
|
||||||
if (this.projectId) {
|
if (this.projectId) {
|
||||||
this.result = this.$get("/case/node/list/" + this.projectId, response => {
|
this.result = this.$get("/case/node/list/" + this.projectId, response => {
|
||||||
this.treeNodes = response.data;
|
this.treeNodes = response.data;
|
||||||
|
this.treeNodes.forEach(node => {
|
||||||
|
buildTree(node, {path: ''});
|
||||||
|
});
|
||||||
if (this.$refs.nodeTree) {
|
if (this.$refs.nodeTree) {
|
||||||
this.$refs.nodeTree.filter();
|
this.$refs.nodeTree.filter();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2115bd28a90854d2b6276a90878934715498c584
|
Subproject commit 07951ba17aef6f29e50cfd68e40de3266f9a60cd
|
Loading…
Reference in New Issue