diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionController.java b/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionController.java index e6f86102d2..6394fd7e8d 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionController.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionController.java @@ -15,12 +15,10 @@ import io.metersphere.api.service.definition.ApiDefinitionImportService; import io.metersphere.api.service.definition.ApiDefinitionLogService; import io.metersphere.api.service.definition.ApiDefinitionNoticeService; import io.metersphere.api.service.definition.ApiDefinitionService; -import io.metersphere.api.utils.JsonSchemaBuilder; import io.metersphere.project.service.FileModuleService; import io.metersphere.sdk.constants.DefaultRepositoryDir; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.dto.api.task.TaskRequestDTO; -import io.metersphere.sdk.util.JSON; import io.metersphere.system.dto.OperationHistoryDTO; import io.metersphere.system.dto.request.OperationHistoryRequest; import io.metersphere.system.dto.request.OperationHistoryVersionRequest; @@ -284,7 +282,7 @@ public class ApiDefinitionController { @Operation(summary = "接口测试-接口管理-接口-json-schema-预览") @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ) public String preview(@RequestBody JsonSchemaItem jsonSchemaItem) { - return JsonSchemaBuilder.preview(JSON.toJSONString(jsonSchemaItem)); + return apiDefinitionService.preview(jsonSchemaItem); } @PostMapping("/debug") diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/request/http/body/JsonBody.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/request/http/body/JsonBody.java index e75b3d40cf..7e2de71c76 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/request/http/body/JsonBody.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/request/http/body/JsonBody.java @@ -11,6 +11,11 @@ import lombok.Data; */ @Data public class JsonBody { + /** + * 是否 json-schema + * 默认false + */ + private Boolean enableJsonSchema = false; /** * json 参数值 */ diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java index 74e7516d22..878a99ad21 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java @@ -11,12 +11,15 @@ import io.metersphere.api.dto.debug.ApiResourceRunRequest; import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.request.ApiEditPosRequest; import io.metersphere.api.dto.request.ApiTransferRequest; +import io.metersphere.api.dto.schema.JsonSchemaItem; import io.metersphere.api.mapper.*; import io.metersphere.api.service.ApiCommonService; import io.metersphere.api.service.ApiExecuteService; import io.metersphere.api.service.ApiFileResourceService; import io.metersphere.api.utils.ApiDataUtils; +import io.metersphere.api.utils.JsonSchemaBuilder; import io.metersphere.plugin.api.spi.AbstractMsTestElement; +import io.metersphere.project.constants.PropertyConstant; import io.metersphere.project.domain.FileAssociation; import io.metersphere.project.domain.FileMetadata; import io.metersphere.project.dto.MoveNodeSortDTO; @@ -51,6 +54,7 @@ import io.metersphere.system.utils.CustomFieldUtils; import io.metersphere.system.utils.ServiceUtils; import jakarta.annotation.Resource; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.SqlSession; @@ -1184,4 +1188,57 @@ public class ApiDefinitionService extends MoveNodeService { public List getReference(ReferenceRequest request) { return extApiDefinitionMapper.getReference(request); } + + public String preview(JsonSchemaItem jsonSchemaItem) { + if (BooleanUtils.isFalse(jsonSchemaItem.getEnable())) { + return "{}"; + } + filterDisableItem(jsonSchemaItem); + return JsonSchemaBuilder.preview(JSON.toJSONString(jsonSchemaItem)); + } + + private void filterDisableItem(JsonSchemaItem jsonSchemaItem) { + if (isObjectItem(jsonSchemaItem)) { + Map properties = jsonSchemaItem.getProperties(); + if (properties != null) { + Iterator iterator = properties.keySet().iterator(); + while (iterator.hasNext()) { + String key = iterator.next(); + JsonSchemaItem item = properties.get(key); + if (item == null) { + continue; + } + if (BooleanUtils.isFalse(item.getEnable())) { + iterator.remove(); + } else if (isObjectItem(jsonSchemaItem) || isArrayItem(jsonSchemaItem)) { + filterDisableItem(item); + } + } + } + } else if (isArrayItem(jsonSchemaItem)) { + List items = jsonSchemaItem.getItems(); + if (items != null) { + Iterator iterator = items.iterator(); + while (iterator.hasNext()) { + JsonSchemaItem item = iterator.next(); + if (item == null) { + continue; + } + if (BooleanUtils.isFalse(item.getEnable())) { + iterator.remove(); + } else if (isObjectItem(jsonSchemaItem) || isArrayItem(jsonSchemaItem)){ + filterDisableItem(item); + } + } + } + } + } + + private boolean isArrayItem(JsonSchemaItem jsonSchemaItem) { + return StringUtils.equals(jsonSchemaItem.getType(), PropertyConstant.ARRAY); + } + + private boolean isObjectItem(JsonSchemaItem jsonSchemaItem) { + return StringUtils.equals(jsonSchemaItem.getType(), PropertyConstant.OBJECT); + } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/utils/JsonSchemaBuilder.java b/backend/services/api-test/src/main/java/io/metersphere/api/utils/JsonSchemaBuilder.java index babacac9ba..05d0dbcbc4 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/utils/JsonSchemaBuilder.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/utils/JsonSchemaBuilder.java @@ -4,11 +4,11 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.*; import io.metersphere.jmeter.mock.Mock; import io.metersphere.project.constants.PropertyConstant; -import io.metersphere.sdk.util.LogUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; +import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; @@ -17,23 +17,18 @@ import java.util.regex.Pattern; public class JsonSchemaBuilder { public static String jsonSchemaToJson(String jsonSchemaString) { - try { - // 解析 JSON Schema 字符串为 JsonNode - JsonNode jsonSchemaNode = ApiDataUtils.readTree(jsonSchemaString); - Map processMap = new HashMap<>(); - // 生成符合 JSON Schema 的 JSON - JsonNode jsonNode = generateJson(jsonSchemaNode, processMap); - String jsonString = ApiDataUtils.writerWithDefaultPrettyPrinter(jsonNode); - if (MapUtils.isNotEmpty(processMap)) { - for (String str : processMap.keySet()) { - jsonString = jsonString.replace(str, processMap.get(str)); - } + // 解析 JSON Schema 字符串为 JsonNode + JsonNode jsonSchemaNode = ApiDataUtils.readTree(jsonSchemaString); + Map processMap = new HashMap<>(); + // 生成符合 JSON Schema 的 JSON + JsonNode jsonNode = generateJson(jsonSchemaNode, processMap); + String jsonString = ApiDataUtils.writerWithDefaultPrettyPrinter(jsonNode); + if (MapUtils.isNotEmpty(processMap)) { + for (String str : processMap.keySet()) { + jsonString = jsonString.replace(str, processMap.get(str)); } - return jsonString; - } catch (Exception exception) { - LogUtils.error("jsonSchemaToJson error", exception); - return jsonSchemaString; } + return jsonString; } private static JsonNode generateJson(JsonNode jsonSchemaNode, Map processMap) { @@ -42,7 +37,7 @@ public class JsonSchemaBuilder { if (jsonSchemaNode instanceof NullNode) { return NullNode.getInstance(); } - String type = jsonSchemaNode.get(PropertyConstant.TYPE).asText(); + String type = jsonSchemaNode.get(PropertyConstant.TYPE) == null ? StringUtils.EMPTY : jsonSchemaNode.get(PropertyConstant.TYPE).asText(); if (StringUtils.equals(type, PropertyConstant.OBJECT)) { JsonNode propertiesNode = jsonSchemaNode.get(PropertyConstant.PROPERTIES); // 遍历 properties @@ -57,10 +52,10 @@ public class JsonSchemaBuilder { }); } } else if (StringUtils.equals(type, PropertyConstant.ARRAY)) { - JsonNode itemsNode = jsonSchemaNode.get(PropertyConstant.ITEMS); - if (itemsNode != null) { + JsonNode items = jsonSchemaNode.get(PropertyConstant.ITEMS); + if (items != null) { ArrayNode arrayNode = new ArrayNode(JsonNodeFactory.instance); - arrayNode.add(generateValue(null, itemsNode, processMap)); + items.forEach(item -> arrayNode.add(generateValue(null, item, processMap))); return arrayNode; } } @@ -72,8 +67,8 @@ public class JsonSchemaBuilder { if (propertyNode instanceof NullNode) { return NullNode.getInstance(); } - String type = propertyNode.get(PropertyConstant.TYPE).asText(); - String value = propertyNode.get(PropertyConstant.EXAMPLE).asText(); + String type = propertyNode.get(PropertyConstant.TYPE) == null ? StringUtils.EMPTY : propertyNode.get(PropertyConstant.TYPE).asText(); + String value = propertyNode.get(PropertyConstant.EXAMPLE) == null ? StringUtils.EMPTY : propertyNode.get(PropertyConstant.EXAMPLE).asText(); return switch (type) { case PropertyConstant.STRING -> new TextNode(!StringUtils.equals(value, PropertyConstant.NULL) ? value : "string"); @@ -88,7 +83,11 @@ public class JsonSchemaBuilder { if (isVariable(value)) { yield getJsonNodes(propertyName, processMap, value); } else { - yield new DecimalNode(propertyNode.get(PropertyConstant.EXAMPLE).decimalValue()); + try { + yield new DecimalNode(new BigDecimal(propertyNode.get(PropertyConstant.EXAMPLE).asText())); + } catch (Exception e) { + yield new DecimalNode(propertyNode.get(PropertyConstant.EXAMPLE).decimalValue()); + } } } case PropertyConstant.BOOLEAN -> { @@ -102,9 +101,9 @@ public class JsonSchemaBuilder { case PropertyConstant.OBJECT -> generateJson(propertyNode, processMap); case PropertyConstant.ARRAY -> { ArrayNode arrayNode = new ArrayNode(JsonNodeFactory.instance); - JsonNode itemsNode = propertyNode.get(PropertyConstant.ITEMS); - if (itemsNode != null) { - arrayNode.add(generateValue(null, itemsNode, processMap)); + JsonNode items = propertyNode.get(PropertyConstant.ITEMS); + if (items != null) { + items.forEach(item -> arrayNode.add(generateValue(null, item, processMap))); } yield arrayNode; } diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java index 552505358c..4d8e8d5ac0 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java @@ -13,6 +13,7 @@ import io.metersphere.api.dto.request.ApiEditPosRequest; import io.metersphere.api.dto.request.ApiTransferRequest; import io.metersphere.api.dto.request.ImportRequest; import io.metersphere.api.dto.request.http.MsHTTPElement; +import io.metersphere.api.dto.schema.JsonSchemaItem; import io.metersphere.api.mapper.*; import io.metersphere.api.model.CheckLogModel; import io.metersphere.api.service.ApiCommonService; @@ -1712,541 +1713,69 @@ public class ApiDefinitionControllerTests extends BaseTest { @Order(103) public void testPreview() throws Exception { String jsonString = """ - { - "example": null, - "id": null, - "title": null, - "type": "object", - "description": null, - "items": null, - "properties": { - "id": { - "example": 10, - "id": null, - "title": null, - "type": "integer", - "description": "", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": "int64", - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "name": { - "example": "@string", - "id": null, - "title": null, - "type": "string", - "description": "", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": "", - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "category": { - "example": null, - "id": null, - "title": null, - "type": "object", - "description": null, - "items": null, - "properties": { - "id": { - "example": "@integer", - "id": null, - "title": null, - "type": "integer", - "description": "", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": "int64", - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "name": { - "example": "Dogs", - "id": null, - "title": null, - "type": "string", - "description": "", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": "", - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - } - }, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": null, - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "photoUrls": { - "example": null, - "id": null, - "title": null, - "type": "array", - "description": null, - "items": { - "example": null, - "id": null, - "title": null, - "type": "string", - "description": "", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": "", - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": null, - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "tags": { - "example": null, - "id": null, - "title": null, - "type": "array", - "description": null, - "items": { - "example": null, - "id": null, - "title": null, - "type": "object", - "description": null, - "items": null, - "properties": { - "id": { - "example": null, - "id": null, - "title": null, - "type": "integer", - "description": "", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": "int64", - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "name": { - "example": null, - "id": null, - "title": null, - "type": "string", - "description": "", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "mainimum": null, - "maximum": null, - "schema": null, - "format": "", - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - } - }, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": null, - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": null, - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "status": { - "example": "available", - "id": null, - "title": null, - "type": "string", - "description": "pet status in the store", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": "", - "enumString": [ - "available", - "pending", - "sold" - ], - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "testnumber": { - "example": 1.23139183198000000283719387, - "id": null, - "title": null, - "type": "number", - "description": "pet status in the store", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": "", - "enumString": [ - "available", - "pending", - "sold" - ], - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "testnumber11": { - "example": "@number", - "id": null, - "title": null, - "type": "number", - "description": "pet status in the store", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": "", - "enumString": [ - "available", - "pending", - "sold" - ], - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "testfalse": { - "example": "@boolean", - "id": null, - "title": null, - "type": "boolean", - "description": "pet status in the store", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": "", - "enumString": [ - "available", - "pending", - "sold" - ], - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "testfalse": { - "example": false, - "id": null, - "title": null, - "type": "boolean", - "description": "pet status in the store", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": "", - "enumString": [ - "available", - "pending", - "sold" - ], - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "testnull": { - "example": null, - "id": null, - "title": null, - "type": null, - "description": "pet status in the store", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": "", - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "testass": null - }, - "additionalProperties": null, - "required": [ - "name", - "photoUrls" - ], - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": null, - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - } - """; + {"example":null,"id":null,"title":null,"type":"object","description":null,"items":null,"properties":{"id":{"example":10,"id":null,"title":null,"type":"integer","description":"","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":"int64","enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null},"name":{"example":"@string","id":null,"title":null,"type":"string","description":"","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":"","enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null},"category":{"example":null,"id":null,"title":null,"type":"object","description":null,"items":null,"properties":{"id":{"example":"@integer","id":null,"title":null,"type":"integer","description":"","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":"int64","enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null},"name":{"example":"Dogs","id":null,"title":null,"type":"string","description":"","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":"","enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null}},"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":null,"enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null},"photoUrls":{"example":null,"id":null,"title":null,"type":"array","description":null,"items":[{"example":null,"id":null,"title":null,"type":"string","description":"","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":"","enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null}],"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":null,"enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null},"tags":{"example":null,"id":null,"title":null,"type":"array","description":null,"items":[{"example":null,"id":null,"title":null,"type":"object","description":null,"items":null,"properties":{"id":{"example":null,"id":null,"title":null,"type":"integer","description":"","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":"int64","enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null},"name":{"example":null,"id":null,"title":null,"type":"string","description":"","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"mainimum":null,"maximum":null,"schema":null,"format":"","enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null}},"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":null,"enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null}],"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":null,"enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null},"status":{"example":"available","id":null,"title":null,"type":"string","description":"pet status in the store","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":"","enumString":["available","pending","sold"],"enumInteger":null,"enumNumber":null,"extensions":null},"testnumber":{"example":1.23139183198000000283719387,"id":null,"title":null,"type":"number","description":"pet status in the store","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":"","enumString":["available","pending","sold"],"enumInteger":null,"enumNumber":null,"extensions":null},"testnumber11":{"example":"@number","id":null,"title":null,"type":"number","description":"pet status in the store","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":"","enumString":["available","pending","sold"],"enumInteger":null,"enumNumber":null,"extensions":null},"testfalse":{"example":"@boolean","id":null,"title":null,"type":"boolean","description":"pet status in the store","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":"","enumString":["available","pending","sold"],"enumInteger":null,"enumNumber":null,"extensions":null},"testfalse":{"example":false,"id":null,"title":null,"type":"boolean","description":"pet status in the store","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":"","enumString":["available","pending","sold"],"enumInteger":null,"enumNumber":null,"extensions":null},"testnull":{"example":null,"id":null,"title":null,"type":"null","description":"pet status in the store","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":"","enumInteger":null,"enumNumber":null,"extensions":null},"testass": null},"additionalProperties":null,"required":["name","photoUrls"],"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":null,"enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null} + """; //正常数据; - requestPost("preview", jsonString).andExpect(status().isOk()); - //非正常json数据 会走try catch - String abnormalString = """ - { - "id" : 10, - "name" : @string, - "category" : { - "id" : "@integer", - "name" : "Dogs" - }, - "photoUrls" : [ "string" ], - "tags" : [ { - "id" : 0, - "name" : "string" - } ], - "status" : "available", - "testnumber" : 1.23139183198000000283719387, - "testfalse" : false - } - """; - requestPost("preview", abnormalString).andExpect(status().isOk()); + requestPost("preview", JSON.parseObject(jsonString, JsonSchemaItem.class)).andExpect(status().isOk()); //正常array数据 String jsonArray = """ - { - "example": null, - "id": null, - "title": null, - "type": "array", - "description": null, - "items": { - "example": null, - "id": null, - "title": null, - "type": "object", - "description": null, - "items": null, - "properties": { - "id": { - "example": "@integer", - "id": null, - "title": null, - "type": "integer", - "description": "", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": "int64", - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "name": { - "example": null, - "id": null, - "title": null, - "type": "string", - "description": "", - "items": null, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "mainimum": null, - "maximum": null, - "schema": null, - "format": "", - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - } - }, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": null, - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - }, - "properties": null, - "additionalProperties": null, - "required": null, - "pattern": null, - "maxLength": null, - "minLength": null, - "minimum": null, - "maximum": null, - "schema": null, - "format": null, - "enumString": null, - "enumInteger": null, - "enumNumber": null, - "extensions": null - } + {"example":null,"id":null,"title":null,"type":"array","description":null,"items":{"example":null,"id":null,"title":null,"type":"object","description":null,"items":null,"properties":{"id":{"example":"@integer","id":null,"title":null,"type":"integer","description":"","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":"int64","enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null},"name":{"example":null,"id":null,"title":null,"type":"string","description":"","items":null,"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"mainimum":null,"maximum":null,"schema":null,"format":"","enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null}},"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":null,"enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null},"properties":null,"additionalProperties":null,"required":null,"pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"schema":null,"format":null,"enumString":null,"enumInteger":null,"enumNumber":null,"extensions":null} """; - requestPost("preview", jsonArray).andExpect(status().isOk()); + requestPost("preview", JSON.parseObject(jsonArray, JsonSchemaItem.class)).andExpect(status().isOk()); + + // 校验转换是否正确 + String schema = """ + {"type":"object","enable":true,"properties":{"array":{"type":"array","enable":true,"items":[{"type":"string","example":"1","enable":true},{"type":"number","example":"2","enable":true}]},"string":{"type":"string","example":"stringValue","enable":true},"int":{"type":"integer","example":"1","enable":true},"num":{"type":"number","example":"1.00","enable":true},"boolean":{"type":"boolean","example":"booleanValue","enable":true},"null":{"type":"null","enable":true}}} + """; + String jsonResult = """ + { + "array" : [ "1", 2 ], + "string" : "stringValue", + "int" : 1, + "num" : 1.00, + "boolean" : false, + "null" : null + } + """; + MvcResult mvcResult = requestPostWithOkAndReturn("preview", JSON.parseObject(schema, JsonSchemaItem.class)); + String resultData = getResultData(mvcResult, String.class); + Assertions.assertEquals(JSON.parseObject(jsonResult), JSON.parseObject(resultData)); + + // 校验根节点数组是否正确 + schema = """ + {"type":"array","enable":true,"items":[{"type":"array","enable":true,"items":[{"type":"string","example":"1","description":"","additionalProperties":null,"defaultValue":"","pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"maxItems":null,"minItems":null,"format":null,"enable":true},{"type":"number","example":"2","description":"","additionalProperties":null,"defaultValue":"","pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"maxItems":null,"minItems":null,"format":null,"enable":true}]},{"type":"string","example":"stringValue","description":"","additionalProperties":null,"defaultValue":"","pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"maxItems":null,"minItems":null,"format":null,"enable":true},{"type":"integer","example":"intValue","description":"","additionalProperties":null,"defaultValue":"","pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"maxItems":null,"minItems":null,"format":null,"enable":true},{"type":"number","example":"1.00","description":"","additionalProperties":null,"defaultValue":"","pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"maxItems":null,"minItems":null,"format":null,"enable":true},{"type":"boolean","example":"booleanValue","description":"","additionalProperties":null,"defaultValue":"","pattern":null,"maxLength":null,"minLength":null,"minimum":null,"maximum":null,"maxItems":null,"minItems":null,"format":null,"enable":true},{"type":"null","enable":true}]} + """; + jsonResult = """ + [ + [ + "1", + 2 + ], + "stringValue", + 0, + 1.00, + false, + null + ] + """; + mvcResult = requestPostWithOkAndReturn("preview", JSON.parseObject(schema, JsonSchemaItem.class)); + resultData = getResultData(mvcResult, String.class); + Assertions.assertEquals(JSON.parseObject(jsonResult), JSON.parseObject(resultData)); + + // 校验禁用 + schema = """ + {"type":"object","enable":false} + """; + mvcResult = requestPostWithOkAndReturn("preview", JSON.parseObject(schema, JsonSchemaItem.class)); + Assertions.assertEquals(getResultData(mvcResult, String.class), "{}"); + + // 校验禁用 + schema = """ + {"type":"object","enable":true,"properties":{"array":{"type":"array","enable":false,"items":[{"type":"string","example":"1","enable":false},{"type":"number","example":"2","enable":false}]},"string":{"type":"string","example":"stringValue","enable":false},"int":{"type":"integer","example":"1","enable":false},"num":{"type":"number","example":"1.00","enable":false},"boolean":{"type":"boolean","example":"booleanValue","enable":false},"null":{"type":"null","enable":false}}} + """; + mvcResult = requestPostWithOkAndReturn("preview", JSON.parseObject(schema, JsonSchemaItem.class)); + resultData = getResultData(mvcResult, String.class); + Assertions.assertEquals(JSON.parseObject("{}"), JSON.parseObject(resultData)); } @Test diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/constants/PropertyConstant.java b/backend/services/project-management/src/main/java/io/metersphere/project/constants/PropertyConstant.java index 0aad540cd6..4b91272486 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/constants/PropertyConstant.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/constants/PropertyConstant.java @@ -18,5 +18,6 @@ public class PropertyConstant { public final static String TYPE = "type"; public final static String ITEMS = "items"; public final static String PROPERTIES = "properties"; + public final static String ENABLE = "enable"; } diff --git a/frontend/src/components/business/ms-minders/testPlanMinder/index.vue b/frontend/src/components/business/ms-minders/testPlanMinder/index.vue index 52cdb3e95f..ed52ad6c06 100644 --- a/frontend/src/components/business/ms-minders/testPlanMinder/index.vue +++ b/frontend/src/components/business/ms-minders/testPlanMinder/index.vue @@ -181,20 +181,13 @@
{{ t('ms.minders.failStop') }}
- - +
diff --git a/frontend/src/enums/testPlanEnum.ts b/frontend/src/enums/testPlanEnum.ts index d4b76da5c4..691eb5724b 100644 --- a/frontend/src/enums/testPlanEnum.ts +++ b/frontend/src/enums/testPlanEnum.ts @@ -9,11 +9,6 @@ export enum RunMode { PARALLEL = 'PARALLEL', // 并行 } -export enum FailRetry { - STEP = 'STEP', - SCENARIO = 'SCENARIO', -} - // 功能:FUNCTIONAL_CASE/接口定义:API/接口用例:API_CASE/场景:SCENARIO_CASE export enum PlanMinderAssociateType { FUNCTIONAL_CASE = 'FUNCTIONAL', diff --git a/frontend/src/models/testPlan/testPlan.ts b/frontend/src/models/testPlan/testPlan.ts index 33c9b90870..690de9ef64 100644 --- a/frontend/src/models/testPlan/testPlan.ts +++ b/frontend/src/models/testPlan/testPlan.ts @@ -6,7 +6,6 @@ import type { TableQueryParams } from '@/models/common'; import { BatchApiParams, DragSortParams } from '@/models/common'; import { LastExecuteResults } from '@/enums/caseEnum'; import { - type FailRetry, type PlanMinderAssociateType, type PlanMinderCollectionType, type RunMode, @@ -397,7 +396,6 @@ export interface PlanMinderNodeData extends MinderJsonNodeData { environmentId: string; testResourcePoolId: string; retryOnFail: boolean; - retryType: FailRetry; // 失败重试类型(步骤/场景) retryTimes: number; retryInterval: number; stopOnFail: boolean;