refactor(接口测试): TCP请求的请求体改为json,xml,raw格式;场景增加批量创建性能测试按钮
TCP请求的请求体改为json,xml,raw格式;场景增加批量创建性能测试按钮
This commit is contained in:
parent
c79c753654
commit
929d3ae465
|
@ -298,9 +298,7 @@ public class APITestController {
|
||||||
|
|
||||||
long taskCountInThisWeek = scheduleService.countTaskByProjectIdInThisWeek(projectId);
|
long taskCountInThisWeek = scheduleService.countTaskByProjectIdInThisWeek(projectId);
|
||||||
apiCountResult.setThisWeekAddedCount(taskCountInThisWeek);
|
apiCountResult.setThisWeekAddedCount(taskCountInThisWeek);
|
||||||
// long api_executedInThisWeekCountNumber = apiReportService.countByProjectIdAndCreateInThisWeek(projectId);
|
|
||||||
long executedInThisWeekCountNumber = apiScenarioReportService.countByProjectIdAndCreateAndByScheduleInThisWeek(projectId);
|
long executedInThisWeekCountNumber = apiScenarioReportService.countByProjectIdAndCreateAndByScheduleInThisWeek(projectId);
|
||||||
// long executedInThisWeekCountNumber = api_executedInThisWeekCountNumber+scene_executedInThisWeekCountNumber;
|
|
||||||
apiCountResult.setThisWeekExecutedCount(executedInThisWeekCountNumber);
|
apiCountResult.setThisWeekExecutedCount(executedInThisWeekCountNumber);
|
||||||
|
|
||||||
//统计 失败 成功 以及总数
|
//统计 失败 成功 以及总数
|
||||||
|
|
|
@ -242,6 +242,11 @@ public class ApiAutomationController {
|
||||||
return apiAutomationService.genPerformanceTestJmx(runRequest);
|
return apiAutomationService.genPerformanceTestJmx(runRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/batchGenPerformanceTestJmx")
|
||||||
|
public List<JmxInfoDTO> batchGenPerformanceTestJmx(@RequestBody ApiScenarioBatchRequest request) {
|
||||||
|
return apiAutomationService.batchGenPerformanceTestJmx(request);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/file/download")
|
@PostMapping("/file/download")
|
||||||
public ResponseEntity<byte[]> download(@RequestBody FileOperationRequest fileOperationRequest) {
|
public ResponseEntity<byte[]> download(@RequestBody FileOperationRequest fileOperationRequest) {
|
||||||
byte[] bytes = apiAutomationService.loadFileAsBytes(fileOperationRequest);
|
byte[] bytes = apiAutomationService.loadFileAsBytes(fileOperationRequest);
|
||||||
|
|
|
@ -13,9 +13,15 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@AllArgsConstructor
|
|
||||||
public class JmxInfoDTO {
|
public class JmxInfoDTO {
|
||||||
private String name;
|
private String name;
|
||||||
private String xml;
|
private String xml;
|
||||||
|
private String id;
|
||||||
private Map<String, String> attachFiles;
|
private Map<String, String> attachFiles;
|
||||||
|
|
||||||
|
public JmxInfoDTO(String name,String xml,Map<String, String> attachFiles){
|
||||||
|
this.name = name;
|
||||||
|
this.xml = xml;
|
||||||
|
this.attachFiles = attachFiles;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,180 @@
|
||||||
|
package io.metersphere.api.dto.automation;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dom4j.Document;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* //ESB数据格式
|
||||||
|
*
|
||||||
|
* @author song.tianyang
|
||||||
|
* @Date 2021/3/15 4:37 下午
|
||||||
|
* @Description
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TcpTreeTableDataStruct {
|
||||||
|
private String uuid;
|
||||||
|
private String name;
|
||||||
|
private String value;
|
||||||
|
private String type;
|
||||||
|
private String systemName;
|
||||||
|
private String contentType;
|
||||||
|
private boolean required;
|
||||||
|
private String description;
|
||||||
|
private List<TcpTreeTableDataStruct> children;
|
||||||
|
private String status = "";
|
||||||
|
|
||||||
|
public void init(){
|
||||||
|
this.uuid = UUID.randomUUID().toString();
|
||||||
|
this.systemName = "";
|
||||||
|
this.description = "";
|
||||||
|
this.value="";
|
||||||
|
this.required = true;
|
||||||
|
this.contentType = "";
|
||||||
|
this.type = "";
|
||||||
|
this.children = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean initDefaultData(String name, String typeLength,String chineseName,String desc){
|
||||||
|
this.init();
|
||||||
|
if(StringUtils.isEmpty(name)){return false; }
|
||||||
|
if(typeLength == null){
|
||||||
|
typeLength = "";
|
||||||
|
}else{
|
||||||
|
typeLength = typeLength.trim();
|
||||||
|
typeLength = typeLength.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.name = name;
|
||||||
|
|
||||||
|
if(typeLength.startsWith("string")){
|
||||||
|
this.type = "string";
|
||||||
|
String lengthStr = typeLength.substring(6);
|
||||||
|
if(lengthStr.startsWith("(") && lengthStr.endsWith(")")){
|
||||||
|
try {
|
||||||
|
int length = Integer.parseInt(lengthStr.substring(1,lengthStr.length()-1));
|
||||||
|
this.contentType = String.valueOf(length);
|
||||||
|
}catch (Exception e){ }
|
||||||
|
|
||||||
|
}
|
||||||
|
}else if(typeLength.startsWith("array")){
|
||||||
|
this.type = "array";
|
||||||
|
}else{
|
||||||
|
this.type = "object";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(StringUtils.isEmpty(desc)){desc = "";}
|
||||||
|
if(StringUtils.isNotEmpty(chineseName)){
|
||||||
|
this.description = chineseName+":"+desc;
|
||||||
|
}else{
|
||||||
|
this.description =desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.description.endsWith(":")){
|
||||||
|
this.description = this.description.substring(0,this.description.length()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TcpTreeTableDataStruct copy(boolean copyChildren) {
|
||||||
|
TcpTreeTableDataStruct returnObj = new TcpTreeTableDataStruct();
|
||||||
|
returnObj.name = this.name;
|
||||||
|
returnObj.value = this.value;
|
||||||
|
returnObj.type = this.type;
|
||||||
|
returnObj.systemName = this.systemName;
|
||||||
|
returnObj.contentType = this.contentType;
|
||||||
|
returnObj.required = this.required;
|
||||||
|
returnObj.description = this.description;
|
||||||
|
if (copyChildren) {
|
||||||
|
returnObj.children = this.children;
|
||||||
|
} else {
|
||||||
|
returnObj.children = new ArrayList<>();
|
||||||
|
}
|
||||||
|
return returnObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Element genXmlElementByChildren(Element document) {
|
||||||
|
this.name = this.name.replace("&", "&").replace("<", "<").replace(">", ">")
|
||||||
|
.replace("\"", """).replace("©", "'");
|
||||||
|
if (StringUtils.isEmpty(this.name)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Element element = null;
|
||||||
|
try {
|
||||||
|
element = document.addElement(this.name);
|
||||||
|
if (StringUtils.equalsAnyIgnoreCase(type, "string", "array")) {
|
||||||
|
long lengthNum = Long.parseLong(this.contentType);
|
||||||
|
String attrString = "";
|
||||||
|
if (StringUtils.equalsIgnoreCase(this.type, "string")) {
|
||||||
|
attrString = "s," + contentType;
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(this.type, "array")) {
|
||||||
|
attrString = "a," + contentType;
|
||||||
|
}
|
||||||
|
element.addAttribute("attr", attrString);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(this.name);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element != null) {
|
||||||
|
if (this.children == null || this.children.isEmpty()) {
|
||||||
|
if(this.value == null ){
|
||||||
|
this.value = "";
|
||||||
|
}
|
||||||
|
element.addText(this.value);
|
||||||
|
} else {
|
||||||
|
for (TcpTreeTableDataStruct child : children) {
|
||||||
|
child.genXmlElementByChildren(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Element genXmlElementByDocument(Document document) {
|
||||||
|
this.name = this.name.replace("&", "&").replace("<", "<").replace(">", ">")
|
||||||
|
.replace("\"", """).replace("©", "'");
|
||||||
|
if (StringUtils.isEmpty(this.name)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Element element = null;
|
||||||
|
try {
|
||||||
|
element = document.addElement(this.name);
|
||||||
|
if (StringUtils.equalsAnyIgnoreCase(type, "string", "array")) {
|
||||||
|
long lengthNum = Long.parseLong(this.contentType);
|
||||||
|
String attrString = "";
|
||||||
|
if (StringUtils.equalsIgnoreCase(this.type, "string")) {
|
||||||
|
attrString = "s," + contentType;
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(this.type, "array")) {
|
||||||
|
attrString = "a," + contentType;
|
||||||
|
}
|
||||||
|
element.addAttribute("attr", attrString);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(this.name);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element != null) {
|
||||||
|
if (this.children == null || this.children.isEmpty()) {
|
||||||
|
element.addText(this.value);
|
||||||
|
} else {
|
||||||
|
for (TcpTreeTableDataStruct child : children) {
|
||||||
|
child.genXmlElementByChildren(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package io.metersphere.api.dto.automation.parse;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.automation.TcpTreeTableDataStruct;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dom4j.Document;
|
||||||
|
import org.dom4j.DocumentHelper;
|
||||||
|
import org.dom4j.io.OutputFormat;
|
||||||
|
import org.dom4j.io.XMLWriter;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author song.tianyang
|
||||||
|
* @Date 2021/3/15 5:00 下午
|
||||||
|
* @Description
|
||||||
|
*/
|
||||||
|
public class TcpTreeTableDataParser {
|
||||||
|
public static String treeTableData2Xml(List<TcpTreeTableDataStruct> treeDataList) {
|
||||||
|
String xmlString = "";
|
||||||
|
try {
|
||||||
|
if (treeDataList == null || treeDataList.isEmpty()) {
|
||||||
|
return xmlString;
|
||||||
|
}
|
||||||
|
// 创建解析器工厂
|
||||||
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
|
DocumentBuilder db = factory.newDocumentBuilder();
|
||||||
|
Document document = DocumentHelper.createDocument();
|
||||||
|
|
||||||
|
TcpTreeTableDataStruct dataStruct = null;
|
||||||
|
if(treeDataList.size()>1){
|
||||||
|
dataStruct = new TcpTreeTableDataStruct();
|
||||||
|
dataStruct.setName("ROOT");
|
||||||
|
dataStruct.setChildren(treeDataList);
|
||||||
|
}else {
|
||||||
|
dataStruct = treeDataList.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataStruct.genXmlElementByDocument(document);
|
||||||
|
xmlString = document.getRootElement().asXML();
|
||||||
|
|
||||||
|
// 设置XML文档格式
|
||||||
|
OutputFormat outputFormat = OutputFormat.createPrettyPrint();
|
||||||
|
// 设置XML编码方式,即是用指定的编码方式保存XML文档到字符串(String),这里也可以指定为GBK或是ISO8859-1
|
||||||
|
outputFormat.setEncoding("UTF-8");
|
||||||
|
//outputFormat.setSuppressDeclaration(true); //是否生产xml头
|
||||||
|
outputFormat.setIndent(true); //设置是否缩进
|
||||||
|
outputFormat.setNewlines(true); //设置是否换行
|
||||||
|
|
||||||
|
try {
|
||||||
|
// stringWriter字符串是用来保存XML文档的
|
||||||
|
StringWriter stringWriter = new StringWriter();
|
||||||
|
// xmlWriter是用来把XML文档写入字符串的(工具)
|
||||||
|
XMLWriter xmlWriter = new XMLWriter(stringWriter, outputFormat);
|
||||||
|
// 把创建好的XML文档写入字符串
|
||||||
|
xmlWriter.write(document);
|
||||||
|
|
||||||
|
// 打印字符串,即是XML文档
|
||||||
|
xmlString = stringWriter.toString();
|
||||||
|
xmlWriter.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(xmlString)) {
|
||||||
|
xmlString = "";
|
||||||
|
} else {
|
||||||
|
xmlString = xmlString.replaceAll(" ", "");
|
||||||
|
}
|
||||||
|
return xmlString;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import io.metersphere.api.dto.automation.EsbDataStruct;
|
import io.metersphere.api.dto.automation.EsbDataStruct;
|
||||||
|
import io.metersphere.api.dto.automation.TcpTreeTableDataStruct;
|
||||||
import io.metersphere.api.dto.definition.request.MsTestElement;
|
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||||
import io.metersphere.api.dto.definition.request.ParameterConfig;
|
import io.metersphere.api.dto.definition.request.ParameterConfig;
|
||||||
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
|
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
|
||||||
|
@ -88,6 +89,14 @@ public class MsTCPSampler extends MsTestElement {
|
||||||
private String projectId;
|
private String projectId;
|
||||||
@JSONField(ordinal = 40)
|
@JSONField(ordinal = 40)
|
||||||
private String connectEncoding;
|
private String connectEncoding;
|
||||||
|
@JSONField(ordinal = 41)
|
||||||
|
private String reportType;
|
||||||
|
@JSONField(ordinal = 42)
|
||||||
|
private List<TcpTreeTableDataStruct> xmlDataStruct;
|
||||||
|
@JSONField(ordinal = 43)
|
||||||
|
private String jsonDataStruct;
|
||||||
|
@JSONField(ordinal = 44)
|
||||||
|
private String rawDataStruct;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -466,7 +466,6 @@ public class APITestService {
|
||||||
/**
|
/**
|
||||||
* 更新jmx数据,处理jmx里的各种参数
|
* 更新jmx数据,处理jmx里的各种参数
|
||||||
* <p>
|
* <p>
|
||||||
* 注: 与1.7分支合并时,如果该方法产生冲突,请以master为准
|
|
||||||
*
|
*
|
||||||
* @param jmxString 原JMX文件
|
* @param jmxString 原JMX文件
|
||||||
* @param testNameParam 某些节点要替换的testName
|
* @param testNameParam 某些节点要替换的testName
|
||||||
|
@ -475,7 +474,6 @@ public class APITestService {
|
||||||
* @author song tianyang
|
* @author song tianyang
|
||||||
*/
|
*/
|
||||||
public JmxInfoDTO updateJmxString(String jmxString, String testNameParam, boolean isFromScenario) {
|
public JmxInfoDTO updateJmxString(String jmxString, String testNameParam, boolean isFromScenario) {
|
||||||
//注: 与1.7分支合并时,如果该方法产生冲突,请以master为准
|
|
||||||
String attribute_testName = "testname";
|
String attribute_testName = "testname";
|
||||||
String[] requestElementNameArr = new String[]{"HTTPSamplerProxy", "TCPSampler", "JDBCSampler", "DubboSample"};
|
String[] requestElementNameArr = new String[]{"HTTPSamplerProxy", "TCPSampler", "JDBCSampler", "DubboSample"};
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,8 @@ public class ApiAutomationService {
|
||||||
private ProjectMapper projectMapper;
|
private ProjectMapper projectMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private TestPlanMapper testPlanMapper;
|
private TestPlanMapper testPlanMapper;
|
||||||
|
@Resource
|
||||||
|
private TcpApiParamService tcpApiParamService;
|
||||||
|
|
||||||
public ApiScenarioWithBLOBs getDto(String id) {
|
public ApiScenarioWithBLOBs getDto(String id) {
|
||||||
return apiScenarioMapper.selectByPrimaryKey(id);
|
return apiScenarioMapper.selectByPrimaryKey(id);
|
||||||
|
@ -320,6 +322,8 @@ public class ApiAutomationService {
|
||||||
|
|
||||||
//检查场景的请求步骤。如果含有ESB请求步骤的话,要做参数计算处理。
|
//检查场景的请求步骤。如果含有ESB请求步骤的话,要做参数计算处理。
|
||||||
esbApiParamService.checkScenarioRequests(request);
|
esbApiParamService.checkScenarioRequests(request);
|
||||||
|
//如果场景有TCP步骤的话,也要做参数计算处理
|
||||||
|
tcpApiParamService.checkTestElement(request.getScenarioDefinition());
|
||||||
|
|
||||||
final ApiScenarioWithBLOBs scenario = buildSaveScenario(request);
|
final ApiScenarioWithBLOBs scenario = buildSaveScenario(request);
|
||||||
|
|
||||||
|
@ -1346,21 +1350,9 @@ public class ApiAutomationService {
|
||||||
return request.getId();
|
return request.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void preduceTestElement(RunDefinitionRequest request) throws Exception {
|
public void preduceTestElement(RunDefinitionRequest request) throws Exception {
|
||||||
if (request.getTestElement() != null) {
|
if (request.getTestElement() != null) {
|
||||||
for (MsTestElement threadGroup : request.getTestElement().getHashTree()) {
|
tcpApiParamService.checkTestElement(request.getTestElement());
|
||||||
if (threadGroup instanceof MsThreadGroup && threadGroup.getHashTree() != null) {
|
|
||||||
for (MsTestElement scenario : threadGroup.getHashTree()) {
|
|
||||||
if (scenario instanceof MsScenario && scenario.getHashTree() != null) {
|
|
||||||
for (MsTestElement itemElement : scenario.getHashTree()) {
|
|
||||||
if (itemElement instanceof MsScenario) {
|
|
||||||
itemElement.setId(UUID.randomUUID().toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1548,8 +1540,10 @@ public class ApiAutomationService {
|
||||||
List<String> ids = request.getIds();
|
List<String> ids = request.getIds();
|
||||||
apiScenarios = extApiScenarioMapper.selectIds(ids);
|
apiScenarios = extApiScenarioMapper.selectIds(ids);
|
||||||
String testName = "";
|
String testName = "";
|
||||||
|
String id = "";
|
||||||
if (!apiScenarios.isEmpty()) {
|
if (!apiScenarios.isEmpty()) {
|
||||||
testName = apiScenarios.get(0).getName();
|
testName = apiScenarios.get(0).getName();
|
||||||
|
id = apiScenarios.get(0).getId();
|
||||||
}
|
}
|
||||||
if (CollectionUtils.isEmpty(apiScenarios)) {
|
if (CollectionUtils.isEmpty(apiScenarios)) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -1560,6 +1554,7 @@ public class ApiAutomationService {
|
||||||
|
|
||||||
String name = request.getName() + ".jmx";
|
String name = request.getName() + ".jmx";
|
||||||
dto.setName(name);
|
dto.setName(name);
|
||||||
|
dto.setId(id);
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2117,4 +2112,28 @@ public class ApiAutomationService {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<JmxInfoDTO> batchGenPerformanceTestJmx(ApiScenarioBatchRequest request) {
|
||||||
|
ServiceUtils.getSelectAllIds(request, request.getCondition(),
|
||||||
|
(query) -> extApiScenarioMapper.selectIdsByQuery((ApiScenarioRequest) query));
|
||||||
|
List<JmxInfoDTO> returnList = new ArrayList<>();
|
||||||
|
|
||||||
|
List<String> ids = request.getIds();
|
||||||
|
List<ApiScenarioWithBLOBs> apiScenarioList = extApiScenarioMapper.selectIds(ids);
|
||||||
|
if (CollectionUtils.isEmpty(apiScenarioList)) {
|
||||||
|
return returnList;
|
||||||
|
}else {
|
||||||
|
apiScenarioList.forEach(item ->{
|
||||||
|
String testName = item.getName();
|
||||||
|
MsTestPlan testPlan = new MsTestPlan();
|
||||||
|
testPlan.setHashTree(new LinkedList<>());
|
||||||
|
JmxInfoDTO dto = apiTestService.updateJmxString(generateJmx(item), testName, true);
|
||||||
|
String name = item.getName() + ".jmx";
|
||||||
|
dto.setId(item.getId());
|
||||||
|
dto.setName(name);
|
||||||
|
returnList.add(dto);
|
||||||
|
});
|
||||||
|
return returnList;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,8 @@ public class ApiDefinitionService {
|
||||||
@Resource
|
@Resource
|
||||||
private EsbApiParamService esbApiParamService;
|
private EsbApiParamService esbApiParamService;
|
||||||
@Resource
|
@Resource
|
||||||
|
private TcpApiParamService tcpApiParamService;
|
||||||
|
@Resource
|
||||||
private ApiModuleMapper apiModuleMapper;
|
private ApiModuleMapper apiModuleMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private SystemParameterService systemParameterService;
|
private SystemParameterService systemParameterService;
|
||||||
|
@ -277,6 +279,8 @@ public class ApiDefinitionService {
|
||||||
if (StringUtils.equals(request.getMethod(), "ESB")) {
|
if (StringUtils.equals(request.getMethod(), "ESB")) {
|
||||||
//ESB的接口类型数据,采用TCP方式去发送。并将方法类型改为TCP。 并修改发送数据
|
//ESB的接口类型数据,采用TCP方式去发送。并将方法类型改为TCP。 并修改发送数据
|
||||||
request = esbApiParamService.handleEsbRequest(request);
|
request = esbApiParamService.handleEsbRequest(request);
|
||||||
|
}else if(StringUtils.equals(request.getMethod(), "TCP")) {
|
||||||
|
request = tcpApiParamService.handleTcpRequest(request);
|
||||||
}
|
}
|
||||||
final ApiDefinitionWithBLOBs test = new ApiDefinitionWithBLOBs();
|
final ApiDefinitionWithBLOBs test = new ApiDefinitionWithBLOBs();
|
||||||
test.setId(request.getId());
|
test.setId(request.getId());
|
||||||
|
@ -581,6 +585,13 @@ public class ApiDefinitionService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try{
|
||||||
|
//检查TCP数据结构,等其他进行处理
|
||||||
|
tcpApiParamService.checkTestElement(request.getTestElement());
|
||||||
|
}catch (Exception e){
|
||||||
|
}
|
||||||
|
|
||||||
HashTree hashTree = request.getTestElement().generateHashTree(config);
|
HashTree hashTree = request.getTestElement().generateHashTree(config);
|
||||||
String runMode = ApiRunMode.DEFINITION.name();
|
String runMode = ApiRunMode.DEFINITION.name();
|
||||||
if (StringUtils.isNotBlank(request.getType()) && StringUtils.equals(request.getType(), ApiRunMode.API_PLAN.name())) {
|
if (StringUtils.isNotBlank(request.getType()) && StringUtils.equals(request.getType(), ApiRunMode.API_PLAN.name())) {
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
package io.metersphere.api.service;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.automation.TcpTreeTableDataStruct;
|
||||||
|
import io.metersphere.api.dto.automation.parse.TcpTreeTableDataParser;
|
||||||
|
import io.metersphere.api.dto.definition.*;
|
||||||
|
import io.metersphere.api.dto.definition.request.MsScenario;
|
||||||
|
import io.metersphere.api.dto.definition.request.MsTestElement;
|
||||||
|
import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author song.tianyang
|
||||||
|
* @Date 2021/3/16 4:57 下午
|
||||||
|
* @Description
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public class TcpApiParamService {
|
||||||
|
|
||||||
|
public SaveApiDefinitionRequest handleTcpRequest(SaveApiDefinitionRequest request) {
|
||||||
|
MsTCPSampler tcpSampler = this.handleTcpRequest(request.getRequest());
|
||||||
|
if(tcpSampler != null){
|
||||||
|
request.setRequest(tcpSampler);
|
||||||
|
}
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
public MsTCPSampler handleTcpRequest(MsTestElement testElement){
|
||||||
|
MsTCPSampler tcpSampler = null;
|
||||||
|
try {
|
||||||
|
if(testElement instanceof MsTCPSampler){
|
||||||
|
tcpSampler = (MsTCPSampler)testElement;
|
||||||
|
String reportType = tcpSampler.getReportType();
|
||||||
|
if (StringUtils.isNotEmpty(reportType)) {
|
||||||
|
switch (reportType) {
|
||||||
|
case "raw":
|
||||||
|
tcpSampler.setRequest(tcpSampler.getRawDataStruct());
|
||||||
|
break;
|
||||||
|
case "xml":
|
||||||
|
String xmlDataStruct = this.genValueFromEsbDataStructByParam(tcpSampler.getXmlDataStruct());
|
||||||
|
tcpSampler.setRequest(xmlDataStruct);
|
||||||
|
break;
|
||||||
|
case "json":
|
||||||
|
tcpSampler.setRequest(tcpSampler.getJsonDataStruct());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return tcpSampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
//通过报文模版中的变量参数,解析报文数据结构,生成对应的xml数据
|
||||||
|
private String genValueFromEsbDataStructByParam(List<TcpTreeTableDataStruct> dataStructRequestList) {
|
||||||
|
String returnValue = TcpTreeTableDataParser.treeTableData2Xml(dataStructRequestList);
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkTestElement(MsTestElement testElement) {
|
||||||
|
if(testElement != null){
|
||||||
|
if(testElement instanceof MsTCPSampler){
|
||||||
|
this.handleTcpRequest(testElement);
|
||||||
|
}else if (testElement instanceof MsScenario) {
|
||||||
|
testElement.setId(UUID.randomUUID().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(testElement.getHashTree() != null){
|
||||||
|
for (MsTestElement itemElement : testElement.getHashTree()) {
|
||||||
|
this.checkTestElement(itemElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -709,6 +709,11 @@
|
||||||
"name": "创建性能测试",
|
"name": "创建性能测试",
|
||||||
"resourceId": "PROJECT_API_SCENARIO"
|
"resourceId": "PROJECT_API_SCENARIO"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "PROJECT_API_SCENARIO:READ+CREATE_PERFORMANCE_BATCH",
|
||||||
|
"name": "批量创建性能测试",
|
||||||
|
"resourceId": "PROJECT_API_SCENARIO"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "PROJECT_API_REPORT:READ",
|
"id": "PROJECT_API_REPORT:READ",
|
||||||
"name": "查询报告",
|
"name": "查询报告",
|
||||||
|
|
|
@ -368,6 +368,11 @@ export default {
|
||||||
handleClick: this.handleBatchEdit,
|
handleClick: this.handleBatchEdit,
|
||||||
permissions: ['PROJECT_API_SCENARIO:READ+EDIT']
|
permissions: ['PROJECT_API_SCENARIO:READ+EDIT']
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: this.$t('api_test.create_performance_test_batch'),
|
||||||
|
handleClick: this.batchCreatePerformance,
|
||||||
|
permissions: ['PROJECT_API_SCENARIO:READ+CREATE_PERFORMANCE_BATCH']
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: this.$t('test_track.case.batch_move_case'),
|
name: this.$t('test_track.case.batch_move_case'),
|
||||||
handleClick: this.handleBatchMove,
|
handleClick: this.handleBatchMove,
|
||||||
|
@ -821,7 +826,39 @@ export default {
|
||||||
},
|
},
|
||||||
callBackSelect(selection){
|
callBackSelect(selection){
|
||||||
this.$emit('selection', selection);
|
this.$emit('selection', selection);
|
||||||
}
|
},
|
||||||
|
batchCreatePerformance() {
|
||||||
|
this.$alert(this.$t('api_test.definition.request.batch_to_performance_confirm') + " ?", '', {
|
||||||
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
|
callback: (action) => {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
this.infoDb = false;
|
||||||
|
let param = {};
|
||||||
|
this.buildBatchParam(param);
|
||||||
|
this.$post('/api/automation/batchGenPerformanceTestJmx/', param, response => {
|
||||||
|
let returnDataList = response.data;
|
||||||
|
let jmxObjList = [];
|
||||||
|
returnDataList.forEach(item => {
|
||||||
|
let jmxObj = {};
|
||||||
|
jmxObj.name = item.name;
|
||||||
|
jmxObj.xml = item.xml;
|
||||||
|
jmxObj.attachFiles = item.attachFiles;
|
||||||
|
jmxObj.attachByteFiles = item.attachByteFiles;
|
||||||
|
jmxObj.scenarioId = item.id;
|
||||||
|
jmxObjList.push(jmxObj);
|
||||||
|
});
|
||||||
|
this.$store.commit('setScenarioJmxs', {
|
||||||
|
name: 'Scenarios',
|
||||||
|
jmxs: jmxObjList
|
||||||
|
});
|
||||||
|
this.$router.push({
|
||||||
|
path: "/performance/test/create"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -44,10 +44,13 @@
|
||||||
:showScript="false"
|
:showScript="false"
|
||||||
:is-read-only="this.isCompReadOnly"
|
:is-read-only="this.isCompReadOnly"
|
||||||
ref="esbDefinition"/>
|
ref="esbDefinition"/>
|
||||||
<ms-tcp-basis-parameters v-if="(request.protocol==='TCP'|| request.type==='TCPSampler')&& request.esbDataStruct==null "
|
<!-- <ms-tcp-basis-parameters v-if="(request.protocol==='TCP'|| request.type==='TCPSampler')&& request.esbDataStruct==null "-->
|
||||||
:request="request"
|
<!-- :request="request"-->
|
||||||
:is-read-only="isCompReadOnly"
|
<!-- :is-read-only="isCompReadOnly"-->
|
||||||
:showScript="false"/>
|
<!-- :showScript="false"/>-->
|
||||||
|
<ms-tcp-format-parameters v-if="(request.protocol==='TCP'|| request.type==='TCPSampler')&& request.esbDataStruct==null "
|
||||||
|
:is-read-only="isCompReadOnly"
|
||||||
|
:show-script="false" :request="request"/>
|
||||||
<ms-sql-basis-parameters v-if="request.protocol==='SQL'|| request.type==='JDBCSampler'"
|
<ms-sql-basis-parameters v-if="request.protocol==='SQL'|| request.type==='JDBCSampler'"
|
||||||
:request="request"
|
:request="request"
|
||||||
:is-read-only="isCompReadOnly"
|
:is-read-only="isCompReadOnly"
|
||||||
|
@ -91,7 +94,8 @@
|
||||||
|
|
||||||
<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 MsTcpFormatParameters from "../../../definition/components/request/tcp/TcpFormatParameters";
|
||||||
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 MsRequestResultTail from "../../../definition/components/response/RequestResultTail";
|
import MsRequestResultTail from "../../../definition/components/response/RequestResultTail";
|
||||||
|
@ -131,7 +135,7 @@ export default {
|
||||||
components: {
|
components: {
|
||||||
CustomizeReqInfo,
|
CustomizeReqInfo,
|
||||||
ApiBaseComponent, ApiResponseComponent,
|
ApiBaseComponent, ApiResponseComponent,
|
||||||
MsSqlBasisParameters, MsTcpBasisParameters, MsDubboBasisParameters, MsApiRequestForm, MsRequestResultTail, MsRun,
|
MsSqlBasisParameters, MsTcpFormatParameters, MsDubboBasisParameters, MsApiRequestForm, MsRequestResultTail, MsRun,
|
||||||
"esbDefinition": esbDefinition.default,
|
"esbDefinition": esbDefinition.default,
|
||||||
"esbDefinitionResponse": esbDefinitionResponse.default
|
"esbDefinitionResponse": esbDefinitionResponse.default
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
<!-- 请求参数 -->
|
<!-- 请求参数 -->
|
||||||
<div v-if="apiProtocol=='TCP'">
|
<div v-if="apiProtocol=='TCP'">
|
||||||
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
|
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
|
||||||
<ms-basis-parameters :show-script="false" :request="request"/>
|
<!-- <ms-basis-parameters :show-script="false" :request="request"/>-->
|
||||||
|
<ms-tcp-format-parameters :show-script="false" :request="request"/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="apiProtocol=='ESB'">
|
<div v-else-if="apiProtocol=='ESB'">
|
||||||
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
|
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
|
||||||
|
@ -43,7 +44,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import MsTcpBasicApi from "./TCPBasicApi";
|
import MsTcpBasicApi from "./TCPBasicApi";
|
||||||
import MsBasisParameters from "../request/tcp/TcpBasisParameters";
|
import MsTcpFormatParameters from "../request/tcp/TcpFormatParameters";
|
||||||
import MsChangeHistory from "../../../../history/ChangeHistory";
|
import MsChangeHistory from "../../../../history/ChangeHistory";
|
||||||
import {hasLicense} from "@/common/js/utils";
|
import {hasLicense} from "@/common/js/utils";
|
||||||
|
|
||||||
|
@ -52,7 +53,7 @@ const esbDefinition = (requireComponent!=null&&requireComponent.keys().length) >
|
||||||
const esbDefinitionResponse = (requireComponent!=null&&requireComponent.keys().length) > 0 ? requireComponent("./apidefinition/EsbDefinitionResponse.vue") : {};
|
const esbDefinitionResponse = (requireComponent!=null&&requireComponent.keys().length) > 0 ? requireComponent("./apidefinition/EsbDefinitionResponse.vue") : {};
|
||||||
export default {
|
export default {
|
||||||
name: "MsAddCompleteTcpApi",
|
name: "MsAddCompleteTcpApi",
|
||||||
components: {MsTcpBasicApi, MsBasisParameters,MsChangeHistory,
|
components: {MsTcpBasicApi, MsTcpFormatParameters,MsChangeHistory,
|
||||||
"esbDefinition": esbDefinition.default,
|
"esbDefinition": esbDefinition.default,
|
||||||
"esbDefinitionResponse": esbDefinitionResponse.default},
|
"esbDefinitionResponse": esbDefinitionResponse.default},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -0,0 +1,292 @@
|
||||||
|
<template>
|
||||||
|
<div class="ms-border">
|
||||||
|
<el-table
|
||||||
|
:data="tableData" @cell-dblclick="editRow"
|
||||||
|
row-key="uuid" :expand-row-keys="tableExpandRowKayArray"
|
||||||
|
default-expand-all
|
||||||
|
v-loading="loading"
|
||||||
|
:tree-props="{children: 'children', hasChildren: 'hasChildren'}">
|
||||||
|
|
||||||
|
<el-table-column prop="name" :label="$t('api_test.definition.request.esb_table.name')" width="230">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input v-if="scope.row.status" v-model="scope.row.name" style="width: 140px"></el-input>
|
||||||
|
<span v-else>{{scope.row.name}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="type" :label="$t('api_test.definition.request.esb_table.type')" width="120">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-select v-if="scope.row.status" v-model="scope.row.type" :placeholder="$t('commons.please_select')">
|
||||||
|
<el-option v-for="item in typeSelectOptions " :key="item.value" :label="item.value" :value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
<span v-else>{{scope.row.type}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="length" :label="$t('api_test.definition.request.esb_table.length')" width="80">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input v-if="scope.row.status" v-model="scope.row.contentType"></el-input>
|
||||||
|
<span v-else>{{scope.row.contentType}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="description" :label="$t('api_test.definition.request.esb_table.desc')" min-width="200">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input v-if="scope.row.status" v-model="scope.row.description"></el-input>
|
||||||
|
<span v-else>{{scope.row.description}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="value" :label="$t('api_test.definition.request.esb_table.value')" width="180">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input v-if="scope.row.status" v-model="scope.row.value"></el-input>
|
||||||
|
<span v-else>{{scope.row.value}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column v-if="showOptionsButton" :label="$t('commons.operating')" width="140" fixed="right">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>
|
||||||
|
<el-button size="mini" p="$t('commons.next_level')" icon="el-icon-plus" type="primary" circle @click="nextRow(scope.row)"
|
||||||
|
class="ht-btn-confirm"/>
|
||||||
|
<el-button size="mini" p="$t('commons.copy')" icon="el-icon-copy-document" type="primary" circle @click="copyDataStructConfirm(scope.row)"
|
||||||
|
class="ht-btn-confirm"/>
|
||||||
|
<el-button size="mini" p="$t('commons.remove')" icon="el-icon-close" circle @click="remove(scope.row)"
|
||||||
|
class="ht-btn-remove"/>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div v-if="showOptionsButton">
|
||||||
|
<el-button class="ht-btn-add" size="mini" p="$t('commons.add')" icon="el-icon-circle-plus-outline" @click="add">{{$t("commons.add")}}</el-button>
|
||||||
|
<el-button class="ht-btn-add" size="mini" p="$t('commons.add')" icon="el-icon-circle-plus-outline" @click="saveTableData">{{$t("commons.save")}}</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MsTcpXmlTable",
|
||||||
|
components: {},
|
||||||
|
props: {
|
||||||
|
tableData: Array,
|
||||||
|
showOptionsButton:Boolean,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading:false,
|
||||||
|
typeSelectOptions:[
|
||||||
|
{ value: 'object', label: '[object]' },
|
||||||
|
{ value: 'string', label: '[string]' },
|
||||||
|
{ value: 'array', label: '[array]' },
|
||||||
|
],
|
||||||
|
requiredSelectOptions:[
|
||||||
|
{ value: true, label: '必填' },
|
||||||
|
{ value: false, label: '非必填' },
|
||||||
|
],
|
||||||
|
tableExpandRowKayArray:["name","systemName"],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if(this.tableData && this.tableData.length>0){
|
||||||
|
this.tableData.forEach(row => {
|
||||||
|
if(row.name == null || row.name === ""){
|
||||||
|
this.remove(row);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
saveTableData:function(){
|
||||||
|
this.$emit('saveTableData',this.tableData);
|
||||||
|
},
|
||||||
|
remove: function (row) {
|
||||||
|
this.removeTableRow(row);
|
||||||
|
},
|
||||||
|
add: function (r) {
|
||||||
|
let row = this.getNewRow(null);
|
||||||
|
this.pushTableData(row);
|
||||||
|
},
|
||||||
|
nextRow:function (row) {
|
||||||
|
//首先保存当前行内容
|
||||||
|
let confirmRowFlag = this.confirm(row);
|
||||||
|
if(confirmRowFlag){
|
||||||
|
let nextRow = this.getNewRow(null);
|
||||||
|
this.pushTableData(nextRow,row.uuid);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//复制当前数据结构
|
||||||
|
copyDataStructConfirm:function (row){
|
||||||
|
this.$alert(this.$t('api_test.definition.request.esb_copy_confirm') + " ?", '', {
|
||||||
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
|
callback: (action) => {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
this.copyDataStruct(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
copyDataStruct:function (row){
|
||||||
|
let parentRow = this.selectParentRow(this.tableData,row.uuid);
|
||||||
|
let newRow = this.createNewId(row);
|
||||||
|
if(parentRow!=null){
|
||||||
|
if(parentRow.children == null){
|
||||||
|
parentRow.children = [];
|
||||||
|
}
|
||||||
|
parentRow.children.push(newRow);
|
||||||
|
}else{
|
||||||
|
this.$emit('xmlTableDataPushRow',newRow);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
createNewId(row){
|
||||||
|
let newRow = this.getNewRow(row);
|
||||||
|
if(row.children!=null && row.children.length > 0){
|
||||||
|
row.children.forEach(child => {
|
||||||
|
let newChild = this.createNewId(child);
|
||||||
|
newRow.children.push(newChild);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return newRow;
|
||||||
|
},
|
||||||
|
selectParentRow(dataStruct,rowId){
|
||||||
|
let returnRow = null;
|
||||||
|
if(dataStruct == null || dataStruct.length === 0){
|
||||||
|
return returnRow;
|
||||||
|
}
|
||||||
|
dataStruct.forEach( itemData => {
|
||||||
|
if(itemData.children != null && itemData.children.length > 0){
|
||||||
|
itemData.children.forEach( child => {
|
||||||
|
if(child.uuid === rowId){
|
||||||
|
returnRow = itemData;
|
||||||
|
return returnRow;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if(returnRow == null ){
|
||||||
|
if(itemData.children != null && itemData.children.length > 0){
|
||||||
|
returnRow = this.selectParentRow(itemData.children,rowId);
|
||||||
|
if(returnRow!=null){
|
||||||
|
return returnRow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return returnRow;
|
||||||
|
},
|
||||||
|
confirm: function (row) {
|
||||||
|
this.validateRowData(row) ? row.status = '' : row.status;
|
||||||
|
if (row.status === "") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
getNewRow(param){
|
||||||
|
if(param == null ){
|
||||||
|
let row = {
|
||||||
|
name: '',systemName: '',status: 'edit',type: '[object]',contentType: '',required: false,description: '',uuid: this.uuid(),children: []
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
}else{
|
||||||
|
let row = {
|
||||||
|
name: param.name,
|
||||||
|
systemName: param.systemName,
|
||||||
|
status: '',
|
||||||
|
type: param.type,
|
||||||
|
contentType: param.contentType,
|
||||||
|
required: param.required,
|
||||||
|
description: param.description,
|
||||||
|
uuid: this.uuid(),
|
||||||
|
children: []
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
validateRowData(row) {
|
||||||
|
if(row.name == null || row.name === ''){
|
||||||
|
// this.$warning(this.$t('load_test.input_ip'));
|
||||||
|
this.$warning("参数名"+"不能为空,且不能包含英文小数点[.]");
|
||||||
|
return false;
|
||||||
|
}else if(row.name.indexOf(".")>0){
|
||||||
|
this.$warning("参数名["+row.name+"]不合法,不能包含英文小数点\".\"!");
|
||||||
|
return false;
|
||||||
|
}else if(row.type == null || row.type === ''){
|
||||||
|
this.$warning("类型"+"不能为空!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
editRow: function (row) {
|
||||||
|
row.status = 'edit';
|
||||||
|
},
|
||||||
|
uuid: function () {
|
||||||
|
return (((1 + Math.random()) * 0x100000) | 0).toString(16).substring(1);
|
||||||
|
},
|
||||||
|
pushTableData: function(dataRow,rowId){
|
||||||
|
if(rowId === "" || rowId == null){
|
||||||
|
if(this.tableData){
|
||||||
|
this.$emit("initXmlTableData");
|
||||||
|
}
|
||||||
|
this.tableData.push(dataRow);
|
||||||
|
}else {
|
||||||
|
this.appendDataWithDeepForeach(this.tableData,rowId,dataRow);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
appendDataWithDeepForeach(datas,rowId,appendData){
|
||||||
|
datas.forEach( row => {
|
||||||
|
if(row.uuid === rowId){
|
||||||
|
if(row.children == null){
|
||||||
|
row.children = [];
|
||||||
|
}
|
||||||
|
row.children.push(appendData);
|
||||||
|
}else if(row.children.length>0){
|
||||||
|
let appendResult = this.appendDataWithDeepForeach(row.children,rowId,appendData);
|
||||||
|
if(appendResult){
|
||||||
|
return appendResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
removeTableRow: function (row){
|
||||||
|
this.removeFromDataStruct(this.tableData,row);
|
||||||
|
},
|
||||||
|
removeFromDataStruct(dataStruct,row){
|
||||||
|
if(dataStruct == null || dataStruct.length === 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let rowIndex = dataStruct.indexOf(row);
|
||||||
|
if(rowIndex >= 0){
|
||||||
|
dataStruct.splice(rowIndex,1);
|
||||||
|
}else {
|
||||||
|
dataStruct.forEach( itemData => {
|
||||||
|
if(itemData.children != null && itemData.children.length > 0){
|
||||||
|
this.removeFromDataStruct(itemData.children,row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.ht-btn-remove {
|
||||||
|
color: white;
|
||||||
|
background-color: #DCDFE6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ht-btn-confirm {
|
||||||
|
color: white;
|
||||||
|
/*background-color: #1483F6;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.ht-btn-add {
|
||||||
|
border: 0px;
|
||||||
|
margin-top: 10px;
|
||||||
|
color: #783887;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ht-tb {
|
||||||
|
background-color: white;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -27,8 +27,8 @@
|
||||||
|
|
||||||
<p class="tip">{{$t('api_test.definition.request.req_param')}} </p>
|
<p class="tip">{{$t('api_test.definition.request.req_param')}} </p>
|
||||||
<!-- TCP 请求参数 -->
|
<!-- TCP 请求参数 -->
|
||||||
<tcp-basis-parameters :request="request" @callback="runDebug" ref="requestForm"/>
|
<!-- <tcp-basis-parameters :request="request" @callback="runDebug" ref="requestForm"/>-->
|
||||||
|
<ms-tcp-format-parameters :request="request" @callback="runDebug" ref="requestForm"/>
|
||||||
<!-- TCP 请求返回数据 -->
|
<!-- TCP 请求返回数据 -->
|
||||||
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
|
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
|
||||||
<ms-request-result-tail :response="responseData" :currentProtocol="currentProtocol" ref="debugResult"/>
|
<ms-request-result-tail :response="responseData" :currentProtocol="currentProtocol" ref="debugResult"/>
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
import {createComponent} from "../jmeter/components";
|
import {createComponent} from "../jmeter/components";
|
||||||
import {REQ_METHOD} from "../../model/JsonData";
|
import {REQ_METHOD} from "../../model/JsonData";
|
||||||
import MsRequestResultTail from "../response/RequestResultTail";
|
import MsRequestResultTail from "../response/RequestResultTail";
|
||||||
import TcpBasisParameters from "../request/tcp/TcpBasisParameters";
|
import MsTcpFormatParameters from "@/business/components/api/definition/components/request/tcp/TcpFormatParameters";
|
||||||
import MsJmxStep from "../step/JmxStep";
|
import MsJmxStep from "../step/JmxStep";
|
||||||
import MsApiCaseList from "../case/ApiCaseList";
|
import MsApiCaseList from "../case/ApiCaseList";
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
name: "ApiConfig",
|
name: "ApiConfig",
|
||||||
components: {
|
components: {
|
||||||
MsJmxStep,
|
MsJmxStep,
|
||||||
TcpBasisParameters,
|
MsTcpFormatParameters,
|
||||||
MsRequestResultTail, MsResponseResult, MsApiRequestForm, MsRequestMetric, MsResponseText, MsRun, MsApiCaseList
|
MsRequestResultTail, MsResponseResult, MsApiRequestForm, MsRequestMetric, MsResponseText, MsRun, MsApiCaseList
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -0,0 +1,497 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="21" style="padding-bottom: 20px">
|
||||||
|
<div style="border:1px #DCDFE6 solid; height: 100%;border-radius: 4px ;width: 100% ;margin: 10px">
|
||||||
|
<el-form class="tcp" :model="request" :rules="rules" ref="request" :disabled="isReadOnly" style="margin: 20px">
|
||||||
|
<el-tabs v-model="activeName" class="request-tabs">
|
||||||
|
<!--query 参数-->
|
||||||
|
<el-tab-pane :label="$t('api_test.definition.document.request_body')" name="request">
|
||||||
|
<el-radio-group v-model="reportType" size="mini" style="margin: 10px 0px;">
|
||||||
|
<el-radio :disabled="isReadOnly" label="json" @change="changeReportType">
|
||||||
|
json
|
||||||
|
</el-radio>
|
||||||
|
<el-radio :disabled="isReadOnly" label="xml" @change="changeReportType">
|
||||||
|
xml
|
||||||
|
</el-radio>
|
||||||
|
<el-radio :disabled="isReadOnly" label="raw" @change="changeReportType">
|
||||||
|
raw
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
<div style="min-width: 1200px;" v-if="request.reportType === 'xml'">
|
||||||
|
<tcp-xml-table :table-data="request.xmlDataStruct" :show-options-button="true"
|
||||||
|
@initXmlTableData="initXmlTableData"
|
||||||
|
@saveTableData="saveXmlTableData" ref="treeTable"></tcp-xml-table>
|
||||||
|
</div>
|
||||||
|
<div style="min-width: 1200px;" v-if="request.reportType === 'json'">
|
||||||
|
<div class="send-request">
|
||||||
|
<ms-code-edit mode="json" :read-only="isReadOnly" :data.sync="request.jsonDataStruct" :modes="['text', 'json', 'xml', 'html']" theme="eclipse"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="min-width: 1200px;" v-if="request.reportType === 'raw'">
|
||||||
|
<div class="send-request">
|
||||||
|
<ms-code-edit mode="text" :read-only="isReadOnly" :data.sync="request.rawDataStruct" :modes="['text', 'json', 'xml', 'html']" theme="eclipse"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane :label="$t('api_test.definition.request.pre_script')" name="script">
|
||||||
|
<jsr233-processor-content
|
||||||
|
:jsr223-processor="request.tcpPreProcessor"
|
||||||
|
:is-pre-processor="true"
|
||||||
|
:is-read-only="isReadOnly"/>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane :label="$t('api_test.definition.request.other_config')" name="other" class="other-config">
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-form-item label="TCPClient" prop="classname">
|
||||||
|
<el-select v-model="request.classname" style="width: 100%" size="small">
|
||||||
|
<el-option v-for="c in classes" :key="c" :label="c" :value="c"/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-form-item :label="$t('api_test.request.tcp.connect')" prop="ctimeout">
|
||||||
|
<el-input-number v-model="request.ctimeout" controls-position="right" :min="0" size="small"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-form-item :label="$t('api_test.request.tcp.response')" prop="timeout">
|
||||||
|
<el-input-number v-model="request.timeout" controls-position="right" :min="0" size="small"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="10">
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item :label="$t('api_test.request.tcp.so_linger')" prop="soLinger">
|
||||||
|
<el-input v-model="request.soLinger" size="small"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item :label="$t('api_test.request.tcp.eol_byte')" prop="eolByte">
|
||||||
|
<el-input v-model="request.eolByte" size="small"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item :label="$t('api_test.request.tcp.username')" prop="username">
|
||||||
|
<el-input v-model="request.username" maxlength="100" show-word-limit size="small"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item :label="$t('api_test.request.tcp.password')" prop="password">
|
||||||
|
<el-input v-model="request.password" maxlength="30" show-word-limit show-password
|
||||||
|
autocomplete="new-password" size="small"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="10" style="margin-left: 30px">
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item :label="$t('api_test.request.tcp.re_use_connection')">
|
||||||
|
<el-checkbox v-model="request.reUseConnection"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item :label="$t('api_test.request.tcp.close_connection')">
|
||||||
|
<el-checkbox v-model="request.closeConnection"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item :label="$t('api_test.request.tcp.no_delay')">
|
||||||
|
<el-checkbox v-model="request.nodelay"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="Connect encoding">
|
||||||
|
<el-select v-model="request.connectEncoding" style="width: 100px" size="small">
|
||||||
|
<el-option v-for="item in connectEncodingArr" :key="item.key" :label="item.value" :value="item.key"/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<!--操作按钮-->
|
||||||
|
<api-definition-step-button :request="request" v-if="!referenced && showScript"/>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsApiKeyValue from "../../ApiKeyValue";
|
||||||
|
import MsApiAssertions from "../../assertion/ApiAssertions";
|
||||||
|
import MsApiExtract from "../../extract/ApiExtract";
|
||||||
|
import ApiRequestMethodSelect from "../../collapse/ApiRequestMethodSelect";
|
||||||
|
import MsCodeEdit from "../../../../../common/components/MsCodeEdit";
|
||||||
|
import MsApiScenarioVariables from "../../ApiScenarioVariables";
|
||||||
|
import {createComponent} from "../../jmeter/components";
|
||||||
|
import {Assertions, Extract} from "../../../model/ApiTestModel";
|
||||||
|
import {parseEnvironment} from "../../../model/EnvironmentModel";
|
||||||
|
import ApiEnvironmentConfig from "../../environment/ApiEnvironmentConfig";
|
||||||
|
import {API_STATUS} from "../../../model/JsonData";
|
||||||
|
import TCPSampler from "../../jmeter/components/sampler/tcp-sampler";
|
||||||
|
import {getCurrentProjectID, getUUID} from "@/common/js/utils";
|
||||||
|
import MsApiVariable from "../../ApiVariable";
|
||||||
|
import MsInstructionsIcon from "../../../../../common/components/MsInstructionsIcon";
|
||||||
|
import Jsr233ProcessorContent from "../../../../automation/scenario/common/Jsr233ProcessorContent";
|
||||||
|
import JSR223PreProcessor from "../../jmeter/components/pre-processors/jsr223-pre-processor";
|
||||||
|
import ApiDefinitionStepButton from "../components/ApiDefinitionStepButton";
|
||||||
|
import TcpXmlTable from "@/business/components/api/definition/components/complete/table/TcpXmlTable";
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MsTcpFormatParameters",
|
||||||
|
components: {
|
||||||
|
TcpXmlTable,
|
||||||
|
ApiDefinitionStepButton,
|
||||||
|
Jsr233ProcessorContent,
|
||||||
|
MsInstructionsIcon,
|
||||||
|
MsApiVariable,
|
||||||
|
MsApiScenarioVariables,
|
||||||
|
MsCodeEdit,
|
||||||
|
ApiRequestMethodSelect, MsApiExtract, MsApiAssertions, MsApiKeyValue, ApiEnvironmentConfig
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
request: {},
|
||||||
|
basisData: {},
|
||||||
|
moduleOptions: Array,
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
showScript: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
referenced: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeName: "request",
|
||||||
|
classes: TCPSampler.CLASSES,
|
||||||
|
reportType:"xml",
|
||||||
|
isReloadData: false,
|
||||||
|
refreshedXmlTable:true,
|
||||||
|
options: API_STATUS,
|
||||||
|
currentProjectId: "",
|
||||||
|
connectEncodingArr:[
|
||||||
|
{
|
||||||
|
'key':'UTF-8',
|
||||||
|
'value':'UTF-8',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'key':'GBK',
|
||||||
|
'value':'GBK',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
classname: [{required: true, message: "请选择TCPClient", trigger: 'change'}],
|
||||||
|
server: [{required: true, message: this.$t('api_test.request.tcp.server_cannot_be_empty'), trigger: 'blur'}],
|
||||||
|
port: [{required: true, message: this.$t('commons.port_cannot_be_empty'), trigger: 'change'}],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch:{
|
||||||
|
reportType(){
|
||||||
|
this.request.reportType = this.reportType;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.currentProjectId = getCurrentProjectID();
|
||||||
|
if (!this.request.parameters) {
|
||||||
|
this.$set(this.request, 'parameters', []);
|
||||||
|
this.request.parameters = [];
|
||||||
|
}
|
||||||
|
if (!this.request.tcpPreProcessor) {
|
||||||
|
this.$set(this.request, 'tcpPreProcessor', new JSR223PreProcessor())
|
||||||
|
}
|
||||||
|
if(!this.request.connectEncoding){
|
||||||
|
this.request.connectEncoding = "UTF-8";
|
||||||
|
}
|
||||||
|
this.getEnvironments();
|
||||||
|
|
||||||
|
if(this.request){
|
||||||
|
if(!this.request.reportType){
|
||||||
|
this.request.reportType = "raw";
|
||||||
|
}else {
|
||||||
|
if(this.request.reportType !== "json" && this.request.reportType !== "xml"&&this.request.reportType !== "raw"){
|
||||||
|
this.request.reportType = "raw";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.reportType = this.request.reportType;
|
||||||
|
|
||||||
|
if(!this.request.xmlDataStruct){
|
||||||
|
this.initXmlTableData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addPre() {
|
||||||
|
let jsr223PreProcessor = createComponent("JSR223PreProcessor");
|
||||||
|
this.request.hashTree.push(jsr223PreProcessor);
|
||||||
|
this.reload();
|
||||||
|
},
|
||||||
|
addPost() {
|
||||||
|
let jsr223PostProcessor = createComponent("JSR223PostProcessor");
|
||||||
|
this.request.hashTree.push(jsr223PostProcessor);
|
||||||
|
this.reload();
|
||||||
|
},
|
||||||
|
addAssertions() {
|
||||||
|
let assertions = new Assertions();
|
||||||
|
this.request.hashTree.push(assertions);
|
||||||
|
this.reload();
|
||||||
|
},
|
||||||
|
addExtract() {
|
||||||
|
let jsonPostProcessor = new Extract();
|
||||||
|
this.request.hashTree.push(jsonPostProcessor);
|
||||||
|
this.reload();
|
||||||
|
},
|
||||||
|
remove(row) {
|
||||||
|
let index = this.request.hashTree.indexOf(row);
|
||||||
|
this.request.hashTree.splice(index, 1);
|
||||||
|
this.reload();
|
||||||
|
},
|
||||||
|
copyRow(row) {
|
||||||
|
let obj =JSON.parse(JSON.stringify(row));
|
||||||
|
obj.id = getUUID();
|
||||||
|
this.request.hashTree.push(obj);
|
||||||
|
this.reload();
|
||||||
|
},
|
||||||
|
reload() {
|
||||||
|
this.isReloadData = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.isReloadData = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
validateApi() {
|
||||||
|
if (this.currentProjectId === null) {
|
||||||
|
this.$error(this.$t('api_test.select_project'), 2000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$refs['basicForm'].validate();
|
||||||
|
},
|
||||||
|
saveApi() {
|
||||||
|
this.basisData.method = this.basisData.protocol;
|
||||||
|
this.$emit('saveApi', this.basisData);
|
||||||
|
},
|
||||||
|
runTest() {
|
||||||
|
|
||||||
|
},
|
||||||
|
validate() {
|
||||||
|
if (this.currentProjectId === null) {
|
||||||
|
this.$error(this.$t('api_test.select_project'), 2000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$refs['request'].validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.$emit('callback');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getEnvironments() {
|
||||||
|
if (this.currentProjectId) {
|
||||||
|
this.environments = [];
|
||||||
|
this.$get('/api/environment/list/' + this.currentProjectId, response => {
|
||||||
|
this.environments = response.data;
|
||||||
|
this.environments.forEach(environment => {
|
||||||
|
parseEnvironment(environment);
|
||||||
|
});
|
||||||
|
this.initDataSource();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openEnvironmentConfig() {
|
||||||
|
if (!this.currentProjectId) {
|
||||||
|
this.$error(this.$t('api_test.select_project'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$refs.environmentConfig.open(this.currentProjectId);
|
||||||
|
},
|
||||||
|
initDataSource() {
|
||||||
|
for (let i in this.environments) {
|
||||||
|
if (this.environments[i].id === this.request.environmentId) {
|
||||||
|
this.databaseConfigsOptions = [];
|
||||||
|
this.environments[i].config.databaseConfigs.forEach(item => {
|
||||||
|
this.databaseConfigsOptions.push(item);
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
environmentChange(value) {
|
||||||
|
this.request.dataSource = undefined;
|
||||||
|
for (let i in this.environments) {
|
||||||
|
if (this.environments[i].id === value) {
|
||||||
|
this.databaseConfigsOptions = [];
|
||||||
|
this.environments[i].config.databaseConfigs.forEach(item => {
|
||||||
|
this.databaseConfigsOptions.push(item);
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
environmentConfigClose() {
|
||||||
|
this.getEnvironments();
|
||||||
|
},
|
||||||
|
|
||||||
|
changeReportType(){
|
||||||
|
},
|
||||||
|
|
||||||
|
//以下是xml树形表格相关的方法
|
||||||
|
updateXmlTableData(dataStruct){
|
||||||
|
this.request.xmlDataStruct = dataStruct;
|
||||||
|
},
|
||||||
|
saveXmlTableData(dataStruct){
|
||||||
|
let valedataResult = this.validateXmlDataStruct(dataStruct);
|
||||||
|
if(valedataResult){
|
||||||
|
this.request.xmlDataStruct = dataStruct;
|
||||||
|
this.refreshXmlTable();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
validateXmlDataStruct(dataStruct){
|
||||||
|
this.refreshXmlTableDataStruct(dataStruct);
|
||||||
|
let result = this.checkXmlTableDataStructData(dataStruct);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
refreshXmlTableDataStruct(dataStruct){
|
||||||
|
if(dataStruct && dataStruct.length > 0){
|
||||||
|
dataStruct.forEach( row => {
|
||||||
|
row.status = "";
|
||||||
|
if(row.children == null || row.children.length === 0){
|
||||||
|
row.children = [];
|
||||||
|
}else if(row.children.length>0){
|
||||||
|
this.refreshXmlTableDataStruct(row.children);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
checkXmlTableDataStructData(dataStruct){
|
||||||
|
let allCheckResult = true;
|
||||||
|
if(dataStruct && dataStruct.length > 0){
|
||||||
|
for(let i = 0;i<dataStruct.length;i++){
|
||||||
|
let row = dataStruct[i];
|
||||||
|
allCheckResult = this.$refs.treeTable.validateRowData(row);
|
||||||
|
if(allCheckResult){
|
||||||
|
if(row.children != null && row.children.length > 0){
|
||||||
|
allCheckResult = this.checkXmlTableDataStructData(row.children);
|
||||||
|
if(!allCheckResult){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allCheckResult;
|
||||||
|
},
|
||||||
|
initXmlTableData(){
|
||||||
|
if(this.request){
|
||||||
|
this.request.xmlDataStruct = [];
|
||||||
|
this.refreshXmlTable();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xmlTableDataPushRow(newRow){
|
||||||
|
if(this.request){
|
||||||
|
if(!this.request.xmlDataStruct){
|
||||||
|
this.request.xmlDataStruct = [];
|
||||||
|
}
|
||||||
|
this.request.xmlDataStruct.push(newRow);
|
||||||
|
this.refreshXmlTable();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xmlTableDataRemoveRow(row){
|
||||||
|
if(this.request){
|
||||||
|
if(this.request.xmlDataStruct){
|
||||||
|
this.removeFromDataStruct(this.request.xmlDataStruct,row);
|
||||||
|
this.refreshXmlTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeFromDataStruct(dataStruct,row){
|
||||||
|
if(!dataStruct || dataStruct.length === 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let rowIndex = dataStruct.indexOf(row);
|
||||||
|
if(rowIndex >= 0){
|
||||||
|
dataStruct.splice(rowIndex,1);
|
||||||
|
}else {
|
||||||
|
dataStruct.forEach( itemData => {
|
||||||
|
if(!itemData.children && itemData.children.length > 0){
|
||||||
|
this.removeFromDataStruct(itemData.children,row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
refreshXmlTable(){
|
||||||
|
this.refreshedXmlTable = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.refreshedXmlTable = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.tcp >>> .el-input-number {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.send-request {
|
||||||
|
padding: 0px 0;
|
||||||
|
height: 300px;
|
||||||
|
border: 1px #DCDFE6 solid;
|
||||||
|
border-radius: 4px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ms-left-cell {
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ms-left-buttion {
|
||||||
|
margin: 6px 0px 8px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .el-form-item {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ms-left-cell {
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ms-left-buttion {
|
||||||
|
margin: 6px 0px 8px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .el-form-item {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .instructions-icon {
|
||||||
|
font-size: 14px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request-tabs {
|
||||||
|
margin: 20px;
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other-config {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -33,7 +33,8 @@
|
||||||
|
|
||||||
<div v-if="api.method=='TCP'">
|
<div v-if="api.method=='TCP'">
|
||||||
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
|
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
|
||||||
<ms-basis-parameters :request="api.request" @callback="runTest" ref="requestForm"/>
|
<!-- <ms-basis-parameters :request="api.request" @callback="runTest" ref="requestForm"/>-->
|
||||||
|
<ms-tcp-format-parameters :request="api.request" @callback="runTest" ref="requestForm"/>
|
||||||
<!--返回结果-->
|
<!--返回结果-->
|
||||||
<!-- HTTP 请求返回数据 -->
|
<!-- HTTP 请求返回数据 -->
|
||||||
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
|
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
|
||||||
|
@ -74,7 +75,7 @@ import MsContainer from "../../../../common/components/MsContainer";
|
||||||
import MsBottomContainer from "../BottomContainer";
|
import MsBottomContainer from "../BottomContainer";
|
||||||
import MsRequestResultTail from "../response/RequestResultTail";
|
import MsRequestResultTail from "../response/RequestResultTail";
|
||||||
import MsRun from "../Run";
|
import MsRun from "../Run";
|
||||||
import MsBasisParameters from "../request/tcp/TcpBasisParameters";
|
import MsTcpFormatParameters from "@/business/components/api/definition/components/request/tcp/TcpFormatParameters";
|
||||||
import {REQ_METHOD} from "../../model/JsonData";
|
import {REQ_METHOD} from "../../model/JsonData";
|
||||||
import EnvironmentSelect from "../environment/EnvironmentSelect";
|
import EnvironmentSelect from "../environment/EnvironmentSelect";
|
||||||
import MsJmxStep from "../step/JmxStep";
|
import MsJmxStep from "../step/JmxStep";
|
||||||
|
@ -92,7 +93,7 @@ export default {
|
||||||
MsBottomContainer,
|
MsBottomContainer,
|
||||||
MsRequestResultTail,
|
MsRequestResultTail,
|
||||||
MsRun,
|
MsRun,
|
||||||
MsBasisParameters,
|
MsTcpFormatParameters,
|
||||||
"esbDefinition": esbDefinition.default,
|
"esbDefinition": esbDefinition.default,
|
||||||
"esbDefinitionResponse": esbDefinitionResponse.default
|
"esbDefinitionResponse": esbDefinitionResponse.default
|
||||||
},
|
},
|
||||||
|
|
|
@ -160,7 +160,7 @@ export default {
|
||||||
if (apiTest.jmx.caseId) {
|
if (apiTest.jmx.caseId) {
|
||||||
this.$refs.basicConfig.importCase(apiTest.jmx);
|
this.$refs.basicConfig.importCase(apiTest.jmx);
|
||||||
}
|
}
|
||||||
if (JSON.stringify(apiTest.jmx.attachFiles) != "{}") {
|
if (JSON.stringify(apiTest.jmx.attachFiles) !== "{}") {
|
||||||
let attachFiles = [];
|
let attachFiles = [];
|
||||||
for (let fileID in apiTest.jmx.attachFiles) {
|
for (let fileID in apiTest.jmx.attachFiles) {
|
||||||
attachFiles.push(fileID);
|
attachFiles.push(fileID);
|
||||||
|
@ -171,6 +171,33 @@ export default {
|
||||||
}
|
}
|
||||||
this.active = '1';
|
this.active = '1';
|
||||||
this.$store.commit("clearTest");
|
this.$store.commit("clearTest");
|
||||||
|
}else {
|
||||||
|
let scenarioJmxs = this.$store.state.scenarioJmxs;
|
||||||
|
if(scenarioJmxs && scenarioJmxs.name){
|
||||||
|
this.$set(this.test, "name", scenarioJmxs.name);
|
||||||
|
if(scenarioJmxs.jmxs){
|
||||||
|
scenarioJmxs.jmxs.forEach(item => {
|
||||||
|
if (item.scenarioId) {
|
||||||
|
this.$refs.basicConfig.importScenario(item.scenarioId);
|
||||||
|
this.$refs.basicConfig.handleUpload();
|
||||||
|
}
|
||||||
|
if (item.caseId) {
|
||||||
|
this.$refs.basicConfig.importCase(item);
|
||||||
|
}
|
||||||
|
if (JSON.stringify(item.attachFiles) !== "{}") {
|
||||||
|
let attachFiles = [];
|
||||||
|
for (let fileID in item.attachFiles) {
|
||||||
|
attachFiles.push(fileID);
|
||||||
|
}
|
||||||
|
if (attachFiles.length > 0) {
|
||||||
|
this.$refs.basicConfig.selectAttachFileById(attachFiles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.active = '1';
|
||||||
|
this.$store.commit("clearScenarioJmxs");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getTest(testId) {
|
getTest(testId) {
|
||||||
|
|
|
@ -669,6 +669,7 @@ export default {
|
||||||
key: "Key",
|
key: "Key",
|
||||||
value: "Value",
|
value: "Value",
|
||||||
create_performance_test: "Create Performance Test",
|
create_performance_test: "Create Performance Test",
|
||||||
|
create_performance_test_batch: "Batch Create Performance Test",
|
||||||
export_config: "Export",
|
export_config: "Export",
|
||||||
enable_validate_tip: "No request available",
|
enable_validate_tip: "No request available",
|
||||||
copy: "Copy Test",
|
copy: "Copy Test",
|
||||||
|
@ -760,6 +761,7 @@ export default {
|
||||||
res_param: "Response content",
|
res_param: "Response content",
|
||||||
batch_delete: "Batch deletion",
|
batch_delete: "Batch deletion",
|
||||||
delete_confirm: "Confirm deletion",
|
delete_confirm: "Confirm deletion",
|
||||||
|
batch_to_performance_confirm: "Confirm Batch Create Performance Test",
|
||||||
delete_case_confirm: "Confirm case deletion",
|
delete_case_confirm: "Confirm case deletion",
|
||||||
delete_confirm_step: "Confirm deletion step",
|
delete_confirm_step: "Confirm deletion step",
|
||||||
assertions_rule: "Assertion rule",
|
assertions_rule: "Assertion rule",
|
||||||
|
|
|
@ -668,6 +668,7 @@ export default {
|
||||||
key: "键",
|
key: "键",
|
||||||
value: "值",
|
value: "值",
|
||||||
create_performance_test: "创建性能测试",
|
create_performance_test: "创建性能测试",
|
||||||
|
create_performance_test_batch: "批量创建性能测试",
|
||||||
export_config: "导出",
|
export_config: "导出",
|
||||||
enable_validate_tip: "没有可用请求",
|
enable_validate_tip: "没有可用请求",
|
||||||
copy: "复制测试",
|
copy: "复制测试",
|
||||||
|
@ -760,6 +761,7 @@ export default {
|
||||||
res_param: "响应内容",
|
res_param: "响应内容",
|
||||||
batch_delete: "批量删除",
|
batch_delete: "批量删除",
|
||||||
delete_confirm: "确认删除接口",
|
delete_confirm: "确认删除接口",
|
||||||
|
batch_to_performance_confirm: "确认批量创建性能测试",
|
||||||
delete_case_confirm: "确认删除用例",
|
delete_case_confirm: "确认删除用例",
|
||||||
delete_confirm_step: "确认删除步骤",
|
delete_confirm_step: "确认删除步骤",
|
||||||
assertions_rule: "断言规则",
|
assertions_rule: "断言规则",
|
||||||
|
|
|
@ -668,6 +668,7 @@ export default {
|
||||||
key: "鍵",
|
key: "鍵",
|
||||||
value: "值",
|
value: "值",
|
||||||
create_performance_test: "創建性能測試",
|
create_performance_test: "創建性能測試",
|
||||||
|
create_performance_test_batch: "批量創建性能測試",
|
||||||
export_config: "導出",
|
export_config: "導出",
|
||||||
enable_validate_tip: "沒有可用請求",
|
enable_validate_tip: "沒有可用請求",
|
||||||
copy: "復制測試",
|
copy: "復制測試",
|
||||||
|
@ -760,6 +761,7 @@ export default {
|
||||||
res_param: "響應內容",
|
res_param: "響應內容",
|
||||||
batch_delete: "批量刪除",
|
batch_delete: "批量刪除",
|
||||||
delete_confirm: "確認刪除接口",
|
delete_confirm: "確認刪除接口",
|
||||||
|
batch_to_performance_confirm: "確認批量創建性能測試",
|
||||||
delete_case_confirm: "確認刪除用例",
|
delete_case_confirm: "確認刪除用例",
|
||||||
delete_confirm_step: "確認刪除步驟",
|
delete_confirm_step: "確認刪除步驟",
|
||||||
assertions_rule: "斷言規則",
|
assertions_rule: "斷言規則",
|
||||||
|
|
|
@ -9,6 +9,7 @@ Vue.use(Vuex)
|
||||||
const state = {
|
const state = {
|
||||||
projectId: "",
|
projectId: "",
|
||||||
test: {},
|
test: {},
|
||||||
|
scenarioJmxs:{},
|
||||||
versionSwitch: "new",
|
versionSwitch: "new",
|
||||||
isReadOnly: true,
|
isReadOnly: true,
|
||||||
theme: undefined,
|
theme: undefined,
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
const mutations = {
|
const mutations = {
|
||||||
setProjectId: (state, projectId) => state.projectId = projectId,
|
setProjectId: (state, projectId) => state.projectId = projectId,
|
||||||
setTest: (state, test) => state.test = test,
|
setTest: (state, test) => state.test = test,
|
||||||
|
setScenarioJmxs: (state, scenarioJmxs) => state.scenarioJmxs = scenarioJmxs,
|
||||||
clearTest: state => state.test = {},
|
clearTest: state => state.test = {},
|
||||||
|
clearScenarioJmxs:state => state.scenarioJmxs = {},
|
||||||
setVersionSwitch: (state, value) => state.versionSwitch = value,
|
setVersionSwitch: (state, value) => state.versionSwitch = value,
|
||||||
setTheme: (state, value) => state.theme = value,
|
setTheme: (state, value) => state.theme = value,
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue