This commit is contained in:
wenyann 2021-02-23 14:11:37 +08:00
commit 7e51a7eb61
73 changed files with 1480 additions and 1533 deletions

View File

@ -10,16 +10,11 @@ import io.metersphere.api.dto.datacount.response.ApiDataCountDTO;
import io.metersphere.api.dto.datacount.response.ExecutedCaseInfoDTO; import io.metersphere.api.dto.datacount.response.ExecutedCaseInfoDTO;
import io.metersphere.api.dto.datacount.response.TaskInfoResult; import io.metersphere.api.dto.datacount.response.TaskInfoResult;
import io.metersphere.api.dto.definition.RunDefinitionRequest; import io.metersphere.api.dto.definition.RunDefinitionRequest;
import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter; import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter;
import io.metersphere.api.service.*; import io.metersphere.api.service.*;
import io.metersphere.base.domain.ApiDefinition;
import io.metersphere.base.domain.ApiTest; import io.metersphere.base.domain.ApiTest;
import io.metersphere.base.domain.LoadTest;
import io.metersphere.base.domain.Schedule; import io.metersphere.base.domain.Schedule;
import io.metersphere.commons.constants.PerformanceTestStatus;
import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.constants.RoleConstants;
import io.metersphere.commons.constants.ScheduleGroup;
import io.metersphere.commons.utils.CronUtils; import io.metersphere.commons.utils.CronUtils;
import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.PageUtils;
import io.metersphere.commons.utils.Pager; import io.metersphere.commons.utils.Pager;
@ -28,24 +23,14 @@ import io.metersphere.controller.request.QueryScheduleRequest;
import io.metersphere.dto.ScheduleDao; import io.metersphere.dto.ScheduleDao;
import io.metersphere.performance.service.PerformanceTestService; import io.metersphere.performance.service.PerformanceTestService;
import io.metersphere.service.CheckPermissionService; import io.metersphere.service.CheckPermissionService;
import io.metersphere.service.FileService;
import io.metersphere.service.ScheduleService; import io.metersphere.service.ScheduleService;
import io.metersphere.track.request.testplan.SaveTestPlanRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.ContentType;
import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.HashTree;
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.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@ -393,7 +378,7 @@ public class APITestController {
String testName = runRequest.getName(); String testName = runRequest.getName();
//将jmx处理封装为通用方法 //将jmx处理封装为通用方法
jmxString = apiTestService.updateJmxString(jmxString,testName,true); jmxString = apiTestService.updateJmxString(jmxString,testName,false);
JmxInfoDTO dto = new JmxInfoDTO(); JmxInfoDTO dto = new JmxInfoDTO();
dto.setName(runRequest.getName() + ".jmx"); dto.setName(runRequest.getName() + ".jmx");

View File

@ -44,13 +44,6 @@ public class ApiAutomationController {
return PageUtils.setPageInfo(page, apiAutomationService.list(request)); return PageUtils.setPageInfo(page, apiAutomationService.list(request));
} }
@PostMapping("/list/all")
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR)
public List<ApiScenarioWithBLOBs> list(@RequestBody ApiScenarioRequest request) {
request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
return apiAutomationService.get(request);
}
@PostMapping(value = "/create") @PostMapping(value = "/create")
public ApiScenario create(@RequestPart("request") SaveApiScenarioRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) { public ApiScenario create(@RequestPart("request") SaveApiScenarioRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
return apiAutomationService.create(request, bodyFiles); return apiAutomationService.create(request, bodyFiles);
@ -167,5 +160,11 @@ public class ApiAutomationController {
return apiAutomationService.export(request); return apiAutomationService.export(request);
} }
@PostMapping(value = "/export/jmx")
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
public List<ApiScenrioExportJmx> exportJmx(@RequestBody ApiScenarioBatchRequest request) {
return apiAutomationService.exportJmx(request);
}
} }

View File

@ -14,6 +14,7 @@ public class ApiTestImportRequest {
private String platform; private String platform;
private Boolean useEnvironment; private Boolean useEnvironment;
private String swaggerUrl; private String swaggerUrl;
private String fileName;
//导入策略 //导入策略
private String modeId; private String modeId;
private String userId; private String userId;

View File

@ -0,0 +1,16 @@
package io.metersphere.api.dto.automation;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ApiScenrioExportJmx {
private String name;
private String jmx;
public ApiScenrioExportJmx(String name, String jmx) {
this.name = name;
this.jmx = jmx;
}
}

View File

@ -0,0 +1,50 @@
package io.metersphere.api.dto.automation.parse;
import io.metersphere.api.dto.automation.ApiScenarioModuleDTO;
import io.metersphere.api.service.ApiScenarioModuleService;
import io.metersphere.base.domain.ApiScenarioModule;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
public class ApiScenarioImportUtil {
public static ApiScenarioModule getSelectModule(String moduleId) {
ApiScenarioModuleService apiModuleService = CommonBeanFactory.getBean(ApiScenarioModuleService.class);
if (StringUtils.isNotBlank(moduleId) && !StringUtils.equals("root", moduleId)) {
ApiScenarioModule module = new ApiScenarioModule();
ApiScenarioModuleDTO moduleDTO = apiModuleService.getNode(moduleId);
if (moduleDTO != null) {
BeanUtils.copyBean(module, moduleDTO);
}
return module;
}
return null;
}
public static ApiScenarioModule buildModule(ApiScenarioModule parentModule, String name, String projectId) {
ApiScenarioModuleService apiModuleService = CommonBeanFactory.getBean(ApiScenarioModuleService.class);
ApiScenarioModule module;
if (parentModule != null) {
module = apiModuleService.getNewModule(name, projectId, parentModule.getLevel() + 1);
module.setParentId(parentModule.getId());
} else {
module = apiModuleService.getNewModule(name, projectId, 1);
}
createModule(module);
return module;
}
public static void createModule(ApiScenarioModule module) {
ApiScenarioModuleService apiModuleService = CommonBeanFactory.getBean(ApiScenarioModuleService.class);
List<ApiScenarioModule> apiModules = apiModuleService.selectSameModule(module);
if (CollectionUtils.isEmpty(apiModules)) {
apiModuleService.addNode(module);
} else {
module.setId(apiModules.get(0).getId());
}
}
}

View File

@ -10,7 +10,6 @@ import io.metersphere.api.dto.automation.ImportPoolsDTO;
import io.metersphere.api.dto.definition.request.MsScenario; import io.metersphere.api.dto.definition.request.MsScenario;
import io.metersphere.api.dto.definition.request.MsTestElement; import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.dto.definition.request.assertions.*; import io.metersphere.api.dto.definition.request.assertions.*;
import io.metersphere.api.dto.definition.request.controller.MsIfController;
import io.metersphere.api.dto.definition.request.controller.MsLoopController; import io.metersphere.api.dto.definition.request.controller.MsLoopController;
import io.metersphere.api.dto.definition.request.controller.loop.CountController; import io.metersphere.api.dto.definition.request.controller.loop.CountController;
import io.metersphere.api.dto.definition.request.controller.loop.MsForEachController; import io.metersphere.api.dto.definition.request.controller.loop.MsForEachController;
@ -37,6 +36,7 @@ import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.dto.scenario.request.BodyFile; import io.metersphere.api.dto.scenario.request.BodyFile;
import io.metersphere.api.dto.scenario.request.RequestType; import io.metersphere.api.dto.scenario.request.RequestType;
import io.metersphere.api.parse.ApiImportAbstractParser;
import io.metersphere.api.service.ApiTestEnvironmentService; import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.base.domain.ApiScenarioModule; import io.metersphere.base.domain.ApiScenarioModule;
import io.metersphere.base.domain.ApiScenarioWithBLOBs; import io.metersphere.base.domain.ApiScenarioWithBLOBs;
@ -51,7 +51,6 @@ import org.apache.commons.collections.CollectionUtils;
import org.apache.jmeter.assertions.*; import org.apache.jmeter.assertions.*;
import org.apache.jmeter.config.ConfigTestElement; import org.apache.jmeter.config.ConfigTestElement;
import org.apache.jmeter.control.ForeachController; import org.apache.jmeter.control.ForeachController;
import org.apache.jmeter.control.IfController;
import org.apache.jmeter.control.LoopController; import org.apache.jmeter.control.LoopController;
import org.apache.jmeter.control.WhileController; import org.apache.jmeter.control.WhileController;
import org.apache.jmeter.extractor.JSR223PostProcessor; import org.apache.jmeter.extractor.JSR223PostProcessor;
@ -76,7 +75,7 @@ import java.io.InputStream;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.*; import java.util.*;
public class MsJmeterParser extends ScenarioImportAbstractParser { public class MsJmeterParser extends ApiImportAbstractParser<ScenarioImport> {
private final String ENV_NAME = "导入数据环境"; private final String ENV_NAME = "导入数据环境";
@Override @Override
@ -88,12 +87,12 @@ public class MsJmeterParser extends ScenarioImportAbstractParser {
preInitPool(request.getProjectId(), testPlan); preInitPool(request.getProjectId(), testPlan);
MsScenario scenario = new MsScenario(); MsScenario scenario = new MsScenario();
scenario.setReferenced("REF"); scenario.setReferenced("IMPORT");
jmterHashTree(testPlan, scenario); jmterHashTree(testPlan, scenario);
this.projectId = request.getProjectId(); this.projectId = request.getProjectId();
ScenarioImport scenarioImport = new ScenarioImport(); ScenarioImport scenarioImport = new ScenarioImport();
scenarioImport.setData(paseObj(scenario, request)); scenarioImport.setData(paseObj(scenario, request));
scenarioImport.setProjectid(request.getProjectId()); scenarioImport.setProjectId(request.getProjectId());
return scenarioImport; return scenarioImport;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -105,7 +104,7 @@ public class MsJmeterParser extends ScenarioImportAbstractParser {
private List<ApiScenarioWithBLOBs> paseObj(MsScenario msScenario, ApiTestImportRequest request) { private List<ApiScenarioWithBLOBs> paseObj(MsScenario msScenario, ApiTestImportRequest request) {
List<ApiScenarioWithBLOBs> scenarioWithBLOBsList = new ArrayList<>(); List<ApiScenarioWithBLOBs> scenarioWithBLOBsList = new ArrayList<>();
ApiScenarioWithBLOBs scenarioWithBLOBs = new ApiScenarioWithBLOBs(); ApiScenarioWithBLOBs scenarioWithBLOBs = new ApiScenarioWithBLOBs();
ApiScenarioModule module = buildModule(getSelectModule(request.getModuleId()), msScenario.getName()); ApiScenarioModule module = ApiScenarioImportUtil.buildModule(ApiScenarioImportUtil.getSelectModule(request.getModuleId()), msScenario.getName(), this.projectId);
scenarioWithBLOBs.setName(msScenario.getName()); scenarioWithBLOBs.setName(msScenario.getName());
scenarioWithBLOBs.setProjectId(request.getProjectId()); scenarioWithBLOBs.setProjectId(request.getProjectId());
if (msScenario != null && CollectionUtils.isNotEmpty(msScenario.getHashTree())) { if (msScenario != null && CollectionUtils.isNotEmpty(msScenario.getHashTree())) {
@ -199,7 +198,6 @@ public class MsJmeterParser extends ScenarioImportAbstractParser {
private void convertDubboSample(MsDubboSampler elementNode, DubboSample sampler) { private void convertDubboSample(MsDubboSampler elementNode, DubboSample sampler) {
elementNode.setName(sampler.getName()); elementNode.setName(sampler.getName());
elementNode.setType("DubboSampler"); elementNode.setType("DubboSampler");
elementNode.setProtocol("dubbo://");
elementNode.set_interface(sampler.getPropertyAsString("FIELD_DUBBO_INTERFACE")); elementNode.set_interface(sampler.getPropertyAsString("FIELD_DUBBO_INTERFACE"));
elementNode.setMethod(sampler.getPropertyAsString("FIELD_DUBBO_METHOD")); elementNode.setMethod(sampler.getPropertyAsString("FIELD_DUBBO_METHOD"));
@ -233,24 +231,24 @@ public class MsJmeterParser extends ScenarioImportAbstractParser {
elementNode.setConsumerAndService(consumerAndService); elementNode.setConsumerAndService(consumerAndService);
List<MethodArgument> methodArguments = Constants.getMethodArgs(sampler); List<MethodArgument> methodArguments = Constants.getMethodArgs(sampler);
List<KeyValue> methodArgs = new LinkedList<>();
if (CollectionUtils.isNotEmpty(methodArguments)) { if (CollectionUtils.isNotEmpty(methodArguments)) {
List<KeyValue> methodArgs = new LinkedList<>();
methodArguments.forEach(item -> { methodArguments.forEach(item -> {
KeyValue keyValue = new KeyValue(item.getParamType(), item.getParamValue()); KeyValue keyValue = new KeyValue(item.getParamType(), item.getParamValue());
methodArgs.add(keyValue); methodArgs.add(keyValue);
}); });
elementNode.setArgs(methodArgs);
} }
elementNode.setArgs(methodArgs);
List<MethodArgument> arguments = Constants.getAttachmentArgs(sampler); List<MethodArgument> arguments = Constants.getAttachmentArgs(sampler);
List<KeyValue> attachmentArgs = new LinkedList<>();
if (CollectionUtils.isNotEmpty(arguments)) { if (CollectionUtils.isNotEmpty(arguments)) {
List<KeyValue> methodArgs = new LinkedList<>();
arguments.forEach(item -> { arguments.forEach(item -> {
KeyValue keyValue = new KeyValue(item.getParamType(), item.getParamValue()); KeyValue keyValue = new KeyValue(item.getParamType(), item.getParamValue());
methodArgs.add(keyValue); attachmentArgs.add(keyValue);
}); });
elementNode.setAttachmentArgs(methodArgs);
} }
elementNode.setAttachmentArgs(attachmentArgs);
} }
/** /**
@ -568,12 +566,12 @@ public class MsJmeterParser extends ScenarioImportAbstractParser {
BeanUtils.copyBean(elementNode, key); BeanUtils.copyBean(elementNode, key);
elementNode.setType("ConstantTimer"); elementNode.setType("ConstantTimer");
} }
// IF条件控制器 // IF条件控制器这里平台方式和jmeter 不同暂时不处理
else if (key instanceof IfController) { // else if (key instanceof IfController) {
elementNode = new MsIfController(); // elementNode = new MsIfController();
BeanUtils.copyBean(elementNode, key); // BeanUtils.copyBean(elementNode, key);
elementNode.setType("IfController"); // elementNode.setType("IfController");
} // }
// 次数循环控制器 // 次数循环控制器
else if (key instanceof LoopController) { else if (key instanceof LoopController) {
elementNode = new MsLoopController(); elementNode = new MsLoopController();

View File

@ -1,205 +0,0 @@
package io.metersphere.api.dto.automation.parse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.request.MsScenario;
import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.dto.parse.postman.*;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.base.domain.ApiScenarioModule;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.commons.constants.MsRequestBodyType;
import io.metersphere.commons.constants.PostmanRequestBodyMode;
import io.metersphere.commons.constants.VariableTypeConstants;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
public class MsPostmanParser extends ScenarioImportAbstractParser {
@Override
public ScenarioImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
PostmanCollection postmanCollection = JSON.parseObject(testStr, PostmanCollection.class);
List<PostmanKeyValue> variables = postmanCollection.getVariable();
ScenarioImport scenarioImport = new ScenarioImport();
// 场景步骤
LinkedList<MsTestElement> apiScenarioWithBLOBs = new LinkedList<>();
PostmanCollectionInfo info = postmanCollection.getInfo();
ApiScenarioWithBLOBs scenario = new ApiScenarioWithBLOBs();
scenario.setName(info.getName());
MsScenario msScenario = new MsScenario();
msScenario.setName(info.getName());
this.projectId = request.getProjectId();
parseItem(postmanCollection.getItem(), variables, msScenario, apiScenarioWithBLOBs);
// 生成场景对象
List<ApiScenarioWithBLOBs> scenarioWithBLOBs = new LinkedList<>();
paseScenario(scenarioWithBLOBs, msScenario, request);
scenarioImport.setData(scenarioWithBLOBs);
return scenarioImport;
}
private void paseScenario(List<ApiScenarioWithBLOBs> scenarioWithBLOBsList, MsScenario msScenario, ApiTestImportRequest request) {
ApiScenarioModule module = buildModule(getSelectModule(request.getModuleId()), msScenario.getName());
ApiScenarioWithBLOBs scenarioWithBLOBs = new ApiScenarioWithBLOBs();
scenarioWithBLOBs.setName(msScenario.getName());
scenarioWithBLOBs.setProjectId(request.getProjectId());
if (msScenario != null && CollectionUtils.isNotEmpty(msScenario.getHashTree())) {
scenarioWithBLOBs.setStepTotal(msScenario.getHashTree().size());
}
if (module != null) {
scenarioWithBLOBs.setApiScenarioModuleId(module.getId());
scenarioWithBLOBs.setModulePath("/" + module.getName());
}
scenarioWithBLOBs.setId(UUID.randomUUID().toString());
scenarioWithBLOBs.setScenarioDefinition(JSON.toJSONString(msScenario));
scenarioWithBLOBsList.add(scenarioWithBLOBs);
}
private void parseItem(List<PostmanItem> items, List<PostmanKeyValue> variables, MsScenario scenario, LinkedList<MsTestElement> results) {
for (PostmanItem item : items) {
List<PostmanItem> childItems = item.getItem();
if (childItems != null) {
parseItem(childItems, variables, scenario, results);
} else {
MsHTTPSamplerProxy request = parsePostman(item);
if (request != null) {
results.add(request);
}
}
}
scenario.setVariables(parseScenarioVariable(variables));
scenario.setHashTree(results);
}
private MsHTTPSamplerProxy parsePostman(PostmanItem requestItem) {
PostmanRequest requestDesc = requestItem.getRequest();
if (requestDesc == null) {
return null;
}
requestDesc.getAuth(); // todo 认证方式等待优化
PostmanUrl url = requestDesc.getUrl();
MsHTTPSamplerProxy request = buildRequest(requestItem.getName(), url.getRaw(), requestDesc.getMethod());
if (StringUtils.isNotBlank(request.getPath())) {
String path = request.getPath().split("\\?")[0];
path = path.replace("{{", "${");
path = path.replace("}}", "}");
request.setPath(path);
} else {
request.setPath("/");
}
parseBody(request.getBody(), requestDesc);
request.setArguments(parseKeyValue(url.getQuery()));
request.setHeaders(parseKeyValue(requestDesc.getHeader()));
addBodyHeader(request);
addPreScript(request, requestItem.getEvent());
return request;
}
private void addPreScript(MsHTTPSamplerProxy request, List<PostmanEvent> event) {
if (request != null && CollectionUtils.isNotEmpty(event)) {
StringBuilder scriptStr = new StringBuilder();
event = event.stream()
.filter(item -> item.getScript() != null)
.collect(Collectors.toList());
event.forEach(item -> {
PostmanScript script = item.getScript();
if (script != null) {
List<String> exec = script.getExec();
if (CollectionUtils.isNotEmpty(exec)) {
exec.forEach(col -> {
if (StringUtils.isNotEmpty(col)) {
scriptStr.append(col + "/n");
}
});
}
}
});
if (StringUtils.isNotBlank(scriptStr)) {
MsJSR223PreProcessor jsr223PreProcessor = new MsJSR223PreProcessor();
jsr223PreProcessor.setName("JSR223PreProcessor");
jsr223PreProcessor.setScriptLanguage("javascript");
jsr223PreProcessor.setScript(scriptStr.toString());
LinkedList<MsTestElement> hashTree = new LinkedList<>();
hashTree.add(jsr223PreProcessor);
request.setHashTree(hashTree);
}
}
}
private List<KeyValue> parseKeyValue(List<PostmanKeyValue> postmanKeyValues) {
if (postmanKeyValues == null) {
return null;
}
List<KeyValue> keyValues = new ArrayList<>();
postmanKeyValues.forEach(item -> keyValues.add(new KeyValue(item.getKey(), item.getValue(), item.getDescription(), item.getContentType())));
return keyValues;
}
private List<ScenarioVariable> parseScenarioVariable(List<PostmanKeyValue> postmanKeyValues) {
if (postmanKeyValues == null) {
return null;
}
List<ScenarioVariable> keyValues = new ArrayList<>();
postmanKeyValues.forEach(item -> keyValues.add(new ScenarioVariable(item.getKey(), item.getValue(), item.getDescription(), VariableTypeConstants.CONSTANT.name())));
return keyValues;
}
private void parseBody(Body body, PostmanRequest requestDesc) {
JSONObject postmanBody = requestDesc.getBody();
if (postmanBody == null) {
return;
}
String bodyMode = postmanBody.getString("mode");
if (StringUtils.isNotEmpty(bodyMode) && StringUtils.equals(bodyMode, PostmanRequestBodyMode.RAW.value())) {
parseRawBody(body, postmanBody, bodyMode);
} else if (StringUtils.isNotEmpty(bodyMode) && StringUtils.equalsAny(bodyMode, PostmanRequestBodyMode.FORM_DATA.value(), PostmanRequestBodyMode.URLENCODED.value())) {
List<PostmanKeyValue> postmanKeyValues = JSON.parseArray(postmanBody.getString(bodyMode), PostmanKeyValue.class);
body.setKvs(parseKeyValue(postmanKeyValues));
if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.FORM_DATA.value())) {
body.setType(Body.FORM_DATA);
} else if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.URLENCODED.value())) {
body.setType(Body.WWW_FROM);
}
} else if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.FILE.value())) {
body.setType(Body.BINARY);
body.setKvs(new ArrayList<>());
}
}
private void parseRawBody(Body body, JSONObject postmanBody, String bodyMode) {
body.setRaw(postmanBody.getString(bodyMode));
body.setType(MsRequestBodyType.RAW.value());
JSONObject options = postmanBody.getJSONObject("options");
if (options != null) {
JSONObject raw = options.getJSONObject(PostmanRequestBodyMode.RAW.value());
if (raw != null && raw.getString("language") != null) {
String bodyType = "";
switch (raw.getString("language")) {
case "json":
bodyType = Body.JSON;
break;
case "xml":
bodyType = Body.XML;
break;
default:
bodyType = Body.RAW;
}
body.setType(bodyType);
}
}
}
}

View File

@ -1,26 +1,49 @@
package io.metersphere.api.dto.automation.parse; package io.metersphere.api.dto.automation.parse;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import io.metersphere.api.dto.ApiTestImportRequest; import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.request.MsScenario;
import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.parse.MsAbstractParser;
import io.metersphere.base.domain.ApiScenarioModule; import io.metersphere.base.domain.ApiScenarioModule;
import io.metersphere.base.domain.ApiScenarioWithBLOBs; import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.io.InputStream; import java.io.InputStream;
import java.util.Arrays; import java.util.*;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
public class MsScenarioParser extends ScenarioImportAbstractParser { public class MsScenarioParser extends MsAbstractParser<ScenarioImport> {
@Override @Override
public ScenarioImport parse(InputStream source, ApiTestImportRequest request) { public ScenarioImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source); String testStr = getApiTestStr(source);
this.projectId = request.getProjectId(); this.projectId = request.getProjectId();
ScenarioImport scenarioImport = parseMsFormat(testStr, request); JSONObject testObject = JSONObject.parseObject(testStr, Feature.OrderedField);
return scenarioImport; if (testObject.get("projectName") != null || testObject.get("projectId") != null ) {
return parseMsFormat(testStr, request);
} else {
ScenarioImport apiImport = new ScenarioImport();
ArrayList<ApiScenarioWithBLOBs> apiScenarioWithBLOBs = new ArrayList<>();
apiScenarioWithBLOBs.add(parsePluginFormat(testObject, request));
apiImport.setData(apiScenarioWithBLOBs);
return apiImport;
}
}
protected ApiScenarioWithBLOBs parsePluginFormat(JSONObject testObject, ApiTestImportRequest importRequest) {
LinkedList<MsTestElement> results = new LinkedList<>();
testObject.keySet().forEach(tag -> {
results.addAll(parseMsHTTPSamplerProxy(testObject, tag));
});
MsScenario msScenario = new MsScenario();
msScenario.setName(importRequest.getFileName());
msScenario.setHashTree(results);
ApiScenarioWithBLOBs scenarioWithBLOBs = parseScenario(msScenario);
scenarioWithBLOBs.setApiScenarioModuleId(importRequest.getModuleId());
return scenarioWithBLOBs;
} }
private ScenarioImport parseMsFormat(String testStr, ApiTestImportRequest importRequest) { private ScenarioImport parseMsFormat(String testStr, ApiTestImportRequest importRequest) {
@ -31,7 +54,7 @@ public class MsScenarioParser extends ScenarioImportAbstractParser {
if (StringUtils.isBlank(item.getModulePath())) { if (StringUtils.isBlank(item.getModulePath())) {
item.setApiScenarioModuleId(null); item.setApiScenarioModuleId(null);
} }
parseModule(item, importRequest); parseModule(item.getModulePath(), importRequest, item);
item.setId(UUID.randomUUID().toString()); item.setId(UUID.randomUUID().toString());
item.setProjectId(this.projectId); item.setProjectId(this.projectId);
}); });
@ -39,8 +62,7 @@ public class MsScenarioParser extends ScenarioImportAbstractParser {
return apiDefinitionImport; return apiDefinitionImport;
} }
private void parseModule(ApiScenarioWithBLOBs apiDefinition, ApiTestImportRequest importRequest) { protected void parseModule(String modulePath, ApiTestImportRequest importRequest, ApiScenarioWithBLOBs apiScenarioWithBLOBs) {
String modulePath = apiDefinition.getModulePath();
if (StringUtils.isEmpty(modulePath)) { if (StringUtils.isEmpty(modulePath)) {
return; return;
} }
@ -51,15 +73,14 @@ public class MsScenarioParser extends ScenarioImportAbstractParser {
modulePath = modulePath.substring(0, modulePath.length() - 1); modulePath = modulePath.substring(0, modulePath.length() - 1);
} }
List<String> modules = Arrays.asList(modulePath.split("/")); List<String> modules = Arrays.asList(modulePath.split("/"));
ApiScenarioModule parent = getSelectModule(importRequest.getModuleId()); ApiScenarioModule parent = ApiScenarioImportUtil.getSelectModule(importRequest.getModuleId());
Iterator<String> iterator = modules.iterator(); Iterator<String> iterator = modules.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
String item = iterator.next(); String item = iterator.next();
parent = buildModule(parent, item); parent = ApiScenarioImportUtil.buildModule(parent, item, this.projectId);
if (!iterator.hasNext()) { if (!iterator.hasNext()) {
apiDefinition.setApiScenarioModuleId(parent.getId()); apiScenarioWithBLOBs.setApiScenarioModuleId(parent.getId());
} }
} }
} }
} }

View File

@ -0,0 +1,82 @@
package io.metersphere.api.dto.automation.parse;
import com.alibaba.fastjson.JSON;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.request.MsScenario;
import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.dto.parse.postman.PostmanCollection;
import io.metersphere.api.dto.parse.postman.PostmanCollectionInfo;
import io.metersphere.api.dto.parse.postman.PostmanItem;
import io.metersphere.api.dto.parse.postman.PostmanKeyValue;
import io.metersphere.api.parse.PostmanAbstractParserParser;
import io.metersphere.base.domain.ApiScenarioModule;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.commons.constants.VariableTypeConstants;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class PostmanScenarioParser extends PostmanAbstractParserParser<ScenarioImport> {
@Override
public ScenarioImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
PostmanCollection postmanCollection = JSON.parseObject(testStr, PostmanCollection.class);
List<PostmanKeyValue> variables = postmanCollection.getVariable();
ScenarioImport scenarioImport = new ScenarioImport();
// 场景步骤
LinkedList<MsTestElement> apiScenarioWithBLOBs = new LinkedList<>();
PostmanCollectionInfo info = postmanCollection.getInfo();
ApiScenarioWithBLOBs scenario = new ApiScenarioWithBLOBs();
scenario.setName(info.getName());
MsScenario msScenario = new MsScenario();
msScenario.setName(info.getName());
this.projectId = request.getProjectId();
parseItem(postmanCollection.getItem(), variables, msScenario, apiScenarioWithBLOBs);
// 生成场景对象
List<ApiScenarioWithBLOBs> scenarioWithBLOBs = new LinkedList<>();
parseScenarioWithBLOBs(scenarioWithBLOBs, msScenario, request);
scenarioImport.setData(scenarioWithBLOBs);
return scenarioImport;
}
private void parseScenarioWithBLOBs(List<ApiScenarioWithBLOBs> scenarioWithBLOBsList, MsScenario msScenario, ApiTestImportRequest request) {
ApiScenarioModule module = ApiScenarioImportUtil.buildModule(ApiScenarioImportUtil.getSelectModule(request.getModuleId()), msScenario.getName(), this.projectId);
ApiScenarioWithBLOBs scenarioWithBLOBs = parseScenario(msScenario);
if (module != null) {
scenarioWithBLOBs.setApiScenarioModuleId(module.getId());
scenarioWithBLOBs.setModulePath("/" + module.getName());
}
scenarioWithBLOBsList.add(scenarioWithBLOBs);
}
private void parseItem(List<PostmanItem> items, List<PostmanKeyValue> variables, MsScenario scenario, LinkedList<MsTestElement> results) {
for (PostmanItem item : items) {
List<PostmanItem> childItems = item.getItem();
if (childItems != null) {
parseItem(childItems, variables, scenario, results);
} else {
MsHTTPSamplerProxy request = parsePostman(item);
if (request != null) {
results.add(request);
}
}
}
scenario.setVariables(parseScenarioVariable(variables));
scenario.setHashTree(results);
}
private List<ScenarioVariable> parseScenarioVariable(List<PostmanKeyValue> postmanKeyValues) {
if (postmanKeyValues == null) {
return null;
}
List<ScenarioVariable> keyValues = new ArrayList<>();
postmanKeyValues.forEach(item -> keyValues.add(new ScenarioVariable(item.getKey(), item.getValue(), item.getDescription(), VariableTypeConstants.CONSTANT.name())));
return keyValues;
}
}

View File

@ -7,6 +7,6 @@ import java.util.List;
@Data @Data
public class ScenarioImport { public class ScenarioImport {
private String projectid; private String projectId;
private List<ApiScenarioWithBLOBs> data; private List<ApiScenarioWithBLOBs> data;
} }

View File

@ -1,169 +0,0 @@
package io.metersphere.api.dto.automation.parse;
import io.metersphere.api.dto.automation.ApiScenarioModuleDTO;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.request.RequestType;
import io.metersphere.api.service.ApiScenarioModuleService;
import io.metersphere.base.domain.ApiScenarioModule;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public abstract class ScenarioImportAbstractParser implements ScenarioImportParser {
protected ApiScenarioModuleService apiModuleService;
protected String projectId;
protected ApiScenarioModule getSelectModule(String moduleId) {
apiModuleService = CommonBeanFactory.getBean(ApiScenarioModuleService.class);
if (StringUtils.isNotBlank(moduleId) && !StringUtils.equals("root", moduleId)) {
ApiScenarioModule module = new ApiScenarioModule();
ApiScenarioModuleDTO moduleDTO = apiModuleService.getNode(moduleId);
if (moduleDTO != null) {
BeanUtils.copyBean(module, moduleDTO);
}
return module;
}
return null;
}
protected ApiScenarioModule buildModule(ApiScenarioModule parentModule, String name) {
apiModuleService = CommonBeanFactory.getBean(ApiScenarioModuleService.class);
ApiScenarioModule module;
if (parentModule != null) {
module = apiModuleService.getNewModule(name, this.projectId, parentModule.getLevel() + 1);
module.setParentId(parentModule.getId());
} else {
module = apiModuleService.getNewModule(name, this.projectId, 1);
}
createModule(module);
return module;
}
protected void createModule(ApiScenarioModule module) {
List<ApiScenarioModule> apiModules = apiModuleService.selectSameModule(module);
if (CollectionUtils.isEmpty(apiModules)) {
apiModuleService.addNode(module);
} else {
module.setId(apiModules.get(0).getId());
}
}
protected String getApiTestStr(InputStream source) {
StringBuilder testStr = null;
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(source, StandardCharsets.UTF_8))) {
testStr = new StringBuilder();
String inputStr;
while ((inputStr = bufferedReader.readLine()) != null) {
testStr.append(inputStr);
}
} catch (Exception e) {
MSException.throwException(e.getMessage());
LogUtil.error(e.getMessage(), e);
} finally {
try {
if (source != null) {
source.close();
}
} catch (IOException e) {
MSException.throwException(e.getMessage());
LogUtil.error(e.getMessage(), e);
}
}
return testStr.toString();
}
private String formatPath(String url) {
try {
URL urlObject = new URL(url);
StringBuilder pathBuffer = new StringBuilder(urlObject.getPath());
if (StringUtils.isNotEmpty(urlObject.getQuery())) {
pathBuffer.append("?").append(urlObject.getQuery());
}
return pathBuffer.toString();
} catch (Exception ex) {
return url;
}
}
protected MsHTTPSamplerProxy buildRequest(String name, String path, String method) {
MsHTTPSamplerProxy request = new MsHTTPSamplerProxy();
request.setName(name);
// 路径去掉域名/IP 地址保留方法名称及参数
request.setPath(formatPath(path));
request.setMethod(method);
request.setProtocol(RequestType.HTTP);
request.setId(UUID.randomUUID().toString());
request.setHeaders(new ArrayList<>());
request.setArguments(new ArrayList<>());
request.setRest(new ArrayList<>());
request.setAuthManager(null);
Body body = new Body();
body.initKvs();
body.initBinary();
request.setBody(body);
return request;
}
protected void addHeader(List<KeyValue> headers, String key, String value, String description, String contentType, boolean required) {
boolean hasContentType = false;
for (KeyValue header : headers) {
if (StringUtils.equalsIgnoreCase(header.getName(), key)) {
hasContentType = true;
}
}
if (!hasContentType) {
headers.add(new KeyValue(key, value, description, contentType, required));
}
}
protected void addHeader(List<KeyValue> headers, String key, String value) {
addHeader(headers, key, value, "", "", true);
}
protected void addContentType(List<KeyValue> headers, String contentType) {
addHeader(headers, "Content-Type", contentType);
}
protected void addBodyHeader(MsHTTPSamplerProxy request) {
String contentType = "";
if (request.getBody() != null && StringUtils.isNotBlank(request.getBody().getType())) {
switch (request.getBody().getType()) {
case Body.JSON:
contentType = "application/json";
break;
case Body.WWW_FROM:
contentType = "application/x-www-form-urlencoded";
break;
case Body.XML:
contentType = "application/xml";
break;
case Body.BINARY:
contentType = "application/octet-stream";
break;
}
List<KeyValue> headers = request.getHeaders();
if (headers == null) {
headers = new ArrayList<>();
request.setHeaders(headers);
}
addContentType(request.getHeaders(), contentType);
}
}
}

View File

@ -1,9 +0,0 @@
package io.metersphere.api.dto.automation.parse;
import io.metersphere.api.dto.ApiTestImportRequest;
import java.io.InputStream;
public interface ScenarioImportParser {
ScenarioImport parse(InputStream source, ApiTestImportRequest request);
}

View File

@ -1,14 +1,15 @@
package io.metersphere.api.dto.automation.parse; package io.metersphere.api.dto.automation.parse;
import io.metersphere.api.parse.ApiImportParser;
import io.metersphere.commons.constants.ApiImportPlatform; import io.metersphere.commons.constants.ApiImportPlatform;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
public class ScenarioImportParserFactory { public class ScenarioImportParserFactory {
public static ScenarioImportParser getImportParser(String platform) { public static ApiImportParser getImportParser(String platform) {
if (StringUtils.equals(ApiImportPlatform.Metersphere.name(), platform)) { if (StringUtils.equals(ApiImportPlatform.Metersphere.name(), platform)) {
return new MsScenarioParser(); return new MsScenarioParser();
} else if (StringUtils.equals(ApiImportPlatform.Postman.name(), platform)) { } else if (StringUtils.equals(ApiImportPlatform.Postman.name(), platform)) {
return new MsPostmanParser(); return new PostmanScenarioParser();
} else if (StringUtils.equals(ApiImportPlatform.Jmeter.name(), platform)) { } else if (StringUtils.equals(ApiImportPlatform.Jmeter.name(), platform)) {
return new MsJmeterParser(); return new MsJmeterParser();
} }

View File

@ -12,6 +12,8 @@ import java.util.List;
public class ApiExportResult { public class ApiExportResult {
private String projectName; private String projectName;
private String protocol; private String protocol;
private String projectId;
private String version;
private List<ApiDefinitionWithBLOBs> data; private List<ApiDefinitionWithBLOBs> data;
private List<ApiTestCaseWithBLOBs> cases; private List<ApiTestCaseWithBLOBs> cases;
} }

View File

@ -14,10 +14,6 @@ public class ApiDefinitionImport {
private String protocol; private String protocol;
private List<ApiDefinitionWithBLOBs> data; private List<ApiDefinitionWithBLOBs> data;
//导入场景
private MsScenario scenarioDefinition;
private List<ApiScenarioWithBLOBs> scenarioDefinitionData;
// 新版本带用例导出 // 新版本带用例导出
private List<ApiTestCaseWithBLOBs> cases; private List<ApiTestCaseWithBLOBs> cases;
} }

View File

@ -1,14 +1,15 @@
package io.metersphere.api.parse; package io.metersphere.api.dto.definition.parse;
import io.metersphere.api.parse.ApiImportParser;
import io.metersphere.commons.constants.ApiImportPlatform; import io.metersphere.commons.constants.ApiImportPlatform;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
public class ApiImportParserFactory { public class ApiDefinitionImportParserFactory {
public static ApiImportParser getApiImportParser(String platform) { public static ApiImportParser getApiImportParser(String platform) {
if (StringUtils.equals(ApiImportPlatform.Metersphere.name(), platform)) { if (StringUtils.equals(ApiImportPlatform.Metersphere.name(), platform)) {
return new MsParser(); return new MsDefinitionParser();
} else if (StringUtils.equals(ApiImportPlatform.Postman.name(), platform)) { } else if (StringUtils.equals(ApiImportPlatform.Postman.name(), platform)) {
return new PostmanParser(); return new PostmanDefinitionParser();
} else if (StringUtils.equals(ApiImportPlatform.Swagger2.name(), platform)) { } else if (StringUtils.equals(ApiImportPlatform.Swagger2.name(), platform)) {
return new Swagger2Parser(); return new Swagger2Parser();
} }

View File

@ -0,0 +1,52 @@
package io.metersphere.api.dto.definition.parse;
import io.metersphere.api.dto.definition.ApiModuleDTO;
import io.metersphere.api.dto.scenario.request.RequestType;
import io.metersphere.api.service.ApiModuleService;
import io.metersphere.base.domain.ApiModule;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
public class ApiDefinitionImportUtil {
public static ApiModule getSelectModule(String moduleId) {
ApiModuleService apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
if (StringUtils.isNotBlank(moduleId) && !StringUtils.equals("root", moduleId)) {
ApiModule module = new ApiModule();
ApiModuleDTO moduleDTO = apiModuleService.getNode(moduleId);
if (moduleDTO != null) {
BeanUtils.copyBean(module, moduleDTO);
}
return module;
}
return null;
}
public static ApiModule buildModule(ApiModule parentModule, String name, String projectId) {
ApiModuleService apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
ApiModule module;
if (parentModule != null) {
module = apiModuleService.getNewModule(name, projectId, parentModule.getLevel() + 1);
module.setParentId(parentModule.getId());
} else {
module = apiModuleService.getNewModule(name, projectId, 1);
}
createModule(module);
return module;
}
public static void createModule(ApiModule module) {
ApiModuleService apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
module.setProtocol(RequestType.HTTP);
List<ApiModule> apiModules = apiModuleService.selectSameModule(module);
if (CollectionUtils.isEmpty(apiModules)) {
apiModuleService.addNode(module);
} else {
module.setId(apiModules.get(0).getId());
}
}
}

View File

@ -0,0 +1,99 @@
package io.metersphere.api.dto.definition.parse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.scenario.request.RequestType;
import io.metersphere.api.parse.MsAbstractParser;
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiModule;
import io.metersphere.commons.constants.ApiImportPlatform;
import org.apache.commons.lang3.StringUtils;
import java.io.InputStream;
import java.util.*;
public class MsDefinitionParser extends MsAbstractParser<ApiDefinitionImport> {
@Override
public ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
JSONObject testObject = JSONObject.parseObject(testStr, Feature.OrderedField);
this.projectId = request.getProjectId();
if (testObject.get("projectName") != null || testObject.get("projectId") != null ) {
return parseMsFormat(testStr, request);
} else {
request.setPlatform(ApiImportPlatform.Plugin.name());
ApiDefinitionImport apiImport = new ApiDefinitionImport();
apiImport.setProtocol(RequestType.HTTP);
apiImport.setData(parsePluginFormat(testObject, request, true));
return apiImport;
}
}
protected List<ApiDefinitionWithBLOBs> parsePluginFormat(JSONObject testObject, ApiTestImportRequest importRequest, Boolean isCreateModule) {
List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
testObject.keySet().forEach(tag -> {
String moduleId = null;
if (isCreateModule) {
moduleId = ApiDefinitionImportUtil.buildModule(ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId()), tag, this.projectId).getId();
}
List<MsHTTPSamplerProxy> msHTTPSamplerProxies = parseMsHTTPSamplerProxy(testObject, tag);
for (MsHTTPSamplerProxy msHTTPSamplerProxy : msHTTPSamplerProxies) {
ApiDefinitionWithBLOBs apiDefinition = buildApiDefinition(msHTTPSamplerProxy.getId(), msHTTPSamplerProxy.getName(), msHTTPSamplerProxy.getPath(), msHTTPSamplerProxy.getMethod(), importRequest);
apiDefinition.setModuleId(moduleId);
apiDefinition.setProjectId(this.projectId);
apiDefinition.setRequest(JSONObject.toJSONString(msHTTPSamplerProxy));
apiDefinition.setName(apiDefinition.getPath() + " [" + apiDefinition.getMethod() + "]");
results.add(apiDefinition);
}
});
return results;
}
private ApiDefinitionImport parseMsFormat(String testStr, ApiTestImportRequest importRequest) {
ApiDefinitionImport apiDefinitionImport = JSON.parseObject(testStr, ApiDefinitionImport.class);
apiDefinitionImport.getData().forEach(apiDefinition -> {
parseApiDefinition(apiDefinition, importRequest);
});
return apiDefinitionImport;
}
private void parseApiDefinition(ApiDefinitionWithBLOBs apiDefinition, ApiTestImportRequest importRequest) {
String id = UUID.randomUUID().toString();
if (StringUtils.isBlank(apiDefinition.getModulePath())) {
apiDefinition.setModuleId(null);
}
parseModule(apiDefinition.getModulePath(), importRequest, apiDefinition);
apiDefinition.setId(id);
apiDefinition.setProjectId(this.projectId);
String request = apiDefinition.getRequest();
JSONObject requestObj = JSONObject.parseObject(request);
requestObj.put("id", id);
apiDefinition.setRequest(JSONObject.toJSONString(requestObj));
}
private void parseModule(String modulePath, ApiTestImportRequest importRequest, ApiDefinitionWithBLOBs apiDefinition) {
if (StringUtils.isEmpty(modulePath)) {
return;
}
if (modulePath.startsWith("/")) {
modulePath = modulePath.substring(1, modulePath.length());
}
if (modulePath.endsWith("/")) {
modulePath = modulePath.substring(0, modulePath.length() - 1);
}
List<String> modules = Arrays.asList(modulePath.split("/"));
ApiModule parent = ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId());
Iterator<String> iterator = modules.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
parent = ApiDefinitionImportUtil.buildModule(parent, item, this.projectId);
if (!iterator.hasNext()) {
apiDefinition.setModuleId(parent.getId());
}
}
}
}

View File

@ -0,0 +1,58 @@
package io.metersphere.api.dto.definition.parse;
import com.alibaba.fastjson.JSON;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.parse.postman.PostmanCollection;
import io.metersphere.api.dto.parse.postman.PostmanItem;
import io.metersphere.api.dto.parse.postman.PostmanKeyValue;
import io.metersphere.api.parse.PostmanAbstractParserParser;
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiModule;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class PostmanDefinitionParser extends PostmanAbstractParserParser<ApiDefinitionImport> {
@Override
public ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
this.projectId = request.getProjectId();
PostmanCollection postmanCollection = JSON.parseObject(testStr, PostmanCollection.class);
List<PostmanKeyValue> variables = postmanCollection.getVariable();
ApiDefinitionImport apiImport = new ApiDefinitionImport();
List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
parseItem(postmanCollection.getItem(), variables, results,
ApiDefinitionImportUtil.buildModule(ApiDefinitionImportUtil.getSelectModule(request.getModuleId()), postmanCollection.getInfo().getName(), this.projectId), true);
apiImport.setData(results);
return apiImport;
}
protected void parseItem(List<PostmanItem> items, List<PostmanKeyValue> variables, List<ApiDefinitionWithBLOBs> results, ApiModule parentModule, Boolean isCreateModule) {
for (PostmanItem item : items) {
List<PostmanItem> childItems = item.getItem();
if (childItems != null) {
ApiModule module = null;
if (isCreateModule) {
module = ApiDefinitionImportUtil.buildModule(parentModule, item.getName(), this.projectId);
}
parseItem(childItems, variables, results, module, isCreateModule);
} else {
MsHTTPSamplerProxy msHTTPSamplerProxy = parsePostman(item);
ApiDefinitionWithBLOBs request = buildApiDefinition(msHTTPSamplerProxy.getId(), msHTTPSamplerProxy.getName(),
msHTTPSamplerProxy.getPath(), msHTTPSamplerProxy.getMethod(), new ApiTestImportRequest());
request.setPath(msHTTPSamplerProxy.getPath());
request.setRequest(JSON.toJSONString(msHTTPSamplerProxy));
if (request != null) {
results.add(request);
}
if (parentModule != null) {
request.setModuleId(parentModule.getId());
}
}
}
}
}

View File

@ -1,10 +1,9 @@
package io.metersphere.api.parse; package io.metersphere.api.dto.definition.parse;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.ApiTestImportRequest; import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.definition.response.HttpResponse; import io.metersphere.api.dto.definition.response.HttpResponse;
import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.Body;
@ -57,7 +56,7 @@ public class Swagger2Parser extends SwaggerAbstractParser {
List<ApiDefinitionWithBLOBs> results = new ArrayList<>(); List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
ApiModule parentNode = getSelectModule(importRequest.getModuleId()); ApiModule parentNode = ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId());
for (String pathName : pathNames) { for (String pathName : pathNames) {
Path path = paths.get(pathName); Path path = paths.get(pathName);

View File

@ -1,10 +1,9 @@
package io.metersphere.api.parse; package io.metersphere.api.dto.definition.parse;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.ApiTestImportRequest; import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.definition.response.HttpResponse; import io.metersphere.api.dto.definition.response.HttpResponse;
import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.Body;
@ -78,7 +77,7 @@ public class Swagger3Parser extends SwaggerAbstractParser {
List<ApiDefinitionWithBLOBs> results = new ArrayList<>(); List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
ApiModule parentNode = getSelectModule(importRequest.getModuleId()); ApiModule parentNode = ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId());
for (String pathName : pathNames) { for (String pathName : pathNames) {
PathItem pathItem = paths.get(pathName); PathItem pathItem = paths.get(pathName);

View File

@ -1,16 +1,17 @@
package io.metersphere.api.parse; package io.metersphere.api.dto.definition.parse;
import io.metersphere.api.parse.ApiImportAbstractParser;
import io.metersphere.base.domain.ApiDefinitionWithBLOBs; import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiModule; import io.metersphere.base.domain.ApiModule;
import java.util.List; import java.util.List;
public abstract class SwaggerAbstractParser extends ApiImportAbstractParser { public abstract class SwaggerAbstractParser extends ApiImportAbstractParser<ApiDefinitionImport> {
protected void buildModule(ApiModule parentModule, ApiDefinitionWithBLOBs apiDefinition, List<String> tags) { protected void buildModule(ApiModule parentModule, ApiDefinitionWithBLOBs apiDefinition, List<String> tags) {
if (tags != null) { if (tags != null) {
tags.forEach(tag -> { tags.forEach(tag -> {
ApiModule module = buildModule(parentModule, tag); ApiModule module = ApiDefinitionImportUtil.buildModule(parentModule, tag, this.projectId);
apiDefinition.setModuleId(module.getId()); apiDefinition.setModuleId(module.getId());
}); });
} }

View File

@ -66,9 +66,6 @@ public class MsScenario extends MsTestElement {
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
if (this.getReferenced() != null && this.getReferenced().equals("Deleted")) { if (this.getReferenced() != null && this.getReferenced().equals("Deleted")) {
return; return;
} else if (this.getReferenced() != null && this.getReferenced().equals("REF")) { } else if (this.getReferenced() != null && this.getReferenced().equals("REF")) {
@ -77,16 +74,15 @@ public class MsScenario extends MsTestElement {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ApiScenarioWithBLOBs scenario = apiAutomationService.getApiScenario(this.getId()); ApiScenarioWithBLOBs scenario = apiAutomationService.getApiScenario(this.getId());
JSONObject element = JSON.parseObject(scenario.getScenarioDefinition()); if (scenario != null && StringUtils.isNotEmpty(scenario.getScenarioDefinition())) {
hashTree = mapper.readValue(element.getString("hashTree"), new TypeReference<LinkedList<MsTestElement>>() { JSONObject element = JSON.parseObject(scenario.getScenarioDefinition());
}); hashTree = mapper.readValue(element.getString("hashTree"), new TypeReference<LinkedList<MsTestElement>>() {
});
}
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
} }
config.setStep(this.getName());
config.setStepType("SCENARIO");
config.setEnableCookieShare(enableCookieShare); config.setEnableCookieShare(enableCookieShare);
if (StringUtils.isNotEmpty(environmentId)) { if (StringUtils.isNotEmpty(environmentId)) {
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class); ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
@ -103,6 +99,9 @@ public class MsScenario extends MsTestElement {
this.addCsvDataSet(tree, variables); this.addCsvDataSet(tree, variables);
this.addCounter(tree, variables); this.addCounter(tree, variables);
this.addRandom(tree, variables); this.addRandom(tree, variables);
if (CollectionUtils.isNotEmpty(this.headers)) {
setHeader(tree, this.headers);
}
if (CollectionUtils.isNotEmpty(hashTree)) { if (CollectionUtils.isNotEmpty(hashTree)) {
for (MsTestElement el : hashTree) { for (MsTestElement el : hashTree) {
// 给所有孩子加一个父亲标志 // 给所有孩子加一个父亲标志
@ -110,9 +109,6 @@ public class MsScenario extends MsTestElement {
el.toHashTree(tree, el.getHashTree(), config); el.toHashTree(tree, el.getHashTree(), config);
} }
} }
if (CollectionUtils.isNotEmpty(this.headers)) {
setHeader(tree, this.headers);
}
} }
public void setOldVariables(List<KeyValue> oldVariables) { public void setOldVariables(List<KeyValue> oldVariables) {

View File

@ -164,9 +164,9 @@ public abstract class MsTestElement {
} }
public Arguments addArguments(ParameterConfig config) { public Arguments addArguments(ParameterConfig config) {
Arguments arguments = new Arguments();
if (config != null && config.getConfig() != null && config.getConfig().getCommonConfig() != null if (config != null && config.getConfig() != null && config.getConfig().getCommonConfig() != null
&& CollectionUtils.isNotEmpty(config.getConfig().getCommonConfig().getVariables())) { && CollectionUtils.isNotEmpty(config.getConfig().getCommonConfig().getVariables())) {
Arguments arguments = new Arguments();
arguments.setEnabled(true); arguments.setEnabled(true);
arguments.setName(name + "Variables"); arguments.setName(name + "Variables");
arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName()); arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName());
@ -174,8 +174,9 @@ public abstract class MsTestElement {
config.getConfig().getCommonConfig().getVariables().stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> config.getConfig().getCommonConfig().getVariables().stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue ->
arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=")
); );
return arguments;
} }
return arguments; return null;
} }
protected EnvironmentConfig getEnvironmentConfig(String environmentId) { protected EnvironmentConfig getEnvironmentConfig(String environmentId) {
@ -255,14 +256,15 @@ public abstract class MsTestElement {
} }
} }
public MsTestElement getRootParent(MsTestElement element) { public void getFullPath(MsTestElement element, StringBuilder path) {
if (element.getParent() == null) { if (element.getParent() == null) {
return element; return;
} }
if (MsTestElementConstants.LoopController.name().equals(element.getType())) { if (MsTestElementConstants.LoopController.name().equals(element.getType())) {
return element; return;
} }
return getRootParent(element.getParent()); path.append(element.getResourceId()).append("/");
getFullPath(element.getParent(), path);
} }
protected String getParentName(MsTestElement parent, ParameterConfig config) { protected String getParentName(MsTestElement parent, ParameterConfig config) {
@ -279,13 +281,11 @@ public abstract class MsTestElement {
return "次数循环-" + "${LoopCounterConfigXXX}"; return "次数循环-" + "${LoopCounterConfigXXX}";
} }
} }
return parent.getName(); // 获取全路径以备后面使用
} else if (config != null && StringUtils.isNotEmpty(config.getStep())) { StringBuilder fullPath = new StringBuilder();
if (MsTestElementConstants.SCENARIO.name().equals(config.getStepType())) { getFullPath(parent, fullPath);
return config.getStep();
} else { return fullPath + "<->" + parent.getName();
return config.getStep() + "-" + "${LoopCounterConfigXXX}";
}
} }
return ""; return "";
} }

View File

@ -45,11 +45,11 @@ public class MsThreadGroup extends MsTestElement {
loopController.setName("LoopController"); loopController.setName("LoopController");
loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName()); loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName());
loopController.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("LoopControlPanel")); loopController.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("LoopControlPanel"));
loopController.setEnabled(true); loopController.setEnabled(this.isEnable());
loopController.setLoops(1); loopController.setLoops(1);
ThreadGroup threadGroup = new ThreadGroup(); ThreadGroup threadGroup = new ThreadGroup();
threadGroup.setEnabled(true); threadGroup.setEnabled(this.isEnable());
threadGroup.setName(this.getName()); threadGroup.setName(this.getName());
threadGroup.setProperty(TestElement.TEST_CLASS, ThreadGroup.class.getName()); threadGroup.setProperty(TestElement.TEST_CLASS, ThreadGroup.class.getName());
threadGroup.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ThreadGroupGui")); threadGroup.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ThreadGroupGui"));

View File

@ -8,15 +8,21 @@ import java.util.List;
@Data @Data
public class ParameterConfig { public class ParameterConfig {
// 环境配置 /**
* 环境配置
*/
private EnvironmentConfig config; private EnvironmentConfig config;
// 公共场景参数 /**
* 公共场景参数
*/
private List<ScenarioVariable> variables; private List<ScenarioVariable> variables;
// 公共Cookie /**
* 公共Cookie
*/
private boolean enableCookieShare; private boolean enableCookieShare;
// 步骤
private String step;
private String stepType;
/**
* 是否是导入/导出操作
*/
private boolean isOperating;
} }

View File

@ -27,9 +27,7 @@ public class MsAssertions extends MsTestElement {
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (this.isEnable()) { addAssertions(tree);
addAssertions(tree);
}
} }
private void addAssertions(HashTree hashTree) { private void addAssertions(HashTree hashTree) {
@ -64,7 +62,7 @@ public class MsAssertions extends MsTestElement {
private ResponseAssertion responseAssertion(MsAssertionRegex assertionRegex) { private ResponseAssertion responseAssertion(MsAssertionRegex assertionRegex) {
ResponseAssertion assertion = new ResponseAssertion(); ResponseAssertion assertion = new ResponseAssertion();
assertion.setEnabled(true); assertion.setEnabled(this.isEnable());
assertion.setName(assertionRegex.getDescription()); assertion.setName(assertionRegex.getDescription());
assertion.setProperty(TestElement.TEST_CLASS, ResponseAssertion.class.getName()); assertion.setProperty(TestElement.TEST_CLASS, ResponseAssertion.class.getName());
assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("AssertionGui")); assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("AssertionGui"));
@ -89,7 +87,7 @@ public class MsAssertions extends MsTestElement {
private JSONPathAssertion jsonPathAssertion(MsAssertionJsonPath assertionJsonPath) { private JSONPathAssertion jsonPathAssertion(MsAssertionJsonPath assertionJsonPath) {
JSONPathAssertion assertion = new JSONPathAssertion(); JSONPathAssertion assertion = new JSONPathAssertion();
assertion.setEnabled(true); assertion.setEnabled(this.isEnable());
assertion.setName(StringUtils.isEmpty(assertionJsonPath.getDescription()) ? "JSONPathAssertion" : assertionJsonPath.getDescription()); assertion.setName(StringUtils.isEmpty(assertionJsonPath.getDescription()) ? "JSONPathAssertion" : assertionJsonPath.getDescription());
assertion.setProperty(TestElement.TEST_CLASS, JSONPathAssertion.class.getName()); assertion.setProperty(TestElement.TEST_CLASS, JSONPathAssertion.class.getName());
assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("JSONPathAssertionGui")); assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("JSONPathAssertionGui"));
@ -104,7 +102,7 @@ public class MsAssertions extends MsTestElement {
private XPath2Assertion xPath2Assertion(MsAssertionXPath2 assertionXPath2) { private XPath2Assertion xPath2Assertion(MsAssertionXPath2 assertionXPath2) {
XPath2Assertion assertion = new XPath2Assertion(); XPath2Assertion assertion = new XPath2Assertion();
assertion.setEnabled(true); assertion.setEnabled(this.isEnable());
assertion.setName(StringUtils.isEmpty(assertionXPath2.getExpression()) ? "XPath2Assertion" : assertionXPath2.getExpression()); assertion.setName(StringUtils.isEmpty(assertionXPath2.getExpression()) ? "XPath2Assertion" : assertionXPath2.getExpression());
assertion.setProperty(TestElement.TEST_CLASS, XPath2Assertion.class.getName()); assertion.setProperty(TestElement.TEST_CLASS, XPath2Assertion.class.getName());
assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("XPath2AssertionGui")); assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("XPath2AssertionGui"));
@ -115,7 +113,7 @@ public class MsAssertions extends MsTestElement {
private DurationAssertion durationAssertion(MsAssertionDuration assertionDuration) { private DurationAssertion durationAssertion(MsAssertionDuration assertionDuration) {
DurationAssertion assertion = new DurationAssertion(); DurationAssertion assertion = new DurationAssertion();
assertion.setEnabled(true); assertion.setEnabled(this.isEnable());
assertion.setName("Response In Time: " + assertionDuration.getValue()); assertion.setName("Response In Time: " + assertionDuration.getValue());
assertion.setProperty(TestElement.TEST_CLASS, DurationAssertion.class.getName()); assertion.setProperty(TestElement.TEST_CLASS, DurationAssertion.class.getName());
assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("DurationAssertionGui")); assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("DurationAssertionGui"));
@ -125,7 +123,7 @@ public class MsAssertions extends MsTestElement {
private JSR223Assertion jsr223Assertion(MsAssertionJSR223 assertionJSR223) { private JSR223Assertion jsr223Assertion(MsAssertionJSR223 assertionJSR223) {
JSR223Assertion assertion = new JSR223Assertion(); JSR223Assertion assertion = new JSR223Assertion();
assertion.setEnabled(true); assertion.setEnabled(this.isEnable());
assertion.setName(StringUtils.isEmpty(assertionJSR223.getDesc()) ? "JSR223Assertion" : assertionJSR223.getDesc()); assertion.setName(StringUtils.isEmpty(assertionJSR223.getDesc()) ? "JSR223Assertion" : assertionJSR223.getDesc());
assertion.setProperty(TestElement.TEST_CLASS, JSR223Assertion.class.getName()); assertion.setProperty(TestElement.TEST_CLASS, JSR223Assertion.class.getName());
assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI")); assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));

View File

@ -27,11 +27,8 @@ public class MsHeaderManager extends MsTestElement {
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
HeaderManager headerManager = new HeaderManager(); HeaderManager headerManager = new HeaderManager();
headerManager.setEnabled(true); headerManager.setEnabled(this.isEnable());
headerManager.setName(this.getName() + "Headers"); headerManager.setName(this.getName() + "Headers");
headerManager.setProperty(TestElement.TEST_CLASS, HeaderManager.class.getName()); headerManager.setProperty(TestElement.TEST_CLASS, HeaderManager.class.getName());
headerManager.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("HeaderPanel")); headerManager.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("HeaderPanel"));

View File

@ -26,9 +26,6 @@ public class MsIfController extends MsTestElement {
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
final HashTree groupTree = tree.add(ifController()); final HashTree groupTree = tree.add(ifController());
if (CollectionUtils.isNotEmpty(hashTree)) { if (CollectionUtils.isNotEmpty(hashTree)) {
hashTree.forEach(el -> { hashTree.forEach(el -> {
@ -41,7 +38,7 @@ public class MsIfController extends MsTestElement {
private IfController ifController() { private IfController ifController() {
IfController ifController = new IfController(); IfController ifController = new IfController();
ifController.setEnabled(true); ifController.setEnabled(this.isEnable());
ifController.setName(StringUtils.isEmpty(this.getName()) ? "IfController" : this.getName()); ifController.setName(StringUtils.isEmpty(this.getName()) ? "IfController" : this.getName());
ifController.setProperty(TestElement.TEST_CLASS, IfController.class.getName()); ifController.setProperty(TestElement.TEST_CLASS, IfController.class.getName());
ifController.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("IfControllerPanel")); ifController.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("IfControllerPanel"));

View File

@ -44,21 +44,6 @@ public class MsLoopController extends MsTestElement {
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
if (StringUtils.equals(this.loopType, LoopConstants.WHILE.name()) && this.whileController != null) {
config.setStep("While 循环");
}
if (StringUtils.equals(this.loopType, LoopConstants.FOREACH.name()) && this.forEachController != null) {
config.setStep("ForEach 循环");
}
if (StringUtils.equals(this.loopType, LoopConstants.LOOP_COUNT.name()) && this.countController != null) {
config.setStep("次数循环");
}
config.setStepType("LOOP");
final HashTree groupTree = controller(tree); final HashTree groupTree = controller(tree);
if (CollectionUtils.isNotEmpty(config.getVariables())) { if (CollectionUtils.isNotEmpty(config.getVariables())) {
this.addCsvDataSet(groupTree, config.getVariables()); this.addCsvDataSet(groupTree, config.getVariables());
@ -104,7 +89,7 @@ public class MsLoopController extends MsTestElement {
private LoopController initLoopController() { private LoopController initLoopController() {
LoopController loopController = new LoopController(); LoopController loopController = new LoopController();
loopController.setEnabled(true); loopController.setEnabled(this.isEnable());
loopController.setName("LoopController"); loopController.setName("LoopController");
loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName()); loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName());
loopController.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("LoopControlPanel")); loopController.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("LoopControlPanel"));
@ -142,7 +127,7 @@ public class MsLoopController extends MsTestElement {
return null; return null;
} }
WhileController controller = new WhileController(); WhileController controller = new WhileController();
controller.setEnabled(true); controller.setEnabled(this.isEnable());
controller.setName("WhileController"); controller.setName("WhileController");
controller.setProperty(TestElement.TEST_CLASS, WhileController.class.getName()); controller.setProperty(TestElement.TEST_CLASS, WhileController.class.getName());
controller.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("WhileControllerGui")); controller.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("WhileControllerGui"));
@ -152,7 +137,7 @@ public class MsLoopController extends MsTestElement {
private ForeachController initForeachController() { private ForeachController initForeachController() {
ForeachController controller = new ForeachController(); ForeachController controller = new ForeachController();
controller.setEnabled(true); controller.setEnabled(this.isEnable());
controller.setName("ForeachController"); controller.setName("ForeachController");
controller.setProperty(TestElement.TEST_CLASS, ForeachController.class.getName()); controller.setProperty(TestElement.TEST_CLASS, ForeachController.class.getName());
controller.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ForeachControlPanel")); controller.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ForeachControlPanel"));
@ -188,7 +173,7 @@ public class MsLoopController extends MsTestElement {
private ConstantTimer getCnstantTimer() { private ConstantTimer getCnstantTimer() {
ConstantTimer constantTimer = new ConstantTimer(); ConstantTimer constantTimer = new ConstantTimer();
constantTimer.setEnabled(true); constantTimer.setEnabled(this.isEnable());
constantTimer.setProperty(TestElement.TEST_CLASS, ConstantTimer.class.getName()); constantTimer.setProperty(TestElement.TEST_CLASS, ConstantTimer.class.getName());
constantTimer.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ConstantTimerGui")); constantTimer.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ConstantTimerGui"));
if (StringUtils.equals(this.loopType, LoopConstants.WHILE.name()) && this.whileController != null) { if (StringUtils.equals(this.loopType, LoopConstants.WHILE.name()) && this.whileController != null) {

View File

@ -30,9 +30,6 @@ public class MsExtract extends MsTestElement {
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
addRequestExtractors(tree); addRequestExtractors(tree);
} }
@ -68,7 +65,7 @@ public class MsExtract extends MsTestElement {
private RegexExtractor regexExtractor(MsExtractRegex extractRegex, StringJoiner extract) { private RegexExtractor regexExtractor(MsExtractRegex extractRegex, StringJoiner extract) {
RegexExtractor extractor = new RegexExtractor(); RegexExtractor extractor = new RegexExtractor();
extractor.setEnabled(true); extractor.setEnabled(this.isEnable());
extractor.setName(extractRegex.getVariable() + " RegexExtractor"); extractor.setName(extractRegex.getVariable() + " RegexExtractor");
extractor.setProperty(TestElement.TEST_CLASS, RegexExtractor.class.getName()); extractor.setProperty(TestElement.TEST_CLASS, RegexExtractor.class.getName());
extractor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("RegexExtractorGui")); extractor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("RegexExtractorGui"));
@ -86,7 +83,7 @@ public class MsExtract extends MsTestElement {
private XPath2Extractor xPath2Extractor(MsExtractXPath extractXPath, StringJoiner extract) { private XPath2Extractor xPath2Extractor(MsExtractXPath extractXPath, StringJoiner extract) {
XPath2Extractor extractor = new XPath2Extractor(); XPath2Extractor extractor = new XPath2Extractor();
extractor.setEnabled(true); extractor.setEnabled(this.isEnable());
extractor.setName(extractXPath.getVariable() + " XPath2Extractor"); extractor.setName(extractXPath.getVariable() + " XPath2Extractor");
extractor.setProperty(TestElement.TEST_CLASS, XPath2Extractor.class.getName()); extractor.setProperty(TestElement.TEST_CLASS, XPath2Extractor.class.getName());
extractor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("XPath2ExtractorGui")); extractor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("XPath2ExtractorGui"));
@ -101,7 +98,7 @@ public class MsExtract extends MsTestElement {
private JSONPostProcessor jsonPostProcessor(MsExtractJSONPath extractJSONPath, StringJoiner extract) { private JSONPostProcessor jsonPostProcessor(MsExtractJSONPath extractJSONPath, StringJoiner extract) {
JSONPostProcessor extractor = new JSONPostProcessor(); JSONPostProcessor extractor = new JSONPostProcessor();
extractor.setEnabled(true); extractor.setEnabled(this.isEnable());
extractor.setName(extractJSONPath.getVariable() + " JSONExtractor"); extractor.setName(extractJSONPath.getVariable() + " JSONExtractor");
extractor.setProperty(TestElement.TEST_CLASS, JSONPostProcessor.class.getName()); extractor.setProperty(TestElement.TEST_CLASS, JSONPostProcessor.class.getName());
extractor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("JSONPostProcessorGui")); extractor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("JSONPostProcessorGui"));

View File

@ -29,18 +29,15 @@ public class MsJSR223Processor extends MsTestElement {
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
JSR223Sampler processor = new JSR223Sampler(); JSR223Sampler processor = new JSR223Sampler();
processor.setEnabled(true); processor.setEnabled(this.isEnable());
if (StringUtils.isNotEmpty(this.getName())) { if (StringUtils.isNotEmpty(this.getName())) {
processor.setName(this.getName()); processor.setName(this.getName());
} else { } else {
processor.setName("JSR223Processor"); processor.setName("JSR223Processor");
} }
String name = this.getParentName(this.getParent(), config); String name = this.getParentName(this.getParent(), config);
if (StringUtils.isNotEmpty(name)) { if (StringUtils.isNotEmpty(name) && !config.isOperating()) {
processor.setName(this.getName() + "<->" + name); processor.setName(this.getName() + "<->" + name);
} }
processor.setProperty(TestElement.TEST_CLASS, JSR223Sampler.class.getName()); processor.setProperty(TestElement.TEST_CLASS, JSR223Sampler.class.getName());

View File

@ -29,11 +29,8 @@ public class MsJSR223PostProcessor extends MsTestElement {
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
JSR223PostProcessor processor = new JSR223PostProcessor(); JSR223PostProcessor processor = new JSR223PostProcessor();
processor.setEnabled(true); processor.setEnabled(this.isEnable());
if (StringUtils.isNotEmpty(this.getName())) { if (StringUtils.isNotEmpty(this.getName())) {
processor.setName(this.getName()); processor.setName(this.getName());
} else { } else {

View File

@ -29,9 +29,6 @@ public class MsJSR223PreProcessor extends MsTestElement {
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
final HashTree jsr223PreTree = tree.add(getJSR223PreProcessor()); final HashTree jsr223PreTree = tree.add(getJSR223PreProcessor());
if (CollectionUtils.isNotEmpty(hashTree)) { if (CollectionUtils.isNotEmpty(hashTree)) {
hashTree.forEach(el -> { hashTree.forEach(el -> {
@ -42,7 +39,7 @@ public class MsJSR223PreProcessor extends MsTestElement {
public JSR223PreProcessor getJSR223PreProcessor() { public JSR223PreProcessor getJSR223PreProcessor() {
JSR223PreProcessor processor = new JSR223PreProcessor(); JSR223PreProcessor processor = new JSR223PreProcessor();
processor.setEnabled(true); processor.setEnabled(this.isEnable());
if (StringUtils.isNotEmpty(this.getName())) { if (StringUtils.isNotEmpty(this.getName())) {
processor.setName(this.getName()); processor.setName(this.getName());
} else { } else {

View File

@ -33,7 +33,7 @@ public class MsDubboSampler extends MsTestElement {
private String type = "DubboSampler"; private String type = "DubboSampler";
@JSONField(ordinal = 52) @JSONField(ordinal = 52)
private String protocol = "DUBBO"; private final String protocol = "dubbo://";
@JsonProperty(value = "interface") @JsonProperty(value = "interface")
@JSONField(ordinal = 53, name = "interface") @JSONField(ordinal = 53, name = "interface")
private String _interface; private String _interface;
@ -52,14 +52,11 @@ public class MsDubboSampler extends MsTestElement {
@JSONField(ordinal = 59) @JSONField(ordinal = 59)
private List<KeyValue> attachmentArgs; private List<KeyValue> attachmentArgs;
@JSONField(ordinal = 60) // @JSONField(ordinal = 60)
private Object requestResult; // private Object requestResult;
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
if (this.getReferenced() != null && "Deleted".equals(this.getReferenced())) { if (this.getReferenced() != null && "Deleted".equals(this.getReferenced())) {
return; return;
} }
@ -77,9 +74,10 @@ public class MsDubboSampler extends MsTestElement {
private DubboSample dubboSample(ParameterConfig config) { private DubboSample dubboSample(ParameterConfig config) {
DubboSample sampler = new DubboSample(); DubboSample sampler = new DubboSample();
sampler.setEnabled(this.isEnable());
sampler.setName(this.getName()); sampler.setName(this.getName());
String name = this.getParentName(this.getParent(), config); String name = this.getParentName(this.getParent(), config);
if (StringUtils.isNotEmpty(name)) { if (StringUtils.isNotEmpty(name) && !config.isOperating()) {
sampler.setName(this.getName() + "<->" + name); sampler.setName(this.getName() + "<->" + name);
} }
sampler.setProperty(TestElement.TEST_CLASS, DubboSample.class.getName()); sampler.setProperty(TestElement.TEST_CLASS, DubboSample.class.getName());

View File

@ -85,25 +85,23 @@ public class MsHTTPSamplerProxy extends MsTestElement {
@JSONField(ordinal = 34) @JSONField(ordinal = 34)
private List<KeyValue> arguments; private List<KeyValue> arguments;
@JSONField(ordinal = 35) // @JSONField(ordinal = 35)
private Object requestResult; // private Object requestResult;
@JSONField(ordinal = 36) @JSONField(ordinal = 36)
private MsAuthManager authManager; private MsAuthManager authManager;
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) { if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) {
this.getRefElement(this); this.getRefElement(this);
} }
HTTPSamplerProxy sampler = new HTTPSamplerProxy(); HTTPSamplerProxy sampler = new HTTPSamplerProxy();
sampler.setEnabled(true); sampler.setEnabled(this.isEnable());
sampler.setName(this.getName()); sampler.setName(this.getName());
String name = this.getParentName(this.getParent(), config); String name = this.getParentName(this.getParent(), config);
if (StringUtils.isNotEmpty(name)) { if (StringUtils.isNotEmpty(name) && !config.isOperating()) {
sampler.setName(this.getName() + "<->" + name); sampler.setName(this.getName() + "<->" + name);
} }
sampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName()); sampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
@ -124,7 +122,7 @@ public class MsHTTPSamplerProxy extends MsTestElement {
// 添加环境中的公共变量 // 添加环境中的公共变量
Arguments arguments = this.addArguments(config); Arguments arguments = this.addArguments(config);
if (arguments != null) { if (arguments != null) {
tree.add(this.addArguments(config)); tree.add(arguments);
} }
try { try {
if (config != null && config.getConfig() != null) { if (config != null && config.getConfig() != null) {

View File

@ -46,8 +46,8 @@ public class MsJDBCSampler extends MsTestElement {
private List<KeyValue> variables; private List<KeyValue> variables;
@JSONField(ordinal = 26) @JSONField(ordinal = 26)
private String environmentId; private String environmentId;
@JSONField(ordinal = 27) // @JSONField(ordinal = 27)
private Object requestResult; // private Object requestResult;
@JSONField(ordinal = 28) @JSONField(ordinal = 28)
private String dataSourceId; private String dataSourceId;
@JSONField(ordinal = 29) @JSONField(ordinal = 29)
@ -55,9 +55,6 @@ public class MsJDBCSampler extends MsTestElement {
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) { if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) {
this.getRefElement(this); this.getRefElement(this);
} }
@ -70,7 +67,10 @@ public class MsJDBCSampler extends MsTestElement {
} }
final HashTree samplerHashTree = tree.add(jdbcSampler(config)); final HashTree samplerHashTree = tree.add(jdbcSampler(config));
tree.add(jdbcDataSource()); tree.add(jdbcDataSource());
tree.add(arguments(this.getName() + " Variables", this.getVariables())); Arguments arguments = arguments(this.getName() + " Variables", this.getVariables());
if (arguments != null) {
tree.add(arguments);
}
if (CollectionUtils.isNotEmpty(hashTree)) { if (CollectionUtils.isNotEmpty(hashTree)) {
hashTree.forEach(el -> { hashTree.forEach(el -> {
el.toHashTree(samplerHashTree, el.getHashTree(), config); el.toHashTree(samplerHashTree, el.getHashTree(), config);
@ -95,24 +95,26 @@ public class MsJDBCSampler extends MsTestElement {
} }
private Arguments arguments(String name, List<KeyValue> variables) { private Arguments arguments(String name, List<KeyValue> variables) {
Arguments arguments = new Arguments();
if (CollectionUtils.isNotEmpty(variables)) { if (CollectionUtils.isNotEmpty(variables)) {
Arguments arguments = new Arguments();
arguments.setEnabled(true); arguments.setEnabled(true);
arguments.setName(name); arguments.setName(name + "JDBC_Argument");
arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName()); arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName());
arguments.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ArgumentsPanel")); arguments.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ArgumentsPanel"));
variables.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> variables.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue ->
arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=")
); );
return arguments;
} }
return arguments; return null;
} }
private JDBCSampler jdbcSampler(ParameterConfig config) { private JDBCSampler jdbcSampler(ParameterConfig config) {
JDBCSampler sampler = new JDBCSampler(); JDBCSampler sampler = new JDBCSampler();
sampler.setEnabled(this.isEnable());
sampler.setName(this.getName()); sampler.setName(this.getName());
String name = this.getParentName(this.getParent(), config); String name = this.getParentName(this.getParent(), config);
if (StringUtils.isNotEmpty(name)) { if (StringUtils.isNotEmpty(name) && !config.isOperating()) {
sampler.setName(this.getName() + "<->" + name); sampler.setName(this.getName() + "<->" + name);
} }
sampler.setProperty(TestElement.TEST_CLASS, JDBCSampler.class.getName()); sampler.setProperty(TestElement.TEST_CLASS, JDBCSampler.class.getName());

View File

@ -59,8 +59,8 @@ public class MsTCPSampler extends MsTestElement {
private String password = ""; private String password = "";
@JSONField(ordinal = 33) @JSONField(ordinal = 33)
private String request; private String request;
@JSONField(ordinal = 34) // @JSONField(ordinal = 34)
private Object requestResult; // private Object requestResult;
@JSONField(ordinal = 35) @JSONField(ordinal = 35)
private List<KeyValue> parameters; private List<KeyValue> parameters;
@JSONField(ordinal = 36) @JSONField(ordinal = 36)
@ -72,9 +72,6 @@ public class MsTCPSampler extends MsTestElement {
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) { if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) {
this.getRefElement(this); this.getRefElement(this);
} }
@ -84,7 +81,7 @@ public class MsTCPSampler extends MsTestElement {
// 添加环境中的公共变量 // 添加环境中的公共变量
Arguments arguments = this.addArguments(config); Arguments arguments = this.addArguments(config);
if (arguments != null) { if (arguments != null) {
tree.add(this.addArguments(config)); tree.add(arguments);
} }
final HashTree samplerHashTree = new ListedHashTree(); final HashTree samplerHashTree = new ListedHashTree();
@ -110,9 +107,10 @@ public class MsTCPSampler extends MsTestElement {
private TCPSampler tcpSampler(ParameterConfig config) { private TCPSampler tcpSampler(ParameterConfig config) {
TCPSampler tcpSampler = new TCPSampler(); TCPSampler tcpSampler = new TCPSampler();
tcpSampler.setEnabled(this.isEnable());
tcpSampler.setName(this.getName()); tcpSampler.setName(this.getName());
String name = this.getParentName(this.getParent(), config); String name = this.getParentName(this.getParent(), config);
if (StringUtils.isNotEmpty(name)) { if (StringUtils.isNotEmpty(name) && !config.isOperating()) {
tcpSampler.setName(this.getName() + "<->" + name); tcpSampler.setName(this.getName() + "<->" + name);
} }

View File

@ -26,9 +26,7 @@ public class MsConstantTimer extends MsTestElement {
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
final HashTree groupTree = tree.add(constantTimer()); final HashTree groupTree = tree.add(constantTimer());
if (CollectionUtils.isNotEmpty(hashTree)) { if (CollectionUtils.isNotEmpty(hashTree)) {
hashTree.forEach(el -> { hashTree.forEach(el -> {
@ -39,7 +37,7 @@ public class MsConstantTimer extends MsTestElement {
private ConstantTimer constantTimer() { private ConstantTimer constantTimer() {
ConstantTimer constantTimer = new ConstantTimer(); ConstantTimer constantTimer = new ConstantTimer();
constantTimer.setEnabled(true); constantTimer.setEnabled(this.isEnable());
constantTimer.setName(this.getDelay() + " ms"); constantTimer.setName(this.getDelay() + " ms");
constantTimer.setProperty(TestElement.TEST_CLASS, ConstantTimer.class.getName()); constantTimer.setProperty(TestElement.TEST_CLASS, ConstantTimer.class.getName());
constantTimer.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ConstantTimerGui")); constantTimer.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ConstantTimerGui"));

View File

@ -29,17 +29,17 @@ public class MsJmeterElement extends MsTestElement {
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
try { try {
InputStream inputSource = getStrToStream(jmeterElement); InputStream inputSource = getStrToStream(jmeterElement);
if (inputSource != null) { if (inputSource != null) {
Object scriptWrapper = SaveService.loadElement(inputSource); Object scriptWrapper = SaveService.loadElement(inputSource);
HashTree elementTree = tree; HashTree elementTree = tree;
if (!(scriptWrapper instanceof TestPlan) && !(scriptWrapper instanceof ThreadGroup)) { if (config.isOperating()) {
elementTree = tree.add(scriptWrapper);
} else if (!(scriptWrapper instanceof TestPlan) && !(scriptWrapper instanceof ThreadGroup)) {
elementTree = tree.add(scriptWrapper); elementTree = tree.add(scriptWrapper);
} }
if (CollectionUtils.isNotEmpty(hashTree)) { if (CollectionUtils.isNotEmpty(hashTree)) {
for (MsTestElement el : hashTree) { for (MsTestElement el : hashTree) {
el.toHashTree(elementTree, el.getHashTree(), config); el.toHashTree(elementTree, el.getHashTree(), config);

View File

@ -40,6 +40,10 @@ public class ScenarioVariable {
private String minNumber; private String minNumber;
private String maxNumber; private String maxNumber;
public ScenarioVariable() {
}
public ScenarioVariable(String key, String value, String description, String type) { public ScenarioVariable(String key, String value, String description, String type) {
this.name = key; this.name = key;
this.value = value; this.value = value;

View File

@ -48,8 +48,8 @@ public class TestResult {
result.getRequestResults().forEach(item -> { result.getRequestResults().forEach(item -> {
if (StringUtils.isNotEmpty(item.getName()) && item.getName().indexOf(SEPARATOR) != -1) { if (StringUtils.isNotEmpty(item.getName()) && item.getName().indexOf(SEPARATOR) != -1) {
String array[] = item.getName().split(SEPARATOR); String array[] = item.getName().split(SEPARATOR);
String scenarioName = array[array.length - 1]; String scenarioName = item.getName().replace(array[0] + SEPARATOR, "");
item.setName(item.getName().replace(SEPARATOR + scenarioName, "")); item.setName(array[0]);
if (requestResultMap.containsKey(scenarioName)) { if (requestResultMap.containsKey(scenarioName)) {
requestResultMap.get(scenarioName).add(item); requestResultMap.get(scenarioName).add(item);
} else { } else {
@ -80,6 +80,9 @@ public class TestResult {
ScenarioResult scenarioResult = new ScenarioResult(); ScenarioResult scenarioResult = new ScenarioResult();
BeanUtils.copyBean(scenarioResult, result); BeanUtils.copyBean(scenarioResult, result);
scenarioResult.setName(k); scenarioResult.setName(k);
if (k.indexOf(SEPARATOR) != -1) {
scenarioResult.setName(k.split(SEPARATOR)[1]);
}
scenarioResult.setRequestResults(v); scenarioResult.setRequestResults(v);
scenarios.add(scenarioResult); scenarios.add(scenarioResult);
}); });

View File

@ -1,18 +1,16 @@
package io.metersphere.api.parse; package io.metersphere.api.parse;
import com.alibaba.fastjson.JSON;
import io.metersphere.api.dto.ApiTestImportRequest; import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.ApiModuleDTO; import io.metersphere.api.dto.definition.request.MsScenario;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.Scenario; import io.metersphere.api.dto.scenario.Scenario;
import io.metersphere.api.dto.scenario.request.RequestType; import io.metersphere.api.dto.scenario.request.RequestType;
import io.metersphere.api.service.ApiModuleService;
import io.metersphere.base.domain.ApiDefinitionWithBLOBs; import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiModule; import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.SessionUtils; import io.metersphere.commons.utils.SessionUtils;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
@ -29,10 +27,9 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public abstract class ApiImportAbstractParser implements ApiImportParser { public abstract class ApiImportAbstractParser<T> implements ApiImportParser<T> {
protected String projectId; protected String projectId;
protected ApiModuleService apiModuleService;
protected String getApiTestStr(InputStream source) { protected String getApiTestStr(InputStream source) {
StringBuilder testStr = null; StringBuilder testStr = null;
@ -47,7 +44,9 @@ public abstract class ApiImportAbstractParser implements ApiImportParser {
LogUtil.error(e.getMessage(), e); LogUtil.error(e.getMessage(), e);
} finally { } finally {
try { try {
source.close(); if (source != null) {
source.close();
}
} catch (IOException e) { } catch (IOException e) {
MSException.throwException(e.getMessage()); MSException.throwException(e.getMessage());
LogUtil.error(e.getMessage(), e); LogUtil.error(e.getMessage(), e);
@ -62,42 +61,6 @@ public abstract class ApiImportAbstractParser implements ApiImportParser {
} }
} }
protected ApiModule getSelectModule(String moduleId) {
apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
if (StringUtils.isNotBlank(moduleId) && !StringUtils.equals("root", moduleId)) {
ApiModule module = new ApiModule();
ApiModuleDTO moduleDTO = apiModuleService.getNode(moduleId);
if (moduleDTO != null) {
BeanUtils.copyBean(module, moduleDTO);
}
return module;
}
return null;
}
protected ApiModule buildModule(ApiModule parentModule, String name) {
apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
ApiModule module;
if (parentModule != null) {
module = apiModuleService.getNewModule(name, this.projectId, parentModule.getLevel() + 1);
module.setParentId(parentModule.getId());
} else {
module = apiModuleService.getNewModule(name, this.projectId, 1);
}
createModule(module);
return module;
}
protected void createModule(ApiModule module) {
module.setProtocol(RequestType.HTTP);
List<ApiModule> apiModules = apiModuleService.selectSameModule(module);
if (CollectionUtils.isEmpty(apiModules)) {
apiModuleService.addNode(module);
} else {
module.setId(apiModules.get(0).getId());
}
}
protected String getBodyType(String contentType) { protected String getBodyType(String contentType) {
String bodyType = ""; String bodyType = "";
switch (contentType) { switch (contentType) {
@ -233,4 +196,22 @@ public abstract class ApiImportAbstractParser implements ApiImportParser {
headers.add(new KeyValue(key, value, description, contentType, required)); headers.add(new KeyValue(key, value, description, contentType, required));
} }
} }
protected ApiScenarioWithBLOBs parseScenario(MsScenario msScenario) {
// ApiScenarioModule module = ApiScenarioImportUtil.buildModule(ApiScenarioImportUtil.getSelectModule(request.getModuleId()), msScenario.getName(), this.projectId);
ApiScenarioWithBLOBs scenarioWithBLOBs = new ApiScenarioWithBLOBs();
scenarioWithBLOBs.setName(msScenario.getName());
scenarioWithBLOBs.setProjectId(this.projectId);
if (msScenario != null && CollectionUtils.isNotEmpty(msScenario.getHashTree())) {
scenarioWithBLOBs.setStepTotal(msScenario.getHashTree().size());
}
// if (module != null) {
// scenarioWithBLOBs.setApiScenarioModuleId(module.getId());
// scenarioWithBLOBs.setModulePath("/" + module.getName());
// }
scenarioWithBLOBs.setId(UUID.randomUUID().toString());
scenarioWithBLOBs.setScenarioDefinition(JSON.toJSONString(msScenario));
return scenarioWithBLOBs;
// scenarioWithBLOBsList.add(scenarioWithBLOBs);
}
} }

View File

@ -1,10 +1,9 @@
package io.metersphere.api.parse; package io.metersphere.api.parse;
import io.metersphere.api.dto.ApiTestImportRequest; import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import java.io.InputStream; import java.io.InputStream;
public interface ApiImportParser { public interface ApiImportParser<T> {
ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request); T parse(InputStream source, ApiTestImportRequest request);
} }

View File

@ -0,0 +1,99 @@
package io.metersphere.api.parse;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.commons.utils.LogUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
public abstract class MsAbstractParser<T> extends ApiImportAbstractParser<T> {
protected List<MsHTTPSamplerProxy> parseMsHTTPSamplerProxy(JSONObject testObject, String tag) {
JSONObject requests = testObject.getJSONObject(tag);
List<MsHTTPSamplerProxy> msHTTPSamplerProxies = new ArrayList<>();
requests.keySet().forEach(requestName -> {
JSONObject requestObject = requests.getJSONObject(requestName);
String path = requestObject.getString("url");
String method = requestObject.getString("method");
MsHTTPSamplerProxy request = buildRequest(requestName, path, method);
parseBody(requestObject, request.getBody());
parseHeader(requestObject, request.getHeaders());
parsePath(request);
msHTTPSamplerProxies.add(request);
});
return msHTTPSamplerProxies;
}
private void parsePath(MsHTTPSamplerProxy request) {
if (StringUtils.isNotBlank(request.getPath())) {
String[] split = request.getPath().split("\\?");
String path = split[0];
parseQueryParameters(split, request.getArguments());
request.setPath(path);
} else {
request.setPath("/");
}
}
private void parseQueryParameters(String[] split, List<KeyValue> arguments) {
if (split.length > 1) {
try {
String queryParams = split[1];
queryParams = URLDecoder.decode(queryParams, "UTF-8");
String[] params = queryParams.split("&");
for (String param : params) {
String[] kv = param.split("=");
arguments.add(new KeyValue(kv[0], kv.length < 2 ? null : kv[1]));
}
} catch (UnsupportedEncodingException e) {
LogUtil.info(e.getMessage(), e);
return;
}
}
}
private void parseHeader(JSONObject requestObject, List<KeyValue> msHeaders) {
JSONArray headers = requestObject.getJSONArray("headers");
if (CollectionUtils.isNotEmpty(headers)) {
for (int i = 0; i < headers.size(); i++) {
JSONObject header = headers.getJSONObject(i);
msHeaders.add(new KeyValue(header.getString("name"), header.getString("value")));
}
}
}
private void parseBody(JSONObject requestObject, Body msBody) {
if (requestObject.containsKey("body")) {
Object body = requestObject.get("body");
if (body instanceof JSONArray) {
JSONArray bodies = requestObject.getJSONArray("body");
if (bodies != null) {
StringBuilder bodyStr = new StringBuilder();
for (int i = 0; i < bodies.size(); i++) {
String tmp = bodies.getString(i);
bodyStr.append(tmp);
}
msBody.setType(Body.RAW);
msBody.setRaw(bodyStr.toString());
}
} else if (body instanceof JSONObject) {
JSONObject bodyObj = requestObject.getJSONObject("body");
if (bodyObj != null) {
ArrayList<KeyValue> kvs = new ArrayList<>();
bodyObj.keySet().forEach(key -> {
kvs.add(new KeyValue(key, bodyObj.getString(key)));
});
msBody.setKvs(kvs);
msBody.setType(Body.WWW_FROM);
}
}
}
}
}

View File

@ -1,192 +0,0 @@
package io.metersphere.api.parse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.request.RequestType;
import io.metersphere.api.service.ApiModuleService;
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiModule;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.commons.constants.ApiImportPlatform;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import java.util.function.Consumer;
public class MsParser extends ApiImportAbstractParser {
@Override
public ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
JSONObject testObject = JSONObject.parseObject(testStr, Feature.OrderedField);
apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
this.projectId = request.getProjectId();
if (testObject.get("projectName") != null) {
return parseMsFormat(testStr, request);
} else {
request.setPlatform(ApiImportPlatform.Plugin.name());
return parsePluginFormat(testObject, request, true);
}
}
private ApiDefinitionImport parseMsFormat(String testStr, ApiTestImportRequest importRequest) {
ApiDefinitionImport apiDefinitionImport = JSON.parseObject(testStr, ApiDefinitionImport.class);
apiDefinitionImport.getData().forEach(apiDefinition -> {
parseApiDefinition(apiDefinition, importRequest);
});
return apiDefinitionImport;
}
private void parseApiDefinition(ApiDefinitionWithBLOBs apiDefinition, ApiTestImportRequest importRequest) {
String id = UUID.randomUUID().toString();
if (StringUtils.isBlank(apiDefinition.getModulePath())) {
apiDefinition.setModuleId(null);
}
parseModule(apiDefinition.getModulePath(), importRequest, apiDefinition::setModuleId);
apiDefinition.setId(id);
apiDefinition.setProjectId(this.projectId);
String request = apiDefinition.getRequest();
JSONObject requestObj = JSONObject.parseObject(request);
requestObj.put("id", id);
apiDefinition.setRequest(JSONObject.toJSONString(requestObj));
}
protected ApiDefinitionImport parsePluginFormat(JSONObject testObject, ApiTestImportRequest importRequest, Boolean isCreateModule) {
List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
ApiDefinitionImport apiImport = new ApiDefinitionImport();
apiImport.setProtocol(RequestType.HTTP);
apiImport.setData(results);
testObject.keySet().forEach(tag -> {
String moduleId = "";
if (isCreateModule) {
moduleId = buildModule(getSelectModule(importRequest.getModuleId()), tag).getId();
}
JSONObject requests = testObject.getJSONObject(tag);
String finalModuleId = moduleId;
requests.keySet().forEach(requestName -> {
JSONObject requestObject = requests.getJSONObject(requestName);
String path = requestObject.getString("url");
String method = requestObject.getString("method");
MsHTTPSamplerProxy request = buildRequest(requestName, path, method);
ApiDefinitionWithBLOBs apiDefinition = buildApiDefinition(request.getId(), requestName, path, method,importRequest);
apiDefinition.setModuleId(finalModuleId);
apiDefinition.setProjectId(this.projectId);
parseBody(requestObject, request.getBody());
parseHeader(requestObject, request.getHeaders());
parsePath(request, apiDefinition);
apiDefinition.setRequest(JSONObject.toJSONString(request));
results.add(apiDefinition);
});
});
return apiImport;
}
private void parsePath(MsHTTPSamplerProxy request, ApiDefinitionWithBLOBs apiDefinition) {
if (StringUtils.isNotBlank(request.getPath())) {
String[] split = request.getPath().split("\\?");
String path = split[0];
parseQueryParameters(split, request.getArguments());
request.setPath(path);
apiDefinition.setPath(path);
} else {
request.setPath("/");
apiDefinition.setPath("/");
}
apiDefinition.setName(apiDefinition.getPath() + " [" + apiDefinition.getMethod() + "]");
}
private void parseQueryParameters(String[] split, List<KeyValue> arguments) {
if (split.length > 1) {
try {
String queryParams = split[1];
queryParams = URLDecoder.decode(queryParams, "UTF-8");
String[] params = queryParams.split("&");
for (String param : params) {
String[] kv = param.split("=");
arguments.add(new KeyValue(kv[0], kv[1]));
}
} catch (UnsupportedEncodingException e) {
LogUtil.info(e.getMessage(), e);
return;
}
}
}
private void parseHeader(JSONObject requestObject, List<KeyValue> msHeaders) {
JSONArray headers = requestObject.getJSONArray("headers");
if (CollectionUtils.isNotEmpty(headers)) {
for (int i = 0; i < headers.size(); i++) {
JSONObject header = headers.getJSONObject(i);
msHeaders.add(new KeyValue(header.getString("name"), header.getString("value")));
}
}
}
private void parseBody(JSONObject requestObject, Body msBody) {
if (requestObject.containsKey("body")) {
Object body = requestObject.get("body");
if (body instanceof JSONArray) {
JSONArray bodies = requestObject.getJSONArray("body");
if (bodies != null) {
StringBuilder bodyStr = new StringBuilder();
for (int i = 0; i < bodies.size(); i++) {
String tmp = bodies.getString(i);
bodyStr.append(tmp);
}
msBody.setType(Body.RAW);
msBody.setRaw(bodyStr.toString());
}
} else if (body instanceof JSONObject) {
JSONObject bodyObj = requestObject.getJSONObject("body");
if (bodyObj != null) {
ArrayList<KeyValue> kvs = new ArrayList<>();
bodyObj.keySet().forEach(key -> {
kvs.add(new KeyValue(key, bodyObj.getString(key)));
});
msBody.setKvs(kvs);
msBody.setType(Body.WWW_FROM);
}
}
}
}
protected void parseModule(String modulePath, ApiTestImportRequest importRequest, Consumer<String> consumer) {
if (StringUtils.isBlank(modulePath)) {
return;
}
if (modulePath.startsWith("/")) {
modulePath = modulePath.substring(1, modulePath.length());
}
if (modulePath.endsWith("/")) {
modulePath = modulePath.substring(0, modulePath.length() - 1);
}
List<String> modules = Arrays.asList(modulePath.split("/"));
ApiModule parent = getSelectModule(importRequest.getModuleId());
Iterator<String> iterator = modules.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
parent = buildModule(parent, item);
if (!iterator.hasNext()) {
consumer.accept(parent.getId());
}
}
}
}

View File

@ -2,64 +2,25 @@ package io.metersphere.api.parse;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import io.metersphere.api.dto.definition.request.MsTestElement; import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor; import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.parse.postman.*; import io.metersphere.api.dto.parse.postman.*;
import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiModule;
import io.metersphere.commons.constants.MsRequestBodyType; import io.metersphere.commons.constants.MsRequestBodyType;
import io.metersphere.commons.constants.PostmanRequestBodyMode; import io.metersphere.commons.constants.PostmanRequestBodyMode;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class PostmanParser extends ApiImportAbstractParser { public abstract class PostmanAbstractParserParser<T> extends ApiImportAbstractParser<T> {
@Override protected MsHTTPSamplerProxy parsePostman(PostmanItem requestItem) {
public ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
this.projectId = request.getProjectId();
PostmanCollection postmanCollection = JSON.parseObject(testStr, PostmanCollection.class);
List<PostmanKeyValue> variables = postmanCollection.getVariable();
ApiDefinitionImport apiImport = new ApiDefinitionImport();
List<ApiDefinitionWithBLOBs> results = new ArrayList<>();
parseItem(postmanCollection.getItem(), variables, results, buildModule(getSelectModule(request.getModuleId()), postmanCollection.getInfo().getName()), true);
apiImport.setData(results);
return apiImport;
}
protected void parseItem(List<PostmanItem> items, List<PostmanKeyValue> variables, List<ApiDefinitionWithBLOBs> results, ApiModule parentModule, Boolean isCreateModule) {
for (PostmanItem item : items) {
List<PostmanItem> childItems = item.getItem();
if (childItems != null) {
ApiModule module = null;
if (isCreateModule) {
module = buildModule(parentModule, item.getName());
}
parseItem(childItems, variables, results, module, isCreateModule);
} else {
ApiDefinitionWithBLOBs request = parsePostman(item);
if (request != null) {
results.add(request);
}
if (parentModule != null) {
request.setModuleId(parentModule.getId());
}
}
}
}
private ApiDefinitionWithBLOBs parsePostman(PostmanItem requestItem) {
PostmanRequest requestDesc = requestItem.getRequest(); PostmanRequest requestDesc = requestItem.getRequest();
if (requestDesc == null) { if (requestDesc == null) {
return null; return null;
@ -67,44 +28,45 @@ public class PostmanParser extends ApiImportAbstractParser {
requestDesc.getAuth(); // todo 认证方式等待优化 requestDesc.getAuth(); // todo 认证方式等待优化
PostmanUrl url = requestDesc.getUrl(); PostmanUrl url = requestDesc.getUrl();
MsHTTPSamplerProxy request = buildRequest(requestItem.getName(), url.getRaw(), requestDesc.getMethod()); MsHTTPSamplerProxy request = buildRequest(requestItem.getName(), url.getRaw(), requestDesc.getMethod());
ApiDefinitionWithBLOBs apiDefinition =
buildApiDefinition(request.getId(), requestItem.getName(), url.getRaw(), requestDesc.getMethod(),new ApiTestImportRequest());
if (StringUtils.isNotBlank(request.getPath())) { if (StringUtils.isNotBlank(request.getPath())) {
String path = request.getPath().split("\\?")[0]; String path = request.getPath().split("\\?")[0];
path = path.replace("{{", "${"); path = path.replace("{{", "${");
path = path.replace("}}", "}"); path = path.replace("}}", "}");
request.setPath(path); request.setPath(path);
apiDefinition.setPath(path);
} else { } else {
request.setPath("/"); request.setPath("/");
apiDefinition.setPath("/");
} }
parseBody(request.getBody(), requestDesc); parseBody(request.getBody(), requestDesc);
request.setArguments(parseKeyValue(url.getQuery())); request.setArguments(parseKeyValue(url.getQuery()));
request.setHeaders(parseKeyValue(requestDesc.getHeader())); request.setHeaders(parseKeyValue(requestDesc.getHeader()));
addBodyHeader(request); addBodyHeader(request);
addPreScript(request, requestItem.getEvent()); addPreScript(request, requestItem.getEvent());
apiDefinition.setRequest(JSON.toJSONString(request)); return request;
return apiDefinition;
} }
private void addPreScript(MsHTTPSamplerProxy request, List<PostmanEvent> event) { private void addPreScript(MsHTTPSamplerProxy request, List<PostmanEvent> event) {
if (CollectionUtils.isNotEmpty(event)) { if (request != null && CollectionUtils.isNotEmpty(event)) {
StringBuilder scriptStr = new StringBuilder(); StringBuilder scriptStr = new StringBuilder();
event = event.stream() event = event.stream()
.filter(item -> item.getScript() != null) .filter(item -> item.getScript() != null)
.collect(Collectors.toList()); .collect(Collectors.toList());
event.forEach(item -> { event.forEach(item -> {
PostmanScript script = item.getScript(); PostmanScript script = item.getScript();
List<String> exec = script.getExec(); if (script != null && item.getListen().contains("prerequest")) {
if (CollectionUtils.isNotEmpty(exec)) { List<String> exec = script.getExec();
exec.forEach(col -> { if (CollectionUtils.isNotEmpty(exec)) {
scriptStr.append(col + "/n"); exec.forEach(col -> {
}); if (StringUtils.isNotEmpty(col)) {
scriptStr.append(col + "\n");
}
});
}
} }
}); });
if (StringUtils.isNotBlank(scriptStr)) { if (StringUtils.isNotBlank(scriptStr)) {
MsJSR223PreProcessor jsr223PreProcessor = new MsJSR223PreProcessor(); MsJSR223PreProcessor jsr223PreProcessor = new MsJSR223PreProcessor();
jsr223PreProcessor.setName("JSR223PreProcessor");
jsr223PreProcessor.setScriptLanguage("javascript"); jsr223PreProcessor.setScriptLanguage("javascript");
jsr223PreProcessor.setScript(scriptStr.toString()); jsr223PreProcessor.setScript(scriptStr.toString());
LinkedList<MsTestElement> hashTree = new LinkedList<>(); LinkedList<MsTestElement> hashTree = new LinkedList<>();
@ -129,6 +91,9 @@ public class PostmanParser extends ApiImportAbstractParser {
return; return;
} }
String bodyMode = postmanBody.getString("mode"); String bodyMode = postmanBody.getString("mode");
if (StringUtils.isBlank(bodyMode)) {
return;
}
if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.RAW.value())) { if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.RAW.value())) {
parseRawBody(body, postmanBody, bodyMode); parseRawBody(body, postmanBody, bodyMode);
} else if (StringUtils.equalsAny(bodyMode, PostmanRequestBodyMode.FORM_DATA.value(), PostmanRequestBodyMode.URLENCODED.value())) { } else if (StringUtils.equalsAny(bodyMode, PostmanRequestBodyMode.FORM_DATA.value(), PostmanRequestBodyMode.URLENCODED.value())) {

View File

@ -1,71 +0,0 @@
package io.metersphere.api.parse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.automation.ApiScenrioExportResult;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import io.metersphere.api.dto.definition.request.MsScenario;
import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.service.ApiModuleService;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.commons.constants.ApiImportPlatform;
import io.metersphere.commons.utils.CommonBeanFactory;
import org.apache.commons.lang3.StringUtils;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.UUID;
public class ScenarioMsParser extends MsParser {
@Override
public ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request) {
String testStr = getApiTestStr(source);
JSONObject testObject = JSONObject.parseObject(testStr, Feature.OrderedField);
apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
this.projectId = request.getProjectId();
if (testObject.get("projectId") != null) {
return parseMsFormat(testStr, request);
} else {
request.setPlatform(ApiImportPlatform.Plugin.name());
ApiDefinitionImport apiDefinitionImport = parsePluginFormat(testObject, request, false);
MsScenario msScenario = new MsScenario();
LinkedList<MsTestElement> msHTTPSamplerProxies = new LinkedList<>();
apiDefinitionImport.getData().forEach(res -> {
msHTTPSamplerProxies.add(JSONObject.parseObject(res.getRequest(), MsHTTPSamplerProxy.class));
});
msScenario.setHashTree(msHTTPSamplerProxies);
msScenario.setType("scenario");
apiDefinitionImport.setScenarioDefinition(msScenario);
return apiDefinitionImport;
}
}
private ApiDefinitionImport parseMsFormat(String testStr, ApiTestImportRequest importRequest) {
ApiScenrioExportResult apiScenrioExportResult = JSON.parseObject(testStr, ApiScenrioExportResult.class);
apiScenrioExportResult.getData().forEach(scenario -> {
parseApiDefinition(scenario, importRequest);
});
ApiDefinitionImport apiDefinitionImport = new ApiDefinitionImport();
apiDefinitionImport.setScenarioDefinitionData(apiScenrioExportResult.getData());
return apiDefinitionImport;
}
private void parseApiDefinition(ApiScenarioWithBLOBs scenario, ApiTestImportRequest importRequest) {
String id = UUID.randomUUID().toString();
if (StringUtils.isBlank(scenario.getModulePath())) {
scenario.setApiScenarioModuleId(null);
}
// parseModule(scenario.getModulePath(), importRequest, scenario::setApiScenarioModuleId);
scenario.setId(id);
scenario.setProjectId(this.projectId);
String scenarioDefinition = scenario.getScenarioDefinition();
JSONObject scenarioDefinitionObj = JSONObject.parseObject(scenarioDefinition);
scenarioDefinitionObj.put("id", id);
scenarioDefinitionObj.put("name", scenario.getName());
scenario.setScenarioDefinition(JSONObject.toJSONString(scenarioDefinitionObj));
}
}

View File

@ -35,6 +35,7 @@ import org.aspectj.util.FileUtil;
import org.dom4j.Document; import org.dom4j.Document;
import org.dom4j.DocumentHelper; import org.dom4j.DocumentHelper;
import org.dom4j.Element; import org.dom4j.Element;
import org.dom4j.QName;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
@ -461,55 +462,55 @@ public class APITestService {
}); });
} }
public String updateJmxString(String jmxString,String testName,boolean updateHTTPSamplerProxyName) { /**
* 更新jmx数据处理jmx里的各种参数
* <p>
* 与1.7分支合并时如果该方法产生冲突请以master为准
*
* @param jmxString 原JMX文件
* @param testNameParam 某些节点要替换的testName
* @param isFromScenario 是否来源于场景 来源于场景的话testName要进行处理
* @return
* @author song tianyang
*/
public String updateJmxString(String jmxString, String testNameParam, boolean isFromScenario) {
// 与1.7分支合并时如果该方法产生冲突请以master为准
String attribute_testName = "testname";
String[] requestElementNameArr = new String[]{"HTTPSamplerProxy", "TCPSampler", "JDBCSampler", "DubboSample"};
try { try {
//将ThreadGroup的testname改为接口名称 //将ThreadGroup的testname改为接口名称
Document doc = DocumentHelper.parseText(jmxString);// 获取可续保保单列表报文模板 Document doc = DocumentHelper.parseText(jmxString);// 获取可续保保单列表报文模板
Element root = doc.getRootElement(); Element root = doc.getRootElement();
Element rootHashTreeElement = root.element("hashTree"); Element rootHashTreeElement = root.element("hashTree");
Element innerHashTreeElement = rootHashTreeElement.elements("hashTree").get(0);
Element theadGroupElement = innerHashTreeElement.elements("ThreadGroup").get(0);
theadGroupElement.attribute("testname").setText(testName);
List<Element> thirdHashTreeElementList = innerHashTreeElement.elements("hashTree"); List<Element> innerHashTreeElementList = rootHashTreeElement.elements("hashTree");
for (Element element : thirdHashTreeElementList) { for (Element innerHashTreeElement : innerHashTreeElementList) {
if(updateHTTPSamplerProxyName){ //转换DubboDefaultConfigGui
List<Element> sampleProxyElementList = element.elements("HTTPSamplerProxy"); List<Element> configTestElementList = innerHashTreeElement.elements("ConfigTestElement");
for (Element itemElement : sampleProxyElementList) { for (Element configTestElement : configTestElementList) {
itemElement.attribute("testname").setText(testName); this.updateDubboDefaultConfigGuiElement(configTestElement);
}
List<Element> theadGroupElementList = innerHashTreeElement.elements("ThreadGroup");
for (Element theadGroupElement : theadGroupElementList) {
if (StringUtils.isNotEmpty(testNameParam)) {
theadGroupElement.attribute(attribute_testName).setText(testNameParam);
} }
} }
//检查有没有自定义参数 List<Element> thirdHashTreeElementList = innerHashTreeElement.elements("hashTree");
List<Element> scriptHashTreeElementList = element.elements("hashTree"); for (Element element : thirdHashTreeElementList) {
for (Element scriptHashTreeElement : scriptHashTreeElementList) { String testName = testNameParam;
boolean isRemove = false;
List<Element> removeElement = new ArrayList<>();
List<Element> scriptElementItemList = scriptHashTreeElement.elements();
for (Element hashTreeItemElement : scriptElementItemList) {
String className = hashTreeItemElement.attributeValue("testclass");
String qname = hashTreeItemElement.getQName().getName();
if (isRemove) { //更新请求类节点的部份属性
if (org.apache.commons.lang3.StringUtils.equals("hashTree", qname)) { this.updateRequestElementInfo(element, testNameParam, requestElementNameArr, isFromScenario);
removeElement.add(hashTreeItemElement); //检查有无jmeter不是别的自定义参数
} this.checkPrivateFunctionNode(element);
}
isRemove = false;
if (org.apache.commons.lang3.StringUtils.equals(className, "JSR223PostProcessor")) {
List<Element> scriptElements = hashTreeItemElement.elements("stringProp");
for (Element scriptElement : scriptElements) {
String scriptName = scriptElement.attributeValue("name");
String contentValue = scriptElement.getStringValue();
if ("script".equals(scriptName) && contentValue.startsWith("io.metersphere.api.jmeter.JMeterVars.addVars")) { //转换DubboDefaultConfigGui
isRemove = true; List<Element> hashTreeConfigTestElementList = element.elements("ConfigTestElement");
removeElement.add(hashTreeItemElement); for (Element configTestElement : hashTreeConfigTestElementList) {
} this.updateDubboDefaultConfigGuiElement(configTestElement);
}
}
}
for (Element itemElement : removeElement) {
scriptHashTreeElement.remove(itemElement);
} }
} }
} }
@ -517,6 +518,86 @@ public class APITestService {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
if (!jmxString.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")) {
jmxString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + jmxString;
}
return jmxString; return jmxString;
} }
private void updateDubboDefaultConfigGuiElement(Element configTestElement) {
String dubboDefaultConfigGuiClassName = "io.github.ningyu.jmeter.plugin.dubbo.gui.DubboDefaultConfigGui";
if (configTestElement == null) {
return;
}
String guiClassValue = configTestElement.attributeValue("guiclass");
if (StringUtils.equals(guiClassValue, "DubboDefaultConfigGui")) {
configTestElement.attribute("guiclass").setText(dubboDefaultConfigGuiClassName);
}
}
private void checkPrivateFunctionNode(Element element) {
List<Element> scriptHashTreeElementList = element.elements("hashTree");
for (Element scriptHashTreeElement : scriptHashTreeElementList) {
boolean isRemove = false;
List<Element> removeElement = new ArrayList<>();
List<Element> scriptElementItemList = scriptHashTreeElement.elements();
for (Element hashTreeItemElement : scriptElementItemList) {
String className = hashTreeItemElement.attributeValue("testclass");
String qname = hashTreeItemElement.getQName().getName();
if (isRemove) {
if (org.apache.commons.lang3.StringUtils.equals("hashTree", qname)) {
removeElement.add(hashTreeItemElement);
}
}
isRemove = false;
if (org.apache.commons.lang3.StringUtils.equals(className, "JSR223PostProcessor")) {
List<Element> scriptElements = hashTreeItemElement.elements("stringProp");
for (Element scriptElement : scriptElements) {
String scriptName = scriptElement.attributeValue("name");
String contentValue = scriptElement.getStringValue();
if ("script".equals(scriptName) && contentValue.startsWith("io.metersphere.api.jmeter.JMeterVars.addVars")) {
isRemove = true;
removeElement.add(hashTreeItemElement);
}
}
}
}
for (Element itemElement : removeElement) {
scriptHashTreeElement.remove(itemElement);
}
}
}
private void updateRequestElementInfo(Element element, String testNameParam, String[] requestElementNameArr, boolean isFromScenario) {
String attribute_testName = "testname";
String scenarioCaseNameSplit = "<->";
String testName = testNameParam;
for (String requestElementName : requestElementNameArr) {
List<Element> sampleProxyElementList = element.elements(requestElementName);
for (Element itemElement : sampleProxyElementList) {
if (isFromScenario) {
testName = itemElement.attributeValue(attribute_testName);
String[] testNameArr = testName.split(scenarioCaseNameSplit);
if (testNameArr.length > 0) {
testName = testNameArr[0];
}
}
itemElement.attribute(attribute_testName).setText(testName);
//double的话有额外处理方式
if (StringUtils.equals(requestElementName, "DubboSample")) {
//dubbo节点要更新 标签guiClass testClass
itemElement.setName("io.github.ningyu.jmeter.plugin.dubbo.sample.DubboSample");
itemElement.attribute("testclass").setText("io.github.ningyu.jmeter.plugin.dubbo.sample.DubboSample");
itemElement.attribute("guiclass").setText("io.github.ningyu.jmeter.plugin.dubbo.gui.DubboSampleGui");
}
}
}
}
} }

View File

@ -10,14 +10,15 @@ import io.metersphere.api.dto.DeleteAPIReportRequest;
import io.metersphere.api.dto.JmxInfoDTO; import io.metersphere.api.dto.JmxInfoDTO;
import io.metersphere.api.dto.automation.*; import io.metersphere.api.dto.automation.*;
import io.metersphere.api.dto.automation.parse.ScenarioImport; import io.metersphere.api.dto.automation.parse.ScenarioImport;
import io.metersphere.api.dto.automation.parse.ScenarioImportParser;
import io.metersphere.api.dto.automation.parse.ScenarioImportParserFactory; import io.metersphere.api.dto.automation.parse.ScenarioImportParserFactory;
import io.metersphere.api.dto.datacount.ApiDataCountResult; import io.metersphere.api.dto.datacount.ApiDataCountResult;
import io.metersphere.api.dto.definition.RunDefinitionRequest; import io.metersphere.api.dto.definition.RunDefinitionRequest;
import io.metersphere.api.dto.definition.request.*; import io.metersphere.api.dto.definition.request.*;
import io.metersphere.api.dto.definition.request.unknown.MsJmeterElement;
import io.metersphere.api.dto.definition.request.variable.ScenarioVariable; import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; 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.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiScenarioMapper; import io.metersphere.base.mapper.ApiScenarioMapper;
import io.metersphere.base.mapper.ApiScenarioReportMapper; import io.metersphere.base.mapper.ApiScenarioReportMapper;
@ -435,6 +436,56 @@ public class ApiAutomationService {
return jmeterHashTree; return jmeterHashTree;
} }
private String generateJmx(ApiScenarioWithBLOBs apiScenario) {
HashTree jmeterHashTree = new ListedHashTree();
MsTestPlan testPlan = new MsTestPlan();
testPlan.setName(apiScenario.getName());
testPlan.setHashTree(new LinkedList<>());
ParameterConfig config = new ParameterConfig();
config.setOperating(true);
try {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JSONObject element = JSON.parseObject(apiScenario.getScenarioDefinition());
MsScenario scenario = JSONObject.parseObject(apiScenario.getScenarioDefinition(), MsScenario.class);
// 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取
if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) {
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
new TypeReference<LinkedList<MsTestElement>>() {
});
scenario.setHashTree(elements);
}
if (StringUtils.isNotEmpty(element.getString("variables"))) {
LinkedList<ScenarioVariable> variables = mapper.readValue(element.getString("variables"),
new TypeReference<LinkedList<ScenarioVariable>>() {
});
scenario.setVariables(variables);
}
// 针对导入的jmx 处理
if (CollectionUtils.isNotEmpty(scenario.getHashTree()) && (scenario.getHashTree().get(0) instanceof MsJmeterElement)) {
scenario.toHashTree(jmeterHashTree, scenario.getHashTree(), config);
return scenario.getJmx(jmeterHashTree);
} else {
MsThreadGroup group = new MsThreadGroup();
group.setLabel(apiScenario.getName());
group.setName(apiScenario.getName());
group.setEnableCookieShare(scenario.isEnableCookieShare());
group.setHashTree(new LinkedList<MsTestElement>() {{
this.add(scenario);
}});
testPlan.getHashTree().add(group);
}
} catch (Exception ex) {
ex.printStackTrace();
MSException.throwException(ex.getMessage());
}
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), config);
return testPlan.getJmx(jmeterHashTree);
}
/** /**
* 场景测试执行 * 场景测试执行
* *
@ -515,7 +566,6 @@ public class ApiAutomationService {
ParameterConfig config = new ParameterConfig(); ParameterConfig config = new ParameterConfig();
config.setConfig(envConfig); config.setConfig(envConfig);
HashTree hashTree = request.getTestElement().generateHashTree(config); HashTree hashTree = request.getTestElement().generateHashTree(config);
System.out.println(request.getTestElement().getJmx(hashTree));
// 调用执行方法 // 调用执行方法
createScenarioReport(request.getId(), request.getScenarioId(), request.getScenarioName(), ReportTriggerMode.MANUAL.name(), request.getExecuteType(), request.getProjectId(), createScenarioReport(request.getId(), request.getScenarioId(), request.getScenarioName(), ReportTriggerMode.MANUAL.name(), request.getExecuteType(), request.getProjectId(),
SessionUtils.getUserId()); SessionUtils.getUserId());
@ -668,7 +718,7 @@ public class ApiAutomationService {
HashTree jmeterHashTree = generateHashTree(apiScenarios, request, null); HashTree jmeterHashTree = generateHashTree(apiScenarios, request, null);
String jmx = testPlan.getJmx(jmeterHashTree); String jmx = testPlan.getJmx(jmeterHashTree);
jmx = apiTestService.updateJmxString(jmx,testName,false); jmx = apiTestService.updateJmxString(jmx, testName, true);
//将ThreadGroup的testname改为接口名称 //将ThreadGroup的testname改为接口名称
// Document doc = DocumentHelper.parseText(jmx);// 获取可续保保单列表报文模板 // Document doc = DocumentHelper.parseText(jmx);// 获取可续保保单列表报文模板
@ -720,16 +770,6 @@ public class ApiAutomationService {
} }
} }
public List<ApiScenarioWithBLOBs> get(ApiScenarioRequest request) {
ApiScenarioExample example = new ApiScenarioExample();
if (CollectionUtils.isNotEmpty(request.getIds())) {
example.createCriteria().andIdIn(request.getIds());
} else {
example.createCriteria().andProjectIdEqualTo(request.getProjectId());
}
return apiScenarioMapper.selectByExampleWithBLOBs(example);
}
public List<ApiScenarioWithBLOBs> getWithBLOBs(ApiScenarioWithBLOBs request) { public List<ApiScenarioWithBLOBs> getWithBLOBs(ApiScenarioWithBLOBs request) {
ApiScenarioExample example = new ApiScenarioExample(); ApiScenarioExample example = new ApiScenarioExample();
example.createCriteria().andNameEqualTo(request.getName()).andProjectIdEqualTo(request.getProjectId()).andStatusNotEqualTo("Trash").andIdNotEqualTo(request.getId()); example.createCriteria().andNameEqualTo(request.getName()).andProjectIdEqualTo(request.getProjectId()).andStatusNotEqualTo("Trash").andIdNotEqualTo(request.getId());
@ -801,10 +841,12 @@ public class ApiAutomationService {
} }
public ScenarioImport scenarioImport(MultipartFile file, ApiTestImportRequest request) { public ScenarioImport scenarioImport(MultipartFile file, ApiTestImportRequest request) {
ScenarioImportParser apiImportParser = ScenarioImportParserFactory.getImportParser(request.getPlatform()); ApiImportParser apiImportParser = ScenarioImportParserFactory.getImportParser(request.getPlatform());
ScenarioImport apiImport = null; ScenarioImport apiImport = null;
Optional.ofNullable(file)
.ifPresent(item -> request.setFileName(file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf("."))));
try { try {
apiImport = Objects.requireNonNull(apiImportParser).parse(file == null ? null : file.getInputStream(), request); apiImport = (ScenarioImport) Objects.requireNonNull(apiImportParser).parse(file == null ? null : file.getInputStream(), request);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e.getMessage(), e); LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("parse_data_error")); MSException.throwException(Translator.get("parse_data_error"));
@ -815,16 +857,33 @@ public class ApiAutomationService {
return apiImport; return apiImport;
} }
public ApiScenrioExportResult export(ApiScenarioBatchRequest request) { private List<ApiScenarioWithBLOBs> getExportResult(ApiScenarioBatchRequest request) {
ServiceUtils.getSelectAllIds(request, request.getCondition(), ServiceUtils.getSelectAllIds(request, request.getCondition(),
(query) -> extApiScenarioMapper.selectIdsByQuery((ApiScenarioRequest) query)); (query) -> extApiScenarioMapper.selectIdsByQuery((ApiScenarioRequest) query));
ApiScenarioExample example = new ApiScenarioExample(); ApiScenarioExample example = new ApiScenarioExample();
example.createCriteria().andIdIn(request.getIds()); example.createCriteria().andIdIn(request.getIds());
List<ApiScenarioWithBLOBs> apiScenarioWithBLOBs = apiScenarioMapper.selectByExampleWithBLOBs(example); List<ApiScenarioWithBLOBs> apiScenarioWithBLOBs = apiScenarioMapper.selectByExampleWithBLOBs(example);
ApiScenrioExportResult result = new ApiScenrioExportResult(); return apiScenarioWithBLOBs;
result.setData(apiScenarioWithBLOBs); }
public ApiScenrioExportResult export(ApiScenarioBatchRequest request) {
ApiScenrioExportResult result = new ApiScenrioExportResult();
result.setData(getExportResult(request));
result.setProjectId(request.getProjectId()); result.setProjectId(request.getProjectId());
result.setVersion(System.getenv("MS_VERSION")); result.setVersion(System.getenv("MS_VERSION"));
return result; return result;
} }
public List<ApiScenrioExportJmx> exportJmx(ApiScenarioBatchRequest request) {
List<ApiScenarioWithBLOBs> apiScenarioWithBLOBs = getExportResult(request);
// 生成jmx
List<ApiScenrioExportJmx> resList = new ArrayList<>();
apiScenarioWithBLOBs.forEach(item -> {
String jmx = generateJmx(item);
ApiScenrioExportJmx scenrioExportJmx = new ApiScenrioExportJmx(item.getName(), apiTestService.updateJmxString(jmx, null, true));
resList.add(scenrioExportJmx);
});
return resList;
}
} }

View File

@ -18,7 +18,7 @@ import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.jmeter.RequestResult; import io.metersphere.api.jmeter.RequestResult;
import io.metersphere.api.jmeter.TestResult; import io.metersphere.api.jmeter.TestResult;
import io.metersphere.api.parse.ApiImportParser; import io.metersphere.api.parse.ApiImportParser;
import io.metersphere.api.parse.ApiImportParserFactory; import io.metersphere.api.dto.definition.parse.ApiDefinitionImportParserFactory;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*; import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.*; import io.metersphere.base.mapper.ext.*;
@ -130,6 +130,9 @@ public class ApiDefinitionService {
public void create(SaveApiDefinitionRequest request, List<MultipartFile> bodyFiles) { public void create(SaveApiDefinitionRequest request, List<MultipartFile> bodyFiles) {
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds()); List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
if (StringUtils.equals(request.getProtocol(), "DUBBO")) {
request.setMethod("dubbo://");
}
createTest(request); createTest(request);
FileUtils.createBodyFiles(bodyUploadIds, bodyFiles); FileUtils.createBodyFiles(bodyUploadIds, bodyFiles);
} }
@ -140,6 +143,9 @@ public class ApiDefinitionService {
} }
List<String> bodyUploadIds = request.getBodyUploadIds(); List<String> bodyUploadIds = request.getBodyUploadIds();
request.setBodyUploadIds(null); request.setBodyUploadIds(null);
if (StringUtils.equals(request.getProtocol(), "DUBBO")) {
request.setMethod("dubbo://");
}
updateTest(request); updateTest(request);
FileUtils.createBodyFiles(bodyUploadIds, bodyFiles); FileUtils.createBodyFiles(bodyUploadIds, bodyFiles);
} }
@ -382,6 +388,9 @@ public class ApiDefinitionService {
apiTestCase.setUpdateUserId(SessionUtils.getUserId()); apiTestCase.setUpdateUserId(SessionUtils.getUserId());
apiTestCase.setNum(getNextNum(apiTestCase.getApiDefinitionId())); apiTestCase.setNum(getNextNum(apiTestCase.getApiDefinitionId()));
apiTestCase.setPriority("P0"); apiTestCase.setPriority("P0");
if (apiTestCase.getName().length() > 255) {
apiTestCase.setName(apiTestCase.getName().substring(0, 255));
}
if (!isInsert) { if (!isInsert) {
apiTestCase.setName(apiTestCase.getName() + "_" + apiTestCase.getId().substring(0, 5)); apiTestCase.setName(apiTestCase.getName() + "_" + apiTestCase.getId().substring(0, 5));
} }
@ -490,10 +499,10 @@ public class ApiDefinitionService {
public ApiDefinitionImport apiTestImport(MultipartFile file, ApiTestImportRequest request) { public ApiDefinitionImport apiTestImport(MultipartFile file, ApiTestImportRequest request) {
ApiImportParser apiImportParser = ApiImportParserFactory.getApiImportParser(request.getPlatform()); ApiImportParser apiImportParser = ApiDefinitionImportParserFactory.getApiImportParser(request.getPlatform());
ApiDefinitionImport apiImport = null; ApiDefinitionImport apiImport = null;
try { try {
apiImport = Objects.requireNonNull(apiImportParser).parse(file == null ? null : file.getInputStream(), request); apiImport = (ApiDefinitionImport) Objects.requireNonNull(apiImportParser).parse(file == null ? null : file.getInputStream(), request);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e.getMessage(), e); LogUtil.error(e.getMessage(), e);
MSException.throwException(Translator.get("parse_data_error")); MSException.throwException(Translator.get("parse_data_error"));
@ -615,7 +624,7 @@ public class ApiDefinitionService {
return example; return example;
} }
private List<String> getAllApiIdsByFontedSelect(Map<String, List<String>> filters, String name, List<String> moduleIds, String projectId, List<String> unSelectIds,String protocol) { private List<String> getAllApiIdsByFontedSelect(Map<String, List<String>> filters, String name, List<String> moduleIds, String projectId, List<String> unSelectIds, String protocol) {
ApiDefinitionRequest request = new ApiDefinitionRequest(); ApiDefinitionRequest request = new ApiDefinitionRequest();
request.setFilters(filters); request.setFilters(filters);
request.setName(name); request.setName(name);
@ -744,6 +753,8 @@ public class ApiDefinitionService {
apiExportResult.setCases(apiTestCaseService.selectCasesBydApiIds(request.getIds())); apiExportResult.setCases(apiTestCaseService.selectCasesBydApiIds(request.getIds()));
apiExportResult.setProjectName(request.getProjectId()); apiExportResult.setProjectName(request.getProjectId());
apiExportResult.setProtocol(request.getProtocol()); apiExportResult.setProtocol(request.getProtocol());
apiExportResult.setProjectId(request.getProjectId());
apiExportResult.setVersion(System.getenv("MS_VERSION"));
return apiExportResult; return apiExportResult;
} }
} }

View File

@ -5,13 +5,13 @@
SELECT api.id,api.name FROM Api_definition api SELECT api.id,api.name FROM Api_definition api
<where> <where>
<if test="request.projectId != null"> <if test="request.projectId != null">
api.project_Id = #{request.projectId} AND api.project_Id = #{request.projectId}
</if> </if>
<if test="request.name != null"> <if test="request.name != null and request.name != '' ">
api.project_Id like CONCAT('%', #{request.name},'%') AND api.name like CONCAT('%', #{request.name},'%')
</if> </if>
<if test="request.type != null"> <if test="request.type != null and request.type != '' and request.type != 'ALL' ">
api.method = #{request.type} AND api.method = #{request.type}
</if> </if>
<if test="request.moduleIds != null and request.moduleIds.size() > 0"> <if test="request.moduleIds != null and request.moduleIds.size() > 0">

View File

@ -4,7 +4,6 @@ import io.metersphere.commons.exception.MSException;
import io.metersphere.controller.request.BaseQueryRequest; import io.metersphere.controller.request.BaseQueryRequest;
import io.metersphere.controller.request.OrderRequest; import io.metersphere.controller.request.OrderRequest;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -26,13 +25,14 @@ public class ServiceUtils {
} }
/** /**
* 获取前端全选的id列表 * 获取前端全选的id列表
*
* @param queryRequest 查询条件 * @param queryRequest 查询条件
* @param func 查询id列表的数据库查询 * @param func 查询id列表的数据库查询
* @return * @return
*/ */
public static<T> void getSelectAllIds( T batchRequest, BaseQueryRequest queryRequest, Function<BaseQueryRequest, List<String>> func) { public static <T> void getSelectAllIds(T batchRequest, BaseQueryRequest queryRequest, Function<BaseQueryRequest, List<String>> func) {
if (queryRequest.isSelectAll()) { if (queryRequest != null && queryRequest.isSelectAll()) {
List<String> ids = func.apply(queryRequest); List<String> ids = func.apply(queryRequest);
if (!ids.isEmpty()) { if (!ids.isEmpty()) {
ids = ids.stream() ids = ids.stream()

@ -1 +1 @@
Subproject commit 5e0b365f1080197e84055e80071165787e2e79c5 Subproject commit b9042074b780205e275c674f64417799110519fd

View File

@ -9,6 +9,7 @@
@setNodeTree="setNodeTree" @setNodeTree="setNodeTree"
@enableTrash="enableTrash" @enableTrash="enableTrash"
@exportAPI="exportAPI" @exportAPI="exportAPI"
@exportJmx="exportJmx"
@refreshAll="refreshAll" @refreshAll="refreshAll"
:type="'edit'" :type="'edit'"
ref="nodeTree"/> ref="nodeTree"/>
@ -69,7 +70,6 @@
import MsApiScenarioModule from "@/business/components/api/automation/scenario/ApiScenarioModule"; import MsApiScenarioModule from "@/business/components/api/automation/scenario/ApiScenarioModule";
import MsEditApiScenario from "./scenario/EditApiScenario"; import MsEditApiScenario from "./scenario/EditApiScenario";
import {getCurrentProjectID} from "../../../../common/js/utils"; import {getCurrentProjectID} from "../../../../common/js/utils";
import {PROJECT_NAME} from "../../../../common/js/constants";
export default { export default {
name: "ApiAutomation", name: "ApiAutomation",
@ -131,25 +131,10 @@
}, },
methods: { methods: {
exportAPI() { exportAPI() {
let obj = {projectName: localStorage.getItem(PROJECT_NAME)} this.$refs.apiScenarioList.exportApi();
let condition = {projectId: getCurrentProjectID(), ids: this.$refs.apiScenarioList.selection};
let url = "/api/automation/list/all";
this.loading = true;
this.$post(url, condition, response => {
obj.data = response.data;
this.buildApiPath(obj.data);
this.loading = false;
downloadFile("Metersphere_Scenario_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj));
});
}, },
buildApiPath(apis) { exportJmx(){
apis.forEach((api) => { this.$refs.apiScenarioList.exportJmx();
this.moduleOptions.forEach(item => {
if (api.moduleId === item.id) {
api.modulePath = item.path;
}
});
});
}, },
checkRedirectEditPage(redirectParam) { checkRedirectEditPage(redirectParam) {
if (redirectParam != null) { if (redirectParam != null) {

View File

@ -167,50 +167,50 @@
</template> </template>
<script> <script>
import MsTableHeader from "@/business/components/common/components/MsTableHeader"; import MsTableHeader from "@/business/components/common/components/MsTableHeader";
import MsTablePagination from "@/business/components/common/pagination/TablePagination"; import MsTablePagination from "@/business/components/common/pagination/TablePagination";
import ShowMoreBtn from "@/business/components/track/case/components/ShowMoreBtn"; import ShowMoreBtn from "@/business/components/track/case/components/ShowMoreBtn";
import MsTag from "../../../common/components/MsTag"; import MsTag from "../../../common/components/MsTag";
import {downloadFile, getCurrentProjectID, getCurrentUser, getUUID} from "@/common/js/utils"; import {downloadFile, getCurrentProjectID, getCurrentUser, getUUID} from "@/common/js/utils";
import MsApiReportDetail from "../report/ApiReportDetail"; import MsApiReportDetail from "../report/ApiReportDetail";
import MsTableMoreBtn from "./TableMoreBtn"; import MsTableMoreBtn from "./TableMoreBtn";
import MsScenarioExtendButtons from "@/business/components/api/automation/scenario/ScenarioExtendBtns"; import MsScenarioExtendButtons from "@/business/components/api/automation/scenario/ScenarioExtendBtns";
import MsTestPlanList from "./testplan/TestPlanList"; import MsTestPlanList from "./testplan/TestPlanList";
import MsTableHeaderSelectPopover from "@/business/components/common/components/table/MsTableHeaderSelectPopover"; import MsTableHeaderSelectPopover from "@/business/components/common/components/table/MsTableHeaderSelectPopover";
import {API_SCENARIO_CONFIGS} from "@/business/components/common/components/search/search-components"; import {API_SCENARIO_CONFIGS} from "@/business/components/common/components/search/search-components";
import MsTableOperatorButton from "@/business/components/common/components/MsTableOperatorButton"; import MsTableOperatorButton from "@/business/components/common/components/MsTableOperatorButton";
import PriorityTableItem from "../../../track/common/tableItems/planview/PriorityTableItem"; import PriorityTableItem from "../../../track/common/tableItems/planview/PriorityTableItem";
import PlanStatusTableItem from "../../../track/common/tableItems/plan/PlanStatusTableItem"; import PlanStatusTableItem from "../../../track/common/tableItems/plan/PlanStatusTableItem";
import BatchEdit from "../../../track/case/components/BatchEdit"; import BatchEdit from "../../../track/case/components/BatchEdit";
import {API_SCENARIO_LIST, TEST_CASE_LIST, TEST_PLAN_LIST, WORKSPACE_ID} from "../../../../../common/js/constants"; import {API_SCENARIO_LIST, TEST_CASE_LIST, TEST_PLAN_LIST, WORKSPACE_ID} from "../../../../../common/js/constants";
import {PROJECT_NAME} from "../../../../../common/js/constants"; import {PROJECT_NAME} from "../../../../../common/js/constants";
import EnvironmentSelect from "../../definition/components/environment/EnvironmentSelect"; import EnvironmentSelect from "../../definition/components/environment/EnvironmentSelect";
import BatchMove from "../../../track/case/components/BatchMove"; import BatchMove from "../../../track/case/components/BatchMove";
import {_sort} from "@/common/js/tableUtils"; import {_sort} from "@/common/js/tableUtils";
import {Api_Scenario_List, Track_Test_Case} from "@/business/components/common/model/JsonData"; import {Api_Scenario_List} from "@/business/components/common/model/JsonData";
import HeaderCustom from "@/business/components/common/head/HeaderCustom"; import HeaderCustom from "@/business/components/common/head/HeaderCustom";
import { import {
_filter, _filter,
_handleSelect, _handleSelect,
_handleSelectAll, _handleSelectAll,
getSelectDataCounts, getSelectDataCounts,
setUnSelectIds, toggleAllSelection setUnSelectIds, toggleAllSelection
} from "@/common/js/tableUtils"; } from "@/common/js/tableUtils";
export default { export default {
name: "MsApiScenarioList", name: "MsApiScenarioList",
components: { components: {
HeaderCustom, HeaderCustom,
BatchMove, BatchMove,
EnvironmentSelect, EnvironmentSelect,
BatchEdit, BatchEdit,
PlanStatusTableItem, PlanStatusTableItem,
PriorityTableItem, PriorityTableItem,
MsTableHeaderSelectPopover, MsTableHeaderSelectPopover,
MsTablePagination, MsTablePagination,
MsTableMoreBtn, MsTableMoreBtn,
ShowMoreBtn, ShowMoreBtn,
MsTableHeader, MsTableHeader,
MsTag, MsTag,
MsApiReportDetail, MsApiReportDetail,
MsScenarioExtendButtons, MsScenarioExtendButtons,
@ -554,12 +554,15 @@ export default {
_handleSelectAll(this, selection, this.tableData, this.selectRows); _handleSelectAll(this, selection, this.tableData, this.selectRows);
setUnSelectIds(this.tableData, this.condition, this.selectRows); setUnSelectIds(this.tableData, this.condition, this.selectRows);
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows); this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
this.$emit('selection', selection);
}, },
handleSelect(selection, row) { handleSelect(selection, row) {
_handleSelect(this, selection, row, this.selectRows); _handleSelect(this, selection, row, this.selectRows);
setUnSelectIds(this.tableData, this.condition, this.selectRows); setUnSelectIds(this.tableData, this.condition, this.selectRows);
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows); this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
this.$emit('selection', selection);
}, },
isSelectDataAll(data) { isSelectDataAll(data) {
this.condition.selectAll = data; this.condition.selectAll = data;
setUnSelectIds(this.tableData, this.condition, this.selectRows); setUnSelectIds(this.tableData, this.condition, this.selectRows);
@ -587,7 +590,7 @@ export default {
scenarioIds.push(row.id); scenarioIds.push(row.id);
run.id = getUUID(); run.id = getUUID();
run.projectId = getCurrentProjectID(); run.projectId = getCurrentProjectID();
run.scenarioIds = scenarioIds; run.ids = scenarioIds;
this.$post(url, run, response => { this.$post(url, run, response => {
let data = response.data; let data = response.data;
this.runVisible = true; this.runVisible = true;
@ -672,6 +675,24 @@ export default {
downloadFile("Metersphere_Scenario_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj)); downloadFile("Metersphere_Scenario_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj));
}); });
}, },
exportJmx() {
let param = {};
this.buildBatchParam(param);
if (param.ids === undefined || param.ids.length < 1) {
this.$warning(this.$t("api_test.automation.scenario.check_case"));
return;
}
this.loading = true;
this.result = this.$post("/api/automation/export/jmx", param, response => {
this.loading = false;
let obj = response.data;
if (obj && obj.length > 0) {
obj.forEach(item => {
downloadFile(item.name + ".jmx", item.jmx);
})
}
});
},
buildApiPath(scenarios) { buildApiPath(scenarios) {
scenarios.forEach((scenario) => { scenarios.forEach((scenario) => {
this.moduleOptions.forEach(item => { this.moduleOptions.forEach(item => {

View File

@ -25,7 +25,8 @@
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item command="add-scenario">{{ $t('api_test.automation.add_scenario') }}</el-dropdown-item> <el-dropdown-item command="add-scenario">{{ $t('api_test.automation.add_scenario') }}</el-dropdown-item>
<el-dropdown-item command="import">{{ $t('api_test.api_import.label') }}</el-dropdown-item> <el-dropdown-item command="import">{{ $t('api_test.api_import.label') }}</el-dropdown-item>
<el-dropdown-item command="export">{{ $t('report.export') }}</el-dropdown-item> <el-dropdown-item command="export">{{ $t('report.export') }}MS</el-dropdown-item>
<el-dropdown-item command="exportJmx">{{ $t('report.export') }}JMX</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</template> </template>
@ -33,14 +34,14 @@
<module-trash-button v-if="!isReadOnly" :condition="condition" :exe="enableTrash"/> <module-trash-button v-if="!isReadOnly" :condition="condition" :exe="enableTrash"/>
<!-- 是否保留这个 --> <!-- 是否保留这个 -->
<!--<api-scenario-module-header--> <!--<api-scenario-module-header-->
<!--:condition="condition"--> <!--:condition="condition"-->
<!--:current-module="currentModule"--> <!--:current-module="currentModule"-->
<!--:is-read-only="isReadOnly"--> <!--:is-read-only="isReadOnly"-->
<!--:project-id="projectId"--> <!--:project-id="projectId"-->
<!--@exportAPI="exportAPI"--> <!--@exportAPI="exportAPI"-->
<!--@addScenario="addScenario"--> <!--@addScenario="addScenario"-->
<!--@refreshTable="$emit('refreshTable')"--> <!--@refreshTable="$emit('refreshTable')"-->
<!--@refresh="refresh"/>--> <!--@refresh="refresh"/>-->
</template> </template>
</ms-node-tree> </ms-node-tree>
@ -56,27 +57,26 @@
</template> </template>
<script> <script>
import SelectMenu from "../../../track/common/SelectMenu"; import SelectMenu from "../../../track/common/SelectMenu";
import MsAddBasisScenario from "@/business/components/api/automation/scenario/AddBasisScenario"; import MsAddBasisScenario from "@/business/components/api/automation/scenario/AddBasisScenario";
import {getCurrentProjectID} from "@/common/js/utils"; import {getCurrentProjectID} from "@/common/js/utils";
import MsNodeTree from "../../../track/common/NodeTree"; import MsNodeTree from "../../../track/common/NodeTree";
import {buildNodePath} from "../../definition/model/NodeTree"; import {buildNodePath} from "../../definition/model/NodeTree";
import ModuleTrashButton from "../../definition/components/module/ModuleTrashButton"; import ModuleTrashButton from "../../definition/components/module/ModuleTrashButton";
import ApiScenarioModuleHeader from "@/business/components/api/automation/scenario/module/ApiScenarioModuleHeader"; import ApiImport from "./common/ScenarioImport";
import ApiImport from "./common/ScenarioImport";
export default { export default {
name: 'MsApiScenarioModule', name: 'MsApiScenarioModule',
components: { components: {
ApiImport, ApiImport,
ModuleTrashButton, ModuleTrashButton,
MsNodeTree, MsNodeTree,
MsAddBasisScenario, MsAddBasisScenario,
SelectMenu, SelectMenu,
}, },
props: { props: {
isReadOnly: { isReadOnly: {
type: Boolean, type: Boolean,
default() { default() {
return false return false
} }
@ -145,6 +145,9 @@ export default {
case "export": case "export":
this.$emit('exportAPI'); this.$emit('exportAPI');
break; break;
case "exportJmx":
this.$emit('exportJmx');
break;
} }
}, },
list() { list() {

View File

@ -204,44 +204,44 @@
</template> </template>
<script> <script>
import {API_STATUS, PRIORITY} from "../../definition/model/JsonData"; import {API_STATUS, PRIORITY} from "../../definition/model/JsonData";
import {WORKSPACE_ID} from '@/common/js/constants'; import {WORKSPACE_ID} from '@/common/js/constants';
import { import {
Assertions, Assertions,
ConstantTimer, ConstantTimer,
Extract, Extract,
IfController, IfController,
JSR223Processor, JSR223Processor,
LoopController LoopController
} from "../../definition/model/ApiTestModel"; } from "../../definition/model/ApiTestModel";
import {parseEnvironment} from "../../definition/model/EnvironmentModel"; import {parseEnvironment} from "../../definition/model/EnvironmentModel";
import {ELEMENT_TYPE, ELEMENTS} from "./Setting"; import {ELEMENT_TYPE, ELEMENTS} from "./Setting";
import MsApiCustomize from "./ApiCustomize"; import MsApiCustomize from "./ApiCustomize";
import {getCurrentProjectID, getUUID} from "@/common/js/utils"; import {getCurrentProjectID, getUUID} from "@/common/js/utils";
import ApiEnvironmentConfig from "../../definition/components/environment/ApiEnvironmentConfig"; import ApiEnvironmentConfig from "../../definition/components/environment/ApiEnvironmentConfig";
import MsInputTag from "./MsInputTag"; import MsInputTag from "./MsInputTag";
import MsRun from "./DebugRun"; import MsRun from "./DebugRun";
import MsApiReportDetail from "../report/ApiReportDetail"; import MsApiReportDetail from "../report/ApiReportDetail";
import MsVariableList from "./variable/VariableList"; import MsVariableList from "./variable/VariableList";
import ApiImport from "../../definition/components/import/ApiImport"; import ApiImport from "../../definition/components/import/ApiImport";
import "@/common/css/material-icons.css" import "@/common/css/material-icons.css"
import OutsideClick from "@/common/js/outside-click"; import OutsideClick from "@/common/js/outside-click";
import ScenarioApiRelevance from "./api/ApiRelevance"; import ScenarioApiRelevance from "./api/ApiRelevance";
import ScenarioRelevance from "./api/ScenarioRelevance"; import ScenarioRelevance from "./api/ScenarioRelevance";
import MsComponentConfig from "./component/ComponentConfig"; import MsComponentConfig from "./component/ComponentConfig";
import {handleCtrlSEvent} from "../../../../../common/js/utils"; import {handleCtrlSEvent} from "../../../../../common/js/utils";
export default { export default {
name: "EditApiScenario", name: "EditApiScenario",
props: { props: {
moduleOptions: Array, moduleOptions: Array,
currentScenario: {}, currentScenario: {},
}, },
components: { components: {
MsVariableList, MsVariableList,
ScenarioRelevance, ScenarioRelevance,
ScenarioApiRelevance, ScenarioApiRelevance,
ApiEnvironmentConfig, ApiEnvironmentConfig,
MsApiReportDetail, MsApiReportDetail,
MsInputTag, MsRun, MsInputTag, MsRun,
MsApiCustomize, MsApiCustomize,
@ -596,6 +596,9 @@ export default {
if (item.protocol) { if (item.protocol) {
request.protocol = item.protocol; request.protocol = item.protocol;
} }
if (request.protocol === "DUBBO") {
request.protocol = "dubbo://";
}
request.id = item.id; request.id = item.id;
request.name = item.name; request.name = item.name;
request.refType = refType; request.refType = refType;

View File

@ -2,13 +2,13 @@
<relevance-dialog :title="$t('api_test.automation.scenario_import')" ref="relevanceDialog"> <relevance-dialog :title="$t('api_test.automation.scenario_import')" ref="relevanceDialog">
<template v-slot:aside> <template v-slot:aside>
<ms-api-scenario-module <ms-api-scenario-module
@nodeSelectEvent="nodeChange" @nodeSelectEvent="nodeChange"
@refreshTable="refresh" @refreshTable="refresh"
@setModuleOptions="setModuleOptions" @setModuleOptions="setModuleOptions"
@enableTrash="false" @enableTrash="false"
:is-read-only="true" :is-read-only="true"
ref="nodeTree"/> ref="nodeTree"/>
</template> </template>
<ms-api-scenario-list <ms-api-scenario-list
@ -27,94 +27,98 @@
</template> </template>
<script> <script>
import ScenarioRelevanceCaseList from "./RelevanceCaseList"; import ScenarioRelevanceCaseList from "./RelevanceCaseList";
import MsApiModule from "../../../definition/components/module/ApiModule"; import MsApiModule from "../../../definition/components/module/ApiModule";
import MsContainer from "../../../../common/components/MsContainer"; import MsContainer from "../../../../common/components/MsContainer";
import MsAsideContainer from "../../../../common/components/MsAsideContainer"; import MsAsideContainer from "../../../../common/components/MsAsideContainer";
import MsMainContainer from "../../../../common/components/MsMainContainer"; import MsMainContainer from "../../../../common/components/MsMainContainer";
import ScenarioRelevanceApiList from "./RelevanceApiList"; import ScenarioRelevanceApiList from "./RelevanceApiList";
import MsApiScenarioModule from "../ApiScenarioModule"; import MsApiScenarioModule from "../ApiScenarioModule";
import MsApiScenarioList from "../ApiScenarioList"; import MsApiScenarioList from "../ApiScenarioList";
import {getUUID} from "../../../../../../common/js/utils"; import {getUUID} from "../../../../../../common/js/utils";
import RelevanceDialog from "../../../../track/plan/view/comonents/base/RelevanceDialog"; import RelevanceDialog from "../../../../track/plan/view/comonents/base/RelevanceDialog";
export default {
name: "ScenarioRelevance", export default {
components: { name: "ScenarioRelevance",
RelevanceDialog, components: {
MsApiScenarioList, RelevanceDialog,
MsApiScenarioModule, MsApiScenarioList,
MsMainContainer, MsAsideContainer, MsContainer}, MsApiScenarioModule,
data() { MsMainContainer, MsAsideContainer, MsContainer
return { },
result: {}, data() {
currentProtocol: null, return {
selectNodeIds: [], result: {},
moduleOptions: {}, currentProtocol: null,
isApiListEnable: true, selectNodeIds: [],
currentScenario: [], moduleOptions: {},
currentScenarioIds: [], isApiListEnable: true,
} currentScenario: [],
currentScenarioIds: [],
}
},
methods: {
reference() {
let scenarios = [];
if (!this.currentScenario || this.currentScenario.length < 1) {
this.$emit('请选择场景');
return;
}
this.currentScenario.forEach(item => {
let obj = {id: item.id, name: item.name, type: "scenario", referenced: 'REF', resourceId: getUUID()};
scenarios.push(obj);
});
this.$emit('save', scenarios);
this.close();
}, },
methods: { copy() {
reference() { let scenarios = [];
let scenarios = []; if (!this.currentScenarioIds || this.currentScenarioIds.length < 1) {
if (!this.currentScenario || this.currentScenario.length < 1) { this.$warning('请选择场景');
this.$emit('请选择场景'); return;
return; }
} this.result = this.$post("/api/automation/getApiScenarios/", this.currentScenarioIds, response => {
this.currentScenario.forEach(item => { if (response.data) {
let obj = {id: item.id, name: item.name, type: "scenario", referenced: 'REF', resourceId: getUUID()}; response.data.forEach(item => {
scenarios.push(obj); let scenarioDefinition = JSON.parse(item.scenarioDefinition);
}); if (scenarioDefinition && scenarioDefinition.hashTree) {
this.$emit('save', scenarios);
this.close();
},
copy() {
let scenarios = [];
if (!this.currentScenarioIds || this.currentScenarioIds.length < 1) {
this.$emit('请选择场景');
return;
}
this.result = this.$post("/api/automation/getApiScenarios/", this.currentScenarioIds, response => {
if (response.data) {
response.data.forEach(item => {
let scenarioDefinition = JSON.parse(item.scenarioDefinition);
let obj = {id: item.id, name: item.name, type: "scenario", referenced: 'Copy', resourceId: getUUID(), hashTree: scenarioDefinition.hashTree}; let obj = {id: item.id, name: item.name, type: "scenario", referenced: 'Copy', resourceId: getUUID(), hashTree: scenarioDefinition.hashTree};
scenarios.push(obj); scenarios.push(obj);
}); }
this.$emit('save', scenarios); });
this.close(); this.$emit('save', scenarios);
} this.close();
})
},
close() {
this.refresh();
this.$refs.relevanceDialog.close();
},
open() {
this.$refs.relevanceDialog.open();
if (this.$refs.apiScenarioList) {
this.$refs.apiScenarioList.search();
} }
}, })
nodeChange(node, nodeIds, pNodes) { },
this.selectNodeIds = nodeIds; close() {
}, this.refresh();
handleProtocolChange(protocol) { this.$refs.relevanceDialog.close();
this.currentProtocol = protocol; },
}, open() {
setModuleOptions(data) { this.$refs.relevanceDialog.open();
this.moduleOptions = data; if (this.$refs.apiScenarioList) {
}, this.$refs.apiScenarioList.search();
refresh() { }
this.$refs.apiScenarioList.search(); },
}, nodeChange(node, nodeIds, pNodes) {
setData(data) { this.selectNodeIds = nodeIds;
this.currentScenario = Array.from(data).map(row => row); },
this.currentScenarioIds = Array.from(data).map(row => row.id); handleProtocolChange(protocol) {
}, this.currentProtocol = protocol;
} },
setModuleOptions(data) {
this.moduleOptions = data;
},
refresh() {
this.$refs.apiScenarioList.search();
},
setData(data) {
this.currentScenario = Array.from(data).map(row => row);
this.currentScenarioIds = Array.from(data).map(row => row.id);
},
} }
}
</script> </script>
<style scoped> <style scoped>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-dialog :close-on-click-modal="false" :title="$t('api_test.api_import.title')" width="30%" <el-dialog :close-on-click-modal="false" :title="$t('api_test.automation.scenario_import')" width="30%"
:visible.sync="visible" class="api-import" v-loading="result.loading" @close="close"> :visible.sync="visible" class="api-import" v-loading="result.loading" @close="close">
<div class="header-bar"> <div class="header-bar">

View File

@ -22,23 +22,23 @@
</template> </template>
<script> <script>
import MsSqlBasisParameters from "../../../definition/components/request/database/BasisParameters"; import MsSqlBasisParameters from "../../../definition/components/request/database/BasisParameters";
import MsTcpBasisParameters from "../../../definition/components/request/tcp/TcpBasisParameters"; import MsTcpBasisParameters from "../../../definition/components/request/tcp/TcpBasisParameters";
import MsDubboBasisParameters from "../../../definition/components/request/dubbo/BasisParameters"; import MsDubboBasisParameters from "../../../definition/components/request/dubbo/BasisParameters";
import MsApiRequestForm from "../../../definition/components/request/http/ApiHttpRequestForm"; import MsApiRequestForm from "../../../definition/components/request/http/ApiHttpRequestForm";
import ApiBaseComponent from "../common/ApiBaseComponent"; import ApiBaseComponent from "../common/ApiBaseComponent";
export default { export default {
name: "ApiScenarioComponent", name: "ApiScenarioComponent",
props: { props: {
scenario: {}, scenario: {},
node: {}, node: {},
draggable: { draggable: {
type: Boolean, type: Boolean,
default: false, default: false,
},
}, },
}, watch: {},
watch: {},
created() { created() {
if (this.scenario.id && this.scenario.referenced === 'REF' && !this.scenario.loaded) { if (this.scenario.id && this.scenario.referenced === 'REF' && !this.scenario.loaded) {
this.result = this.$get("/api/automation/getApiScenario/" + this.scenario.id, response => { this.result = this.$get("/api/automation/getApiScenario/" + this.scenario.id, response => {
@ -79,8 +79,10 @@ export default {
this.$emit('remove', this.scenario, this.node); this.$emit('remove', this.scenario, this.node);
}, },
active(item) { active(item) {
item.active = !item.active; if (item && item.active) {
this.reload(); item.active = !item.active;
this.reload();
}
}, },
copyRow() { copyRow() {
this.$emit('copyRow', this.scenario, this.node); this.$emit('copyRow', this.scenario, this.node);

View File

@ -81,7 +81,7 @@
</el-link> </el-link>
</el-row> </el-row>
<div style="min-height: 400px"> <div style="min-height: 400px">
<ms-api-key-value :items="headers"/> <ms-api-key-value :items="headers" :suggestions="headerSuggestions"/>
<batch-add-parameter @batchSave="batchSave" ref="batchAddParameter"/> <batch-add-parameter @batchSave="batchSave" ref="batchAddParameter"/>
</div> </div>
</el-tab-pane> </el-tab-pane>
@ -95,33 +95,34 @@
</template> </template>
<script> <script>
import MsEditConstant from "./EditConstant"; import MsEditConstant from "./EditConstant";
import MsDialogFooter from "../../../../common/components/MsDialogFooter"; import MsDialogFooter from "../../../../common/components/MsDialogFooter";
import MsTableHeader from "@/business/components/common/components/MsTableHeader"; import MsTableHeader from "@/business/components/common/components/MsTableHeader";
import MsTablePagination from "@/business/components/common/pagination/TablePagination"; import MsTablePagination from "@/business/components/common/pagination/TablePagination";
import MsEditCounter from "./EditCounter"; import MsEditCounter from "./EditCounter";
import MsEditRandom from "./EditRandom"; import MsEditRandom from "./EditRandom";
import MsEditListValue from "./EditListValue"; import MsEditListValue from "./EditListValue";
import MsEditCsv from "./EditCsv"; import MsEditCsv from "./EditCsv";
import {getUUID} from "@/common/js/utils"; import {getUUID} from "@/common/js/utils";
import MsApiKeyValue from "../../../definition/components/ApiKeyValue"; import MsApiKeyValue from "../../../definition/components/ApiKeyValue";
import BatchAddParameter from "../../../definition/components/basis/BatchAddParameter"; import BatchAddParameter from "../../../definition/components/basis/BatchAddParameter";
import {KeyValue} from "../../../definition/model/ApiTestModel"; import {KeyValue} from "../../../definition/model/ApiTestModel";
import {REQUEST_HEADERS} from "@/common/js/constants";
export default { export default {
name: "MsVariableList", name: "MsVariableList",
components: { components: {
MsEditConstant, MsEditConstant,
MsDialogFooter, MsDialogFooter,
MsTableHeader, MsTableHeader,
MsTablePagination, MsTablePagination,
MsEditCounter, MsEditCounter,
MsEditRandom, MsEditRandom,
MsEditListValue, MsEditListValue,
MsEditCsv, MsEditCsv,
MsApiKeyValue, MsApiKeyValue,
BatchAddParameter BatchAddParameter
}, },
data() { data() {
return { return {
variables: [], variables: [],
@ -144,6 +145,7 @@ export default {
editData: {}, editData: {},
pageSize: 10, pageSize: 10,
total: 0, total: 0,
headerSuggestions: REQUEST_HEADERS,
} }
}, },
methods: { methods: {
@ -285,19 +287,19 @@ export default {
</script> </script>
<style> <style>
.ms-variable-hidden-row { .ms-variable-hidden-row {
display: none; display: none;
} }
.ms-variable-header { .ms-variable-header {
background: #783887; background: #783887;
color: white; color: white;
height: 18px; height: 18px;
border-radius: 42%; border-radius: 42%;
} }
.ms-variable-link { .ms-variable-link {
float: right; float: right;
margin-right: 45px; margin-right: 45px;
} }
</style> </style>

View File

@ -384,6 +384,7 @@ export default {
} }
let simpleInfoUrl = "/api/document/selectApiSimpleInfo"; let simpleInfoUrl = "/api/document/selectApiSimpleInfo";
this.apiSimpleInfoArray = [];
this.$post(simpleInfoUrl, simpleRequest, response => { this.$post(simpleInfoUrl, simpleRequest, response => {
this.apiSimpleInfoArray = response.data; this.apiSimpleInfoArray = response.data;
this.apiStepIndex = 0; this.apiStepIndex = 0;

View File

@ -699,6 +699,10 @@ export default {
exportApi() { exportApi() {
let param = this.buildBatchParam(); let param = this.buildBatchParam();
param.protocol = this.currentProtocol; param.protocol = this.currentProtocol;
if (param.ids === undefined || param.ids.length < 1) {
this.$warning(this.$t("api_test.definition.check_select"));
return;
}
this.result = this.$post("/api/definition/export", param, response => { this.result = this.$post("/api/definition/export", param, response => {
let obj = response.data; let obj = response.data;
obj.protocol = this.currentProtocol; obj.protocol = this.currentProtocol;

View File

@ -1,83 +1,86 @@
<template> <template>
<el-form :model="config" :rules="rules" ref="config" label-width="100px" size="small" :disabled="isReadOnly"> <el-form :model="config" :rules="rules" ref="config" label-width="100px" size="small" :disabled="isReadOnly">
<div class="dubbo-form-description" v-if="description"> <el-row>
{{ description }} <div class="dubbo-form-description" v-if="description">
</div> {{ description }}
<el-form-item label="Protocol" prop="protocol" class="dubbo-form-item"> </div>
<el-select v-model="config.protocol" class="select-100" clearable> </el-row>
<el-option v-for="p in protocols" :key="p" :label="p" :value="p"/>
</el-select>
</el-form-item>
<el-form-item label="Group" prop="group" class="dubbo-form-item"> <el-row>
<el-input v-model="config.group" maxlength="300" show-word-limit <el-form-item label="Protocol" prop="protocol" class="dubbo-form-item">
:placeholder="$t('commons.input_content')"/> <el-select v-model="config.protocol" class="select-100" clearable>
</el-form-item> <el-option v-for="p in protocols" :key="p" :label="p" :value="p"/>
</el-select>
</el-form-item>
<el-form-item label="Group" prop="group" class="dubbo-form-item">
<el-input v-model="config.group" maxlength="300" show-word-limit
:placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item label="Namespace" prop="namespace" class="dubbo-form-item">
<el-input v-model="config.namespace" maxlength="300" show-word-limit
:placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item label="Timeout" prop="timeout" class="dubbo-form-item">
<el-input type="number" v-model="config.timeout" :placeholder="$t('commons.input_content')"/>
</el-form-item>
</el-row>
<el-row>
<el-form-item label="Address" prop="address" class="dubbo-form-item-long">
<el-input v-model="config.address" maxlength="300" show-word-limit
:placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item label="Namespace" prop="namespace" class="dubbo-form-item"> <el-form-item label="UserName" prop="username" class="dubbo-form-item">
<el-input v-model="config.namespace" maxlength="300" show-word-limit <el-input v-model="config.username" maxlength="100" show-word-limit
:placeholder="$t('commons.input_content')"/> :placeholder="$t('commons.input_content')"/>
</el-form-item> </el-form-item>
<el-form-item label="Timeout" prop="timeout" class="dubbo-form-item">
<el-input type="number" v-model="config.timeout" :placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item label="Address" prop="address" class="dubbo-form-item-long">
<el-input v-model="config.address" maxlength="300" show-word-limit
:placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item label="UserName" prop="username" class="dubbo-form-item">
<el-input v-model="config.username" maxlength="100" show-word-limit
:placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item label="Password" prop="password" class="dubbo-form-item">
<el-input v-model="config.password" maxlength="30" show-word-limit show-password autocomplete="new-password"
:placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item label="Password" prop="password" class="dubbo-form-item">
<el-input v-model="config.password" maxlength="30" show-word-limit show-password autocomplete="new-password"
:placeholder="$t('commons.input_content')"/>
</el-form-item>
</el-row>
</el-form> </el-form>
</template> </template>
<script> <script>
import './dubbo.css' import './dubbo.css'
import {ConfigCenter} from "@/business/components/api/definition/model/ApiTestModel"; import {ConfigCenter} from "@/business/components/api/definition/model/ApiTestModel";
export default { export default {
name: "MsDubboConfigCenter", name: "MsDubboConfigCenter",
props: { props: {
description: String, description: String,
config: {}, config: {},
isReadOnly: { isReadOnly: {
type: Boolean, type: Boolean,
default: false default: false
} }
}, },
data() { data() {
return { return {
protocols: ConfigCenter.PROTOCOLS, protocols: ConfigCenter.PROTOCOLS,
methods: [], methods: [],
rules: { rules: {
group: [ group: [
{max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'} {max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'}
], ],
namespace: [ namespace: [
{max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'} {max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'}
], ],
username: [ username: [
{max: 100, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'} {max: 100, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'}
], ],
password: [ password: [
{max: 30, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'} {max: 30, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'}
], ],
address: [ address: [
{max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'} {max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'}
] ]
}
} }
} }
} }
}
</script> </script>

View File

@ -1,82 +1,86 @@
<template> <template>
<el-form :model="consumer" :rules="rules" ref="consumer" label-width="100px" size="small" :disabled="isReadOnly"> <el-form :model="consumer" :rules="rules" ref="consumer" label-width="100px" size="small" :disabled="isReadOnly">
<div class="dubbo-form-description" v-if="description"> <el-row>
{{ description }} <div class="dubbo-form-description" v-if="description">
</div> {{ description }}
<el-form-item label="Timeout" prop="timeout" class="dubbo-form-item"> </div>
<el-input type="number" v-model="consumer.timeout" :placeholder="$t('commons.input_content')"/> </el-row>
</el-form-item> <el-row>
<el-form-item label="Timeout" prop="timeout" class="dubbo-form-item">
<el-input type="number" v-model="consumer.timeout" :placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item label="Version" prop="version" class="dubbo-form-item">
<el-input v-model="consumer.version" maxlength="30" show-word-limit
:placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item label="Version" prop="version" class="dubbo-form-item"> <el-form-item label="Retries" prop="retries" class="dubbo-form-item">
<el-input v-model="consumer.version" maxlength="30" show-word-limit <el-input type="number" v-model="consumer.retries" :placeholder="$t('commons.input_content')"/>
:placeholder="$t('commons.input_content')"/> </el-form-item>
</el-form-item>
<el-form-item label="Retries" prop="retries" class="dubbo-form-item"> <el-form-item label="Cluster" prop="cluster" class="dubbo-form-item">
<el-input type="number" v-model="consumer.retries" :placeholder="$t('commons.input_content')"/> <el-input v-model="consumer.cluster" maxlength="300" show-word-limit
</el-form-item> :placeholder="$t('commons.input_content')"/>
</el-form-item>
</el-row>
<el-row>
<el-form-item label="Group" prop="group" class="dubbo-form-item">
<el-input v-model="consumer.group" maxlength="300" show-word-limit
:placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item label="Cluster" prop="cluster" class="dubbo-form-item"> <el-form-item label="Connections" prop="connections" class="dubbo-form-item">
<el-input v-model="consumer.cluster" maxlength="300" show-word-limit <el-input type="number" v-model="consumer.connections" :placeholder="$t('commons.input_content')"/>
:placeholder="$t('commons.input_content')"/> </el-form-item>
</el-form-item>
<el-form-item label="Group" prop="group" class="dubbo-form-item"> <el-form-item label="Async" prop="async" class="dubbo-form-item">
<el-input v-model="consumer.group" maxlength="300" show-word-limit <el-select v-model="consumer.async" class="select-100" clearable>
:placeholder="$t('commons.input_content')"/> <el-option v-for="option in asyncOptions" :key="option" :label="option" :value="option"/>
</el-form-item> </el-select>
</el-form-item>
<el-form-item label="Connections" prop="connections" class="dubbo-form-item"> <el-form-item label="LoadBalance" prop="loadBalance" class="dubbo-form-item">
<el-input type="number" v-model="consumer.connections" :placeholder="$t('commons.input_content')"/> <el-select v-model="consumer.loadBalance" class="select-100" clearable>
</el-form-item> <el-option v-for="option in loadBalances" :key="option" :label="option" :value="option"/>
</el-select>
<el-form-item label="Async" prop="async" class="dubbo-form-item"> </el-form-item>
<el-select v-model="consumer.async" class="select-100" clearable> </el-row>
<el-option v-for="option in asyncOptions" :key="option" :label="option" :value="option"/>
</el-select>
</el-form-item>
<el-form-item label="LoadBalance" prop="loadBalance" class="dubbo-form-item">
<el-select v-model="consumer.loadBalance" class="select-100" clearable>
<el-option v-for="option in loadBalances" :key="option" :label="option" :value="option"/>
</el-select>
</el-form-item>
</el-form> </el-form>
</template> </template>
<script> <script>
import './dubbo.css' import './dubbo.css'
import {ConsumerAndService, RegistryCenter} from "@/business/components/api/definition/model/ApiTestModel"; import {ConsumerAndService, RegistryCenter} from "@/business/components/api/definition/model/ApiTestModel";
export default { export default {
name: "MsDubboConsumerService", name: "MsDubboConsumerService",
props: { props: {
description: String, description: String,
consumer: {}, consumer: {},
isReadOnly: { isReadOnly: {
type: Boolean, type: Boolean,
default: false default: false
} }
}, },
data() { data() {
return { return {
asyncOptions: ConsumerAndService.ASYNC_OPTIONS, asyncOptions: ConsumerAndService.ASYNC_OPTIONS,
loadBalances: ConsumerAndService.LOAD_BALANCE_OPTIONS, loadBalances: ConsumerAndService.LOAD_BALANCE_OPTIONS,
methods: [], methods: [],
rules: { rules: {
version: [ version: [
{max: 30, message: this.$t('commons.input_limit', [0, 30]), trigger: 'blur'} {max: 30, message: this.$t('commons.input_limit', [0, 30]), trigger: 'blur'}
], ],
cluster: [ cluster: [
{max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'} {max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'}
], ],
group: [ group: [
{max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'} {max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'}
] ]
}
} }
} }
} }
}
</script> </script>

View File

@ -117,7 +117,7 @@
<style scoped> <style scoped>
.get-provider { .get-provider {
margin-bottom: 22px; margin: 5px 5px 10px;
} }
.select-100 { .select-100 {

View File

@ -1,73 +1,78 @@
<template> <template>
<el-form :model="registry" :rules="rules" ref="registry" label-width="100px" size="small" :disabled="isReadOnly"> <el-form :model="registry" :rules="rules" ref="registry" label-width="100px" size="small" :disabled="isReadOnly">
<div class="dubbo-form-description" v-if="description"> <el-row>
{{ description }} <div class="dubbo-form-description" v-if="description">
</div> {{ description }}
<el-form-item label="Protocol" prop="protocol" class="dubbo-form-item"> </div>
<el-select v-model="registry.protocol" class="select-100" clearable> </el-row>
<el-option v-for="p in protocols" :key="p" :label="p" :value="p"/> <el-row>
</el-select> <el-form-item label="Protocol" prop="protocol" class="dubbo-form-item">
</el-form-item> <el-select v-model="registry.protocol" class="select-100" clearable>
<el-option v-for="p in protocols" :key="p" :label="p" :value="p"/>
</el-select>
</el-form-item>
<el-form-item label="Group" prop="group" class="dubbo-form-item"> <el-form-item label="Group" prop="group" class="dubbo-form-item">
<el-input v-model="registry.group" maxlength="300" show-word-limit <el-input v-model="registry.group" maxlength="300" show-word-limit
:placeholder="$t('commons.input_content')"/> :placeholder="$t('commons.input_content')"/>
</el-form-item> </el-form-item>
<el-form-item label="UserName" prop="username" class="dubbo-form-item"> <el-form-item label="UserName" prop="username" class="dubbo-form-item">
<el-input v-model="registry.username" maxlength="100" show-word-limit <el-input v-model="registry.username" maxlength="100" show-word-limit
:placeholder="$t('commons.input_content')"/> :placeholder="$t('commons.input_content')"/>
</el-form-item> </el-form-item>
<el-form-item label="Password" prop="password" class="dubbo-form-item"> <el-form-item label="Password" prop="password" class="dubbo-form-item">
<el-input v-model="registry.password" maxlength="30" show-word-limit show-password autocomplete="new-password" <el-input v-model="registry.password" maxlength="30" show-word-limit show-password autocomplete="new-password"
:placeholder="$t('commons.input_content')"/> :placeholder="$t('commons.input_content')"/>
</el-form-item> </el-form-item>
</el-row>
<el-row>
<el-form-item label="Address" prop="address" class="dubbo-form-item-long">
<el-input v-model="registry.address" maxlength="300" show-word-limit
:placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item label="Address" prop="address" class="dubbo-form-item-long"> <el-form-item label="Timeout" prop="timeout" class="dubbo-form-item">
<el-input v-model="registry.address" maxlength="300" show-word-limit <el-input type="number" v-model="registry.timeout" :placeholder="$t('commons.input_content')"/>
:placeholder="$t('commons.input_content')"/> </el-form-item>
</el-form-item> </el-row>
<el-form-item label="Timeout" prop="timeout" class="dubbo-form-item">
<el-input type="number" v-model="registry.timeout" :placeholder="$t('commons.input_content')"/>
</el-form-item>
</el-form> </el-form>
</template> </template>
<script> <script>
import './dubbo.css' import './dubbo.css'
import {RegistryCenter} from "@/business/components/api/definition/model/ApiTestModel"; import {RegistryCenter} from "@/business/components/api/definition/model/ApiTestModel";
export default { export default {
name: "MsDubboRegistryCenter", name: "MsDubboRegistryCenter",
props: { props: {
description: String, description: String,
registry: {}, registry: {},
isReadOnly: { isReadOnly: {
type: Boolean, type: Boolean,
default: false default: false
} }
}, },
data() { data() {
return { return {
protocols: RegistryCenter.PROTOCOLS, protocols: RegistryCenter.PROTOCOLS,
methods: [], methods: [],
rules: { rules: {
group: [ group: [
{max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'} {max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'}
], ],
username: [ username: [
{max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'} {max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'}
], ],
password: [ password: [
{max: 30, message: this.$t('commons.input_limit', [0, 30]), trigger: 'blur'} {max: 30, message: this.$t('commons.input_limit', [0, 30]), trigger: 'blur'}
], ],
address: [ address: [
{max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'} {max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'}
] ]
}
} }
} }
} }
}
</script> </script>

View File

@ -8,18 +8,21 @@
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_test.definition.request.response_header')" name="headers" class="pane"> <el-tab-pane :label="$t('api_test.definition.request.response_header')" name="headers" class="pane">
<div style="width: 400px"> <!--<div style="width: 400px">-->
<pre>{{ response.responseResult.headers }}</pre> <!--<pre>{{ response.responseResult.headers }}</pre>-->
</div> <!--</div>-->
<ms-code-edit :mode="'text'" :read-only="true" :data.sync="response.responseResult.headers"/>
</el-tab-pane> </el-tab-pane>
<!--<el-tab-pane label="Cookie" name="cookie" class="pane cookie">--> <!--<el-tab-pane label="Cookie" name="cookie" class="pane cookie">-->
<!--<pre>{{response.cookies}}</pre>--> <!--<pre>{{response.cookies}}</pre>-->
<!--</el-tab-pane>--> <!--</el-tab-pane>-->
<el-tab-pane :label="$t('api_test.definition.request.console')" name="console" class="pane"> <el-tab-pane :label="$t('api_test.definition.request.console')" name="console" class="pane">
<div style="width: 400px"> <!--<div style="width: 400px">-->
<pre>{{response.responseResult.console}}</pre> <!--<pre>{{response.responseResult.console}}</pre>-->
</div> <!--</div>-->
<ms-code-edit :mode="'text'" :read-only="true" :data.sync="response.responseResult.console"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_report.assertions')" name="assertions" class="pane assertions"> <el-tab-pane :label="$t('api_report.assertions')" name="assertions" class="pane assertions">
@ -27,29 +30,30 @@
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_test.request.extract.label')" name="label" class="pane"> <el-tab-pane :label="$t('api_test.request.extract.label')" name="label" class="pane">
<div style="width: 400px"> <!--<div style="width: 400px">-->
<pre>{{response.responseResult.vars}}</pre> <!--<pre>{{response.responseResult.vars}}</pre>-->
</div> <!--</div>-->
<ms-code-edit :mode="'text'" :read-only="true" :data.sync="response.responseResult.vars"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_report.request_body')" name="request_body" class="pane"> <el-tab-pane :label="$t('api_report.request_body')" name="request_body" class="pane">
<div class="ms-div"> <!--<div class="ms-div">-->
{{$t('api_test.request.address')}} : <!--{{$t('api_test.request.address')}} :-->
<pre>{{ response.url }}</pre> <!--<pre>{{ response.url }}</pre>-->
</div> <!--</div>-->
<div class="ms-div"> <!--<div class="ms-div">-->
{{$t('api_test.scenario.headers')}} : <!--{{$t('api_test.scenario.headers')}} :-->
<pre>{{ response.headers }}</pre> <!--<pre>{{ response.headers }}</pre>-->
</div> <!--</div>-->
<div class="ms-div"> <!--<div class="ms-div">-->
Cookies : <!--Cookies :-->
<pre>{{response.cookies}}</pre> <!--<pre>{{response.cookies}}</pre>-->
</div> <!--</div>-->
<div class="ms-div"> <!--<div class="ms-div">-->
Body : <!--Body :-->
<pre>{{response.body ? response.body:""}}</pre> <!--<pre>{{response.body ? response.body:""}}</pre>-->
</div> <!--</div>-->
<ms-code-edit :mode="'text'" :read-only="true" :data.sync="reqMessages"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane v-if="activeName == 'body'" :disabled="true" name="mode" class="pane cookie"> <el-tab-pane v-if="activeName == 'body'" :disabled="true" name="mode" class="pane cookie">
@ -63,23 +67,23 @@
</template> </template>
<script> <script>
import MsAssertionResults from "./AssertionResults"; import MsAssertionResults from "./AssertionResults";
import MsCodeEdit from "../MsCodeEdit"; import MsCodeEdit from "../MsCodeEdit";
import MsDropdown from "../../../../common/components/MsDropdown"; import MsDropdown from "../../../../common/components/MsDropdown";
import {BODY_FORMAT} from "../../model/ApiTestModel"; import {BODY_FORMAT} from "../../model/ApiTestModel";
import MsSqlResultTable from "./SqlResultTable"; import MsSqlResultTable from "./SqlResultTable";
export default { export default {
name: "MsResponseResult", name: "MsResponseResult",
components: { components: {
MsDropdown, MsDropdown,
MsCodeEdit, MsCodeEdit,
MsAssertionResults, MsAssertionResults,
MsSqlResultTable MsSqlResultTable
}, },
props: { props: {
response: Object, response: Object,
currentProtocol: String, currentProtocol: String,
}, },
@ -91,12 +95,14 @@ export default {
modes: ['text', 'json', 'xml', 'html'], modes: ['text', 'json', 'xml', 'html'],
sqlModes: ['text', 'table'], sqlModes: ['text', 'table'],
mode: BODY_FORMAT.TEXT, mode: BODY_FORMAT.TEXT,
isMsCodeEditShow: true isMsCodeEditShow: true,
reqMessages: "",
} }
}, },
watch: { watch: {
response() { response() {
this.setBodyType(); this.setBodyType();
this.setReqMessage();
} }
}, },
methods: { methods: {
@ -126,9 +132,29 @@ export default {
this.isMsCodeEditShow = true; this.isMsCodeEditShow = true;
}); });
}, },
setReqMessage() {
if (this.response) {
if (!this.response.url) {
this.response.url = "";
}
if (!this.response.headers) {
this.response.headers = "";
}
if (!this.response.cookies) {
this.response.cookies = "";
}
if (!this.response.body) {
this.response.body = "";
}
this.reqMessages = this.$t('api_test.request.address') + ":\n" + this.response.url + "\n" +
this.$t('api_test.scenario.headers') + ":\n" + this.response.headers + "\n" + "Cookies :\n" +
this.response.cookies + "\n" + "Bpdy:" + "\n" + this.response.body;
}
},
}, },
mounted() { mounted() {
this.setBodyType(); this.setBodyType();
this.setReqMessage();
}, },
computed: { computed: {
isSqlType() { isSqlType() {

View File

@ -254,8 +254,12 @@ export default {
let resultValidate = {validate: true, msg: this.$t('test_resource_pool.fill_the_data')}; let resultValidate = {validate: true, msg: this.$t('test_resource_pool.fill_the_data')};
this.infoList.forEach(info => { this.infoList.forEach(info => {
for (let key in info) { for (let key in info) {
//
if (key === 'nodeSelector') {
continue;
}
if (info[key] != '0' && !info[key]) { if (info[key] != '0' && !info[key]) {
resultValidate.validate = false resultValidate.validate = false;
return false; return false;
} }
} }

View File

@ -533,6 +533,7 @@ export default {
api_case_passing_rate: "Use case pass rate", api_case_passing_rate: "Use case pass rate",
create_tip: "Note: Detailed interface information can be filled out on the edit page", create_tip: "Note: Detailed interface information can be filled out on the edit page",
api_import: "Api Import", api_import: "Api Import",
check_select: "Please check the API",
select_comp: { select_comp: {
no_data: "No Data", no_data: "No Data",
add_data: "Add Data" add_data: "Add Data"

View File

@ -533,6 +533,7 @@ export default {
api_case_passing_rate: "用例通过率", api_case_passing_rate: "用例通过率",
create_tip: "注: 详细的接口信息可以在编辑页面填写", create_tip: "注: 详细的接口信息可以在编辑页面填写",
api_import: "接口导入", api_import: "接口导入",
check_select: "请勾选接口",
select_comp: { select_comp: {
no_data: "无数据", no_data: "无数据",
add_data: "去添加" add_data: "去添加"

View File

@ -532,6 +532,7 @@ export default {
api_case_passing_rate: "用例通過率", api_case_passing_rate: "用例通過率",
create_tip: "註: 詳細的接口信息可以在編輯頁面填寫", create_tip: "註: 詳細的接口信息可以在編輯頁面填寫",
api_import: "接口導入", api_import: "接口導入",
check_select: "請勾選接口",
select_comp: { select_comp: {
no_data: "無數據", no_data: "無數據",
add_data: "去添加" add_data: "去添加"