fix(接口测试): 修复Chrome插件录制脚本导入后步骤顺序错乱问题

--bug=1027722 --user=赵勇 【通用功能】github#25517,使用MS 的录制插件录制的脚本,保存json格式再导入到接口自动化里,这些接口都是无序的,还需要手动调整接口的前后顺序;但是如果把录制脚本保存为jmx格式再导入,接口都是有序的,即接口的前后顺序和录制脚本里一致。 https://www.tapd.cn/55049933/s/1392647

Signed-off-by: fit2-zhao <yong.zhao@fit2cloud.com>
This commit is contained in:
fit2-zhao 2023-07-13 10:31:28 +08:00 committed by fit2-zhao
parent 302c987207
commit c9a4138c71
3 changed files with 62 additions and 76 deletions

View File

@ -1,11 +1,12 @@
package io.metersphere.api.parse;
import com.fasterxml.jackson.databind.JsonNode;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.parse.api.ms.NodeTree;
import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.utils.JSONUtil;
import io.metersphere.commons.utils.LogUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
@ -13,9 +14,16 @@ import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public abstract class MsAbstractParser<T> extends ApiImportAbstractParser<T> {
private static final String URL = "url";
private static final String METHOD = "method";
private static final String HEADERS = "headers";
private static final String BODY = "body";
protected List<MsHTTPSamplerProxy> parseMsHTTPSamplerProxy(JSONObject testObject, String tag, boolean isSetUrl) {
JSONObject requests = testObject.optJSONObject(tag);
@ -23,8 +31,8 @@ public abstract class MsAbstractParser<T> extends ApiImportAbstractParser<T> {
if (requests != null) {
requests.keySet().forEach(requestName -> {
JSONObject requestObject = requests.optJSONObject(requestName);
String path = requestObject.optString("url");
String method = requestObject.optString("method");
String path = requestObject.optString(URL);
String method = requestObject.optString(METHOD);
MsHTTPSamplerProxy request = buildRequest(requestName, path, method);
parseBody(requestObject, request.getBody());
parseHeader(requestObject, request.getHeaders());
@ -38,6 +46,29 @@ public abstract class MsAbstractParser<T> extends ApiImportAbstractParser<T> {
return msHTTPSamplerProxies;
}
protected List<MsHTTPSamplerProxy> parseMsHTTPSamplerProxy(JsonNode requests, boolean isSetUrl) {
List<MsHTTPSamplerProxy> samplerProxies = new ArrayList<>();
Iterator<Map.Entry<String, JsonNode>> fields = requests.fields();
while (fields.hasNext()) {
Map.Entry<String, JsonNode> field = fields.next();
if (field.getValue().isNull()) {
continue;
}
JSONObject requestObject = JSONUtil.parseObject(JSON.toJSONString(field.getValue()));
String path = requestObject.optString(URL);
String method = requestObject.optString(METHOD);
MsHTTPSamplerProxy request = buildRequest(field.getKey(), path, method);
parseBody(requestObject, request.getBody());
parseHeader(requestObject, request.getHeaders());
parsePath(request);
if (isSetUrl) {
request.setUrl(path);
}
samplerProxies.add(request);
}
return samplerProxies;
}
private void parsePath(MsHTTPSamplerProxy request) {
if (StringUtils.isNotBlank(request.getPath())) {
String[] split = request.getPath().split("\\?");
@ -60,14 +91,13 @@ public abstract class MsAbstractParser<T> extends ApiImportAbstractParser<T> {
arguments.add(new KeyValue(kv[0], kv.length < 2 ? null : kv[1]));
}
} catch (UnsupportedEncodingException e) {
LogUtil.info(e.getMessage(), e);
return;
LogUtil.error(e);
}
}
}
private void parseHeader(JSONObject requestObject, List<KeyValue> msHeaders) {
JSONArray headers = requestObject.optJSONArray("headers");
JSONArray headers = requestObject.optJSONArray(HEADERS);
if (headers != null) {
for (int i = 0; i < headers.length(); i++) {
JSONObject header = headers.optJSONObject(i);
@ -77,10 +107,10 @@ public abstract class MsAbstractParser<T> extends ApiImportAbstractParser<T> {
}
private void parseBody(JSONObject requestObject, Body msBody) {
if (requestObject.has("body")) {
Object body = requestObject.get("body");
if (requestObject.has(BODY)) {
Object body = requestObject.get(BODY);
if (body instanceof JSONArray) {
JSONArray bodies = requestObject.optJSONArray("body");
JSONArray bodies = requestObject.optJSONArray(BODY);
if (bodies != null) {
StringBuilder bodyStr = new StringBuilder();
for (int i = 0; i < bodies.length(); i++) {
@ -91,7 +121,7 @@ public abstract class MsAbstractParser<T> extends ApiImportAbstractParser<T> {
msBody.setRaw(bodyStr.toString());
}
} else if (body instanceof JSONObject) {
JSONObject bodyObj = requestObject.optJSONObject("body");
JSONObject bodyObj = requestObject.optJSONObject(BODY);
if (bodyObj != null) {
ArrayList<KeyValue> kvs = new ArrayList<>();
bodyObj.keySet().forEach(key -> {
@ -103,64 +133,4 @@ public abstract class MsAbstractParser<T> extends ApiImportAbstractParser<T> {
}
}
}
/**
* 删除没有用例的节点
*
* @param nodeTree
* @param ids
* @return
*/
public void cutDownTree(List<NodeTree> nodeTree, Set<String> ids) {
Iterator<NodeTree> iterator = nodeTree.iterator();
while (iterator.hasNext()) {
NodeTree item = iterator.next();
if (cutDownTree(item, ids)) {
iterator.remove();
}
}
}
private boolean cutDownTree(NodeTree nodeTree, Set<String> ids) {
boolean delete = true;
if (ids.contains(nodeTree.getId())) {
delete = false;
}
List<NodeTree> children = nodeTree.getChildren();
if (CollectionUtils.isNotEmpty(children)) {
Iterator<NodeTree> iterator = children.iterator();
while (iterator.hasNext()) {
NodeTree item = iterator.next();
if (cutDownTree(item, ids)) {
iterator.remove();
} else {
delete = false;
}
}
}
return delete;
}
public Map<String, NodeTree> getNodeMap(List<NodeTree> nodeTree) {
Map<String, NodeTree> nodeMap = new HashMap<>();
if (CollectionUtils.isNotEmpty(nodeTree)) {
nodeTree.forEach(item -> {
getNodeMap(nodeMap, item);
});
}
return nodeMap;
}
private void getNodeMap(Map<String, NodeTree> nodeMap, NodeTree nodeTree) {
nodeMap.put(nodeTree.getId(), nodeTree);
List<NodeTree> children = nodeTree.getChildren();
if (CollectionUtils.isNotEmpty(children)) {
children.forEach(item -> {
getNodeMap(nodeMap, item);
});
}
}
}

View File

@ -1,6 +1,7 @@
package io.metersphere.api.parse.scenario;
import com.fasterxml.jackson.databind.JsonNode;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.EnvironmentType;
import io.metersphere.api.dto.definition.request.MsScenario;
@ -30,18 +31,21 @@ public class MsScenarioParser extends MsAbstractParser<ScenarioImport> {
if (StringUtils.isNotEmpty(testObject.optString("projectName")) || StringUtils.isNotEmpty(testObject.optString("projectId"))) {
return parseMsFormat(testStr, request);
} else {
JsonNode node = JSONUtil.parseNode(testStr);
ScenarioImport apiImport = new ScenarioImport();
ArrayList<ApiScenarioWithBLOBs> apiScenarioWithBLOBs = new ArrayList<>();
apiScenarioWithBLOBs.add(parsePluginFormat(testObject, request));
apiScenarioWithBLOBs.add(parsePluginFormat(node, request));
apiImport.setData(apiScenarioWithBLOBs);
return apiImport;
}
}
protected ApiScenarioWithBLOBs parsePluginFormat(JSONObject testObject, ApiTestImportRequest importRequest) {
protected ApiScenarioWithBLOBs parsePluginFormat(JsonNode testObject, ApiTestImportRequest importRequest) {
LinkedList<MsTestElement> results = new LinkedList<>();
testObject.keySet().forEach(tag -> {
results.addAll(parseMsHTTPSamplerProxy(testObject, tag, true));
testObject.forEach(node -> {
if(node != null ) {
results.addAll(parseMsHTTPSamplerProxy(node, true));
}
});
MsScenario msScenario = new MsScenario();
msScenario.setName(importRequest.getFileName());

View File

@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.StreamReadConstraints;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ArrayNode;
@ -235,6 +236,17 @@ public class JSONUtil {
}
}
public static JsonNode parseNode(String value) {
try {
if (StringUtils.isEmpty(value)) {
MSException.throwException("value is null");
}
return objectMapper.readTree(value);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static JSONArray parseArray(String text) {
List<Object> list = JSON.parseObject(text, List.class);
return new JSONArray(list);