feat(接口定义): 请求数据格式按照jmeter 数据格式重构完成
This commit is contained in:
parent
8fd084db51
commit
bdaff53eaf
|
@ -5,6 +5,7 @@ import com.github.pagehelper.PageHelper;
|
|||
import io.metersphere.api.dto.APIReportResult;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionRequest;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
||||
import io.metersphere.api.dto.definition.RunDefinitionRequest;
|
||||
import io.metersphere.api.dto.definition.SaveApiDefinitionRequest;
|
||||
import io.metersphere.api.service.ApiDefinitionService;
|
||||
import io.metersphere.base.domain.ApiDefinition;
|
||||
|
@ -61,12 +62,12 @@ public class ApiDefinitionController {
|
|||
}
|
||||
|
||||
@PostMapping(value = "/run/debug", consumes = {"multipart/form-data"})
|
||||
public String runDebug(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||
public String runDebug(@RequestPart("request") RunDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||
return apiDefinitionService.run(request, bodyFiles);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/run", consumes = {"multipart/form-data"})
|
||||
public String run(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||
public String run(@RequestPart("request") RunDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||
return apiDefinitionService.run(request, bodyFiles);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,13 +29,13 @@ public class ApiTestCaseController {
|
|||
}
|
||||
|
||||
@PostMapping(value = "/create", consumes = {"multipart/form-data"})
|
||||
public void create(@RequestPart("request") SaveApiTestCaseRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||
apiTestCaseService.create(request, file, bodyFiles);
|
||||
public void create(@RequestPart("request") SaveApiTestCaseRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||
apiTestCaseService.create(request, bodyFiles);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/update", consumes = {"multipart/form-data"})
|
||||
public void update(@RequestPart("request") SaveApiTestCaseRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||
apiTestCaseService.update(request, file, bodyFiles);
|
||||
public void update(@RequestPart("request") SaveApiTestCaseRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
|
||||
apiTestCaseService.update(request, bodyFiles);
|
||||
}
|
||||
|
||||
@GetMapping("/delete/{id}")
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package io.metersphere.api.dto.definition;
|
||||
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.definition.response.Response;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class RunDefinitionRequest {
|
||||
|
||||
private String id;
|
||||
|
||||
private String reportId;
|
||||
|
||||
private MsTestElement testElement;
|
||||
|
||||
private Response response;
|
||||
|
||||
private List<String> bodyUploadIds;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package io.metersphere.api.dto.definition;
|
||||
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.definition.response.Response;
|
||||
import io.metersphere.api.dto.scenario.Scenario;
|
||||
import io.metersphere.base.domain.Schedule;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
@ -31,10 +31,8 @@ public class SaveApiDefinitionRequest {
|
|||
private String modulePath;
|
||||
|
||||
private String method;
|
||||
|
||||
private Scenario scenario;
|
||||
|
||||
private Object request;
|
||||
|
||||
private MsTestElement request;
|
||||
|
||||
private Response response;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package io.metersphere.api.dto.definition;
|
||||
|
||||
import io.metersphere.api.dto.scenario.request.Request;
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
|
@ -22,7 +22,7 @@ public class SaveApiTestCaseRequest {
|
|||
|
||||
private String description;
|
||||
|
||||
private Request request;
|
||||
private MsTestElement request;
|
||||
|
||||
private String response;
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
package io.metersphere.api.dto.definition.request;
|
||||
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
|
||||
public class Element {
|
||||
public String id;
|
||||
public String type;
|
||||
public String name;
|
||||
|
||||
public HashTree elementHashTree;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
package io.metersphere.api.dto.definition.request;
|
||||
|
||||
public class HTTPSamplerProxy extends Element {
|
||||
public String protocol;
|
||||
public String domain;
|
||||
public String port;
|
||||
public String method;
|
||||
public String path;
|
||||
public String contentEncoding;
|
||||
public boolean autoRedirects;
|
||||
public boolean followRedirects;
|
||||
public boolean useKeepalive;
|
||||
public boolean postBodyRaw;
|
||||
public boolean doMultipartPost;
|
||||
public boolean browserCompatibleMultipart;
|
||||
public String embeddedUrlRe;
|
||||
public String connectTimeout;
|
||||
public String responseTimeout;
|
||||
public String arguments;
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package io.metersphere.api.dto.definition.request;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.metersphere.api.dto.definition.request.configurations.MsHeaderManager;
|
||||
import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor;
|
||||
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
|
||||
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import lombok.Data;
|
||||
import org.apache.jmeter.save.SaveService;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
import org.apache.jorphan.collections.ListedHashTree;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = MsHTTPSamplerProxy.class, name = "HTTPSamplerProxy"),
|
||||
@JsonSubTypes.Type(value = MsHeaderManager.class, name = "HeaderManager"),
|
||||
@JsonSubTypes.Type(value = MsJSR223PostProcessor.class, name = "JSR223PostProcessor"),
|
||||
@JsonSubTypes.Type(value = MsJSR223PreProcessor.class, name = "JSR223PreProcessor"),
|
||||
@JsonSubTypes.Type(value = MsTestPlan.class, name = "TestPlan"),
|
||||
@JsonSubTypes.Type(value = MsThreadGroup.class, name = "ThreadGroup"),
|
||||
|
||||
})
|
||||
@JSONType(seeAlso = {MsHTTPSamplerProxy.class, MsHeaderManager.class, MsJSR223PostProcessor.class, MsJSR223PreProcessor.class}, typeKey = "type")
|
||||
@Data
|
||||
public class MsTestElement {
|
||||
private String type;
|
||||
@JSONField(ordinal = 1)
|
||||
private String id;
|
||||
@JSONField(ordinal = 2)
|
||||
private String name;
|
||||
@JSONField(ordinal = 3)
|
||||
private String label;
|
||||
@JSONField(ordinal = 4)
|
||||
private LinkedList<MsTestElement> hashTree;
|
||||
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree) {
|
||||
for (MsTestElement el : hashTree) {
|
||||
el.toHashTree(tree, el.hashTree);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换JMX
|
||||
*
|
||||
* @param hashTree
|
||||
* @return
|
||||
*/
|
||||
public String getJmx(HashTree hashTree) {
|
||||
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||
SaveService.saveTree(hashTree, baos);
|
||||
System.out.print(baos.toString());
|
||||
return baos.toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
LogUtil.warn("HashTree error, can't log jmx content");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public HashTree get() {
|
||||
HashTree jmeterTestPlanHashTree = new ListedHashTree();
|
||||
this.toHashTree(jmeterTestPlanHashTree, this.hashTree);
|
||||
return jmeterTestPlanHashTree;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package io.metersphere.api.dto.definition.request;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.jmeter.config.Arguments;
|
||||
import org.apache.jmeter.save.SaveService;
|
||||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jmeter.testelement.TestPlan;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@JSONType(typeName = "TestPlan")
|
||||
public class MsTestPlan extends MsTestElement {
|
||||
private String type = "TestPlan";
|
||||
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree) {
|
||||
final HashTree testPlanTree = tree.add(getPlan());
|
||||
if (CollectionUtils.isNotEmpty(hashTree)) {
|
||||
hashTree.forEach(el -> {
|
||||
el.toHashTree(testPlanTree, el.getHashTree());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public TestPlan getPlan() {
|
||||
TestPlan testPlan = new TestPlan(this.getName() + "TestPlan");
|
||||
testPlan.setProperty(TestElement.TEST_CLASS, TestPlan.class.getName());
|
||||
testPlan.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestPlanGui"));
|
||||
testPlan.setEnabled(true);
|
||||
testPlan.setFunctionalMode(false);
|
||||
testPlan.setSerialized(true);
|
||||
testPlan.setTearDownOnShutdown(true);
|
||||
testPlan.setUserDefinedVariables(new Arguments());
|
||||
return testPlan;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package io.metersphere.api.dto.definition.request;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.jmeter.control.LoopController;
|
||||
import org.apache.jmeter.save.SaveService;
|
||||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jmeter.threads.ThreadGroup;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@JSONType(typeName = "ThreadGroup")
|
||||
public class MsThreadGroup extends MsTestElement {
|
||||
private String type = "ThreadGroup";
|
||||
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree) {
|
||||
final HashTree groupTree = tree.add(getThreadGroup());
|
||||
if (CollectionUtils.isNotEmpty(hashTree)) {
|
||||
hashTree.forEach(el -> {
|
||||
el.toHashTree(groupTree, el.getHashTree());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public ThreadGroup getThreadGroup() {
|
||||
LoopController loopController = new LoopController();
|
||||
loopController.setName("LoopController");
|
||||
loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName());
|
||||
loopController.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("LoopControlPanel"));
|
||||
loopController.setEnabled(true);
|
||||
loopController.setLoops(1);
|
||||
|
||||
ThreadGroup threadGroup = new ThreadGroup();
|
||||
threadGroup.setEnabled(true);
|
||||
threadGroup.setName(this.getName() + "ThreadGroup");
|
||||
threadGroup.setProperty(TestElement.TEST_CLASS, ThreadGroup.class.getName());
|
||||
threadGroup.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ThreadGroupGui"));
|
||||
threadGroup.setNumThreads(1);
|
||||
threadGroup.setRampUp(1);
|
||||
threadGroup.setDelay(0);
|
||||
threadGroup.setDuration(0);
|
||||
threadGroup.setProperty(ThreadGroup.ON_SAMPLE_ERROR, ThreadGroup.ON_SAMPLE_ERROR_CONTINUE);
|
||||
threadGroup.setScheduler(false);
|
||||
threadGroup.setSamplerController(loopController);
|
||||
return threadGroup;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package io.metersphere.api.dto.definition.request.configurations;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.jmeter.protocol.http.control.Header;
|
||||
import org.apache.jmeter.protocol.http.control.HeaderManager;
|
||||
import org.apache.jmeter.save.SaveService;
|
||||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@JSONType(typeName = "HeaderManager")
|
||||
public class MsHeaderManager extends MsTestElement {
|
||||
|
||||
private String type = "HeaderManager";
|
||||
@JSONField(ordinal = 10)
|
||||
private List<KeyValue> headers;
|
||||
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree) {
|
||||
HeaderManager headerManager = new HeaderManager();
|
||||
headerManager.setEnabled(true);
|
||||
headerManager.setName(this.getName() + "Headers");
|
||||
headerManager.setProperty(TestElement.TEST_CLASS, HeaderManager.class.getName());
|
||||
headerManager.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("HeaderPanel"));
|
||||
headers.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue ->
|
||||
headerManager.add(new Header(keyValue.getName(), keyValue.getValue()))
|
||||
);
|
||||
final HashTree headersTree = tree.add(headerManager);
|
||||
if (CollectionUtils.isNotEmpty(hashTree)) {
|
||||
hashTree.forEach(el -> {
|
||||
el.toHashTree(headersTree, el.getHashTree());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package io.metersphere.api.dto.definition.request.dns;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
||||
import io.metersphere.api.dto.scenario.environment.Host;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.jmeter.config.Arguments;
|
||||
import org.apache.jmeter.protocol.http.control.DNSCacheManager;
|
||||
import org.apache.jmeter.save.SaveService;
|
||||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@JSONType(typeName = "DNSCacheManager")
|
||||
public class MsDNSCacheManager extends MsTestElement {
|
||||
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree) {
|
||||
for (MsTestElement el : hashTree) {
|
||||
el.toHashTree(tree, el.getHashTree());
|
||||
}
|
||||
}
|
||||
|
||||
public static void addEnvironmentVariables(HashTree samplerHashTree, String name, EnvironmentConfig config) {
|
||||
name += "Environment Variables";
|
||||
samplerHashTree.add(arguments(name, config.getCommonConfig().getVariables()));
|
||||
}
|
||||
|
||||
public static void addEnvironmentDNS(HashTree samplerHashTree, String name, EnvironmentConfig config) {
|
||||
if (config.getCommonConfig().isEnableHost() && CollectionUtils.isNotEmpty(config.getCommonConfig().getHosts())) {
|
||||
String domain = config.getHttpConfig().getDomain().trim();
|
||||
List<Host> hosts = new ArrayList<>();
|
||||
config.getCommonConfig().getHosts().forEach(host -> {
|
||||
if (StringUtils.isNotBlank(host.getDomain())) {
|
||||
String hostDomain = host.getDomain().trim().replace("http://", "").replace("https://", "");
|
||||
if (StringUtils.equals(hostDomain, domain)) {
|
||||
host.setDomain(hostDomain); // 域名去掉协议
|
||||
hosts.add(host);
|
||||
}
|
||||
}
|
||||
});
|
||||
samplerHashTree.add(dnsCacheManager(name + " DNSCacheManager", hosts));
|
||||
}
|
||||
}
|
||||
|
||||
private static Arguments arguments(String name, List<KeyValue> variables) {
|
||||
Arguments arguments = new Arguments();
|
||||
arguments.setEnabled(true);
|
||||
arguments.setName(name);
|
||||
arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName());
|
||||
arguments.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ArgumentsPanel"));
|
||||
variables.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue ->
|
||||
arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=")
|
||||
);
|
||||
return arguments;
|
||||
}
|
||||
|
||||
private static DNSCacheManager dnsCacheManager(String name, List<Host> hosts) {
|
||||
DNSCacheManager dnsCacheManager = new DNSCacheManager();
|
||||
dnsCacheManager.setEnabled(true);
|
||||
dnsCacheManager.setName(name);
|
||||
dnsCacheManager.setProperty(TestElement.TEST_CLASS, DNSCacheManager.class.getName());
|
||||
dnsCacheManager.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("DNSCachePanel"));
|
||||
dnsCacheManager.setCustomResolver(true);
|
||||
hosts.forEach(host -> dnsCacheManager.addHost(host.getDomain(), host.getIp()));
|
||||
|
||||
return dnsCacheManager;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package io.metersphere.api.dto.definition.request.processors.post;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.definition.request.prop.StringProp;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.jmeter.extractor.JSR223PostProcessor;
|
||||
import org.apache.jmeter.save.SaveService;
|
||||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@JSONType(typeName = "JSR223PostProcessor")
|
||||
public class MsJSR223PostProcessor extends MsTestElement {
|
||||
private String type = "JSR223PostProcessor";
|
||||
|
||||
@JSONField(ordinal = 10)
|
||||
private StringProp script;
|
||||
|
||||
@JSONField(ordinal = 11)
|
||||
private StringProp scriptLanguage;
|
||||
|
||||
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree) {
|
||||
JSR223PostProcessor processor = new JSR223PostProcessor();
|
||||
processor.setEnabled(true);
|
||||
processor.setName(this.getName() + "JSR223PostProcessor");
|
||||
processor.setProperty(TestElement.TEST_CLASS, JSR223PostProcessor.class.getName());
|
||||
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
||||
processor.setProperty("cacheKey", "true");
|
||||
processor.setProperty("scriptLanguage", this.getScriptLanguage().getValue());
|
||||
processor.setProperty("script", this.getScript().getValue());
|
||||
|
||||
final HashTree jsr223PostTree = tree.add(processor);
|
||||
if (CollectionUtils.isNotEmpty(hashTree)) {
|
||||
hashTree.forEach(el -> {
|
||||
el.toHashTree(jsr223PostTree, el.getHashTree());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package io.metersphere.api.dto.definition.request.processors.pre;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.definition.request.prop.StringProp;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.jmeter.modifiers.JSR223PreProcessor;
|
||||
import org.apache.jmeter.save.SaveService;
|
||||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@JSONType(typeName = "JSR223PreProcessor")
|
||||
public class MsJSR223PreProcessor extends MsTestElement {
|
||||
private String type = "JSR223PreProcessor";
|
||||
|
||||
@JSONField(ordinal = 10)
|
||||
private StringProp script;
|
||||
|
||||
@JSONField(ordinal = 11)
|
||||
private StringProp scriptLanguage;
|
||||
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree) {
|
||||
JSR223PreProcessor processor = new JSR223PreProcessor();
|
||||
processor.setEnabled(true);
|
||||
processor.setName(this.getName() + "JSR223PreProcessor");
|
||||
processor.setProperty(TestElement.TEST_CLASS, JSR223PreProcessor.class.getName());
|
||||
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
|
||||
processor.setProperty("cacheKey", "true");
|
||||
processor.setProperty("scriptLanguage", this.getScriptLanguage().getValue());
|
||||
processor.setProperty("script", this.getScript().getValue());
|
||||
|
||||
final HashTree jsr223PreTree = tree.add(processor);
|
||||
if (CollectionUtils.isNotEmpty(hashTree)) {
|
||||
hashTree.forEach(el -> {
|
||||
el.toHashTree(jsr223PreTree, el.getHashTree());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package io.metersphere.api.dto.definition.request.prop;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class BoolProp {
|
||||
private String id;
|
||||
private String key;
|
||||
private String name;
|
||||
private String type;
|
||||
private boolean value;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package io.metersphere.api.dto.definition.request.prop;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class StringProp {
|
||||
private String id;
|
||||
private String key;
|
||||
private String name;
|
||||
private String type;
|
||||
private String value;
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
package io.metersphere.api.dto.definition.request.sampler;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||
import io.metersphere.api.dto.definition.request.dns.MsDNSCacheManager;
|
||||
import io.metersphere.api.dto.definition.request.prop.BoolProp;
|
||||
import io.metersphere.api.dto.definition.request.prop.StringProp;
|
||||
import io.metersphere.api.dto.scenario.AuthConfig;
|
||||
import io.metersphere.api.dto.scenario.Body;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
||||
import io.metersphere.api.service.ApiTestEnvironmentService;
|
||||
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.jmeter.config.Arguments;
|
||||
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
|
||||
import org.apache.jmeter.protocol.http.util.HTTPArgument;
|
||||
import org.apache.jmeter.protocol.http.util.HTTPFileArg;
|
||||
import org.apache.jmeter.save.SaveService;
|
||||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@JSONType(typeName = "HTTPSamplerProxy")
|
||||
public class MsHTTPSamplerProxy extends MsTestElement {
|
||||
private String type = "HTTPSamplerProxy";
|
||||
|
||||
@JSONField(ordinal = 10)
|
||||
private StringProp protocol;
|
||||
|
||||
@JSONField(ordinal = 11)
|
||||
private StringProp domain;
|
||||
|
||||
@JSONField(ordinal = 12)
|
||||
private StringProp port;
|
||||
|
||||
@JSONField(ordinal = 13)
|
||||
private StringProp method;
|
||||
|
||||
@JSONField(ordinal = 14)
|
||||
private StringProp path;
|
||||
|
||||
@JSONField(ordinal = 15)
|
||||
private StringProp connectTimeout;
|
||||
@JSONField(ordinal = 16)
|
||||
|
||||
private StringProp responseTimeout;
|
||||
@JSONField(ordinal = 17)
|
||||
|
||||
private List<KeyValue> arguments;
|
||||
|
||||
@JSONField(ordinal = 18)
|
||||
private Body body;
|
||||
|
||||
@JSONField(ordinal = 19)
|
||||
private List<KeyValue> rest;
|
||||
|
||||
@JSONField(ordinal = 20)
|
||||
private AuthConfig authConfig;
|
||||
|
||||
@JSONField(ordinal = 21)
|
||||
private BoolProp followRedirects;
|
||||
|
||||
@JSONField(ordinal = 22)
|
||||
private BoolProp doMultipartPost;
|
||||
|
||||
@JSONField(ordinal = 23)
|
||||
private String useEnvironment;
|
||||
|
||||
@JSONField(ordinal = 24)
|
||||
private String url;
|
||||
|
||||
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree) {
|
||||
HTTPSamplerProxy sampler = new HTTPSamplerProxy();
|
||||
sampler.setEnabled(true);
|
||||
sampler.setName(this.getName());
|
||||
sampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
|
||||
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("HttpTestSampleGui"));
|
||||
sampler.setMethod(this.getMethod().getValue());
|
||||
sampler.setContentEncoding("UTF-8");
|
||||
sampler.setConnectTimeout(this.getConnectTimeout().getValue() == null ? "6000" : this.getConnectTimeout().getValue());
|
||||
sampler.setResponseTimeout(this.getResponseTimeout().getValue() == null ? "6000" : this.getResponseTimeout().getValue());
|
||||
sampler.setFollowRedirects(this.getFollowRedirects() != null ? this.getFollowRedirects().isValue() : true);
|
||||
sampler.setUseKeepAlive(true);
|
||||
sampler.setDoMultipart(this.getDoMultipartPost() != null ? this.getDoMultipartPost().isValue() : true);
|
||||
EnvironmentConfig config = null;
|
||||
if (useEnvironment != null) {
|
||||
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
|
||||
ApiTestEnvironmentWithBLOBs environment = environmentService.get(useEnvironment);
|
||||
config = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class);
|
||||
}
|
||||
try {
|
||||
if (config != null) {
|
||||
String url = "";
|
||||
sampler.setDomain(config.getHttpConfig().getDomain());
|
||||
sampler.setPort(config.getHttpConfig().getPort());
|
||||
sampler.setProtocol(config.getHttpConfig().getProtocol());
|
||||
url = config.getHttpConfig().getProtocol() + "://" + config.getHttpConfig().getSocket();
|
||||
URL urlObject = new URL(url);
|
||||
String envPath = StringUtils.equals(urlObject.getPath(), "/") ? "" : urlObject.getPath();
|
||||
if (StringUtils.isNotBlank(this.getPath().getValue())) {
|
||||
envPath += this.getPath().getValue();
|
||||
}
|
||||
sampler.setPath(getPostQueryParameters(URLDecoder.decode(envPath, "UTF-8")));
|
||||
} else {
|
||||
String url = this.getUrl();
|
||||
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
||||
url = "http://" + url;
|
||||
}
|
||||
URL urlObject = new URL(url);
|
||||
sampler.setDomain(URLDecoder.decode(urlObject.getHost(), "UTF-8"));
|
||||
sampler.setPort(urlObject.getPort());
|
||||
sampler.setProtocol(urlObject.getProtocol());
|
||||
sampler.setPath(getPostQueryParameters(URLDecoder.decode(urlObject.getPath(), "UTF-8")));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e);
|
||||
}
|
||||
|
||||
// 请求参数
|
||||
if (CollectionUtils.isNotEmpty(this.getArguments())) {
|
||||
sampler.setArguments(httpArguments(this.getArguments()));
|
||||
}
|
||||
// rest参数处理
|
||||
if (CollectionUtils.isNotEmpty(this.getRest())) {
|
||||
sampler.setArguments(httpArguments(this.getRest()));
|
||||
}
|
||||
|
||||
// 请求体
|
||||
if (!StringUtils.equals(this.getMethod().getValue(), "GET")) {
|
||||
List<KeyValue> body = new ArrayList<>();
|
||||
if (this.getBody().isKV()) {
|
||||
body = this.getBody().getKvs().stream().filter(KeyValue::isValid).collect(Collectors.toList());
|
||||
sampler.setHTTPFiles(httpFileArgs());
|
||||
} else if (this.getBody().isBinary()) {
|
||||
// 上传二进制数据处理
|
||||
} else if (this.getBody().isJson()) {
|
||||
|
||||
} else {
|
||||
if (StringUtils.isNotBlank(this.getBody().getRaw())) {
|
||||
sampler.setPostBodyRaw(true);
|
||||
KeyValue keyValue = new KeyValue("", this.getBody().getRaw());
|
||||
keyValue.setEnable(true);
|
||||
keyValue.setEncode(false);
|
||||
body.add(keyValue);
|
||||
}
|
||||
if (StringUtils.isNotBlank(this.getBody().getXml())) {
|
||||
sampler.setPostBodyRaw(true);
|
||||
KeyValue keyValue = new KeyValue("", this.getBody().getXml());
|
||||
keyValue.setEnable(true);
|
||||
keyValue.setEncode(false);
|
||||
body.add(keyValue);
|
||||
}
|
||||
}
|
||||
sampler.setArguments(httpArguments(body));
|
||||
}
|
||||
|
||||
final HashTree httpSamplerTree = tree.add(sampler);
|
||||
|
||||
//判断是否要开启DNS
|
||||
if (config != null && config.getCommonConfig() != null && config.getCommonConfig().isEnableHost()) {
|
||||
MsDNSCacheManager.addEnvironmentVariables(httpSamplerTree, this.getName(), config);
|
||||
MsDNSCacheManager.addEnvironmentDNS(httpSamplerTree, this.getName(), config);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(hashTree)) {
|
||||
hashTree.forEach(el -> {
|
||||
el.toHashTree(httpSamplerTree, el.getHashTree());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private String getPostQueryParameters(String path) {
|
||||
if (!StringUtils.equals(this.getMethod().getValue(), "GET")) {
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
stringBuffer.append(path);
|
||||
stringBuffer.append("?");
|
||||
this.getArguments().stream().filter(KeyValue::isEnable).filter(KeyValue::isValid).forEach(keyValue ->
|
||||
stringBuffer.append(keyValue.getName()).append("=").append(keyValue.getValue()).append("&")
|
||||
);
|
||||
return stringBuffer.substring(0, stringBuffer.length() - 1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
private Arguments httpArguments(List<KeyValue> list) {
|
||||
Arguments arguments = new Arguments();
|
||||
list.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> {
|
||||
HTTPArgument httpArgument = new HTTPArgument(keyValue.getName(), keyValue.getValue());
|
||||
httpArgument.setAlwaysEncoded(keyValue.isEncode());
|
||||
if (StringUtils.isNotBlank(keyValue.getContentType())) {
|
||||
httpArgument.setContentType(keyValue.getContentType());
|
||||
}
|
||||
arguments.addArgument(httpArgument);
|
||||
}
|
||||
);
|
||||
return arguments;
|
||||
}
|
||||
|
||||
private HTTPFileArg[] httpFileArgs() {
|
||||
final String BODY_FILE_DIR = "/opt/metersphere/data/body";
|
||||
List<HTTPFileArg> list = new ArrayList<>();
|
||||
this.getBody().getKvs().stream().filter(KeyValue::isFile).filter(KeyValue::isEnable).forEach(keyValue -> {
|
||||
if (keyValue.getFiles() != null) {
|
||||
keyValue.getFiles().forEach(file -> {
|
||||
String paramName = keyValue.getName();
|
||||
String path = BODY_FILE_DIR + '/' + this.getId() + '/' + file.getId() + '_' + file.getName();
|
||||
String mimetype = keyValue.getContentType();
|
||||
list.add(new HTTPFileArg(path, paramName, mimetype));
|
||||
});
|
||||
}
|
||||
});
|
||||
return list.toArray(new HTTPFileArg[0]);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -10,6 +10,7 @@ public class Body {
|
|||
private String type;
|
||||
private String raw;
|
||||
private String format;
|
||||
private List<KeyValue> fromUrlencoded;
|
||||
private List<KeyValue> kvs;
|
||||
private List<KeyValue> binary;
|
||||
private Object json;
|
||||
|
|
|
@ -27,6 +27,8 @@ import org.apache.jmeter.visualizers.backend.AbstractBackendListenerClient;
|
|||
import org.apache.jmeter.visualizers.backend.BackendListenerContext;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
|
@ -63,6 +65,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
|||
|
||||
@Override
|
||||
public void setupTest(BackendListenerContext context) throws Exception {
|
||||
setConsole();
|
||||
setParam(context);
|
||||
apiTestService = CommonBeanFactory.getBean(APITestService.class);
|
||||
if (apiTestService == null) {
|
||||
|
@ -109,6 +112,18 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
|||
super.setupTest(context);
|
||||
}
|
||||
|
||||
//获得控制台内容
|
||||
private PrintStream oldPrintStream = System.out;
|
||||
private ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
|
||||
private void setConsole() {
|
||||
System.setOut(new PrintStream(bos)); //设置新的out
|
||||
}
|
||||
|
||||
private String getConsole() {
|
||||
System.setOut(oldPrintStream);
|
||||
return bos.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSampleResults(List<SampleResult> sampleResults, BackendListenerContext context) {
|
||||
|
@ -120,8 +135,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
|||
TestResult testResult = new TestResult();
|
||||
testResult.setTestId(testId);
|
||||
testResult.setTotal(queue.size());
|
||||
|
||||
// 一个脚本里可能包含多个场景(ThreadGroup),所以要区分开,key: 场景Id
|
||||
// 一个脚本里可能包含多个场景(MsThreadGroup),所以要区分开,key: 场景Id
|
||||
final Map<String, ScenarioResult> scenarios = new LinkedHashMap<>();
|
||||
queue.forEach(result -> {
|
||||
// 线程名称: <场景名> <场景Index>-<请求Index>, 例如:Scenario 2-1
|
||||
|
@ -276,7 +290,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
|||
responseResult.setResponseSize(result.getResponseData().length);
|
||||
responseResult.setResponseTime(result.getTime());
|
||||
responseResult.setResponseMessage(result.getResponseMessage());
|
||||
|
||||
responseResult.setConsole(getConsole());
|
||||
if (JMeterVars.get(result.hashCode()) != null) {
|
||||
List<String> vars = new LinkedList<>();
|
||||
JMeterVars.get(result.hashCode()).entrySet().parallelStream().reduce(vars, (first, second) -> {
|
||||
|
|
|
@ -42,12 +42,12 @@ public class JMeterService {
|
|||
return jmxGenerator.parse(testId, testName, scenarios);
|
||||
}
|
||||
|
||||
public void run(String testId, String testName, List<Scenario> scenarios, String debugReportId,String runMode) {
|
||||
public void run(String testId, String testName, List<Scenario> scenarios, String debugReportId, String runMode) {
|
||||
try {
|
||||
init();
|
||||
HashTree testPlan = getHashTree(testId, testName, scenarios);
|
||||
JMeterVars.addJSR223PostProcessor(testPlan);
|
||||
addBackendListener(testId, debugReportId,runMode, testPlan);
|
||||
addBackendListener(testId, debugReportId, runMode, testPlan);
|
||||
LocalRunner runner = new LocalRunner(testPlan);
|
||||
runner.run();
|
||||
} catch (Exception e) {
|
||||
|
@ -82,12 +82,12 @@ public class JMeterService {
|
|||
}
|
||||
}
|
||||
|
||||
private void addBackendListener(String testId, String debugReportId,String runMode, HashTree testPlan) {
|
||||
private void addBackendListener(String testId, String debugReportId, String runMode, HashTree testPlan) {
|
||||
BackendListener backendListener = new BackendListener();
|
||||
backendListener.setName(testId);
|
||||
Arguments arguments = new Arguments();
|
||||
arguments.addArgument(APIBackendListenerClient.TEST_ID, testId);
|
||||
if(StringUtils.isNotBlank(runMode)){
|
||||
if (StringUtils.isNotBlank(runMode)) {
|
||||
arguments.addArgument("runMode", runMode);
|
||||
}
|
||||
if (StringUtils.isNotBlank(debugReportId)) {
|
||||
|
@ -97,4 +97,17 @@ public class JMeterService {
|
|||
backendListener.setClassname(APIBackendListenerClient.class.getCanonicalName());
|
||||
testPlan.add(testPlan.getArray()[0], backendListener);
|
||||
}
|
||||
|
||||
public void runDefinition(String testId, HashTree testPlan, String debugReportId, String runMode) {
|
||||
try {
|
||||
JMeterVars.addJSR223PostProcessor(testPlan);
|
||||
addBackendListener(testId, debugReportId, runMode, testPlan);
|
||||
LocalRunner runner = new LocalRunner(testPlan);
|
||||
runner.run();
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
MSException.throwException(Translator.get("api_load_script_error"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ public class ResponseResult {
|
|||
|
||||
private String vars;
|
||||
|
||||
private String console;
|
||||
|
||||
private final List<ResponseAssertionResult> assertions = new ArrayList<>();
|
||||
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ public class JmeterDocumentParser {
|
|||
private final static String STRING_PROP = "stringProp";
|
||||
private final static String ARGUMENTS = "Arguments";
|
||||
private final static String COLLECTION_PROP = "collectionProp";
|
||||
private final static String HTTP_SAMPLER_PROXY = "HTTPSamplerProxy";
|
||||
private final static String HTTP_SAMPLER_PROXY = "MsHTTPSamplerProxy";
|
||||
private final static String ELEMENT_PROP = "elementProp";
|
||||
|
||||
public static byte[] parse(byte[] source) {
|
||||
|
|
|
@ -3,11 +3,7 @@ package io.metersphere.api.service;
|
|||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.APIReportResult;
|
||||
import io.metersphere.api.dto.definition.ApiComputeResult;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionRequest;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
||||
import io.metersphere.api.dto.definition.SaveApiDefinitionRequest;
|
||||
import io.metersphere.api.dto.scenario.Scenario;
|
||||
import io.metersphere.api.dto.definition.*;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.api.jmeter.TestResult;
|
||||
import io.metersphere.base.domain.*;
|
||||
|
@ -24,6 +20,7 @@ import io.metersphere.commons.utils.SessionUtils;
|
|||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.service.FileService;
|
||||
import io.metersphere.service.QuotaService;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
import org.aspectj.util.FileUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -101,7 +98,6 @@ public class ApiDefinitionService {
|
|||
|
||||
public void update(SaveApiDefinitionRequest request, List<MultipartFile> bodyFiles) {
|
||||
deleteFileByTestId(request.getId());
|
||||
|
||||
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
|
||||
request.setBodyUploadIds(null);
|
||||
ApiDefinition test = updateTest(request);
|
||||
|
@ -210,14 +206,6 @@ public class ApiDefinitionService {
|
|||
return test;
|
||||
}
|
||||
|
||||
private void saveFile(String apiId, MultipartFile file) {
|
||||
final FileMetadata metadata = fileService.saveFile(file);
|
||||
ApiTestFile apiTestFile = new ApiTestFile();
|
||||
apiTestFile.setTestId(apiId);
|
||||
apiTestFile.setFileId(metadata.getId());
|
||||
apiTestFileMapper.insert(apiTestFile);
|
||||
}
|
||||
|
||||
private void deleteFileByTestId(String apiId) {
|
||||
ApiTestFileExample apiTestFileExample = new ApiTestFileExample();
|
||||
apiTestFileExample.createCriteria().andTestIdEqualTo(apiId);
|
||||
|
@ -237,13 +225,13 @@ public class ApiDefinitionService {
|
|||
* @param bodyFiles
|
||||
* @return
|
||||
*/
|
||||
public String run(SaveApiDefinitionRequest request, List<MultipartFile> bodyFiles) {
|
||||
public String run(RunDefinitionRequest request, List<MultipartFile> bodyFiles) {
|
||||
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
|
||||
createBodyFiles(request.getId(), bodyUploadIds, bodyFiles);
|
||||
|
||||
List<Scenario> scenarios = new ArrayList<>();
|
||||
scenarios.add(request.getScenario());
|
||||
jMeterService.run(request.getId(), request.getName(), scenarios, request.getReportId(), ApiRunMode.DELIMIT.name());
|
||||
HashTree hashTree = request.getTestElement().get();
|
||||
// 调用执行方法
|
||||
jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), ApiRunMode.DELIMIT.name());
|
||||
return request.getId();
|
||||
}
|
||||
|
||||
|
@ -281,6 +269,9 @@ public class ApiDefinitionService {
|
|||
*/
|
||||
public APIReportResult getDbResult(String testId) {
|
||||
ApiDefinitionExecResult result = apiDefinitionExecResultMapper.selectByResourceId(testId);
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
APIReportResult reportResult = new APIReportResult();
|
||||
reportResult.setContent(result.getContent());
|
||||
return reportResult;
|
||||
|
|
|
@ -53,21 +53,10 @@ public class ApiTestCaseService {
|
|||
return apiTestCaseMapper.selectByPrimaryKey(id);
|
||||
}
|
||||
|
||||
public void create(SaveApiTestCaseRequest request, MultipartFile file, List<MultipartFile> bodyFiles) {
|
||||
public void create(SaveApiTestCaseRequest request, List<MultipartFile> bodyFiles) {
|
||||
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
|
||||
ApiTestCase test = createTest(request, file);
|
||||
createBodyFiles(test, bodyUploadIds, bodyFiles);
|
||||
}
|
||||
|
||||
private ApiTestCase createTest(SaveApiTestCaseRequest request, MultipartFile file) {
|
||||
if (file == null) {
|
||||
throw new IllegalArgumentException(Translator.get("file_cannot_be_null"));
|
||||
}
|
||||
checkQuota();
|
||||
request.setBodyUploadIds(null);
|
||||
ApiTestCase test = createTest(request);
|
||||
saveFile(test.getId(), file);
|
||||
return test;
|
||||
createBodyFiles(test, bodyUploadIds, bodyFiles);
|
||||
}
|
||||
|
||||
private void checkQuota() {
|
||||
|
@ -77,17 +66,14 @@ public class ApiTestCaseService {
|
|||
}
|
||||
}
|
||||
|
||||
public void update(SaveApiTestCaseRequest request, MultipartFile file, List<MultipartFile> bodyFiles) {
|
||||
if (file == null) {
|
||||
throw new IllegalArgumentException(Translator.get("file_cannot_be_null"));
|
||||
}
|
||||
public void update(SaveApiTestCaseRequest request, List<MultipartFile> bodyFiles) {
|
||||
|
||||
deleteFileByTestId(request.getId());
|
||||
|
||||
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
|
||||
request.setBodyUploadIds(null);
|
||||
ApiTestCase test = updateTest(request);
|
||||
createBodyFiles(test, bodyUploadIds, bodyFiles);
|
||||
saveFile(test.getId(), file);
|
||||
}
|
||||
|
||||
private void createBodyFiles(ApiTestCase test, List<String> bodyUploadIds, List<MultipartFile> bodyFiles) {
|
||||
|
|
|
@ -491,9 +491,9 @@ public class JmeterDocumentParser implements DocumentParser {
|
|||
setupElement.setAttribute("testclass", "SetupThreadGroup");
|
||||
setupElement.setAttribute("testname", "setUp Thread Group");
|
||||
setupElement.setAttribute("enabled", "true");
|
||||
setupElement.appendChild(createStringProp(document, "ThreadGroup.on_sample_error", "stoptestnow"));
|
||||
setupElement.appendChild(createStringProp(document, "MsThreadGroup.on_sample_error", "stoptestnow"));
|
||||
Element elementProp = document.createElement("elementProp");
|
||||
elementProp.setAttribute("name", "ThreadGroup.main_controller");
|
||||
elementProp.setAttribute("name", "MsThreadGroup.main_controller");
|
||||
elementProp.setAttribute("elementType", "LoopController");
|
||||
elementProp.setAttribute("guiclass", "LoopControlPanel");
|
||||
elementProp.setAttribute("testclass", "LoopController");
|
||||
|
@ -502,12 +502,12 @@ public class JmeterDocumentParser implements DocumentParser {
|
|||
elementProp.appendChild(createBoolProp(document, "LoopController.continue_forever", false));
|
||||
elementProp.appendChild(createIntProp(document, "LoopController.loops", 1));
|
||||
setupElement.appendChild(elementProp);
|
||||
setupElement.appendChild(createStringProp(document, "ThreadGroup.num_threads", "1"));
|
||||
setupElement.appendChild(createStringProp(document, "ThreadGroup.ramp_time", "1"));
|
||||
setupElement.appendChild(createStringProp(document, "ThreadGroup.duration", ""));
|
||||
setupElement.appendChild(createStringProp(document, "ThreadGroup.delay", ""));
|
||||
setupElement.appendChild(createBoolProp(document, "ThreadGroup.scheduler", false));
|
||||
setupElement.appendChild(createBoolProp(document, "ThreadGroup.same_user_on_next_iteration", true));
|
||||
setupElement.appendChild(createStringProp(document, "MsThreadGroup.num_threads", "1"));
|
||||
setupElement.appendChild(createStringProp(document, "MsThreadGroup.ramp_time", "1"));
|
||||
setupElement.appendChild(createStringProp(document, "MsThreadGroup.duration", ""));
|
||||
setupElement.appendChild(createStringProp(document, "MsThreadGroup.delay", ""));
|
||||
setupElement.appendChild(createBoolProp(document, "MsThreadGroup.scheduler", false));
|
||||
setupElement.appendChild(createBoolProp(document, "MsThreadGroup.same_user_on_next_iteration", true));
|
||||
hashTree.appendChild(setupElement);
|
||||
|
||||
Element setupHashTree = document.createElement(HASH_TREE_ELEMENT);
|
||||
|
@ -568,17 +568,17 @@ public class JmeterDocumentParser implements DocumentParser {
|
|||
}
|
||||
/*
|
||||
<PostThreadGroup guiclass="PostThreadGroupGui" testclass="PostThreadGroup" testname="tearDown Thread Group" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
|
||||
<stringProp name="MsThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="MsThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
<stringProp name="LoopController.loops">1</stringProp>
|
||||
</elementProp>
|
||||
<stringProp name="ThreadGroup.num_threads">1</stringProp>
|
||||
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
|
||||
<boolProp name="ThreadGroup.scheduler">false</boolProp>
|
||||
<stringProp name="ThreadGroup.duration"></stringProp>
|
||||
<stringProp name="ThreadGroup.delay"></stringProp>
|
||||
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
|
||||
<stringProp name="MsThreadGroup.num_threads">1</stringProp>
|
||||
<stringProp name="MsThreadGroup.ramp_time">1</stringProp>
|
||||
<boolProp name="MsThreadGroup.scheduler">false</boolProp>
|
||||
<stringProp name="MsThreadGroup.duration"></stringProp>
|
||||
<stringProp name="MsThreadGroup.delay"></stringProp>
|
||||
<boolProp name="MsThreadGroup.same_user_on_next_iteration">true</boolProp>
|
||||
</PostThreadGroup>
|
||||
*/
|
||||
Element tearDownElement = document.createElement("PostThreadGroup");
|
||||
|
@ -586,15 +586,15 @@ public class JmeterDocumentParser implements DocumentParser {
|
|||
tearDownElement.setAttribute("testclass", "PostThreadGroup");
|
||||
tearDownElement.setAttribute("testname", "tearDown Thread Group");
|
||||
tearDownElement.setAttribute("enabled", "true");
|
||||
tearDownElement.appendChild(createStringProp(document, "ThreadGroup.on_sample_error", "continue"));
|
||||
tearDownElement.appendChild(createStringProp(document, "ThreadGroup.num_threads", "1"));
|
||||
tearDownElement.appendChild(createStringProp(document, "ThreadGroup.ramp_time", "1"));
|
||||
tearDownElement.appendChild(createStringProp(document, "ThreadGroup.duration", ""));
|
||||
tearDownElement.appendChild(createStringProp(document, "ThreadGroup.delay", ""));
|
||||
tearDownElement.appendChild(createBoolProp(document, "ThreadGroup.scheduler", false));
|
||||
tearDownElement.appendChild(createBoolProp(document, "ThreadGroup.same_user_on_next_iteration", true));
|
||||
tearDownElement.appendChild(createStringProp(document, "MsThreadGroup.on_sample_error", "continue"));
|
||||
tearDownElement.appendChild(createStringProp(document, "MsThreadGroup.num_threads", "1"));
|
||||
tearDownElement.appendChild(createStringProp(document, "MsThreadGroup.ramp_time", "1"));
|
||||
tearDownElement.appendChild(createStringProp(document, "MsThreadGroup.duration", ""));
|
||||
tearDownElement.appendChild(createStringProp(document, "MsThreadGroup.delay", ""));
|
||||
tearDownElement.appendChild(createBoolProp(document, "MsThreadGroup.scheduler", false));
|
||||
tearDownElement.appendChild(createBoolProp(document, "MsThreadGroup.same_user_on_next_iteration", true));
|
||||
Element elementProp = document.createElement("elementProp");
|
||||
elementProp.setAttribute("name", "ThreadGroup.main_controller");
|
||||
elementProp.setAttribute("name", "MsThreadGroup.main_controller");
|
||||
elementProp.setAttribute("elementType", "LoopController");
|
||||
elementProp.setAttribute("guiclass", "LoopControlPanel");
|
||||
elementProp.setAttribute("testclass", "LoopController");
|
||||
|
@ -760,8 +760,8 @@ public class JmeterDocumentParser implements DocumentParser {
|
|||
threadGroup.setAttribute("guiclass", CONCURRENCY_THREAD_GROUP + "Gui");
|
||||
threadGroup.setAttribute("testclass", CONCURRENCY_THREAD_GROUP);
|
||||
/*
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="com.blazemeter.jmeter.control.VirtualUserController"/>
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="MsThreadGroup.main_controller" elementType="com.blazemeter.jmeter.control.VirtualUserController"/>
|
||||
<stringProp name="MsThreadGroup.on_sample_error">continue</stringProp>
|
||||
<stringProp name="TargetLevel">2</stringProp>
|
||||
<stringProp name="RampUp">12</stringProp>
|
||||
<stringProp name="Steps">2</stringProp>
|
||||
|
@ -773,11 +773,11 @@ public class JmeterDocumentParser implements DocumentParser {
|
|||
removeChildren(threadGroup);
|
||||
// elementProp
|
||||
Element elementProp = document.createElement("elementProp");
|
||||
elementProp.setAttribute("name", "ThreadGroup.main_controller");
|
||||
elementProp.setAttribute("name", "MsThreadGroup.main_controller");
|
||||
elementProp.setAttribute("elementType", "com.blazemeter.jmeter.control.VirtualUserController");
|
||||
threadGroup.appendChild(elementProp);
|
||||
|
||||
threadGroup.appendChild(createStringProp(document, "ThreadGroup.on_sample_error", "continue"));
|
||||
threadGroup.appendChild(createStringProp(document, "MsThreadGroup.on_sample_error", "continue"));
|
||||
threadGroup.appendChild(createStringProp(document, "TargetLevel", "2"));
|
||||
threadGroup.appendChild(createStringProp(document, "RampUp", "12"));
|
||||
threadGroup.appendChild(createStringProp(document, "Steps", "2"));
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
<el-col :span="1">
|
||||
<template>
|
||||
<div>
|
||||
<ms-tag v-if="api.api_status == 'Prepare'" type="info"
|
||||
<ms-tag v-if="api.status == 'Prepare'" type="info"
|
||||
:content="$t('test_track.plan.plan_status_prepare')"/>
|
||||
<ms-tag v-if="api.api_status == 'Underway'" type="primary"
|
||||
<ms-tag v-if="api.status == 'Underway'" type="primary"
|
||||
:content="$t('test_track.plan.plan_status_running')"/>
|
||||
<ms-tag v-if="api.api_status == 'Completed'" type="success"
|
||||
<ms-tag v-if="api.status == 'Completed'" type="success"
|
||||
:content="$t('test_track.plan.plan_status_completed')"/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -61,13 +61,7 @@
|
|||
</div>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<!--<div class="ms-api-header-select">-->
|
||||
<!--<el-button size="small" style="background-color: #783887;color: white" @click="createCase">-->
|
||||
<!--+{{$t('api_test.definition.request.case')}}-->
|
||||
<!--</el-button>-->
|
||||
<!--</div>-->
|
||||
|
||||
<el-dropdown size="small" split-button type="primary" class="ms-api-header-select" @click="createCase"
|
||||
<el-dropdown size="small" split-button type="primary" class="ms-api-header-select" @click="addCase"
|
||||
@command="handleCommand">
|
||||
+{{$t('api_test.definition.request.case')}}
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
|
@ -77,7 +71,7 @@
|
|||
|
||||
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<el-col :span="1">
|
||||
<button type="button" aria-label="Close" class="el-card-btn" @click="apiCaseClose()"><i
|
||||
class="el-dialog__close el-icon el-icon-close"></i></button>
|
||||
</el-col>
|
||||
|
@ -124,7 +118,7 @@
|
|||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<ms-tip-button @click="runCase(item)" :tip="$t('api_test.run')" icon="el-icon-video-play"
|
||||
<ms-tip-button @click="singleRun(item)" :tip="$t('api_test.run')" icon="el-icon-video-play"
|
||||
style="background-color: #409EFF;color: white" size="mini" circle/>
|
||||
<ms-tip-button @click="copyCase(item)" :tip="$t('commons.copy')" icon="el-icon-document-copy"
|
||||
size="mini" circle/>
|
||||
|
@ -146,12 +140,11 @@
|
|||
<div v-if="item.active">
|
||||
<p class="tip">{{$t('api_test.definition.request.req_param')}} </p>
|
||||
|
||||
<ms-api-request-form :is-read-only="isReadOnly" :request="item.test.request"/>
|
||||
<ms-api-request-form :is-read-only="isReadOnly" :headers="item.request.hashTree[0].headers " :request="item.request"/>
|
||||
|
||||
<p class="tip">{{$t('api_test.definition.request.assertions_rule')}} </p>
|
||||
|
||||
<ms-api-assertions :request="item.test.request" :is-read-only="isReadOnly"
|
||||
:assertions="item.test.request.assertions"/>
|
||||
<!-- <p class="tip">{{$t('api_test.definition.request.assertions_rule')}} </p>-->
|
||||
<!--<ms-api-assertions :request="item.request" :is-read-only="isReadOnly"-->
|
||||
<!--:assertions="item.request.assertions"/>-->
|
||||
|
||||
<!-- 保存操作 -->
|
||||
<el-button type="primary" size="small" style="margin: 20px; float: right" @click="saveTestCase(item)">
|
||||
|
@ -176,7 +169,6 @@
|
|||
import MsTag from "../../../common/components/MsTag";
|
||||
import MsTipButton from "../../../common/components/MsTipButton";
|
||||
import MsApiRequestForm from "./request/ApiRequestForm";
|
||||
import {Test, RequestFactory} from "../model/ApiTestModel";
|
||||
import {downloadFile, getUUID} from "@/common/js/utils";
|
||||
import {parseEnvironment} from "../model/EnvironmentModel";
|
||||
import ApiEnvironmentConfig from "../../test/components/ApiEnvironmentConfig";
|
||||
|
@ -241,7 +233,7 @@
|
|||
},
|
||||
handleCommand(e) {
|
||||
if (e === "run") {
|
||||
this.runCase();
|
||||
this.batchRun();
|
||||
}
|
||||
},
|
||||
showInput(row) {
|
||||
|
@ -253,35 +245,39 @@
|
|||
this.apiCaseList = [];
|
||||
this.$emit('apiCaseClose');
|
||||
},
|
||||
runCase(row) {
|
||||
batchRun() {
|
||||
if (!this.environment) {
|
||||
this.$warning(this.$t('api_test.environment.select_environment'));
|
||||
return;
|
||||
}
|
||||
this.loading = true;
|
||||
if (this.apiCaseList.length > 0) {
|
||||
this.apiCaseList.forEach(item => {
|
||||
if (item.type != "create") {
|
||||
item.request.name = item.id;
|
||||
item.request.useEnvironment = this.environment.id;
|
||||
this.runData.push(item.request);
|
||||
}
|
||||
})
|
||||
this.loading = true;
|
||||
/*触发执行操作*/
|
||||
this.reportId = getUUID().substring(0, 8);
|
||||
} else {
|
||||
this.$warning("没有可执行的用例!");
|
||||
}
|
||||
},
|
||||
singleRun(row) {
|
||||
if (!this.environment) {
|
||||
this.$warning(this.$t('api_test.environment.select_environment'));
|
||||
return;
|
||||
}
|
||||
this.runData = [];
|
||||
if (row) {
|
||||
row.test.request.url = this.api.url;
|
||||
row.test.request.method = this.api.method;
|
||||
row.test.request.name = row.id;
|
||||
this.loading = true;
|
||||
this.runData.push(row.test.request);
|
||||
/*触发执行操作*/
|
||||
this.reportId = getUUID().substring(0, 8);
|
||||
} else {
|
||||
if (this.apiCaseList.length > 0) {
|
||||
this.apiCaseList.forEach(item => {
|
||||
if (item.type != "create") {
|
||||
item.test.request.name = item.id;
|
||||
this.runData.push(item.test.request);
|
||||
}
|
||||
})
|
||||
this.loading = true;
|
||||
/*触发执行操作*/
|
||||
this.reportId = getUUID().substring(0, 8);
|
||||
} else {
|
||||
this.$warning("没有可执行的用例!");
|
||||
}
|
||||
}
|
||||
this.loading = true;
|
||||
row.request.name = row.id;
|
||||
row.request.useEnvironment = this.environment.id;
|
||||
this.runData.push(row.request);
|
||||
/*触发执行操作*/
|
||||
this.reportId = getUUID().substring(0, 8);
|
||||
},
|
||||
runRefresh(data) {
|
||||
this.loading = false;
|
||||
|
@ -293,42 +289,33 @@
|
|||
this.$get('/api/testcase/delete/' + row.id, () => {
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
this.apiCaseList.splice(index, 1);
|
||||
this.$emit('refresh');
|
||||
});
|
||||
},
|
||||
copyCase(data) {
|
||||
let obj = {
|
||||
name: data.name,
|
||||
priority: data.priority,
|
||||
type: 'create',
|
||||
active: false,
|
||||
test: data.test,
|
||||
};
|
||||
let obj = {name: data.name, priority: data.priority, type: 'create', active: false, request: data.request};
|
||||
this.apiCaseList.unshift(obj);
|
||||
},
|
||||
createCase(row) {
|
||||
let obj = {
|
||||
name: '',
|
||||
priority: 'P0',
|
||||
type: 'create',
|
||||
active: false,
|
||||
};
|
||||
addCase() {
|
||||
// 初始化对象
|
||||
let request = {};
|
||||
if (row) {
|
||||
request = row.request;
|
||||
obj.apiDefinitionId = row.apiDefinitionId;
|
||||
if (this.api.request instanceof Object) {
|
||||
request = this.api.request;
|
||||
} else {
|
||||
request: new RequestFactory(JSON.parse(this.api.request))
|
||||
request = JSON.parse(this.api.request);
|
||||
}
|
||||
obj.test = new Test({request: request});
|
||||
let obj = {apiDefinitionId: this.api.id, name: '', priority: 'P0', type: 'create', active: false};
|
||||
obj.request = request;
|
||||
this.apiCaseList.unshift(obj);
|
||||
},
|
||||
|
||||
active(item) {
|
||||
item.active = !item.active;
|
||||
},
|
||||
getBodyUploadFiles(row) {
|
||||
let bodyUploadFiles = [];
|
||||
row.bodyUploadIds = [];
|
||||
let request = row.test.request;
|
||||
let request = row.request;
|
||||
if (request.body) {
|
||||
request.body.kvs.forEach(param => {
|
||||
if (param.files) {
|
||||
|
@ -343,6 +330,19 @@
|
|||
});
|
||||
}
|
||||
});
|
||||
request.body.binary.forEach(param => {
|
||||
if (param.files) {
|
||||
param.files.forEach(item => {
|
||||
if (item.file) {
|
||||
let fileId = getUUID().substring(0, 8);
|
||||
item.name = item.file.name;
|
||||
item.id = fileId;
|
||||
row.bodyUploadIds.push(fileId);
|
||||
bodyUploadFiles.push(item.file);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return bodyUploadFiles;
|
||||
},
|
||||
|
@ -355,7 +355,7 @@
|
|||
this.$post("/api/testcase/list", condition, response => {
|
||||
for (let index in response.data) {
|
||||
let test = response.data[index];
|
||||
test.test = new Test({request: new RequestFactory(JSON.parse(test.request))});
|
||||
test.request = JSON.parse(test.request);
|
||||
}
|
||||
this.apiCaseList = response.data;
|
||||
});
|
||||
|
@ -371,21 +371,16 @@
|
|||
return;
|
||||
}
|
||||
let bodyFiles = this.getBodyUploadFiles(row);
|
||||
row.test.request.url = this.api.url;
|
||||
row.test.request.method = this.api.method;
|
||||
row.projectId = this.api.projectId;
|
||||
row.apiDefinitionId = row.apiDefinitionId || this.api.id;
|
||||
row.request = row.test.request;
|
||||
let jmx = row.test.toJMX();
|
||||
let blob = new Blob([jmx.xml], {type: "application/octet-stream"});
|
||||
let file = new File([blob], jmx.name);
|
||||
let url = "/api/testcase/create";
|
||||
if (row.id) {
|
||||
url = "/api/testcase/update";
|
||||
}
|
||||
this.$fileUpload(url, file, bodyFiles, row, () => {
|
||||
this.$fileUpload(url, null, bodyFiles, row, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.getApiTest();
|
||||
this.$emit('refresh');
|
||||
});
|
||||
},
|
||||
getEnvironments() {
|
||||
|
|
|
@ -10,10 +10,7 @@
|
|||
|
||||
<script>
|
||||
import MsAddCompleteHttpApi from "./complete/AddCompleteHttpApi";
|
||||
import {RequestFactory, ResponseFactory, Test, Body} from "../model/ApiTestModel";
|
||||
import JMX from "./jmeter/jmx";
|
||||
import JmeterTestPlan from "./jmeter/components/jmeter-test-plan";
|
||||
import TestPlan from "./jmeter/components/test-plan";
|
||||
import {ResponseFactory, Body} from "../model/ApiTestModel";
|
||||
import {getUUID} from "@/common/js/utils";
|
||||
import {createComponent, Request} from "./jmeter/components";
|
||||
import Sampler from "./jmeter/components/sampler/sampler";
|
||||
|
@ -24,10 +21,8 @@
|
|||
components: {MsAddCompleteHttpApi},
|
||||
data() {
|
||||
return {
|
||||
reqType: RequestFactory.TYPES.HTTP,
|
||||
reqType: Request.TYPES.HTTP,
|
||||
reqUrl: "",
|
||||
test: new Test(),
|
||||
jmx: new JMX(),
|
||||
request: Sampler,
|
||||
response: {},
|
||||
headers: [],
|
||||
|
@ -40,20 +35,9 @@
|
|||
protocol: String,
|
||||
},
|
||||
created() {
|
||||
let jmx = new JMX();
|
||||
let rootTestPlan = new JmeterTestPlan();
|
||||
// 创建一个测试计划
|
||||
let testPlan = new TestPlan();
|
||||
rootTestPlan.hashTree = [testPlan];
|
||||
jmx.elements = [rootTestPlan];
|
||||
// 加一个线程组
|
||||
let threadGroup = createComponent("ThreadGroup");
|
||||
testPlan.hashTree = [threadGroup];
|
||||
|
||||
this.jmx = jmx;
|
||||
switch (this.protocol) {
|
||||
case Request.TYPES.SQL:
|
||||
this.request = createComponent("OT");
|
||||
this.request = createComponent("SQL");
|
||||
break;
|
||||
case Request.TYPES.DUBBO:
|
||||
this.request = createComponent("JDBCSampler");
|
||||
|
@ -65,15 +49,11 @@
|
|||
this.createHttp();
|
||||
break;
|
||||
}
|
||||
|
||||
threadGroup.hashTree = [this.request];
|
||||
this.response = this.currentApi.response != null ? new ResponseFactory(JSON.parse(this.currentApi.response)) : {
|
||||
headers: [],
|
||||
body: new Body(),
|
||||
statusCode: [],
|
||||
type: "HTTP"
|
||||
};
|
||||
|
||||
if (this.currentApi.response != null && this.currentApi.response != 'null' && this.currentApi.response != undefined) {
|
||||
this.response = new ResponseFactory(JSON.parse(this.currentApi.response));
|
||||
} else {
|
||||
this.response = {headers: [], body: new Body(), statusCode: [], type: "HTTP"};
|
||||
}
|
||||
if (this.currentApi != null && this.currentApi.id != null) {
|
||||
this.reqUrl = "/api/definition/update";
|
||||
} else {
|
||||
|
@ -84,8 +64,9 @@
|
|||
methods: {
|
||||
runTest(data) {
|
||||
data.projectId = this.currentProject.id;
|
||||
data.request = data.test.request;
|
||||
data.response = data.test.response;
|
||||
this.request.hashTree[0].headers = this.headers;
|
||||
data.request = this.request;
|
||||
data.response = this.response;
|
||||
let bodyFiles = this.getBodyUploadFiles(data);
|
||||
this.$fileUpload(this.reqUrl, null, bodyFiles, data, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
|
@ -94,13 +75,15 @@
|
|||
});
|
||||
},
|
||||
createHttp() {
|
||||
if (this.currentApi.request != null) {
|
||||
if (this.currentApi.request != undefined && this.currentApi.request != null) {
|
||||
this.request = JSON.parse(this.currentApi.request);
|
||||
this.currentApi.request = this.request;
|
||||
this.headers = this.request.hashTree[0].headers;
|
||||
} else {
|
||||
let header = createComponent("HeaderManager");
|
||||
this.request = createComponent("HTTPSamplerProxy");
|
||||
this.request.hashTree = [header];
|
||||
this.currentApi.request = this.request;
|
||||
}
|
||||
},
|
||||
saveApi(data) {
|
||||
|
@ -108,7 +91,6 @@
|
|||
this.request.hashTree[0].headers = this.headers;
|
||||
data.request = this.request;
|
||||
data.response = this.response;
|
||||
console.log(data)
|
||||
let bodyFiles = this.getBodyUploadFiles(data);
|
||||
this.$fileUpload(this.reqUrl, null, bodyFiles, data, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
<div></div>
|
||||
</template>
|
||||
<script>
|
||||
import {Scenario} from "../model/ApiTestModel";
|
||||
import {getUUID} from "@/common/js/utils";
|
||||
import HeaderManager from "./jmeter/components/configurations/header-manager";
|
||||
import ThreadGroup from "./jmeter/components/thread-group";
|
||||
import TestPlan from "./jmeter/components/test-plan";
|
||||
|
||||
export default {
|
||||
name: 'MsRun',
|
||||
|
@ -65,29 +67,35 @@
|
|||
});
|
||||
}
|
||||
});
|
||||
request.body.binary.forEach(param => {
|
||||
if (param.files) {
|
||||
param.files.forEach(item => {
|
||||
if (item.file) {
|
||||
let fileId = getUUID().substring(0, 8);
|
||||
item.name = item.file.name;
|
||||
item.id = fileId;
|
||||
obj.bodyUploadIds.push(fileId);
|
||||
bodyUploadFiles.push(item.file);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return bodyUploadFiles;
|
||||
},
|
||||
run() {
|
||||
let reqObj = {};
|
||||
let scenario = new Scenario({requests: this.runData});
|
||||
let url = "";
|
||||
let reportId = getUUID().substring(0, 8);
|
||||
let testPlan = new TestPlan();
|
||||
let threadGroup = new ThreadGroup();
|
||||
threadGroup.hashTree = [];
|
||||
testPlan.hashTree = [threadGroup];
|
||||
|
||||
this.runData.forEach(item => {
|
||||
threadGroup.hashTree.push(item);
|
||||
})
|
||||
let reqObj = {id: this.reportId, testElement: testPlan};
|
||||
let bodyFiles = this.getBodyUploadFiles(reqObj);
|
||||
scenario.requests.forEach(item => {
|
||||
if (this.environment != null) {
|
||||
item.useEnvironment = true;
|
||||
scenario.environmentId = this.environment.id;
|
||||
}
|
||||
item.definition = true;
|
||||
});
|
||||
scenario.name = reportId;
|
||||
scenario.dubboConfig = null;
|
||||
scenario.tcpConfig = null;
|
||||
reqObj.name = reportId;
|
||||
reqObj.scenario = scenario;
|
||||
reqObj.id = reportId;
|
||||
let url = "";
|
||||
if (this.debug) {
|
||||
url = "/api/definition/run/debug";
|
||||
} else {
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
:autosize="{ minRows: 2, maxRows: 10}"
|
||||
:rows="2" size="small"/>
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
|
@ -48,9 +47,10 @@
|
|||
<script>
|
||||
import MsDialogFooter from "../../../../common/components/MsDialogFooter";
|
||||
import {WORKSPACE_ID} from '../../../../../../common/js/constants';
|
||||
import {Test} from "../../model/ApiTestModel"
|
||||
import {REQ_METHOD} from "../../model/JsonData";
|
||||
import {getCurrentUser} from "../../../../../../common/js/utils";
|
||||
import {getCurrentUser, getUUID} from "../../../../../../common/js/utils";
|
||||
import {createComponent} from "../jmeter/components";
|
||||
import HeaderManager from "../jmeter/components/configurations/header-manager";
|
||||
|
||||
export default {
|
||||
name: "MsAddBasisHttpApi",
|
||||
|
@ -81,22 +81,18 @@
|
|||
if (valid) {
|
||||
let bodyFiles = [];
|
||||
let url = "/api/definition/create";
|
||||
let test = new Test();
|
||||
this.httpForm.bodyUploadIds = [];
|
||||
this.httpForm.request = test.request;
|
||||
this.httpForm.request.url = this.httpForm.url;
|
||||
this.httpForm.request.method = this.httpForm.method;
|
||||
this.httpForm.projectId = this.projectId;
|
||||
this.httpForm.id = test.id;
|
||||
this.httpForm.id = getUUID().substring(0, 8);
|
||||
let header = createComponent("HeaderManager");
|
||||
let request = createComponent("HTTPSamplerProxy");
|
||||
request.hashTree = [header];
|
||||
this.httpForm.request = request;
|
||||
if (this.currentModule != null) {
|
||||
this.httpForm.modulePath = this.currentModule.method != undefined ? this.currentModule.method : null;
|
||||
this.httpForm.moduleId = this.currentModule.id;
|
||||
}
|
||||
let jmx = test.toJMX();
|
||||
let blob = new Blob([jmx.xml], {type: "application/octet-stream"});
|
||||
let file = new File([blob], jmx.name);
|
||||
|
||||
this.result = this.$fileUpload(url, file, bodyFiles, this.httpForm, () => {
|
||||
this.result = this.$fileUpload(url, null, bodyFiles, this.httpForm, () => {
|
||||
this.httpVisible = false;
|
||||
this.$parent.refresh(this.currentModule);
|
||||
});
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('api_report.request')" prop="url">
|
||||
<el-input :placeholder="$t('api_test.definition.request.path_info')" v-model="httpForm.url"
|
||||
<el-input :placeholder="$t('api_test.definition.request.path_info')" v-model="httpForm.request.path.value"
|
||||
class="ms-http-input" size="small" style="margin-top: 5px">
|
||||
<el-select v-model="httpForm.method" slot="prepend" style="width: 100px" size="small">
|
||||
<el-select v-model="httpForm.request.method.value" slot="prepend" style="width: 100px" size="small">
|
||||
<el-option v-for="item in reqOptions" :key="item.id" :label="item.label" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-input>
|
||||
|
@ -127,6 +127,7 @@
|
|||
},
|
||||
setParameter() {
|
||||
this.httpForm.modulePath = this.getPath(this.httpForm.moduleId);
|
||||
this.httpForm.url = this.httpForm.request.path.value;
|
||||
},
|
||||
saveApi() {
|
||||
if (this.currentProject === null) {
|
||||
|
@ -163,7 +164,7 @@
|
|||
|
||||
<style scoped>
|
||||
.ms-http-input {
|
||||
width: 500px;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.tip {
|
||||
|
@ -175,7 +176,7 @@
|
|||
}
|
||||
|
||||
.ms-http-textarea {
|
||||
width: 500px;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.ms-left-cell {
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
<p class="tip">{{$t('api_test.definition.request.req_param')}} </p>
|
||||
<!-- HTTP 请求参数 -->
|
||||
<ms-api-request-form :request="test.request"/>
|
||||
<ms-api-request-form :headers="headers" :request="request"/>
|
||||
|
||||
</el-form>
|
||||
<!-- HTTP 请求返回数据 -->
|
||||
|
@ -41,14 +41,13 @@
|
|||
|
||||
<script>
|
||||
import MsApiRequestForm from "../request/ApiRequestForm";
|
||||
import {Test} from "../../model/ApiTestModel";
|
||||
import MsResponseResult from "../response/ResponseResult";
|
||||
import MsRequestMetric from "../response/RequestMetric";
|
||||
import {getUUID, getCurrentUser} from "@/common/js/utils";
|
||||
import MsResponseText from "../response/ResponseText";
|
||||
import MsRun from "../Run";
|
||||
|
||||
|
||||
import {createComponent, Request} from "../jmeter/components";
|
||||
import HeaderManager from "../jmeter/components/configurations/header-manager";
|
||||
import {REQ_METHOD} from "../../model/JsonData";
|
||||
import MsRequestResultTail from "../response/RequestResultTail";
|
||||
|
||||
|
@ -66,10 +65,27 @@
|
|||
responseData: {type: 'HTTP', responseResult: {}, subRequestResults: []},
|
||||
loading: false,
|
||||
debugResultId: "",
|
||||
test: new Test(),
|
||||
runData: [],
|
||||
headers: [],
|
||||
reportId: "",
|
||||
reqOptions: REQ_METHOD,
|
||||
request: {},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
switch (this.protocol) {
|
||||
case Request.TYPES.SQL:
|
||||
this.request = createComponent("SQL");
|
||||
break;
|
||||
case Request.TYPES.DUBBO:
|
||||
this.request = createComponent("JDBCSampler");
|
||||
break;
|
||||
case Request.TYPES.TCP:
|
||||
this.request = createComponent("TCPSampler");
|
||||
break;
|
||||
default:
|
||||
this.createHttp();
|
||||
break;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -85,15 +101,21 @@
|
|||
this.runDebug();
|
||||
}
|
||||
},
|
||||
createHttp() {
|
||||
let header = createComponent("HeaderManager");
|
||||
this.request = createComponent("HTTPSamplerProxy");
|
||||
this.request.hashTree = [header];
|
||||
},
|
||||
runDebug() {
|
||||
this.$refs['debugForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.loading = true;
|
||||
this.test.request.url = this.debugForm.url;
|
||||
this.test.request.method = this.debugForm.method;
|
||||
this.test.request.name = getUUID().substring(0, 8);
|
||||
this.request.url = this.debugForm.url;
|
||||
this.request.method.value = this.debugForm.method;
|
||||
this.request.hashTree[0].headers = this.headers;
|
||||
this.request.name = getUUID().substring(0, 8);
|
||||
this.runData = [];
|
||||
this.runData.push(this.test.request);
|
||||
this.runData.push(this.request);
|
||||
/*触发执行操作*/
|
||||
this.reportId = getUUID().substring(0, 8);
|
||||
}
|
||||
|
@ -107,7 +129,7 @@
|
|||
saveAs() {
|
||||
this.$refs['debugForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.debugForm.request = JSON.stringify(this.test.request);
|
||||
this.debugForm.request = JSON.stringify(this.request);
|
||||
this.debugForm.userId = getCurrentUser().id;
|
||||
this.debugForm.status = "Underway";
|
||||
this.$emit('saveAs', this.debugForm);
|
||||
|
|
|
@ -15,7 +15,7 @@ const DEFAULT_OPTIONS = {
|
|||
export default class HeaderManager extends Configuration {
|
||||
constructor(options = DEFAULT_OPTIONS) {
|
||||
super(options);
|
||||
|
||||
this.type = "HeaderManager";
|
||||
this.headers = [];
|
||||
let collectionProp = this.initCollectionProp('HeaderManager.headers');
|
||||
collectionProp.forEach(elementProp => {
|
||||
|
|
|
@ -14,7 +14,8 @@ const DEFAULT_OPTIONS = {
|
|||
export default class JSR223PostProcessor extends PostProcessor {
|
||||
constructor(options = DEFAULT_OPTIONS) {
|
||||
super(options);
|
||||
this.scriptLanguage = this.initStringProp("scriptLanguage", "groovy")
|
||||
this.type = "JSR223PostProcessor";
|
||||
this.scriptLanguage = this.initStringProp("scriptLanguage", "java")
|
||||
this.parameters = this.initStringProp("parameters")
|
||||
this.filename = this.initStringProp("filename")
|
||||
this.cacheKey = this.initStringProp("cacheKey", true)
|
||||
|
|
|
@ -14,7 +14,8 @@ const DEFAULT_OPTIONS = {
|
|||
export default class JSR223PreProcessor extends PostProcessor {
|
||||
constructor(options = DEFAULT_OPTIONS) {
|
||||
super(options);
|
||||
this.scriptLanguage = this.initStringProp("scriptLanguage", "groovy")
|
||||
this.type = "JSR223PreProcessor";
|
||||
this.scriptLanguage = this.initStringProp("scriptLanguage", "java")
|
||||
this.parameters = this.initStringProp("parameters")
|
||||
this.filename = this.initStringProp("filename")
|
||||
this.cacheKey = this.initStringProp("cacheKey", true)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {boolProp, elementProp, stringProp} from "../../../props";
|
||||
import Sampler from "../sampler";
|
||||
import {BaseConfig, BODY_TYPE, KeyValue,Body} from "../../../../../model/ApiTestModel";
|
||||
import {BaseConfig, BODY_TYPE, KeyValue, Body} from "../../../../../model/ApiTestModel";
|
||||
|
||||
const DEFAULT_OPTIONS = {
|
||||
options: {
|
||||
|
@ -18,7 +18,7 @@ export default class HTTPSamplerProxy extends Sampler {
|
|||
this.protocol = this.initStringProp('HTTPSampler.protocol', "https");
|
||||
this.domain = this.initStringProp('HTTPSampler.domain');
|
||||
this.port = this.initStringProp('HTTPSampler.port');
|
||||
|
||||
this.type = "HTTPSamplerProxy";
|
||||
this.method = this.initStringProp('HTTPSampler.method', "GET");
|
||||
this.path = this.initStringProp('HTTPSampler.path');
|
||||
this.contentEncoding = this.initStringProp('HTTPSampler.contentEncoding', "UTF-8");
|
||||
|
|
|
@ -13,7 +13,7 @@ export default class TestPlan extends HashTreeElement {
|
|||
constructor(options = DEFAULT_OPTIONS) {
|
||||
super(options);
|
||||
this.$type = TYPE;
|
||||
|
||||
this.type = TYPE;
|
||||
this.functionalMode = this.initBoolProp('TestPlan.functional_mode', false);
|
||||
this.serializeThreadGroups = this.initBoolProp('TestPlan.serialize_threadgroups', false);
|
||||
this.tearDownOnShutdown = this.initBoolProp('TestPlan.tearDown_on_shutdown', true);
|
||||
|
|
|
@ -12,7 +12,7 @@ export default class ThreadGroup extends HashTreeElement {
|
|||
constructor(options = DEFAULT_OPTIONS) {
|
||||
super(options);
|
||||
this.$type = TYPE;
|
||||
|
||||
this.type = TYPE;
|
||||
this.onSampleError = this.initStringProp('ThreadGroup.on_sample_error', 'continue');
|
||||
this.numThreads = this.initStringProp('ThreadGroup.num_threads', 1);
|
||||
this.rampTime = this.initStringProp('ThreadGroup.ramp_time', 1);
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
import Element from "../element";
|
||||
import {loadComponent} from "../components";
|
||||
import JmeterTestPlan from "../components/jmeter-test-plan";
|
||||
import TestPlan from "../components/test-plan";
|
||||
import {js2xml, xml2js} from "xml-js";
|
||||
|
||||
const DEFAULT_OPTIONS = {
|
||||
declaration: {attributes: {version: "1.0", encoding: "UTF-8"}}
|
||||
}
|
||||
|
||||
export default class JMX extends Element {
|
||||
constructor(options = DEFAULT_OPTIONS) {
|
||||
super(options);
|
||||
this.declaration = options.declaration;
|
||||
if (options.elements) {
|
||||
this.elements = [];
|
||||
options.elements.forEach(e => {
|
||||
this.elements.push(loadComponent(e));
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
toJson() {
|
||||
let json = {
|
||||
declaration: this.declaration
|
||||
};
|
||||
if (this.elements) {
|
||||
json.elements = [];
|
||||
this.elements.forEach(e => {
|
||||
json.elements.push(e.toJson());
|
||||
})
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
toXML() {
|
||||
return js2xml(this.toJson(), {spaces: 2});
|
||||
}
|
||||
|
||||
static create() {
|
||||
let jmx = new JMX();
|
||||
let jmeterTestPlan = new JmeterTestPlan();
|
||||
let testPlan = new TestPlan();
|
||||
jmeterTestPlan.hashTree = [testPlan];
|
||||
jmx.elements = [jmeterTestPlan];
|
||||
return jmx;
|
||||
}
|
||||
|
||||
static fromJMX(xml) {
|
||||
return new JMX(xml2js(xml));
|
||||
}
|
||||
}
|
|
@ -3,11 +3,9 @@
|
|||
<el-row>
|
||||
<div>
|
||||
<el-button class="ms-left-buttion" size="small" :type="styleType" plain>{{title}}</el-button>
|
||||
<i class="icon el-icon-arrow-right" :class="{'is-active': active}" @click="changeActive"
|
||||
style="margin-left: 20px"/>
|
||||
|
||||
<el-input size="small" v-model="jsr223ProcessorData.name"
|
||||
class="ms-api-header-select" style="width: 380px"/>
|
||||
<i class="icon el-icon-arrow-right" :class="{'is-active': active}" @click="changeActive" style="margin-left: 20px"/>
|
||||
<el-input size="small" v-model="jsr223ProcessorData.name" class="ms-api-header-select" style="width: 380px"/>
|
||||
<el-button size="small" style="float: right" @click="remove">移除</el-button>
|
||||
</div>
|
||||
</el-row>
|
||||
<el-collapse-transition>
|
||||
|
@ -24,7 +22,7 @@
|
|||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="20" class="script-content">
|
||||
<ms-code-edit v-if="isCodeEditAlive" :mode="codeEditModeMap[jsr223ProcessorData.language]=== null ?'java':'python'"
|
||||
<ms-code-edit v-if="isCodeEditAlive" :mode="jsr223ProcessorData.scriptLanguage.value"
|
||||
:read-only="isReadOnly"
|
||||
:data.sync="jsr223ProcessorData.script.value" theme="eclipse" :modes="['java','python']"
|
||||
ref="codeEdit"/>
|
||||
|
@ -90,7 +88,7 @@
|
|||
],
|
||||
isCodeEditAlive: true,
|
||||
languages: [
|
||||
'beanshell', "python"
|
||||
'java', "python"
|
||||
],
|
||||
codeEditModeMap: {
|
||||
beanshell: 'java',
|
||||
|
@ -102,16 +100,6 @@
|
|||
this.jsr223ProcessorData = this.jsr223Processor;
|
||||
},
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default:
|
||||
"create",
|
||||
}
|
||||
,
|
||||
name: {
|
||||
type: String,
|
||||
}
|
||||
,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default:
|
||||
|
@ -149,21 +137,20 @@
|
|||
this.jsr223ProcessorData.script += ';';
|
||||
}
|
||||
this.reload();
|
||||
}
|
||||
,
|
||||
},
|
||||
remove(){
|
||||
this.$emit('remove', this.jsr223ProcessorData);
|
||||
},
|
||||
reload() {
|
||||
this.isCodeEditAlive = false;
|
||||
this.$nextTick(() => (this.isCodeEditAlive = true));
|
||||
}
|
||||
,
|
||||
},
|
||||
languageChange(language) {
|
||||
this.jsr223ProcessorData.language = language;
|
||||
}
|
||||
,
|
||||
},
|
||||
changeActive() {
|
||||
this.active = !this.active;
|
||||
}
|
||||
,
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -12,12 +12,12 @@
|
|||
|
||||
<!--query 参数-->
|
||||
<el-tab-pane :label="$t('api_test.definition.request.query_param')" name="parameters">
|
||||
<ms-api-variable :is-read-only="isReadOnly" :parameters="request.arguments"/>
|
||||
<ms-api-variable :is-read-only="isReadOnly" :parameters="request.arguments"/>
|
||||
</el-tab-pane>
|
||||
|
||||
<!--REST 参数-->
|
||||
<el-tab-pane :label="$t('api_test.definition.request.rest_param')" name="rest">
|
||||
<ms-api-variable :is-read-only="isReadOnly" :parameters="request.rest"/>
|
||||
<ms-api-variable :is-read-only="isReadOnly" :parameters="request.rest"/>
|
||||
</el-tab-pane>
|
||||
|
||||
<!--请求体-->
|
||||
|
@ -32,10 +32,10 @@
|
|||
</el-tabs>
|
||||
</div>
|
||||
<div v-for="row in request.hashTree" :key="row.id" v-loading="isReloadData">
|
||||
<ms-jsr233-processor v-if="row.label ==='JSR223 PreProcessor'" :is-read-only="false" title="前置脚本" style-type="warning"
|
||||
<ms-jsr233-processor v-if="row.label ==='JSR223 PreProcessor'" @remove="remove" :is-read-only="false" title="前置脚本" style-type="warning"
|
||||
:jsr223-processor="row"/>
|
||||
|
||||
<ms-jsr233-processor v-if="row.label ==='JSR223 PostProcessor'" :is-read-only="false" title="后置脚本" style-type="success"
|
||||
<ms-jsr233-processor v-if="row.label ==='JSR223 PostProcessor'" @remove="remove" :is-read-only="false" title="后置脚本" style-type="success"
|
||||
:jsr223-processor="row"/>
|
||||
|
||||
<!--<ms-api-assertions v-if="row.label.indexOf('Assertion')>0" :is-read-only="isReadOnly" :request="request"/>-->
|
||||
|
@ -137,6 +137,11 @@
|
|||
this.request.hashTree.push(jsonPostProcessor);
|
||||
this.reload();
|
||||
},
|
||||
remove(row) {
|
||||
let index = this.request.hashTree.indexOf(row);
|
||||
this.request.hashTree.splice(index, 1);
|
||||
this.reload();
|
||||
},
|
||||
reload() {
|
||||
this.isReloadData = true
|
||||
this.$nextTick(() => {
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
<p class="tip">{{$t('test_track.plan_view.base_info')}} </p>
|
||||
<!-- 请求方法 -->
|
||||
<el-form-item :label="$t('api_report.request')" prop="method">
|
||||
<el-select v-model="api.method" style="width: 100px" size="small">
|
||||
<el-select v-model="api.request.method.value" style="width: 100px" size="small">
|
||||
<el-option v-for="item in reqOptions" :key="item.id" :label="item.label" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 执行环境 -->
|
||||
<el-form-item prop="environmentId">
|
||||
<el-select v-model="api.environmentId" size="small" class="ms-htt-width"
|
||||
<el-select v-model="api.request.useEnvironment" size="small" class="ms-htt-width"
|
||||
:placeholder="$t('api_test.definition.request.run_env')"
|
||||
@change="environmentChange" clearable>
|
||||
<el-option v-for="(environment, index) in environments" :key="index"
|
||||
|
@ -36,7 +36,7 @@
|
|||
|
||||
<!-- 请求地址 -->
|
||||
<el-form-item prop="url">
|
||||
<el-input :placeholder="$t('api_test.definition.request.path_info')" v-model="api.url" class="ms-htt-width"
|
||||
<el-input :placeholder="$t('api_test.definition.request.path_info')" v-model="api.request.path.value" class="ms-htt-width"
|
||||
size="small" :disabled="false"/>
|
||||
</el-form-item>
|
||||
|
||||
|
@ -59,7 +59,7 @@
|
|||
|
||||
<p class="tip">{{$t('api_test.definition.request.req_param')}} </p>
|
||||
<!-- HTTP 请求参数 -->
|
||||
<ms-api-request-form :request="api.request"/>
|
||||
<ms-api-request-form :headers="api.request.hashTree[0].headers" :request="api.request"/>
|
||||
|
||||
</el-form>
|
||||
<!--返回结果-->
|
||||
|
@ -149,11 +149,9 @@
|
|||
this.$refs['apiData'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.loading = true;
|
||||
this.api.test.request.url = this.api.url;
|
||||
this.api.test.request.method = this.api.method;
|
||||
this.api.test.request.name = this.api.id;
|
||||
this.api.request.name = this.api.id;
|
||||
this.runData = [];
|
||||
this.runData.push(this.api.test.request);
|
||||
this.runData.push(this.api.request);
|
||||
/*触发执行操作*/
|
||||
this.reportId = getUUID().substring(0, 8);
|
||||
}
|
||||
|
@ -197,11 +195,7 @@
|
|||
saveAsCase() {
|
||||
this.isHide = false;
|
||||
this.loaded = false;
|
||||
let testCase = {};
|
||||
testCase.request = this.api.request;
|
||||
testCase.apiDefinitionId = this.api.id;
|
||||
testCase.priority = "P0";
|
||||
this.$refs.caseList.createCase(testCase);
|
||||
this.$refs.caseList.addCase();
|
||||
},
|
||||
saveAsApi() {
|
||||
let data = {};
|
||||
|
@ -216,17 +210,14 @@
|
|||
updateApi() {
|
||||
let url = "/api/definition/update";
|
||||
let bodyFiles = this.getBodyUploadFiles();
|
||||
let jmx = this.api.test.toJMX();
|
||||
let blob = new Blob([jmx.xml], {type: "application/octet-stream"});
|
||||
let file = new File([blob], jmx.name);
|
||||
this.$fileUpload(url, file, bodyFiles, this.api, () => {
|
||||
this.$fileUpload(url, null, bodyFiles, this.api, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.$emit('saveApi', this.api);
|
||||
});
|
||||
},
|
||||
selectTestCase(item) {
|
||||
if (item != null) {
|
||||
this.api.request = new RequestFactory(JSON.parse(item.request));
|
||||
this.api.request = item.request;
|
||||
} else {
|
||||
this.api.request = this.currentRequest;
|
||||
}
|
||||
|
@ -266,7 +257,7 @@
|
|||
environmentChange(value) {
|
||||
for (let i in this.environments) {
|
||||
if (this.environments[i].id === value) {
|
||||
this.api.environment = this.environments[i];
|
||||
this.api.request.useEnvironment = this.environments[i].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -286,6 +277,7 @@
|
|||
},
|
||||
created() {
|
||||
this.api = this.apiData;
|
||||
this.currentRequest = this.api.request;
|
||||
this.getEnvironments();
|
||||
this.getResult();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue