diff --git a/api-test/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsRetryLoopController.java b/api-test/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsRetryLoopController.java new file mode 100644 index 0000000000..f40221243d --- /dev/null +++ b/api-test/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsRetryLoopController.java @@ -0,0 +1,72 @@ +package io.metersphere.api.dto.definition.request.controller; + +import io.metersphere.plugin.core.MsParameter; +import io.metersphere.plugin.core.MsTestElement; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.jmeter.control.WhileController; +import org.apache.jmeter.save.SaveService; +import org.apache.jmeter.testelement.TestElement; +import org.apache.jmeter.visualizers.JSR223Listener; +import org.apache.jorphan.collections.HashTree; + +import java.util.List; +import java.util.UUID; + +@Data +@EqualsAndHashCode(callSuper = true) +public class MsRetryLoopController extends MsTestElement { + private String type = "RetryLoopController"; + private String clazzName = MsRetryLoopController.class.getCanonicalName(); + + private long retryNum; + + private String ms_current_timer = UUID.randomUUID().toString(); + + @Override + public void toHashTree(HashTree tree, List hashTree, MsParameter msParameter) { + final HashTree groupTree = controller(tree); + + if (CollectionUtils.isNotEmpty(hashTree)) { + hashTree.forEach(el -> { + // 给所有孩子加一个父亲标志 + el.setParent(this); + el.toHashTree(groupTree, el.getHashTree(), msParameter); + }); + } + } + + private WhileController initWhileController(String condition) { + if (StringUtils.isEmpty(condition)) { + return null; + } + WhileController controller = new WhileController(); + controller.setEnabled(this.isEnable()); + controller.setName("WhileController"); + controller.setProperty(TestElement.TEST_CLASS, WhileController.class.getName()); + controller.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("WhileControllerGui")); + controller.setCondition(condition); + return controller; + } + + private String script() { + String script = "// 失败重试控制\n" + "try{\n" + "\tint errorCount = prev.getErrorCount();\n" + "\tif(errorCount == 0 && prev.getFirstAssertionFailureMessage() == null ){\n" + "\t vars.put(\"" + ms_current_timer + "\", \"stop\");\n" + "\t}\n" + "\tif(vars.get(\"" + ms_current_timer + "_num\") == null){\n" + "\t\tvars.put(\"" + ms_current_timer + "_num\", \"0\");\n" + "\t}else{\n" + "\t\tint retryNum= Integer.parseInt(vars.get(\"" + ms_current_timer + "_num\"));\n" + "\t\tlog.info(\"重试:\"+ retryNum);\n" + " \tprev.setSampleLabel(\"MsRetry_\"+ (retryNum + 1) + \"_\" + prev.getSampleLabel());\n" + "\t\tretryNum =retryNum +1;\n" + "\t\tvars.put(\"" + ms_current_timer + "_num\",retryNum + \"\");\n" + "\t}\n" + "\tif(vars.get(\"" + ms_current_timer + "_num\").equals( \"" + retryNum + "\")){\n" + "\t\tvars.put(\"" + ms_current_timer + "\", \"stop\");\n" + "\t}\n" + "}catch (Exception e){\n" + "\tvars.put(\"" + ms_current_timer + "\", \"stop\");\n" + "}\n"; + return script; + } + + private HashTree controller(HashTree tree) { + String whileCondition = "${__jexl3(" + "\"${" + ms_current_timer + "}\" !=\"stop\")}"; + HashTree hashTree = tree.add(initWhileController(whileCondition)); + // 添加超时处理,防止死循环 + JSR223Listener postProcessor = new JSR223Listener(); + postProcessor.setName("Retry-controller"); + postProcessor.setProperty(TestElement.TEST_CLASS, JSR223Listener.class.getName()); + postProcessor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI")); + postProcessor.setProperty("scriptLanguage", "beanshell"); + postProcessor.setProperty("script", script()); + hashTree.add(postProcessor); + return hashTree; + } +} diff --git a/api-test/backend/src/main/java/io/metersphere/api/exec/api/ApiCaseSerialService.java b/api-test/backend/src/main/java/io/metersphere/api/exec/api/ApiCaseSerialService.java index 2e60fc0f9b..353c383e3b 100644 --- a/api-test/backend/src/main/java/io/metersphere/api/exec/api/ApiCaseSerialService.java +++ b/api-test/backend/src/main/java/io/metersphere/api/exec/api/ApiCaseSerialService.java @@ -34,7 +34,7 @@ import io.metersphere.plugin.core.MsTestElement; import io.metersphere.service.ApiExecutionQueueService; import io.metersphere.service.RemakeReportService; import io.metersphere.utils.LoggerUtil; -import io.metersphere.xpack.api.service.ApiRetryOnFailureService; +import io.metersphere.service.ApiRetryOnFailureService; import org.apache.commons.lang3.StringUtils; import org.apache.jorphan.collections.HashTree; import org.json.JSONObject; @@ -59,6 +59,8 @@ public class ApiCaseSerialService { private RedisTemplate redisTemplate; @Resource private TestPlanApiCaseMapper testPlanApiCaseMapper; + @Resource + private ApiRetryOnFailureService apiRetryOnFailureService; public void serial(DBTestQueue executionQueue) { ApiExecutionQueueDetail queue = executionQueue.getDetail(); @@ -154,7 +156,6 @@ public class ApiCaseSerialService { String data = element.toString(); if (runRequest.isRetryEnable() && runRequest.getRetryNum() > 0) { // 失败重试 - ApiRetryOnFailureService apiRetryOnFailureService = CommonBeanFactory.getBean(ApiRetryOnFailureService.class); String retryData = apiRetryOnFailureService.retry(data, runRequest.getRetryNum(), true); data = StringUtils.isNotEmpty(retryData) ? retryData : data; // 格式化数据 diff --git a/api-test/backend/src/main/java/io/metersphere/commons/utils/GenerateHashTreeUtil.java b/api-test/backend/src/main/java/io/metersphere/commons/utils/GenerateHashTreeUtil.java index 7ddb0af5c1..4dd18ae99f 100644 --- a/api-test/backend/src/main/java/io/metersphere/commons/utils/GenerateHashTreeUtil.java +++ b/api-test/backend/src/main/java/io/metersphere/commons/utils/GenerateHashTreeUtil.java @@ -23,7 +23,7 @@ import io.metersphere.service.ApiExecutionQueueService; import io.metersphere.service.RemakeReportService; import io.metersphere.utils.LoggerUtil; import io.metersphere.vo.BooleanPool; -import io.metersphere.xpack.api.service.ApiRetryOnFailureService; +import io.metersphere.service.ApiRetryOnFailureService; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.jorphan.collections.HashTree; diff --git a/api-test/backend/src/main/java/io/metersphere/controller/TestDataController.java b/api-test/backend/src/main/java/io/metersphere/controller/TestDataController.java new file mode 100644 index 0000000000..3414fb15e8 --- /dev/null +++ b/api-test/backend/src/main/java/io/metersphere/controller/TestDataController.java @@ -0,0 +1,17 @@ +package io.metersphere.controller; + +import io.metersphere.service.TestDataGenerator; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + + +@RestController +@RequestMapping(value = "/api/test/data") +public class TestDataController { + @PostMapping("/generator") + public String preview(@RequestBody String jsonSchema) { + return TestDataGenerator.generator(jsonSchema); + } +} diff --git a/api-test/backend/src/main/java/io/metersphere/service/ApiRetryOnFailureService.java b/api-test/backend/src/main/java/io/metersphere/service/ApiRetryOnFailureService.java new file mode 100644 index 0000000000..d735975c23 --- /dev/null +++ b/api-test/backend/src/main/java/io/metersphere/service/ApiRetryOnFailureService.java @@ -0,0 +1,90 @@ +package io.metersphere.service; + +import io.metersphere.api.dto.definition.request.controller.MsRetryLoopController; +import io.metersphere.commons.utils.JSON; +import io.metersphere.commons.utils.JSONUtil; +import io.metersphere.commons.utils.LogUtil; +import io.metersphere.plugin.core.MsTestElement; +import org.apache.commons.lang3.StringUtils; +import org.json.JSONArray; +import org.json.JSONObject; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.UUID; + +@Service +public class ApiRetryOnFailureService { + public final static List requests = List.of( + "HTTPSamplerProxy", + "DubboSampler", + "JDBCSampler", + "TCPSampler", + "JSR223Processor"); + + private final static String HASH_TREE_ELEMENT = "hashTree"; + private final static String TYPE = "type"; + private final static String RESOURCE_ID = "resourceId"; + private final static String RETRY = "MsRetry_"; + private final static String LOOP = "LoopController"; + + public String retry(String data, long retryNum, boolean isCase) { + if (StringUtils.isNotEmpty(data)) { + JSONObject element = JSONUtil.parseObject(data); + if (element != null && isCase) { + return formatSampler(element, retryNum).toString(); + } + if (element != null && element.has(HASH_TREE_ELEMENT) && !StringUtils.equalsIgnoreCase(element.optString(TYPE), LOOP)) { + JSONArray hashTree = element.getJSONArray(HASH_TREE_ELEMENT); + setRetry(hashTree, retryNum); + } + return element.toString(); + } + return null; + } + + public MsTestElement retryParse(String data) { + try { + MsRetryLoopController controller = JSON.parseObject(data, MsRetryLoopController.class); + return controller; + } catch (Exception e) { + LogUtil.error(e); + } + return null; + } + + public void setRetry(JSONArray hashTree, long retryNum) { + for (int i = 0; i < hashTree.length(); i++) { + JSONObject element = hashTree.getJSONObject(i); + if (StringUtils.equalsIgnoreCase(element.optString(TYPE), LOOP)) { + continue; + } + JSONObject whileObj = formatSampler(element, retryNum); + if (whileObj != null) { + hashTree.put(i, whileObj); + } else if (element.has(HASH_TREE_ELEMENT)) { + JSONArray elementJSONArray = element.getJSONArray(HASH_TREE_ELEMENT); + setRetry(elementJSONArray, retryNum); + } + } + } + + private JSONObject formatSampler(JSONObject element, long retryNum) { + if (element.has(TYPE) && requests.contains(element.optString(TYPE))) { + MsRetryLoopController loopController = new MsRetryLoopController(); + loopController.setClazzName(MsRetryLoopController.class.getCanonicalName()); + loopController.setName(RETRY + element.optString(RESOURCE_ID)); + loopController.setRetryNum(retryNum); + loopController.setEnable(true); + loopController.setResourceId(UUID.randomUUID().toString()); + + JSONObject whileObj = JSONUtil.parseObject(JSON.toJSONString(loopController)); + JSONArray hashTree = new JSONArray(); + hashTree.put(element); + + whileObj.put(HASH_TREE_ELEMENT, hashTree); + return whileObj; + } + return null; + } +} diff --git a/api-test/backend/src/main/java/io/metersphere/service/MsHashTreeService.java b/api-test/backend/src/main/java/io/metersphere/service/MsHashTreeService.java index 7a0ac16be9..cf6e73052e 100644 --- a/api-test/backend/src/main/java/io/metersphere/service/MsHashTreeService.java +++ b/api-test/backend/src/main/java/io/metersphere/service/MsHashTreeService.java @@ -201,7 +201,7 @@ public class MsHashTreeService { private JSONObject setRefScenario(JSONObject element) { boolean enable = element.has(ENABLE) ? element.optBoolean(ENABLE) : true; if (!element.has(MIX_ENABLE)) { - element.put(MIX_ENABLE, true); + element.put(MIX_ENABLE, false); } ApiScenarioDTO scenarioWithBLOBs = extApiScenarioMapper.selectById(element.optString(ID)); @@ -209,7 +209,7 @@ public class MsHashTreeService { boolean environmentEnable = element.has(ENV_ENABLE) ? element.optBoolean(ENV_ENABLE) : false; boolean variableEnable = element.has(VARIABLE_ENABLE) ? element.optBoolean(VARIABLE_ENABLE) : false; boolean mixEnable = element.has(MIX_ENABLE) - ? element.getBoolean(MIX_ENABLE) : true; + ? element.getBoolean(MIX_ENABLE) : false; if (environmentEnable && StringUtils.isNotEmpty(scenarioWithBLOBs.getEnvironmentJson())) { element.put(ENV_MAP, JSON.parseObject(scenarioWithBLOBs.getEnvironmentJson(), Map.class)); diff --git a/api-test/backend/src/main/java/io/metersphere/service/TestDataGenerator.java b/api-test/backend/src/main/java/io/metersphere/service/TestDataGenerator.java new file mode 100644 index 0000000000..c4f6de99b7 --- /dev/null +++ b/api-test/backend/src/main/java/io/metersphere/service/TestDataGenerator.java @@ -0,0 +1,345 @@ +package io.metersphere.service; + +import com.apifan.common.random.source.DateTimeSource; +import com.apifan.common.random.source.InternetSource; +import com.apifan.common.random.source.NumberSource; +import com.google.gson.*; +import com.mifmif.common.regex.Generex; +import io.metersphere.jmeter.utils.ScriptEngineUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.StringUtils; +import org.json.JSONObject; + +import java.time.LocalDate; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 生成测试数据 + */ +public class TestDataGenerator { + private static final String TYPE = "type"; + private static final String ALL_OF = "allOf"; + private static final String DEFINITIONS = "definitions"; + private static final String PROPERTIES = "properties"; + private static final String ARRAY = "array"; + private static final String OBJECT = "object"; + private static final String MS_OBJECT = "MS-OBJECT"; + private static final String ITEMS = "items"; + private static final String ENUM = "enum"; + private static final String STRING = "string"; + private static final String DEFAULT = "default"; + private static final String MOCK = "mock"; + private static final String MAXLENGTH = "maxLength"; + private static final String MINLENGTH = "minLength"; + private static final String FORMAT = "format"; + private static final String PATTERN = "pattern"; + private static final String INTEGER = "integer"; + private static final String NUMBER = "number"; + private static final String BOOLEAN = "boolean"; + private static final String MINIMUM = "minimum"; + private static final String MAXIMUM = "maximum"; + + public static void analyzeSchema(String json, JSONObject rootObj) { + Gson gson = new Gson(); + JsonElement element = gson.fromJson(json, JsonElement.class); + JsonObject rootElement = element.getAsJsonObject(); + analyzeRootSchemaElement(rootElement, rootObj); + } + + public static void analyzeRootSchemaElement(JsonObject rootElement, JSONObject rootObj) { + if ((rootElement.has(TYPE) || rootElement.has(ALL_OF)) && rootElement != null) { + analyzeObject(rootElement, rootObj); + } + if (rootElement.has(DEFINITIONS)) { + analyzeDefinitions(rootElement); + } + } + + public static void analyzeObject(JsonObject object, JSONObject rootObj) { + if (object.has(ALL_OF)) { + for (JsonElement el : object.get(ALL_OF).getAsJsonArray()) { + JsonObject elObj = el.getAsJsonObject(); + if (elObj.has(PROPERTIES)) { + analyzeProperties(rootObj, elObj); + } + } + } else if (object.has(PROPERTIES)) { + analyzeProperties(rootObj, object); + } else if (object.has(TYPE) && object.get(TYPE).getAsString().equals(ARRAY)) { + analyzeProperty(rootObj, MS_OBJECT, object); + } else if (object.has(TYPE) && !object.get(TYPE).getAsString().equals(OBJECT)) { + analyzeProperty(rootObj, object.getAsString(), object); + } + } + + private static void analyzeProperties(JSONObject rootObj, JsonObject allOfElementObj) { + JsonObject propertiesObj = allOfElementObj.get(PROPERTIES).getAsJsonObject(); + for (Entry entry : propertiesObj.entrySet()) { + String propertyKey = entry.getKey(); + JsonObject propertyObj = propertiesObj.get(propertyKey).getAsJsonObject(); + analyzeProperty(rootObj, propertyKey, propertyObj); + } + } + + public static void analyzeItems(JSONObject concept, String propertyName, JsonObject object) { + // 先设置空值 + List array = new LinkedList<>(); + JsonArray jsonArray = new JsonArray(); + if (object.has(ITEMS) && object.get(ITEMS).isJsonArray()) { + jsonArray = object.get(ITEMS).getAsJsonArray(); + } else { + JsonObject itemsObject = object.get(ITEMS).getAsJsonObject(); + array.add(itemsObject); + } + + for (JsonElement element : jsonArray) { + JsonObject itemsObject = element.getAsJsonObject(); + if (object.has(ITEMS)) { + if (itemsObject.has(ENUM)) { + array.add(analyzeEnumProperty(itemsObject)); + } else if (itemsObject.has(TYPE) && itemsObject.get(TYPE).getAsString().equals(STRING)) { + array.add(analyzeString(itemsObject)); + } else if (itemsObject.has(PROPERTIES)) { + JSONObject propertyConcept = new JSONObject(); + analyzeProperties(propertyConcept, itemsObject); + array.add(propertyConcept); + } else if (itemsObject.has(TYPE) && itemsObject.get(TYPE) instanceof JsonPrimitive) { + JSONObject newJsonObj = new JSONObject(); + analyzeProperty(newJsonObj, propertyName + "_item", itemsObject); + array.add(newJsonObj.get(propertyName + "_item")); + } + } else if (object.has(ITEMS) && object.get(ITEMS).isJsonArray()) { + JsonArray itemsObjectArray = object.get(ITEMS).getAsJsonArray(); + array.add(itemsObjectArray); + } + } + concept.put(propertyName, array); + } + + public static String getMockValue(JsonObject object) { + if (object.has(MOCK) + && object.get(MOCK).getAsJsonObject() != null + && object.get(MOCK).getAsJsonObject().get(MOCK) != null + && StringUtils.isNotBlank(object.get(MOCK).getAsJsonObject().get(MOCK).getAsString())) { + if (StringUtils.startsWithAny(object.get(MOCK).getAsJsonObject().get(MOCK).getAsString(), "@", "${")) { + return ScriptEngineUtils.calculate(object.get(MOCK).getAsJsonObject().get(MOCK).getAsString()); + } + } + return null; + } + + public static String analyzeString(JsonObject object) { + // 先设置空值 + if (object.has(DEFAULT)) { + return object.get(DEFAULT).getAsString(); + } + Object mockValue = getMockValue(object); + if (mockValue != null) { + return mockValue.toString(); + } + int maxLength = 9; + if (object.has(MAXLENGTH)) { + maxLength = object.get(MAXLENGTH).getAsInt(); + } + int minLength = 0; + if (object.has(MINLENGTH)) { + minLength = object.get(MINLENGTH).getAsInt(); + } + String value = RandomStringUtils.randomAlphanumeric(minLength, maxLength); + Object enumObj = analyzeEnumProperty(object); + String v = enumObj == null ? "" : String.valueOf(enumObj); + value = StringUtils.isNotBlank(v) ? v : value; + try { + if (object.has(FORMAT)) { + String propertyFormat = object.get(FORMAT).getAsString(); + switch (propertyFormat) { + case "date-time": + value = DateTimeSource.getInstance().randomTimestamp(LocalDate.now()) + ""; + break; + case "date": + value = DateTimeSource.getInstance().randomDate(LocalDate.now().getYear(), "yyyy-MM-dd"); + break; + case "email": + value = InternetSource.getInstance().randomEmail(maxLength); + break; + case "hostname": + value = InternetSource.getInstance().randomDomain(maxLength); + break; + case "ipv4": + value = InternetSource.getInstance().randomPublicIpv4(); + break; + case "ipv6": + value = InternetSource.getInstance().randomIpV6(); + break; + case "uri": + value = InternetSource.getInstance().randomStaticUrl("jpg"); + break; + } + } + if (object.has(PATTERN)) { + String pattern = object.get(PATTERN).getAsString(); + if (StringUtils.isNotEmpty(pattern)) { + Generex generex = new Generex(pattern); + value = generex.random(); + } + } + return value; + } catch (Exception e) { + return value; + } + } + + public static boolean isNumber(Object obj) { + if (ObjectUtils.isEmpty(obj)) { + return false; + } + Pattern pattern = Pattern.compile("-?[0-9]+\\.?[0-9]*"); + Matcher isNum = pattern.matcher(obj.toString()); + if (!isNum.matches()) { + return false; + } + return true; + } + + public static Object analyzeInteger(JsonObject object) { + // 先设置空值 + if (object.has(DEFAULT) && isNumber(object.get(DEFAULT))) { + return object.get(DEFAULT).getAsInt(); + } + Object mockValue = getMockValue(object); + if (mockValue != null && isNumber(mockValue)) { + return Integer.parseInt(mockValue.toString()); + } + int minimum = 1; + int maximum = 101; + if (object.has(MINIMUM)) { + minimum = object.get(MINIMUM).getAsInt() < 0 ? 0 : object.get(MINIMUM).getAsInt(); + } + if (object.has(MAXIMUM)) { + maximum = object.get(MAXIMUM).getAsInt(); + } + return NumberSource.getInstance().randomInt(minimum, maximum); + } + + public static Object analyzeNumber(JsonObject object) { + if (object != null && object.has(DEFAULT) && isNumber(object.has(DEFAULT))) { + return object.get(DEFAULT).getAsFloat(); + } + Object mockValue = getMockValue(object); + if (mockValue != null && isNumber(mockValue)) { + return Float.parseFloat(mockValue.toString()); + } + float maximum = 200001.0f; + float minimum = 100000.0f; + if (object.has(MINIMUM)) { + float min = object.get(MINIMUM).getAsFloat(); + minimum = min < 0 ? 0 : min; + } + if (object.has(MAXIMUM)) { + float max = object.get(MAXIMUM).getAsFloat(); + maximum = max > 0 ? max : maximum; + } + return NumberSource.getInstance().randomDouble(minimum, maximum); + } + + public static boolean getRandomBoolean() { + return Math.random() < 0.5; + } + + public static Boolean analyzeBoolean(JsonObject object) { + if (object.has(DEFAULT)) { + return object.get(DEFAULT).getAsBoolean(); + } + return getRandomBoolean(); + } + + public static void analyzeProperty(JSONObject concept, String propertyName, JsonObject object) { + if (object != null && object.has(TYPE)) { + String propertyObjType = getPropertyObjType(object); + if (object.has(DEFAULT)) { + concept.put(propertyName, object.get(DEFAULT).getAsString()); + } else if (object.has(ENUM)) { + concept.put(propertyName, analyzeEnumProperty(object)); + } else if (propertyObjType.equals(STRING)) { + concept.put(propertyName, analyzeString(object)); + } else if (propertyObjType.equals(INTEGER)) { + concept.put(propertyName, analyzeInteger(object)); + } else if (propertyObjType.equals(NUMBER)) { + concept.put(propertyName, analyzeNumber(object)); + } else if (propertyObjType.equals(BOOLEAN)) { + concept.put(propertyName, analyzeBoolean(object)); + } else if (propertyObjType.equals(ARRAY)) { + analyzeItems(concept, propertyName, object); + } else if (propertyObjType.equals(OBJECT)) { + JSONObject obj = new JSONObject(); + concept.put(propertyName, obj); + analyzeObject(object, obj); + } + } + } + + public static String getPropertyObjType(JsonObject object) { + if (object.get(TYPE) != null && object.get(TYPE) instanceof JsonPrimitive) { + return object.get(TYPE).getAsString(); + } else if (object.get(TYPE) instanceof JsonArray) { + JsonArray typeArray = object.get(TYPE).getAsJsonArray(); + return typeArray.get(0).getAsString(); + } + return null; + } + + public static Object analyzeEnumProperty(JsonObject object) { + Object enumValue = ""; + try { + if (object.get(ENUM) != null) { + String enums = object.get(ENUM).getAsString(); + if (StringUtils.isNotBlank(enums)) { + String enumArr[] = enums.split("\n"); + int index = (int) (Math.random() * enumArr.length); + enumValue = enumArr[index]; + } + } + String propertyObjType = getPropertyObjType(object); + if (propertyObjType.equals(INTEGER)) { + enumValue = Integer.parseInt(enumValue.toString()); + } else if (propertyObjType.equals(NUMBER)) { + enumValue = Float.parseFloat(enumValue.toString()); + } + } catch (Exception e) { + return enumValue; + } + return enumValue; + } + + public static void analyzeDefinitions(JsonObject object) { + JsonObject definitionsObj = object.get(DEFINITIONS).getAsJsonObject(); + for (Entry entry : definitionsObj.entrySet()) { + String definitionKey = entry.getKey(); + JsonObject definitionObj = definitionsObj.get(definitionKey).getAsJsonObject(); + JSONObject obj = new JSONObject(); + analyzeRootSchemaElement(definitionObj, obj); + } + } + + public static String generator(String jsonSchema) { + try { + if (StringUtils.isEmpty(jsonSchema)) { + return null; + } + JSONObject root = new JSONObject(); + analyzeSchema(jsonSchema, root); + // 格式化返回 + if (root != null && root.has(MS_OBJECT)) { + return root.get(MS_OBJECT).toString(); + } + return root.toString(); + } catch (Exception ex) { + return jsonSchema; + } + } +} diff --git a/api-test/frontend/src/business/automation/report/ApiReportViewHeader.vue b/api-test/frontend/src/business/automation/report/ApiReportViewHeader.vue index 4ab15528ee..5e712ea031 100644 --- a/api-test/frontend/src/business/automation/report/ApiReportViewHeader.vue +++ b/api-test/frontend/src/business/automation/report/ApiReportViewHeader.vue @@ -118,7 +118,6 @@ import {apiProjectByScenarioId, getProjectApplicationConfig} from '../../../api/ import { apiTestReRun } from '../../../api/xpack'; import { getUUID } from 'metersphere-frontend/src/utils'; import { getApiScenarioIdByPlanScenarioId } from '@/api/test-plan'; -import {getScenarioReport} from '../../../api/scenario-report'; export default { name: 'MsApiReportViewHeader', diff --git a/api-test/frontend/src/business/definition/components/debug/DebugHttpPage.vue b/api-test/frontend/src/business/definition/components/debug/DebugHttpPage.vue index 8a3dab46fb..b4a4d06d59 100644 --- a/api-test/frontend/src/business/definition/components/debug/DebugHttpPage.vue +++ b/api-test/frontend/src/business/definition/components/debug/DebugHttpPage.vue @@ -47,7 +47,7 @@ @click.stop @click="generate" style="margin-left: 10px" - v-if="hasPermission('PROJECT_API_DEFINITION:READ+CREATE_API') && hasLicense()"> + v-if="hasPermission('PROJECT_API_DEFINITION:READ+CREATE_API')"> {{ $t('commons.generate_test_data') }} diff --git a/api-test/frontend/src/business/definition/components/mock/Components/MockRequestParam.vue b/api-test/frontend/src/business/definition/components/mock/Components/MockRequestParam.vue index bbb1df8df3..393732d4b6 100644 --- a/api-test/frontend/src/business/definition/components/mock/Components/MockRequestParam.vue +++ b/api-test/frontend/src/business/definition/components/mock/Components/MockRequestParam.vue @@ -111,9 +111,7 @@ :headers="request.headers" :body="request.body" /> - +