From ffa2ab140c25ca624d2a13aeeaca08354869e4b3 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 9 Mar 2021 16:37:47 +0100 Subject: [PATCH] Open API improvements (#667) * Open API improvements --- .../JsonSchemaExtensions.cs | 64 +++++++++++++------ .../GenerateJsonSchema/JsonTypeVisitor.cs | 55 +++++++++------- .../GenerateJsonSchema/SchemaBuilder.cs | 42 ++++++++---- .../Contents/Queries/ContentQueryParser.cs | 2 +- .../Schemas/ContentJsonSchemaBuilder.cs | 4 +- .../Controllers/Contents/Generator/Builder.cs | 51 +++++++++++---- .../Contents/Generator/OperationsBuilder.cs | 2 + .../Generator/SchemasOpenApiGenerator.cs | 22 +------ .../Squidex/Config/Domain/CommandsServices.cs | 1 - .../GenerateJsonSchema/JsonSchemaTests.cs | 46 ++++++------- .../Commands/DomainObjectTests.cs | 1 - 11 files changed, 173 insertions(+), 117 deletions(-) diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs index 88442ef04..77830f68a 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs @@ -14,7 +14,7 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema { public static class JsonSchemaExtensions { - public static JsonSchema BuildFlatJsonSchema(this Schema schema, SchemaResolver schemaResolver, bool withHidden = false) + public static JsonSchema BuildFlatJsonSchema(this Schema schema, SchemaResolver schemaResolver) { Guard.NotNull(schemaResolver, nameof(schemaResolver)); @@ -22,9 +22,9 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema var jsonSchema = SchemaBuilder.Object(); - foreach (var field in schema.Fields.ForApi(withHidden)) + foreach (var field in schema.Fields.ForApi()) { - var property = JsonTypeVisitor.BuildProperty(field, schemaResolver, withHidden); + var property = JsonTypeVisitor.BuildProperty(field, null, false); if (property != null) { @@ -37,42 +37,62 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema return jsonSchema; } - public static JsonSchema BuildJsonSchema(this Schema schema, PartitionResolver partitionResolver, SchemaResolver schemaResolver, bool withHidden = false) + public static JsonSchema BuildDynamicJsonSchema(this Schema schema, SchemaResolver schemaResolver, bool withHidden = false) { Guard.NotNull(schemaResolver, nameof(schemaResolver)); - Guard.NotNull(partitionResolver, nameof(partitionResolver)); - var schemaName = schema.TypeName(); + var jsonSchema = SchemaBuilder.Object(); + + foreach (var field in schema.Fields.ForApi(withHidden)) + { + var propertyItem = JsonTypeVisitor.BuildProperty(field, null, withHidden); + + if (propertyItem != null) + { + var property = + SchemaBuilder.ObjectProperty(propertyItem) + .SetDescription(field) + .SetRequired(field.RawProperties.IsRequired); + + jsonSchema.Properties.Add(field.Name, property); + } + } + + return jsonSchema; + } + + public static JsonSchema BuildJsonSchema(this Schema schema, PartitionResolver partitionResolver, bool withHidden = false) + { + Guard.NotNull(partitionResolver, nameof(partitionResolver)); var jsonSchema = SchemaBuilder.Object(); foreach (var field in schema.Fields.ForApi(withHidden)) { - var partitionObject = SchemaBuilder.Object(); + var propertyObject = SchemaBuilder.Object(); + var partitioning = partitionResolver(field.Partitioning); foreach (var partitionKey in partitioning.AllKeys) { - var partitionItemProperty = JsonTypeVisitor.BuildProperty(field, schemaResolver, withHidden); + var propertyItem = JsonTypeVisitor.BuildProperty(field, null, withHidden); - if (partitionItemProperty != null) + if (propertyItem != null) { var isOptional = partitioning.IsOptional(partitionKey); var name = partitioning.GetName(partitionKey); - partitionItemProperty.Description = name; - partitionItemProperty.SetRequired(field.RawProperties.IsRequired && !isOptional); + propertyItem.SetDescription(name); + propertyItem.SetRequired(field.RawProperties.IsRequired && !isOptional); - partitionObject.Properties.Add(partitionKey, partitionItemProperty); + propertyObject.Properties.Add(partitionKey, propertyItem); } } - if (partitionObject.Properties.Count > 0) + if (propertyObject.Properties.Count > 0) { - var propertyReference = schemaResolver($"{schemaName}{field.Name.ToPascalCase()}PropertyDto", () => partitionObject); - - jsonSchema.Properties.Add(field.Name, CreateProperty(field, propertyReference)); + jsonSchema.Properties.Add(field.Name, CreateProperty(field, propertyObject)); } } @@ -81,8 +101,16 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema public static JsonSchemaProperty CreateProperty(IField field, JsonSchema reference) { - var jsonProperty = SchemaBuilder.ObjectProperty(reference); + var jsonProperty = + SchemaBuilder.ReferenceProperty(reference) + .SetDescription(field) + .SetRequired(field.RawProperties.IsRequired); + + return jsonProperty; + } + private static JsonSchemaProperty SetDescription(this JsonSchemaProperty jsonProperty, IField field) + { if (!string.IsNullOrWhiteSpace(field.RawProperties.Hints)) { jsonProperty.Description = $"{field.Name} ({field.RawProperties.Hints})"; @@ -92,8 +120,6 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema jsonProperty.Description = field.Name; } - jsonProperty.SetRequired(field.RawProperties.IsRequired); - return jsonProperty; } } diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs index 389e48288..3dc2c649a 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs @@ -21,11 +21,11 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema public readonly struct Args { - public readonly SchemaResolver SchemaResolver; + public readonly SchemaResolver? SchemaResolver; public readonly bool WithHiddenFields; - public Args(SchemaResolver schemaResolver, bool withHiddenFields) + public Args(SchemaResolver? schemaResolver, bool withHiddenFields) { SchemaResolver = schemaResolver; @@ -37,7 +37,7 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema { } - public static JsonSchemaProperty? BuildProperty(IField field, SchemaResolver schemaResolver, bool withHiddenFields) + public static JsonSchemaProperty? BuildProperty(IField field, SchemaResolver? schemaResolver, bool withHiddenFields) { var args = new Args(schemaResolver, withHiddenFields); @@ -81,30 +81,41 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema public JsonSchemaProperty? Visit(IField field, Args args) { - var reference = args.SchemaResolver("GeolocationDto", () => + if (args.SchemaResolver != null) { - var geolocationSchema = SchemaBuilder.Object(); + var reference = args.SchemaResolver("GeolocationDto", () => + { + var geolocationSchema = SchemaBuilder.Object(); - geolocationSchema.Format = GeoJson.Format; + geolocationSchema.Format = GeoJson.Format; - geolocationSchema.Properties.Add("latitude", new JsonSchemaProperty - { - Type = JsonObjectType.Number, - Maximum = 90, - Minimum = -90 - }.SetRequired(true)); + geolocationSchema.Properties.Add("latitude", new JsonSchemaProperty + { + Type = JsonObjectType.Number, + Maximum = 90, + Minimum = -90 + }.SetRequired(false)); - geolocationSchema.Properties.Add("longitude", new JsonSchemaProperty - { - Type = JsonObjectType.Number, - Maximum = 180, - Minimum = -180 - }.SetRequired(true)); + geolocationSchema.Properties.Add("longitude", new JsonSchemaProperty + { + Type = JsonObjectType.Number, + Maximum = 180, + Minimum = -180 + }.SetRequired(false)); + + return geolocationSchema; + }); - return geolocationSchema; - }); + return SchemaBuilder.ObjectProperty(reference); + } + else + { + var property = SchemaBuilder.ObjectProperty(); - return SchemaBuilder.ObjectProperty(reference); + property.Format = GeoJson.Format; + + return property; + } } public JsonSchemaProperty? Visit(IField field, Args args) @@ -166,4 +177,4 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema return null; } } -} +} \ No newline at end of file diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/SchemaBuilder.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/SchemaBuilder.cs index dc79e3d6b..03089056a 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/SchemaBuilder.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/SchemaBuilder.cs @@ -23,48 +23,68 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema public static JsonSchemaProperty ArrayProperty(JsonSchema item, string? description = null, bool isRequired = false) { - return Enrich(new JsonSchemaProperty { Type = JsonObjectType.Array, Item = item }, description, isRequired); + return new JsonSchemaProperty { Type = JsonObjectType.Array, Item = item } + .SetDescription(description) + .SetRequired(isRequired); } public static JsonSchemaProperty BooleanProperty(string? description = null, bool isRequired = false) { - return Enrich(new JsonSchemaProperty { Type = JsonObjectType.Boolean }, description, isRequired); + return new JsonSchemaProperty { Type = JsonObjectType.Boolean } + .SetDescription(description) + .SetRequired(isRequired); } public static JsonSchemaProperty DateTimeProperty(string? description = null, bool isRequired = false) { - return Enrich(new JsonSchemaProperty { Type = JsonObjectType.String, Format = JsonFormatStrings.DateTime }, description, isRequired); + return new JsonSchemaProperty { Type = JsonObjectType.String, Format = JsonFormatStrings.DateTime } + .SetDescription(description) + .SetRequired(isRequired); } public static JsonSchemaProperty NumberProperty(string? description = null, bool isRequired = false) { - return Enrich(new JsonSchemaProperty { Type = JsonObjectType.Number }, description, isRequired); + return new JsonSchemaProperty { Type = JsonObjectType.Number } + .SetDescription(description) + .SetRequired(isRequired); } public static JsonSchemaProperty StringProperty(string? description = null, bool isRequired = false) { - return Enrich(new JsonSchemaProperty { Type = JsonObjectType.String }, description, isRequired); + return new JsonSchemaProperty { Type = JsonObjectType.String } + .SetDescription(description) + .SetRequired(isRequired); } - public static JsonSchemaProperty ObjectProperty(JsonSchema reference, string? description = null, bool isRequired = false) + public static JsonSchemaProperty ReferenceProperty(JsonSchema reference, string? description = null, bool isRequired = false) { - return Enrich(new JsonSchemaProperty { Reference = reference }, description, isRequired); + return new JsonSchemaProperty { Reference = reference } + .SetDescription(description) + .SetRequired(isRequired); + } + + public static JsonSchemaProperty ObjectProperty(JsonSchema? value = null, string? description = null, bool isRequired = false) + { + return new JsonSchemaProperty { Type = JsonObjectType.Object, AdditionalPropertiesSchema = value } + .SetDescription(description) + .SetRequired(isRequired); } public static JsonSchemaProperty JsonProperty(string? description = null, bool isRequired = false) { - return Enrich(new JsonSchemaProperty(), description, isRequired); + return new JsonSchemaProperty() + .SetDescription(description) + .SetRequired(isRequired); } - private static JsonSchemaProperty Enrich(JsonSchemaProperty property, string? description = null, bool isRequired = false) + public static T SetDescription(this T property, string? description = null) where T : JsonSchemaProperty { property.Description = description; - property.SetRequired(isRequired); return property; } - public static JsonSchemaProperty SetRequired(this JsonSchemaProperty property, bool isRequired) + public static T SetRequired(this T property, bool isRequired) where T : JsonSchemaProperty { property.IsRequired = isRequired; property.IsNullableRaw = !isRequired; diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryParser.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryParser.cs index 8b70a3395..134f5457c 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryParser.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryParser.cs @@ -235,7 +235,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries private static JsonSchema BuildJsonSchema(Schema schema, IAppEntity app, bool withHiddenFields) { - var dataSchema = schema.BuildJsonSchema(app.PartitionResolver(), (n, action) => action(), withHiddenFields); + var dataSchema = schema.BuildJsonSchema(app.PartitionResolver(), withHiddenFields); return ContentJsonSchemaBuilder.BuildSchema(schema.DisplayName(), dataSchema); } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Schemas/ContentJsonSchemaBuilder.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Schemas/ContentJsonSchemaBuilder.cs index d10f479ba..18b5ee985 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Schemas/ContentJsonSchemaBuilder.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/Schemas/ContentJsonSchemaBuilder.cs @@ -38,8 +38,8 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema if (dataSchema != null) { - jsonSchema.Properties["data"] = SchemaBuilder.ObjectProperty(dataSchema, $"The data of the {name}.", true); - jsonSchema.Properties["dataDraft"] = SchemaBuilder.ObjectProperty(dataSchema, $"The draft data of the {name}."); + jsonSchema.Properties["data"] = SchemaBuilder.ReferenceProperty(dataSchema, $"The data of the {name}.", true); + jsonSchema.Properties["dataDraft"] = SchemaBuilder.ReferenceProperty(dataSchema, $"The draft data of the {name}."); } return jsonSchema; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/Builder.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/Builder.cs index 0262ad5e6..6137f4a64 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/Builder.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/Builder.cs @@ -11,7 +11,6 @@ using NJsonSchema; using NSwag; using NSwag.Generation; using Squidex.Areas.Api.Controllers.Contents.Models; -using Squidex.Domain.Apps.Core; using Squidex.Domain.Apps.Core.GenerateJsonSchema; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Apps; @@ -21,7 +20,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator { internal sealed class Builder { - private readonly PartitionResolver partitionResolver; + private const string ResultTotal = "total"; + private const string ResultItems = "items"; public string AppName { get; } @@ -34,8 +34,6 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator OpenApiSchemaResolver schemaResolver, OpenApiSchemaGenerator schemaGenerator) { - this.partitionResolver = app.PartitionResolver(); - Document = document; AppName = app.Name; @@ -50,16 +48,22 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator return JsonSchema.CreateAnySchema(); }); - var contentSchema = ResolveSchema($"ContentDto", () => + var contentSchema = ResolveSchema("ContentDto", () => { return ContentJsonSchemaBuilder.BuildSchema("Shared", dataSchema, true); }); + var contentsSchema = ResolveSchema("ContentResultDto", () => + { + return BuildResult(contentSchema); + }); + var path = $"/content/{AppName}"; var builder = new OperationsBuilder { ContentSchema = contentSchema, + ContentsSchema = contentsSchema, DataSchema = dataSchema, Path = path, Parent = this, @@ -83,19 +87,27 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator var dataSchema = ResolveSchema($"{typeName}DataDto", () => { - return schema.BuildJsonSchema(partitionResolver, ResolveSchema); + return schema.BuildDynamicJsonSchema(ResolveSchema); }); - var dataFlatSchema = ResolveSchema($"{typeName}FlatDataDto", () => + var contentSchema = ResolveSchema($"{typeName}ContentDto", () => { - return schema.BuildFlatJsonSchema(ResolveSchema); + var contentDataSchema = dataSchema; + + if (flat) + { + contentDataSchema = ResolveSchema($"{typeName}FlatDataDto", () => + { + return schema.BuildFlatJsonSchema(ResolveSchema); + }); + } + + return ContentJsonSchemaBuilder.BuildSchema(displayName, contentDataSchema, true); }); - var contentSchema = ResolveSchema($"{typeName}ContentDto", () => + var contentsSchema = ResolveSchema($"{typeName}ContentResultDto", () => { - var data = flat ? dataFlatSchema : dataSchema; - - return ContentJsonSchemaBuilder.BuildSchema(displayName, data, true); + return BuildResult(contentSchema); }); var path = $"/content/{AppName}/{schema.Name}"; @@ -103,6 +115,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator var builder = new OperationsBuilder { ContentSchema = contentSchema, + ContentsSchema = contentsSchema, DataSchema = dataSchema, Path = path, Parent = this, @@ -127,5 +140,19 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator Reference = Document.Definitions.GetOrAdd(name, x => factory()) }; } + + private static JsonSchema BuildResult(JsonSchema contentSchema) + { + return new JsonSchema + { + AllowAdditionalProperties = false, + Properties = + { + [ResultTotal] = SchemaBuilder.NumberProperty("The total number of content items.", true), + [ResultItems] = SchemaBuilder.ArrayProperty(contentSchema, "The content items.", true) + }, + Type = JsonObjectType.Object + }; + } } } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/OperationsBuilder.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/OperationsBuilder.cs index 524f71237..dd805fe3c 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/OperationsBuilder.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/OperationsBuilder.cs @@ -27,6 +27,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator public JsonSchema ContentSchema { get; init; } + public JsonSchema ContentsSchema { get; init; } + public JsonSchema DataSchema { get; init; } public string FormatText(string text) diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs index 7bc15e97e..f5fd2c4a5 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs @@ -13,7 +13,6 @@ using NJsonSchema; using NSwag; using NSwag.Generation; using NSwag.Generation.Processors.Contexts; -using Squidex.Domain.Apps.Core.GenerateJsonSchema; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Hosting; @@ -82,28 +81,24 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator private static void GenerateSharedOperations(OperationsBuilder builder) { - var contentsSchema = BuildResults(builder); - builder.AddOperation(OpenApiOperationMethod.Get, "/") .RequirePermission(Permissions.AppContentsReadOwn) .Operation("Query") .OperationSummary("Query contents across all schemas.") .HasQuery("ids", JsonObjectType.String, "Comma-separated list of content IDs.") - .Responds(200, "Content items retrieved.", contentsSchema) + .Responds(200, "Content items retrieved.", builder.ContentsSchema) .Responds(400, "Query not valid."); } private static void GenerateSchemaOperations(OperationsBuilder builder) { - var contentsSchema = BuildResults(builder); - builder.AddOperation(OpenApiOperationMethod.Get, "/") .RequirePermission(Permissions.AppContentsReadOwn) .Operation("Query") .OperationSummary("Query schema contents items.") .Describe(Properties.Resources.OpenApiSchemaQuery) .HasQueryOptions(true) - .Responds(200, "Content items retrieved.", contentsSchema) + .Responds(200, "Content items retrieved.", builder.ContentsSchema) .Responds(400, "Query not valid."); builder.AddOperation(OpenApiOperationMethod.Get, "/{id}") @@ -192,19 +187,6 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator .Responds(204, "Content item deleted"); } - private static JsonSchema BuildResults(OperationsBuilder builder) - { - return new JsonSchema - { - Properties = - { - ["total"] = SchemaBuilder.NumberProperty("The total number of content items.", true), - ["items"] = SchemaBuilder.ArrayProperty(builder.ContentSchema, "The content items.", true) - }, - Type = JsonObjectType.Object - }; - } - private OpenApiDocument CreateApiDocument(HttpContext context, IAppEntity app) { var appName = app.Name; diff --git a/backend/src/Squidex/Config/Domain/CommandsServices.cs b/backend/src/Squidex/Config/Domain/CommandsServices.cs index 8971b6973..0071a78a4 100644 --- a/backend/src/Squidex/Config/Domain/CommandsServices.cs +++ b/backend/src/Squidex/Config/Domain/CommandsServices.cs @@ -23,7 +23,6 @@ using Squidex.Domain.Apps.Entities.Schemas.Commands; using Squidex.Domain.Apps.Entities.Schemas.DomainObject; using Squidex.Domain.Apps.Entities.Schemas.Indexes; using Squidex.Infrastructure.Commands; -using Squidex.Infrastructure.EventSourcing; using Squidex.Web.CommandMiddlewares; namespace Squidex.Config.Domain diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs index 50939a266..01a237441 100644 --- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs @@ -6,6 +6,7 @@ // ========================================================================== using System.Collections.Generic; +using System.Linq; using NJsonSchema; using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.GenerateJsonSchema; @@ -25,38 +26,19 @@ namespace Squidex.Domain.Apps.Core.Operations.GenerateJsonSchema { var languagesConfig = LanguagesConfig.English.Set(Language.DE); - var schemaResolver = new SchemaResolver((name, action) => - { - return action(); - }); + var jsonSchema = schema.BuildJsonSchema(languagesConfig.ToResolver()); - var jsonSchema = schema.BuildJsonSchema(languagesConfig.ToResolver(), schemaResolver); - var jsonProperties = AllPropertyNames(jsonSchema); + CheckFields(jsonSchema); + } - void CheckField(IField field) - { - if (!field.IsForApi()) - { - Assert.DoesNotContain(field.Name, jsonProperties); - } - else - { - Assert.Contains(field.Name, jsonProperties); - } + [Fact] + public void Should_build_json_schema_with_resolver() + { + var schemaResolver = new SchemaResolver((name, action) => action()); - if (field is IArrayField array) - { - foreach (var nested in array.Fields) - { - CheckField(nested); - } - } - } + var jsonSchema = schema.BuildDynamicJsonSchema(schemaResolver); - foreach (var field in schema.Fields) - { - CheckField(field); - } + CheckFields(jsonSchema); } [Fact] @@ -70,6 +52,12 @@ namespace Squidex.Domain.Apps.Core.Operations.GenerateJsonSchema }); var jsonSchema = schema.BuildFlatJsonSchema(schemaResolver); + + CheckFields(jsonSchema); + } + + private void CheckFields(JsonSchema jsonSchema) + { var jsonProperties = AllPropertyNames(jsonSchema); void CheckField(IField field) @@ -118,6 +106,8 @@ namespace Squidex.Domain.Apps.Core.Operations.GenerateJsonSchema AddProperties(current.Item); AddProperties(current.Reference); + AddProperties(current.AdditionalItemsSchema); + AddProperties(current.AdditionalPropertiesSchema); } } diff --git a/backend/tests/Squidex.Infrastructure.Tests/Commands/DomainObjectTests.cs b/backend/tests/Squidex.Infrastructure.Tests/Commands/DomainObjectTests.cs index b6eb77eff..072bb4c54 100644 --- a/backend/tests/Squidex.Infrastructure.Tests/Commands/DomainObjectTests.cs +++ b/backend/tests/Squidex.Infrastructure.Tests/Commands/DomainObjectTests.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using FakeItEasy; using Squidex.Infrastructure.EventSourcing;