diff --git a/eng/Versions.props b/eng/Versions.props index 8eb0617b6911..e38d3e392884 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -335,8 +335,8 @@ $(XunitVersion) 2.8.2 5.2.2 - 2.0.0-preview4 - 2.0.0-preview4 + 2.0.0-preview5 + 2.0.0-preview5 6.0.322601 1.10.93 diff --git a/eng/testing/linker/project.csproj.template b/eng/testing/linker/project.csproj.template index d78b5bfc991e..ea368a6caa54 100644 --- a/eng/testing/linker/project.csproj.template +++ b/eng/testing/linker/project.csproj.template @@ -16,8 +16,6 @@ $(InterceptorsPreviewNamespaces);Microsoft.AspNetCore.Http.Generated false - - $(NoWarn);IL2104;IL3053 {AdditionalProperties} @@ -29,19 +27,4 @@ {AdditionalProjectReferences} - - - - - - - - true - true - - - - diff --git a/src/OpenApi/src/Extensions/OpenApiDocumentExtensions.cs b/src/OpenApi/src/Extensions/OpenApiDocumentExtensions.cs index f7e16a091a86..b16171bc27cb 100644 --- a/src/OpenApi/src/Extensions/OpenApiDocumentExtensions.cs +++ b/src/OpenApi/src/Extensions/OpenApiDocumentExtensions.cs @@ -23,7 +23,7 @@ public static OpenApiSchema AddOpenApiSchemaByReference(this OpenApiDocument doc document.Components.Schemas[schemaId] = schema; document.Workspace ??= new(); var location = document.BaseUri + "/components/schemas/" + schemaId; - document.Workspace.RegisterComponent(location, schema); + document.Workspace.RegisterComponentForDocument(document, schema, location); return new OpenApiSchemaReference(schemaId, document); } } diff --git a/src/OpenApi/src/Extensions/OpenApiEndpointRouteBuilderExtensions.cs b/src/OpenApi/src/Extensions/OpenApiEndpointRouteBuilderExtensions.cs index 9777549cc108..52afbe7c58f5 100644 --- a/src/OpenApi/src/Extensions/OpenApiEndpointRouteBuilderExtensions.cs +++ b/src/OpenApi/src/Extensions/OpenApiEndpointRouteBuilderExtensions.cs @@ -59,12 +59,12 @@ public static IEndpointConventionBuilder MapOpenApi(this IEndpointRouteBuilder e { if (UseYaml(pattern)) { - document.Serialize(new OpenApiYamlWriter(writer), documentOptions.OpenApiVersion); + await document.SerializeAsync(new OpenApiYamlWriter(writer), documentOptions.OpenApiVersion); context.Response.ContentType = "text/plain+yaml;charset=utf-8"; } else { - document.Serialize(new OpenApiJsonWriter(writer), documentOptions.OpenApiVersion); + await document.SerializeAsync(new OpenApiJsonWriter(writer), documentOptions.OpenApiVersion); context.Response.ContentType = "application/json;charset=utf-8"; } await context.Response.BodyWriter.WriteAsync(output.ToArray(), context.RequestAborted); diff --git a/src/OpenApi/src/Services/OpenApiDocumentProvider.cs b/src/OpenApi/src/Services/OpenApiDocumentProvider.cs index 79507a44da54..3a26e0ad1f4c 100644 --- a/src/OpenApi/src/Services/OpenApiDocumentProvider.cs +++ b/src/OpenApi/src/Services/OpenApiDocumentProvider.cs @@ -57,7 +57,7 @@ public async Task GenerateAsync(string documentName, TextWriter writer, OpenApiS using var scopedService = serviceProvider.CreateScope(); var document = await targetDocumentService.GetOpenApiDocumentAsync(scopedService.ServiceProvider); var jsonWriter = new OpenApiJsonWriter(writer); - document.Serialize(jsonWriter, openApiSpecVersion); + await document.SerializeAsync(jsonWriter, openApiSpecVersion); } /// diff --git a/src/OpenApi/src/Services/OpenApiDocumentService.cs b/src/OpenApi/src/Services/OpenApiDocumentService.cs index db32e0512642..08cc50a5f953 100644 --- a/src/OpenApi/src/Services/OpenApiDocumentService.cs +++ b/src/OpenApi/src/Services/OpenApiDocumentService.cs @@ -26,6 +26,7 @@ using Microsoft.Extensions.Options; using Microsoft.Net.Http.Headers; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.References; namespace Microsoft.AspNetCore.OpenApi; @@ -59,12 +60,12 @@ public async Task GetOpenApiDocumentAsync(IServiceProvider scop // Schema and operation transformers are scoped per-request and can be // pre-allocated to hold the same number of transformers as the associated // options object. - IOpenApiSchemaTransformer[] schemaTransformers = _options.SchemaTransformers.Count > 0 + var schemaTransformers = _options.SchemaTransformers.Count > 0 ? new IOpenApiSchemaTransformer[_options.SchemaTransformers.Count] - : Array.Empty(); - IOpenApiOperationTransformer[] operationTransformers = _options.OperationTransformers.Count > 0 ? + : []; + var operationTransformers = _options.OperationTransformers.Count > 0 ? new IOpenApiOperationTransformer[_options.OperationTransformers.Count] - : Array.Empty(); + : []; InitializeTransformers(scopedServiceProvider, schemaTransformers, operationTransformers); var document = new OpenApiDocument { @@ -277,14 +278,7 @@ private async Task GetOperationAsync( IOpenApiSchemaTransformer[] schemaTransformers, CancellationToken cancellationToken) { - var tags = GetTags(description); - if (tags != null) - { - foreach (var tag in tags) - { - document.Tags?.Add(tag); - } - } + var tags = GetTags(description, document); var operation = new OpenApiOperation { OperationId = GetOperationId(description), @@ -308,16 +302,27 @@ private async Task GetOperationAsync( => description.ActionDescriptor.AttributeRouteInfo?.Name ?? description.ActionDescriptor.EndpointMetadata.OfType().LastOrDefault()?.EndpointName; - private static List? GetTags(ApiDescription description) + private static List GetTags(ApiDescription description, OpenApiDocument document) { var actionDescriptor = description.ActionDescriptor; if (actionDescriptor.EndpointMetadata?.OfType().LastOrDefault() is { } tagsMetadata) { - return tagsMetadata.Tags.Select(tag => new OpenApiTag { Name = tag }).ToList(); + List tags = []; + foreach (var tag in tagsMetadata.Tags) + { + document.Tags ??= []; + document.Tags.Add(new OpenApiTag { Name = tag }); + tags.Add(new OpenApiTagReference(tag, document)); + + } + return tags; } // If no tags are specified, use the controller name as the tag. This effectively // allows us to group endpoints by the "resource" concept (e.g. users, todos, etc.) - return [new OpenApiTag { Name = description.ActionDescriptor.RouteValues["controller"] }]; + var controllerName = description.ActionDescriptor.RouteValues["controller"]; + document.Tags ??= []; + document.Tags.Add(new OpenApiTag { Name = controllerName }); + return [new OpenApiTagReference(controllerName, document)]; } private async Task GetResponsesAsync( diff --git a/src/OpenApi/src/Services/OpenApiGenerator.cs b/src/OpenApi/src/Services/OpenApiGenerator.cs index be70be1edb25..ce76cfb88694 100644 --- a/src/OpenApi/src/Services/OpenApiGenerator.cs +++ b/src/OpenApi/src/Services/OpenApiGenerator.cs @@ -20,6 +20,7 @@ using Microsoft.Extensions.Internal; using Microsoft.Extensions.Primitives; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.References; namespace Microsoft.AspNetCore.OpenApi; @@ -322,19 +323,22 @@ private static void GenerateDefaultResponses(Dictionary GetOperationTags(MethodInfo methodInfo, EndpointMetadataCollection metadata) + private List GetOperationTags(MethodInfo methodInfo, EndpointMetadataCollection metadata) { var metadataList = metadata.GetOrderedMetadata(); + var document = new OpenApiDocument(); if (metadataList.Count > 0) { - var tags = new List(); + var tags = new List(); foreach (var metadataItem in metadataList) { foreach (var tag in metadataItem.Tags) { - tags.Add(new OpenApiTag() { Name = tag }); + document.Tags ??= []; + document.Tags.Add(new OpenApiTag { Name = tag }); + tags.Add(new OpenApiTagReference(tag, document)); } } @@ -354,7 +358,9 @@ private List GetOperationTags(MethodInfo methodInfo, EndpointMetadat controllerName = _environment?.ApplicationName ?? string.Empty; } - return new List() { new OpenApiTag() { Name = controllerName } }; + document.Tags ??= []; + document.Tags.Add(new OpenApiTag { Name = controllerName }); + return [new(controllerName, document)]; } private List GetOpenApiParameters(MethodInfo methodInfo, RoutePattern pattern, bool disableInferredBody) diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=controllers.verified.txt b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=controllers.verified.txt index e084a63428b5..9eb758a76e24 100644 --- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=controllers.verified.txt +++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=controllers.verified.txt @@ -8,9 +8,7 @@ "/getbyidandname/{id}/{name}": { "get": { "tags": [ - { - "name": "Test" - } + "Test" ], "parameters": [ { @@ -59,9 +57,7 @@ "/forms": { "post": { "tags": [ - { - "name": "Test" - } + "Test" ], "requestBody": { "content": { diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=forms.verified.txt b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=forms.verified.txt index 7a9afdd7473d..190efab5598d 100644 --- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=forms.verified.txt +++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=forms.verified.txt @@ -8,9 +8,7 @@ "/forms/form-file": { "post": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "requestBody": { "content": { @@ -40,9 +38,7 @@ "/forms/form-files": { "post": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "requestBody": { "content": { @@ -72,9 +68,7 @@ "/forms/form-file-multiple": { "post": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "requestBody": { "content": { @@ -118,9 +112,7 @@ "/forms/form-todo": { "post": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "requestBody": { "content": { @@ -147,9 +139,7 @@ "/forms/forms-pocos-and-files": { "post": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "requestBody": { "content": { diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=responses.verified.txt b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=responses.verified.txt index 3b5407eab404..3ac78c75d5d3 100644 --- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=responses.verified.txt +++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=responses.verified.txt @@ -8,9 +8,7 @@ "/responses/200-add-xml": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "responses": { "200": { @@ -34,9 +32,7 @@ "/responses/200-only-xml": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "responses": { "200": { @@ -55,9 +51,7 @@ "/responses/triangle": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "responses": { "200": { @@ -76,9 +70,7 @@ "/responses/shape": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "responses": { "200": { diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=schemas-by-ref.verified.txt b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=schemas-by-ref.verified.txt index 40e2a1b58bb6..b750396361c0 100644 --- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=schemas-by-ref.verified.txt +++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=schemas-by-ref.verified.txt @@ -8,9 +8,7 @@ "/schemas-by-ref/typed-results": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "responses": { "200": { @@ -29,9 +27,7 @@ "/schemas-by-ref/multiple-results": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "responses": { "200": { @@ -60,9 +56,7 @@ "/schemas-by-ref/iresult-no-produces": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "responses": { "200": { @@ -74,9 +68,7 @@ "/schemas-by-ref/iresult-with-produces": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "responses": { "200": { @@ -95,9 +87,7 @@ "/schemas-by-ref/primitives": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "parameters": [ { @@ -131,9 +121,7 @@ "/schemas-by-ref/product": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "requestBody": { "content": { @@ -162,9 +150,7 @@ "/schemas-by-ref/account": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "requestBody": { "content": { @@ -193,9 +179,7 @@ "/schemas-by-ref/array-of-ints": { "post": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "requestBody": { "content": { @@ -229,9 +213,7 @@ "/schemas-by-ref/list-of-ints": { "post": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "requestBody": { "content": { @@ -265,9 +247,7 @@ "/schemas-by-ref/ienumerable-of-ints": { "post": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "responses": { "200": { @@ -287,9 +267,7 @@ "/schemas-by-ref/dictionary-of-ints": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "responses": { "200": { @@ -312,9 +290,7 @@ "/schemas-by-ref/frozen-dictionary-of-ints": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "responses": { "200": { @@ -337,9 +313,7 @@ "/schemas-by-ref/shape": { "post": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "requestBody": { "content": { @@ -361,9 +335,7 @@ "/schemas-by-ref/weatherforecastbase": { "post": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "requestBody": { "content": { @@ -385,9 +357,7 @@ "/schemas-by-ref/person": { "post": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "requestBody": { "content": { diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=v1.verified.txt b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=v1.verified.txt index 45256d45e1a1..4ddd84cfac73 100644 --- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=v1.verified.txt +++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=v1.verified.txt @@ -8,9 +8,7 @@ "/v1/array-of-guids": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "parameters": [ { @@ -55,9 +53,7 @@ "/v1/todos": { "post": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "summary": "Creates a new todo item.", "parameters": [ @@ -90,9 +86,7 @@ "/v1/todos/{id}": { "get": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "description": "Returns a specific todo item.", "parameters": [ diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=v2.verified.txt b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=v2.verified.txt index b93d00d293dd..fed56ba97790 100644 --- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=v2.verified.txt +++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=v2.verified.txt @@ -15,9 +15,7 @@ "/v2/users": { "get": { "tags": [ - { - "name": "users" - } + "users" ], "responses": { "200": { @@ -45,9 +43,7 @@ }, "post": { "tags": [ - { - "name": "Sample" - } + "Sample" ], "externalDocs": { "description": "Documentation for this OpenAPI endpoint", diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiDocumentService/OpenApiDocumentServiceTests.Operations.cs b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiDocumentService/OpenApiDocumentServiceTests.Operations.cs index 8cfe2573f0f5..88ec906628b7 100644 --- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiDocumentService/OpenApiDocumentServiceTests.Operations.cs +++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiDocumentService/OpenApiDocumentServiceTests.Operations.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.OpenApi; using Microsoft.AspNetCore.Routing; using Microsoft.OpenApi.Models; @@ -181,6 +182,62 @@ await VerifyOpenApiDocument(builder, document => }); } + [Fact] + public async Task GetOpenApiOperation_EditingReferenceInOperationThrowsException() + { + // Arrange + var builder = CreateBuilder(); + + // Act + builder.MapGet("/api/todos", () => { }).WithTags(["todos"]); + var options = new OpenApiOptions(); + options.AddOperationTransformer((operation, context, cancellationToken) => + { + foreach (var tag in operation.Tags) + { + tag.Name = "newTag"; // Should throw exception + } + return Task.CompletedTask; + }); + + // Assert + var exception = await Assert.ThrowsAsync(() => VerifyOpenApiDocument(builder, options, _ => { })); + Assert.Equal("Setting the value from the reference is not supported, use the target property instead.", exception.Message); + } + + [Fact] + public async Task GetOpenApiOperation_EditingTargetTagInOperationWorks() + { + // Arrange + var builder = CreateBuilder(); + + // Act + builder.MapGet("/api/todos", () => { }).WithTags(["todos"]); + var options = new OpenApiOptions(); + options.AddOperationTransformer((operation, context, cancellationToken) => + { + foreach (var tag in operation.Tags) + { + tag.Target.Name = "newTag"; + } + return Task.CompletedTask; + }); + + // Assert + await VerifyOpenApiDocument(builder, options, document => + { + var operation = document.Paths["/api/todos"].Operations[OperationType.Get]; + Assert.Collection(operation.Tags, tag => + { + Assert.Equal("newTag", tag.Name); + }); + Assert.Collection(document.Tags, tag => + { + Assert.Equal("newTag", tag.Name); + }); + }); + } + [Fact] public async Task GetOpenApiOperation_CapturesEndpointNameAsOperationId() { diff --git a/src/Tools/GetDocumentInsider/tests/GetDocumentTests.cs b/src/Tools/GetDocumentInsider/tests/GetDocumentTests.cs index af0900881224..29a2cddefe1f 100644 --- a/src/Tools/GetDocumentInsider/tests/GetDocumentTests.cs +++ b/src/Tools/GetDocumentInsider/tests/GetDocumentTests.cs @@ -66,8 +66,7 @@ public void GetDocument_WithOpenApiVersion_Works() // Assert using var stream = new MemoryStream(File.ReadAllBytes(Path.Combine(outputPath.FullName, "Sample.json"))); var result = OpenApiDocument.Load(stream, "json"); - // TODO: Needs https://github.com/microsoft/OpenAPI.NET/issues/2055 to be fixed - // Assert.Empty(result.Diagnostic.Errors); + Assert.Empty(result.Diagnostic.Errors); Assert.Equal(OpenApiSpecVersion.OpenApi2_0, result.Diagnostic.SpecificationVersion); Assert.Equal("GetDocumentSample | v1", result.Document.Info.Title); } @@ -94,8 +93,7 @@ public void GetDocument_WithInvalidOpenApiVersion_Errors() Assert.Contains("Invalid OpenAPI spec version 'OpenApi4_0' provided. Falling back to default: v3.0.", _console.GetOutput()); using var stream = new MemoryStream(File.ReadAllBytes(Path.Combine(outputPath.FullName, "Sample.json"))); var result = OpenApiDocument.Load(stream, "json"); - // TODO: Needs https://github.com/microsoft/OpenAPI.NET/issues/2055 to be fixed - // Assert.Empty(result.Diagnostic.Errors); + Assert.Empty(result.Diagnostic.Errors); Assert.Equal(OpenApiSpecVersion.OpenApi3_1, result.Diagnostic.SpecificationVersion); Assert.Equal("GetDocumentSample | v1", result.Document.Info.Title); } @@ -128,8 +126,7 @@ public void GetDocument_WithDocumentName_Works() using var stream = new MemoryStream(File.ReadAllBytes(Path.Combine(outputPath.FullName, "Sample_internal.json"))); var result = OpenApiDocument.Load(stream, "json"); - // TODO: Needs https://github.com/microsoft/OpenAPI.NET/issues/2055 to be fixed - // Assert.Empty(result.Diagnostic.Errors); + Assert.Empty(result.Diagnostic.Errors); Assert.Equal(OpenApiSpecVersion.OpenApi3_1, result.Diagnostic.SpecificationVersion); // Document name in the title gives us a clue that the correct document was actually resolved Assert.Equal("GetDocumentSample | internal", result.Document.Info.Title);