diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs new file mode 100644 index 000000000..5a1f33e7a --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the response object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiResponse : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible +{ + /// + /// Maps a header name to its definition. + /// + public IDictionary Headers { get; } + + /// + /// A map containing descriptions of potential response payloads. + /// The key is a media type or media type range and the value describes it. + /// + public IDictionary Content { get; } + + /// + /// A map of operations links that can be followed from the response. + /// The key of the map is a short name for the link, + /// following the naming constraints of the names for Component Objects. + /// + public IDictionary Links { get; } +} diff --git a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs index f58d2644a..6d65ef7b1 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs @@ -23,9 +23,9 @@ public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible public IDictionary? Schemas { get; set; } = new Dictionary(); /// - /// An object to hold reusable Objects. + /// An object to hold reusable Objects. /// - public IDictionary? Responses { get; set; } = new Dictionary(); + public IDictionary? Responses { get; set; } = new Dictionary(); /// /// An object to hold reusable Objects. @@ -86,7 +86,7 @@ public OpenApiComponents() { } public OpenApiComponents(OpenApiComponents? components) { Schemas = components?.Schemas != null ? new Dictionary(components.Schemas) : null; - Responses = components?.Responses != null ? new Dictionary(components.Responses) : null; + Responses = components?.Responses != null ? new Dictionary(components.Responses) : null; Parameters = components?.Parameters != null ? new Dictionary(components.Parameters) : null; Examples = components?.Examples != null ? new Dictionary(components.Examples) : null; RequestBodies = components?.RequestBodies != null ? new Dictionary(components.RequestBodies) : null; diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index 52e2243b7..32afbdf90 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -596,7 +596,7 @@ public bool AddComponent(string id, T componentToRegister) Components.Parameters.Add(id, openApiParameter); break; case OpenApiResponse openApiResponse: - Components.Responses ??= new Dictionary(); + Components.Responses ??= new Dictionary(); Components.Responses.Add(id, openApiResponse); break; case OpenApiRequestBody openApiRequestBody: diff --git a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs index 927bf839a..a3ded96eb 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs @@ -279,8 +279,10 @@ public void SerializeAsV2(IOpenApiWriter writer) .SelectMany(static r => r.Value.Content?.Keys ?? []) .Concat( Responses - .Where(static r => r.Value.Reference is {HostDocument: not null}) - .SelectMany(static r => r.Value.Content?.Keys ?? [])) + .Select(static r => r.Value) + .OfType() + .Where(static r => r.Reference is {HostDocument: not null}) + .SelectMany(static r => r.Content?.Keys ?? [])) .Distinct(StringComparer.OrdinalIgnoreCase) .ToArray(); diff --git a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs index 3896c6b76..cf2a54cfb 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs @@ -13,45 +13,22 @@ namespace Microsoft.OpenApi.Models /// /// Response object. /// - public class OpenApiResponse : IOpenApiReferenceable, IOpenApiExtensible + public class OpenApiResponse : IOpenApiReferenceable, IOpenApiExtensible, IOpenApiResponse { - /// - /// REQUIRED. A short description of the response. - /// - public virtual string Description { get; set; } - - /// - /// Maps a header name to its definition. - /// - public virtual IDictionary Headers { get; set; } = new Dictionary(); - - /// - /// A map containing descriptions of potential response payloads. - /// The key is a media type or media type range and the value describes it. - /// - public virtual IDictionary Content { get; set; } = new Dictionary(); + /// + public string Description { get; set; } - /// - /// A map of operations links that can be followed from the response. - /// The key of the map is a short name for the link, - /// following the naming constraints of the names for Component Objects. - /// - public virtual IDictionary Links { get; set; } = new Dictionary(); + /// + public IDictionary Headers { get; set; } = new Dictionary(); - /// - /// This object MAY be extended with Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); + /// + public IDictionary Content { get; set; } = new Dictionary(); - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - public bool UnresolvedReference { get; set; } + /// + public IDictionary Links { get; set; } = new Dictionary(); - /// - /// Reference pointer. - /// - public OpenApiReference Reference { get; set; } + /// + public IDictionary Extensions { get; set; } = new Dictionary(); /// /// Parameterless constructor @@ -59,23 +36,22 @@ public class OpenApiResponse : IOpenApiReferenceable, IOpenApiExtensible public OpenApiResponse() { } /// - /// Initializes a copy of object + /// Initializes a copy of object /// - public OpenApiResponse(OpenApiResponse response) + public OpenApiResponse(IOpenApiResponse response) { + Utils.CheckArgumentNull(response); Description = response?.Description ?? Description; Headers = response?.Headers != null ? new Dictionary(response.Headers) : null; Content = response?.Content != null ? new Dictionary(response.Content) : null; Links = response?.Links != null ? new Dictionary(response.Links) : null; Extensions = response?.Extensions != null ? new Dictionary(response.Extensions) : null; - UnresolvedReference = response?.UnresolvedReference ?? UnresolvedReference; - Reference = response?.Reference != null ? new(response?.Reference) : null; } /// /// Serialize to Open Api v3.1 /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); } @@ -83,12 +59,12 @@ public virtual void SerializeAsV31(IOpenApiWriter writer) /// /// Serialize to Open Api v3.0. /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -116,7 +92,7 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio /// /// Serialize to OpenAPI V2 document without using reference. /// - public virtual void SerializeAsV2(IOpenApiWriter writer) + public void SerializeAsV2(IOpenApiWriter writer) { Utils.CheckArgumentNull(writer); diff --git a/src/Microsoft.OpenApi/Models/OpenApiResponses.cs b/src/Microsoft.OpenApi/Models/OpenApiResponses.cs index 8880c244f..855ac6834 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiResponses.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiResponses.cs @@ -1,12 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using Microsoft.OpenApi.Models.Interfaces; + namespace Microsoft.OpenApi.Models { /// /// Responses object. /// - public class OpenApiResponses : OpenApiExtensibleDictionary + public class OpenApiResponses : OpenApiExtensibleDictionary { /// /// Parameterless constructor diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs index 57d8fba2b..ef6b68fff 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs @@ -5,34 +5,14 @@ using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models.Interfaces; -using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models.References { /// /// Response Object Reference. /// - public class OpenApiResponseReference : OpenApiResponse, IOpenApiReferenceHolder + public class OpenApiResponseReference : BaseOpenApiReferenceHolder, IOpenApiResponse { - internal OpenApiResponse _target; - private readonly OpenApiReference _reference; - private string _description; - - /// - /// Gets the target response. - /// - /// - /// If the reference is not resolved, this will return null. - /// - public OpenApiResponse Target - { - get - { - _target ??= Reference.HostDocument?.ResolveReferenceTo(_reference); - return _target; - } - } - /// /// Constructor initializing the reference object. /// @@ -43,102 +23,43 @@ public OpenApiResponse Target /// 1. a absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - public OpenApiResponseReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null) + public OpenApiResponseReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Response, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - _reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.Response, - ExternalResource = externalResource - }; - - Reference = _reference; } - internal OpenApiResponseReference(string referenceId, OpenApiResponse target) + internal OpenApiResponseReference(OpenApiResponse target, string referenceId):base(target, referenceId, ReferenceType.Response) { - _target ??= target; - - _reference = new OpenApiReference() - { - Id = referenceId, - Type = ReferenceType.Response, - }; - - Reference = _reference; } /// - public override string Description + public string Description { - get => string.IsNullOrEmpty(_description) ? Target?.Description : _description; - set => _description = value; + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + set + { + if (Reference is not null) + { + Reference.Description = value; + } + } } - private IDictionary _content; /// - public override IDictionary Content { get => _content is not null ? _content : Target?.Content; set => _content = value; } + public IDictionary Content { get => Target?.Content; } - private IDictionary _headers; /// - public override IDictionary Headers { get => _headers is not null ? _headers : Target?.Headers; set => _headers = value; } + public IDictionary Headers { get => Target?.Headers; } - private IDictionary _links; /// - public override IDictionary Links { get => _links is not null ? _links : Target?.Links; set => _links = value; } + public IDictionary Links { get => Target?.Links; } - private IDictionary _extensions; - /// - public override IDictionary Extensions { get => _extensions is not null ? _extensions : Target?.Extensions; set => _extensions = value; } - /// - public override void SerializeAsV3(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV3(writer); - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); - } - } - - /// - public override void SerializeAsV31(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV31(writer); - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); - } - } - - /// - public override void SerializeAsV2(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV2(writer); - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV2(writer)); - } - } + public IDictionary Extensions { get => Target?.Extensions; } /// - private void SerializeInternal(IOpenApiWriter writer, - Action action) + public override IOpenApiResponse CopyReferenceAsTargetElementWithOverrides(IOpenApiResponse source) { - Utils.CheckArgumentNull(writer); - action(writer, this); + return source is OpenApiResponse ? new OpenApiResponse(this) : source; } } } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs index ee0bf0c8f..a09d2eab9 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs @@ -235,7 +235,7 @@ public static OpenApiDocument LoadOpenApi(RootNode rootNode) rootNode.GetMap(), openApiDoc.Paths.Values .SelectMany(path => path.Operations?.Values ?? Enumerable.Empty()) - .SelectMany(operation => operation.Responses?.Values ?? Enumerable.Empty()), + .SelectMany(operation => operation.Responses?.Values ?? Enumerable.Empty()), openApiNode.Context); } @@ -257,11 +257,11 @@ public static OpenApiDocument LoadOpenApi(RootNode rootNode) return openApiDoc; } - private static void ProcessResponsesMediaTypes(MapNode mapNode, IEnumerable responses, ParsingContext context) + private static void ProcessResponsesMediaTypes(MapNode mapNode, IEnumerable responses, ParsingContext context) { if (responses != null) { - foreach (var response in responses) + foreach (var response in responses.OfType()) { ProcessProduces(mapNode, response, context); diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs index 957a02ab7..140ad9f3d 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs @@ -121,7 +121,7 @@ internal static OpenApiOperation LoadOperation(ParseNode node, OpenApiDocument h } } - foreach (var response in operation.Responses.Values) + foreach (var response in operation.Responses.Values.OfType()) { ProcessProduces(node.CheckMapNode("responses"), response, node.Context); } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs index 2716c499b..d730c8227 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs @@ -179,7 +179,7 @@ private static void LoadExample(OpenApiResponse response, string mediaType, Pars mediaTypeObject.Example = exampleNode; } - public static OpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("response"); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs index c159443ad..a85ed5fe1 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs @@ -3,6 +3,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -40,7 +41,7 @@ internal static partial class OpenApiV3Deserializer {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("response"); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs index 7288c04b1..6d03fe86b 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -17,8 +18,8 @@ internal static partial class OpenApiV3Deserializer public static readonly PatternFieldMap ResponsesPatternFields = new() { - {s => !s.StartsWith("x-"), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => !s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, + {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiResponses LoadResponses(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs index 8e4057a91..a71fd5369 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs @@ -1,5 +1,6 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -45,7 +46,7 @@ internal static partial class OpenApiV31Deserializer {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("response"); diff --git a/src/Microsoft.OpenApi/Services/CopyReferences.cs b/src/Microsoft.OpenApi/Services/CopyReferences.cs index eadabbaaf..6fbcbcc4a 100644 --- a/src/Microsoft.OpenApi/Services/CopyReferences.cs +++ b/src/Microsoft.OpenApi/Services/CopyReferences.cs @@ -109,9 +109,9 @@ private void AddResponseToComponents(OpenApiResponse response, string referenceI { EnsureComponentsExist(); EnsureResponsesExist(); - if (!Components.Responses.ContainsKey(referenceId ?? response.Reference.Id)) + if (!Components.Responses.ContainsKey(referenceId)) { - Components.Responses.Add(referenceId ?? response.Reference.Id, response); + Components.Responses.Add(referenceId, response); } } private void AddRequestBodyToComponents(OpenApiRequestBody requestBody, string referenceId = null) @@ -210,7 +210,7 @@ private void EnsureParametersExist() private void EnsureResponsesExist() { - _target.Components.Responses ??= new Dictionary(); + _target.Components.Responses ??= new Dictionary(); } private void EnsureRequestBodiesExist() diff --git a/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs b/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs index f118a3f06..b2eb9eab1 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs @@ -176,7 +176,7 @@ public virtual void Visit(IDictionary callbacks) /// /// Visits /// - public virtual void Visit(OpenApiResponse response) + public virtual void Visit(IOpenApiResponse response) { } diff --git a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs index b76f33ad9..41d7561ab 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs @@ -692,7 +692,7 @@ internal void Walk(OpenApiResponses responses) /// /// Visits and child objects /// - internal void Walk(OpenApiResponse response, bool isComponent = false) + internal void Walk(IOpenApiResponse response, bool isComponent = false) { if (response == null) { diff --git a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs index a5a4885de..0e1251d2e 100644 --- a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs +++ b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs @@ -84,7 +84,7 @@ public void AddWarning(OpenApiValidatorWarning warning) public override void Visit(IOpenApiHeader header) => Validate(header); /// - public override void Visit(OpenApiResponse response) => Validate(response); + public override void Visit(IOpenApiResponse response) => Validate(response); /// public override void Visit(OpenApiMediaType mediaType) => Validate(mediaType); diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiResponseRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiResponseRules.cs index f30b49ea0..ff0503f9b 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiResponseRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiResponseRules.cs @@ -3,6 +3,7 @@ using System; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Properties; namespace Microsoft.OpenApi.Validations.Rules @@ -16,7 +17,7 @@ public static class OpenApiResponseRules /// /// Validate the field is required. /// - public static ValidationRule ResponseRequiredFields => + public static ValidationRule ResponseRequiredFields => new(nameof(ResponseRequiredFields), (context, response) => { diff --git a/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs b/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs index 3c3644adf..0d25c7704 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs @@ -60,7 +60,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200",new() + "200",new OpenApiResponse() { Description = "OK" } @@ -97,7 +97,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Success", Content = new Dictionary @@ -162,7 +162,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Success", Content = new Dictionary @@ -210,7 +210,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved entities", Content = new Dictionary @@ -264,7 +264,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved entity", Content = new Dictionary @@ -297,7 +297,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "204", new() + "204", new OpenApiResponse() { Description = "Success" } @@ -335,7 +335,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved navigation property", Content = new Dictionary @@ -390,7 +390,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Success", Content = new Dictionary @@ -432,7 +432,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "204", new() + "204", new OpenApiResponse() { Description = "Success" } @@ -454,7 +454,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved navigation property", Content = new Dictionary @@ -528,7 +528,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "204", new() + "204", new OpenApiResponse() { Description = "Success" } @@ -593,7 +593,7 @@ public static OpenApiDocument CreateOpenApiDocument() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Success", Content = new Dictionary diff --git a/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs b/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs index ad8495494..8440e8df4 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs @@ -74,7 +74,7 @@ public async Task LoadResponseReference() var reference = new OpenApiResponseReference("NotFound", result.Document); // Assert - reference.Should().BeEquivalentTo( + Assert.Equivalent( new OpenApiResponse { Description = "Entity not found.", @@ -82,7 +82,7 @@ public async Task LoadResponseReference() { ["application/json"] = new() } - }, options => options.Excluding(x => x.Reference) + }, reference ); } @@ -93,7 +93,7 @@ public async Task LoadResponseAndSchemaReference() var reference = new OpenApiResponseReference("GeneralError", result.Document); // Assert - reference.Should().BeEquivalentTo( + Assert.Equivalent( new OpenApiResponse { Description = "General Error", @@ -124,13 +124,8 @@ public async Task LoadResponseAndSchemaReference() } } } - }, - Reference = new() - { - Type = ReferenceType.Response, - Id = "GeneralError" } - }, options => options.Excluding(x => x.Reference) + }, reference ); } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs index 0b14a01f9..5993d4e2c 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs @@ -178,7 +178,7 @@ public async Task ShouldParseProducesInAnyOrder() { Responses = { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "An OK response", Content = @@ -187,7 +187,7 @@ public async Task ShouldParseProducesInAnyOrder() ["application/xml"] = okMediaType, } }, - ["default"] = new() + ["default"] = new OpenApiResponse() { Description = "An error response", Content = @@ -202,7 +202,7 @@ public async Task ShouldParseProducesInAnyOrder() { Responses = { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "An OK response", Content = @@ -210,7 +210,7 @@ public async Task ShouldParseProducesInAnyOrder() ["html/text"] = okMediaType } }, - ["default"] = new() + ["default"] = new OpenApiResponse() { Description = "An error response", Content = @@ -224,7 +224,7 @@ public async Task ShouldParseProducesInAnyOrder() { Responses = { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "An OK response", Content = @@ -233,7 +233,7 @@ public async Task ShouldParseProducesInAnyOrder() ["application/xml"] = okMediaType, } }, - ["default"] = new() + ["default"] = new OpenApiResponse() { Description = "An error response", Content = diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs index 35ffd15d5..a86d84bdd 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs @@ -6,7 +6,6 @@ using System.IO; using System.Linq; using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Reader.V2; using Xunit; @@ -116,7 +115,7 @@ public class OpenApiPathItemTests }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "Pet updated.", Content = new Dictionary @@ -125,7 +124,7 @@ public class OpenApiPathItemTests ["application/xml"] = new() } }, - ["405"] = new() + ["405"] = new OpenApiResponse() { Description = "Invalid input", Content = new Dictionary @@ -232,7 +231,7 @@ public class OpenApiPathItemTests }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "Pet updated.", Content = new Dictionary diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs index 267e29ede..c84788ba8 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs @@ -43,7 +43,7 @@ public class OpenApiCallbackTests }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "Success" } @@ -83,7 +83,7 @@ public class OpenApiCallbackTests }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "Success" } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs index c333fcdb7..5c905f238 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs @@ -1120,7 +1120,7 @@ public OpenApiDocumentTests() }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "pet response", Content = new Dictionary @@ -1143,7 +1143,7 @@ public OpenApiDocumentTests() } } }, - ["4XX"] = new() + ["4XX"] = new OpenApiResponse() { Description = "unexpected client error", Content = new Dictionary @@ -1154,7 +1154,7 @@ public OpenApiDocumentTests() } } }, - ["5XX"] = new() + ["5XX"] = new OpenApiResponse() { Description = "unexpected server error", Content = new Dictionary @@ -1185,7 +1185,7 @@ public OpenApiDocumentTests() }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "pet response", Content = new Dictionary @@ -1196,7 +1196,7 @@ public OpenApiDocumentTests() }, } }, - ["4XX"] = new() + ["4XX"] = new OpenApiResponse() { Description = "unexpected client error", Content = new Dictionary @@ -1207,7 +1207,7 @@ public OpenApiDocumentTests() } } }, - ["5XX"] = new() + ["5XX"] = new OpenApiResponse() { Description = "unexpected server error", Content = new Dictionary @@ -1248,7 +1248,7 @@ public OpenApiDocumentTests() }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "pet response", Content = new Dictionary @@ -1263,7 +1263,7 @@ public OpenApiDocumentTests() } } }, - ["4XX"] = new() + ["4XX"] = new OpenApiResponse() { Description = "unexpected client error", Content = new Dictionary @@ -1274,7 +1274,7 @@ public OpenApiDocumentTests() } } }, - ["5XX"] = new() + ["5XX"] = new OpenApiResponse() { Description = "unexpected server error", Content = new Dictionary @@ -1308,11 +1308,11 @@ public OpenApiDocumentTests() }, Responses = new() { - ["204"] = new() + ["204"] = new OpenApiResponse() { Description = "pet deleted" }, - ["4XX"] = new() + ["4XX"] = new OpenApiResponse() { Description = "unexpected client error", Content = new Dictionary @@ -1323,7 +1323,7 @@ public OpenApiDocumentTests() } } }, - ["5XX"] = new() + ["5XX"] = new OpenApiResponse() { Description = "unexpected server error", Content = new Dictionary diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs index 6b3c61417..df6b069ed 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs @@ -58,8 +58,22 @@ public class OpenApiOperationTests }, Responses = new() { - ["200"] = new OpenApiResponseReference("response1", hostDocument: null), - ["400"] = new() + ["200"] = new OpenApiResponseReference(new OpenApiResponse() + { + Content = new Dictionary + { + ["application/json"] = new() + { + Schema = new() + { + Type = JsonSchemaType.Number, + Minimum = 5, + Maximum = 10 + } + } + } + }, "response1"), + ["400"] = new OpenApiResponse() { Content = new Dictionary { @@ -132,8 +146,22 @@ public class OpenApiOperationTests }, Responses = new() { - ["200"] = new OpenApiResponseReference("response1", hostDocument: null), - ["400"] = new() + ["200"] = new OpenApiResponseReference(new OpenApiResponse() + { + Content = new Dictionary + { + ["application/json"] = new() + { + Schema = new() + { + Type = JsonSchemaType.Number, + Minimum = 5, + Maximum = 10 + } + } + } + }, "response1"), + ["400"] = new OpenApiResponse() { Content = new Dictionary { @@ -245,11 +273,11 @@ public class OpenApiOperationTests }, Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "Pet updated." }, - ["405"] = new() + ["405"] = new OpenApiResponse() { Description = "Invalid input" } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs index 14d14e4be..f0991a1cb 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs @@ -101,7 +101,7 @@ public class OpenApiResponseTests } }; - public static OpenApiResponseReference V2OpenApiResponseReference = new OpenApiResponseReference("example1", ReferencedV2Response); + public static OpenApiResponseReference V2OpenApiResponseReference = new OpenApiResponseReference(ReferencedV2Response, "example1"); public static OpenApiResponse ReferencedV2Response = new OpenApiResponse { Description = "A complex object array response", @@ -136,7 +136,7 @@ public class OpenApiResponseTests }, } }; - public static OpenApiResponseReference V3OpenApiResponseReference = new OpenApiResponseReference("example1", ReferencedV3Response); + public static OpenApiResponseReference V3OpenApiResponseReference = new OpenApiResponseReference(ReferencedV3Response, "example1"); public static OpenApiResponse ReferencedV3Response = new OpenApiResponse { diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt similarity index 61% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt index 3b61b5a39..a3164d20f 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -1,3 +1,4 @@ { + "description": "OK response", "$ref": "#/components/responses/OkResponse" } \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..851a6a027 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt @@ -0,0 +1,15 @@ +{ + "description": "OK response", + "content": { + "text/plain": { + "schema": { + "type": "object", + "properties": { + "sound": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..4d825baf4 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"description":"OK response","$ref":"#/components/responses/OkResponse"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..04256c77a --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt @@ -0,0 +1 @@ +{"description":"OK response","content":{"text/plain":{"schema":{"type":"object","properties":{"sound":{"type":"string"}}}}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..2408f8a10 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt @@ -0,0 +1,15 @@ +{ + "description": "OK", + "content": { + "text/plain": { + "schema": { + "type": "object", + "properties": { + "sound": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt deleted file mode 100644 index d4776f5df..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"$ref":"#/components/responses/OkResponse"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt new file mode 100644 index 000000000..c83ea5371 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.SerializeResponseReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt @@ -0,0 +1 @@ +{"description":"OK","content":{"text/plain":{"schema":{"type":"object","properties":{"sound":{"type":"string"}}}}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs index b39d6040b..196759540 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs @@ -104,37 +104,41 @@ public void ResponseReferenceResolutionWorks() } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeResponseReferenceAsV3JsonWorks(bool produceTerseOutput) + [InlineData(true, false)] + [InlineData(false, false)] + [InlineData(true, true)] + [InlineData(false, true)] + public async Task SerializeResponseReferenceAsV3JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput}); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localResponseReference.SerializeAsV3(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeResponseReferenceAsV31JsonWorks(bool produceTerseOutput) + [InlineData(true, false)] + [InlineData(false, false)] + [InlineData(true, true)] + [InlineData(false, true)] + public async Task SerializeResponseReferenceAsV31JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput}); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _localResponseReference.SerializeAsV31(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } } } diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 93aef1c4b..e5c9f7bb1 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -399,6 +399,12 @@ namespace Microsoft.OpenApi.Models.Interfaces Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter ConvertToBodyParameter(Microsoft.OpenApi.Writers.IOpenApiWriter writer); System.Collections.Generic.IEnumerable ConvertToFormDataParameters(Microsoft.OpenApi.Writers.IOpenApiWriter writer); } + public interface IOpenApiResponse : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + { + System.Collections.Generic.IDictionary Content { get; } + System.Collections.Generic.IDictionary Headers { get; } + System.Collections.Generic.IDictionary Links { get; } + } public interface IOpenApiSummarizedElement : Microsoft.OpenApi.Interfaces.IOpenApiElement { string Summary { get; set; } @@ -440,7 +446,7 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IDictionary? Parameters { get; set; } public System.Collections.Generic.IDictionary? PathItems { get; set; } public System.Collections.Generic.IDictionary? RequestBodies { get; set; } - public System.Collections.Generic.IDictionary? Responses { get; set; } + public System.Collections.Generic.IDictionary? Responses { get; set; } public System.Collections.Generic.IDictionary? Schemas { get; set; } public System.Collections.Generic.IDictionary? SecuritySchemes { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -912,22 +918,20 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiResponse : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiResponse : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse { public OpenApiResponse() { } - public OpenApiResponse(Microsoft.OpenApi.Models.OpenApiResponse response) { } - public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public bool UnresolvedReference { get; set; } - public virtual System.Collections.Generic.IDictionary Content { get; set; } - public virtual string Description { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual System.Collections.Generic.IDictionary Headers { get; set; } - public virtual System.Collections.Generic.IDictionary Links { get; set; } - public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public OpenApiResponse(Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse response) { } + public System.Collections.Generic.IDictionary Content { get; set; } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public System.Collections.Generic.IDictionary Headers { get; set; } + public System.Collections.Generic.IDictionary Links { get; set; } + public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiResponses : Microsoft.OpenApi.Models.OpenApiExtensibleDictionary + public class OpenApiResponses : Microsoft.OpenApi.Models.OpenApiExtensibleDictionary { public OpenApiResponses() { } public OpenApiResponses(Microsoft.OpenApi.Models.OpenApiResponses openApiResponses) { } @@ -1277,18 +1281,15 @@ namespace Microsoft.OpenApi.Models.References public override Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody source) { } public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiResponseReference : Microsoft.OpenApi.Models.OpenApiResponse, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiResponseReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse { public OpenApiResponseReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiResponse Target { get; } - public override System.Collections.Generic.IDictionary Content { get; set; } - public override string Description { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override System.Collections.Generic.IDictionary Headers { get; set; } - public override System.Collections.Generic.IDictionary Links { get; set; } - public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public System.Collections.Generic.IDictionary Content { get; } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; } + public System.Collections.Generic.IDictionary Headers { get; } + public System.Collections.Generic.IDictionary Links { get; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse source) { } } public class OpenApiSchemaReference : Microsoft.OpenApi.Models.OpenApiSchema, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -1565,6 +1566,7 @@ namespace Microsoft.OpenApi.Services public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter parameter) { } public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem pathItem) { } public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody requestBody) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse response) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiComponents components) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiContact contact) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiDocument doc) { } @@ -1576,7 +1578,6 @@ namespace Microsoft.OpenApi.Services public virtual void Visit(Microsoft.OpenApi.Models.OpenApiOAuthFlow openApiOAuthFlow) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiOperation operation) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiPaths paths) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiResponse response) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiResponses response) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiSchema schema) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiSecurityRequirement securityRequirement) { } @@ -1664,6 +1665,7 @@ namespace Microsoft.OpenApi.Validations public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter parameter) { } public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem pathItem) { } public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody requestBody) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse response) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiComponents components) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiContact contact) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiDocument doc) { } @@ -1675,7 +1677,6 @@ namespace Microsoft.OpenApi.Validations public override void Visit(Microsoft.OpenApi.Models.OpenApiOAuthFlow openApiOAuthFlow) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiOperation operation) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiPaths paths) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiResponse response) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiResponses response) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiSchema schema) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiSecurityRequirement securityRequirement) { } @@ -1806,7 +1807,7 @@ namespace Microsoft.OpenApi.Validations.Rules [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiResponseRules { - public static Microsoft.OpenApi.Validations.ValidationRule ResponseRequiredFields { get; } + public static Microsoft.OpenApi.Validations.ValidationRule ResponseRequiredFields { get; } } [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiResponsesRules diff --git a/test/Microsoft.OpenApi.Tests/Services/OpenApiUrlTreeNodeTests.cs b/test/Microsoft.OpenApi.Tests/Services/OpenApiUrlTreeNodeTests.cs index 7c21e1a6e..33296cfed6 100644 --- a/test/Microsoft.OpenApi.Tests/Services/OpenApiUrlTreeNodeTests.cs +++ b/test/Microsoft.OpenApi.Tests/Services/OpenApiUrlTreeNodeTests.cs @@ -157,7 +157,7 @@ public void AttachPathWorks() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved entities" } @@ -182,7 +182,7 @@ public void AttachPathWorks() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved entities" } @@ -249,7 +249,7 @@ public void HasOperationsWorks() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved entity" } @@ -277,7 +277,7 @@ public void HasOperationsWorks() Responses = new() { { - "200", new() + "200", new OpenApiResponse() { Description = "Retrieved entity" } @@ -292,7 +292,7 @@ public void HasOperationsWorks() Responses = new() { { - "204", new() + "204", new OpenApiResponse() { Description = "Success." } diff --git a/test/Microsoft.OpenApi.Tests/Services/OpenApiValidatorTests.cs b/test/Microsoft.OpenApi.Tests/Services/OpenApiValidatorTests.cs index 317719fcd..d11786d5b 100644 --- a/test/Microsoft.OpenApi.Tests/Services/OpenApiValidatorTests.cs +++ b/test/Microsoft.OpenApi.Tests/Services/OpenApiValidatorTests.cs @@ -23,28 +23,30 @@ public class OpenApiValidatorTests [Fact] public void ResponseMustHaveADescription() { - var openApiDocument = new OpenApiDocument(); - openApiDocument.Info = new() - { - Title = "foo", - Version = "1.2.2" - }; - openApiDocument.Paths = new() + var openApiDocument = new OpenApiDocument { + Info = new() + { + Title = "foo", + Version = "1.2.2" + }, + Paths = new() { - "/test", - new OpenApiPathItem() - { - Operations = { - [OperationType.Get] = new() + "/test", + new OpenApiPathItem() { - Responses = + Operations = + { + [OperationType.Get] = new() { - ["200"] = new() + Responses = + { + ["200"] = new OpenApiResponse() + } } } - } + } } } }; diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiComponentsValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiComponentsValidationTests.cs index fe2a230e2..de83299fc 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiComponentsValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiComponentsValidationTests.cs @@ -5,6 +5,7 @@ using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Properties; using Microsoft.OpenApi.Validations.Rules; using Xunit; @@ -21,7 +22,7 @@ public void ValidateKeyMustMatchRegularExpressionInComponents() var components = new OpenApiComponents { - Responses = new Dictionary + Responses = new Dictionary { { key, new OpenApiResponse { Description = "any" } } } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs index 646acdbcc..de9d58443 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs @@ -47,7 +47,7 @@ public void ReferencedSchemaShouldOnlyBeValidatedOnce() { Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Content = new Dictionary { @@ -105,7 +105,7 @@ public void UnresolvedSchemaReferencedShouldNotBeValidated() { Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Content = new Dictionary { diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiResponseValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiResponseValidationTests.cs index c1b4ce62d..2350c184b 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiResponseValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiResponseValidationTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Properties; using Microsoft.OpenApi.Services; using Xunit; @@ -22,15 +23,15 @@ public void ValidateDescriptionIsRequiredInResponse() // Act var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet()); var walker = new OpenApiWalker(validator); - walker.Walk(response); + walker.Walk((IOpenApiResponse)response); errors = validator.Errors; - var result = !errors.Any(); // Assert - Assert.False(result); + Assert.NotEmpty(errors); Assert.NotNull(errors); - var error = Assert.Single(errors) as OpenApiValidatorError; + Assert.Single(errors); + var error = Assert.IsType(errors.First()); Assert.Equal(string.Format(SRResource.Validation_FieldIsRequired, "description", "response"), error.Message); Assert.Equal("#/description", error.Pointer); } diff --git a/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs b/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs index 49595a1be..fbe0abf14 100644 --- a/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs @@ -35,7 +35,7 @@ public void ExpectedVirtualsInvolved() visitor.Visit(default(IOpenApiRequestBody)); visitor.Visit(default(IDictionary)); visitor.Visit(default(IDictionary)); - visitor.Visit(default(OpenApiResponse)); + visitor.Visit(default(IOpenApiResponse)); visitor.Visit(default(OpenApiResponses)); visitor.Visit(default(IDictionary)); visitor.Visit(default(OpenApiMediaType)); @@ -184,7 +184,7 @@ public override void Visit(IDictionary callbacks) base.Visit(callbacks); } - public override void Visit(OpenApiResponse response) + public override void Visit(IOpenApiResponse response) { EncodeCall(); base.Visit(response); diff --git a/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs b/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs index c21233b9a..c4ed91658 100644 --- a/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs @@ -74,7 +74,7 @@ public void LocatePathOperationContentSchema() { Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Content = new Dictionary { @@ -192,7 +192,7 @@ public void LocateReferences() { Responses = new() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Content = new Dictionary { @@ -284,7 +284,7 @@ public override void Visit(OpenApiOperation operation) Keys.Add(CurrentKeys.Operation.ToString()); Locations.Add(this.PathString); } - public override void Visit(OpenApiResponse response) + public override void Visit(IOpenApiResponse response) { Keys.Add(CurrentKeys.Response); Locations.Add(this.PathString); diff --git a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs index bd74197b0..14e017fe9 100644 --- a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs @@ -27,7 +27,7 @@ public void OpenApiWorkspacesCanAddComponentsFromAnotherDocument() { Responses = new OpenApiResponses() { - ["200"] = new() + ["200"] = new OpenApiResponse() { Content = new Dictionary() { diff --git a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs index 5fc8be43b..f10dba764 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs @@ -464,7 +464,7 @@ private static OpenApiDocument CreateDocWithSimpleSchemaToInline() [OperationType.Get] = new() { Responses = { - ["200"] = new() + ["200"] = new OpenApiResponse() { Description = "OK", Content = {