diff --git a/.editorconfig b/.editorconfig index fd54f541b9..92b978a85c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -31,3 +31,13 @@ trim_trailing_whitespace = true [*.cs] dotnet_sort_system_directives_first = true + +# Verify settings +[*.{received,verified}.{txt,xml,json}] +charset = "utf-8-bom" +end_of_line = lf +indent_size = unset +indent_style = unset +insert_final_newline = false +tab_width = unset +trim_trailing_whitespace = false \ No newline at end of file diff --git a/.gitattributes b/.gitattributes index e3eb50d710..644430043e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,5 @@ # Set the default end-of-line to UNIX * text=auto eol=lf +*.verified.txt text eol=lf working-tree-encoding=UTF-8 +*.verified.xml text eol=lf working-tree-encoding=UTF-8 +*.verified.json text eol=lf working-tree-encoding=UTF-8 \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b85290bd95..5bdb1b2704 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -33,6 +33,7 @@ updates: xunit: patterns: - xunit* + - Verify.Xunit schedule: interval: weekly day: wednesday diff --git a/.gitignore b/.gitignore index 6709dcea82..c12adce325 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ test/WebSites/CliExample/wwwroot/api-docs/v1/*.json test/WebSites/CliExampleWithFactory/wwwroot/api-docs/v1/*.json test/WebSites/NswagClientExample/NSwagClient/ *ncrunch* +*.received.* diff --git a/Directory.Packages.props b/Directory.Packages.props index b2c9b4f9f0..713a38c156 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -27,8 +27,9 @@ + - + \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithEndpointNameMetadata.verified.txt b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithEndpointNameMetadata.verified.txt new file mode 100644 index 0000000000..aaaed8c375 --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithEndpointNameMetadata.verified.txt @@ -0,0 +1,31 @@ +{ + Info: { + Title: Test API, + Version: V1 + }, + Paths: { + /resource: { + Operations: { + Post: { + Tags: [ + { + Name: Fake, + UnresolvedReference: false + } + ], + OperationId: SomeEndpointName, + Responses: { + 200: { + Description: OK, + UnresolvedReference: false + } + }, + Deprecated: false + } + }, + UnresolvedReference: false + } + }, + Components: {}, + HashCode: A0047BEEDFB7C084AF6BF3412F47917E1914849406956B23249FD5A555B9545157FBFF5C1EAFC073B55E59FDE9BDB1774670EFE402C7319D5EC6A6A43D94E439 +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithProvidedOpenApiMetadata.verified.txt b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithProvidedOpenApiMetadata.verified.txt new file mode 100644 index 0000000000..facec5635b --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithProvidedOpenApiMetadata.verified.txt @@ -0,0 +1,31 @@ +{ + Info: { + Title: Test API, + Version: V1 + }, + Paths: { + /resource: { + Operations: { + Post: { + OperationId: OperationIdSetInMetadata, + Parameters: [ + { + UnresolvedReference: false, + Name: ParameterInMetadata, + Required: false, + Deprecated: false, + AllowEmptyValue: false, + Style: Simple, + Explode: false, + AllowReserved: false + } + ], + Deprecated: false + } + }, + UnresolvedReference: false + } + }, + Components: {}, + HashCode: 76DE54DD44D94D07BC803E615ECB0F6D290C3B8803EFB5EADF02C6B180682B1C20BFDD4C9CD50F71D5AD7042B7B4570903F3AF1CC7970ABCA1CEE20FBF971FFD +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithRequiredMember.verified.txt b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithRequiredMember.verified.txt new file mode 100644 index 0000000000..f8133b12f1 --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithRequiredMember.verified.txt @@ -0,0 +1,52 @@ +{ + Info: { + Title: Test API, + Version: V1 + }, + Paths: { + /resource: { + Operations: { + Post: { + Tags: [ + { + Name: Fake, + UnresolvedReference: false + } + ], + Parameters: [ + { + UnresolvedReference: false, + Name: param, + In: Query, + Required: true, + Deprecated: false, + AllowEmptyValue: false, + Style: Form, + Explode: true, + AllowReserved: false, + Schema: { + Type: string, + ReadOnly: false, + WriteOnly: false, + AdditionalPropertiesAllowed: true, + Nullable: false, + Deprecated: false, + UnresolvedReference: false + } + } + ], + Responses: { + 200: { + Description: OK, + UnresolvedReference: false + } + }, + Deprecated: false + } + }, + UnresolvedReference: false + } + }, + Components: {}, + HashCode: A2DDB9D84BC2303C2E8B82FEE969073D4DCAE3D40331C1ED8376E3F427E46C7CAE5AE2791BC5FE1FFFE026EBE90FC10DE8A0409D9F0B6EBC5DBE6CB294DD6A84 +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithRequiredParameter_action=ActionWithParameterWithBindRequiredAttribute.verified.txt b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithRequiredParameter_action=ActionWithParameterWithBindRequiredAttribute.verified.txt new file mode 100644 index 0000000000..f8133b12f1 --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithRequiredParameter_action=ActionWithParameterWithBindRequiredAttribute.verified.txt @@ -0,0 +1,52 @@ +{ + Info: { + Title: Test API, + Version: V1 + }, + Paths: { + /resource: { + Operations: { + Post: { + Tags: [ + { + Name: Fake, + UnresolvedReference: false + } + ], + Parameters: [ + { + UnresolvedReference: false, + Name: param, + In: Query, + Required: true, + Deprecated: false, + AllowEmptyValue: false, + Style: Form, + Explode: true, + AllowReserved: false, + Schema: { + Type: string, + ReadOnly: false, + WriteOnly: false, + AdditionalPropertiesAllowed: true, + Nullable: false, + Deprecated: false, + UnresolvedReference: false + } + } + ], + Responses: { + 200: { + Description: OK, + UnresolvedReference: false + } + }, + Deprecated: false + } + }, + UnresolvedReference: false + } + }, + Components: {}, + HashCode: A2DDB9D84BC2303C2E8B82FEE969073D4DCAE3D40331C1ED8376E3F427E46C7CAE5AE2791BC5FE1FFFE026EBE90FC10DE8A0409D9F0B6EBC5DBE6CB294DD6A84 +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithRequiredParameter_action=ActionWithParameterWithRequiredAttribute.verified.txt b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithRequiredParameter_action=ActionWithParameterWithRequiredAttribute.verified.txt new file mode 100644 index 0000000000..f8133b12f1 --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithRequiredParameter_action=ActionWithParameterWithRequiredAttribute.verified.txt @@ -0,0 +1,52 @@ +{ + Info: { + Title: Test API, + Version: V1 + }, + Paths: { + /resource: { + Operations: { + Post: { + Tags: [ + { + Name: Fake, + UnresolvedReference: false + } + ], + Parameters: [ + { + UnresolvedReference: false, + Name: param, + In: Query, + Required: true, + Deprecated: false, + AllowEmptyValue: false, + Style: Form, + Explode: true, + AllowReserved: false, + Schema: { + Type: string, + ReadOnly: false, + WriteOnly: false, + AdditionalPropertiesAllowed: true, + Nullable: false, + Deprecated: false, + UnresolvedReference: false + } + } + ], + Responses: { + 200: { + Description: OK, + UnresolvedReference: false + } + }, + Deprecated: false + } + }, + UnresolvedReference: false + } + }, + Components: {}, + HashCode: A2DDB9D84BC2303C2E8B82FEE969073D4DCAE3D40331C1ED8376E3F427E46C7CAE5AE2791BC5FE1FFFE026EBE90FC10DE8A0409D9F0B6EBC5DBE6CB294DD6A84 +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithRouteNameMetadata.verified.txt b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithRouteNameMetadata.verified.txt new file mode 100644 index 0000000000..9c7d1af46d --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionWithRouteNameMetadata.verified.txt @@ -0,0 +1,31 @@ +{ + Info: { + Title: Test API, + Version: V1 + }, + Paths: { + /resource: { + Operations: { + Post: { + Tags: [ + { + Name: Fake, + UnresolvedReference: false + } + ], + OperationId: SomeRouteName, + Responses: { + 200: { + Description: OK, + UnresolvedReference: false + } + }, + Deprecated: false + } + }, + UnresolvedReference: false + } + }, + Components: {}, + HashCode: 8A51577C0837548151E3938DC7033AF6AFDE7FD4E5F6F2FE20CC8931B3D18A883C1FB3FE92120D0A44EC31DDE90DDEDE4A237B3138AD45A37278F8924958D5A7 +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionsWithIllegalHeaderParameters_action=ActionWithAcceptFromHeaderParameter.verified.txt b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionsWithIllegalHeaderParameters_action=ActionWithAcceptFromHeaderParameter.verified.txt new file mode 100644 index 0000000000..49c8aec81d --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionsWithIllegalHeaderParameters_action=ActionWithAcceptFromHeaderParameter.verified.txt @@ -0,0 +1,52 @@ +{ + Info: { + Title: Test API, + Version: V1 + }, + Paths: { + /resource: { + Operations: { + Get: { + Tags: [ + { + Name: Fake, + UnresolvedReference: false + } + ], + Parameters: [ + { + UnresolvedReference: false, + Name: param, + In: Header, + Required: false, + Deprecated: false, + AllowEmptyValue: false, + Style: Simple, + Explode: false, + AllowReserved: false, + Schema: { + Type: string, + ReadOnly: false, + WriteOnly: false, + AdditionalPropertiesAllowed: true, + Nullable: false, + Deprecated: false, + UnresolvedReference: false + } + } + ], + Responses: { + 200: { + Description: OK, + UnresolvedReference: false + } + }, + Deprecated: false + } + }, + UnresolvedReference: false + } + }, + Components: {}, + HashCode: E126911C7FB97665966DB7EA833EA70FDF82A779304ECD9B963D5A50C6E0AE51A3180983631720BDCD1BCDA3CAA7E79F0F0042120949EA990884D6188CE77AF1 +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionsWithIllegalHeaderParameters_action=ActionWithAuthorizationFromHeaderParameter.verified.txt b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionsWithIllegalHeaderParameters_action=ActionWithAuthorizationFromHeaderParameter.verified.txt new file mode 100644 index 0000000000..49c8aec81d --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionsWithIllegalHeaderParameters_action=ActionWithAuthorizationFromHeaderParameter.verified.txt @@ -0,0 +1,52 @@ +{ + Info: { + Title: Test API, + Version: V1 + }, + Paths: { + /resource: { + Operations: { + Get: { + Tags: [ + { + Name: Fake, + UnresolvedReference: false + } + ], + Parameters: [ + { + UnresolvedReference: false, + Name: param, + In: Header, + Required: false, + Deprecated: false, + AllowEmptyValue: false, + Style: Simple, + Explode: false, + AllowReserved: false, + Schema: { + Type: string, + ReadOnly: false, + WriteOnly: false, + AdditionalPropertiesAllowed: true, + Nullable: false, + Deprecated: false, + UnresolvedReference: false + } + } + ], + Responses: { + 200: { + Description: OK, + UnresolvedReference: false + } + }, + Deprecated: false + } + }, + UnresolvedReference: false + } + }, + Components: {}, + HashCode: E126911C7FB97665966DB7EA833EA70FDF82A779304ECD9B963D5A50C6E0AE51A3180983631720BDCD1BCDA3CAA7E79F0F0042120949EA990884D6188CE77AF1 +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionsWithIllegalHeaderParameters_action=ActionWithContentTypeFromHeaderParameter.verified.txt b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionsWithIllegalHeaderParameters_action=ActionWithContentTypeFromHeaderParameter.verified.txt new file mode 100644 index 0000000000..49c8aec81d --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ActionsWithIllegalHeaderParameters_action=ActionWithContentTypeFromHeaderParameter.verified.txt @@ -0,0 +1,52 @@ +{ + Info: { + Title: Test API, + Version: V1 + }, + Paths: { + /resource: { + Operations: { + Get: { + Tags: [ + { + Name: Fake, + UnresolvedReference: false + } + ], + Parameters: [ + { + UnresolvedReference: false, + Name: param, + In: Header, + Required: false, + Deprecated: false, + AllowEmptyValue: false, + Style: Simple, + Explode: false, + AllowReserved: false, + Schema: { + Type: string, + ReadOnly: false, + WriteOnly: false, + AdditionalPropertiesAllowed: true, + Nullable: false, + Deprecated: false, + UnresolvedReference: false + } + } + ], + Responses: { + 200: { + Description: OK, + UnresolvedReference: false + } + }, + Deprecated: false + } + }, + UnresolvedReference: false + } + }, + Components: {}, + HashCode: E126911C7FB97665966DB7EA833EA70FDF82A779304ECD9B963D5A50C6E0AE51A3180983631720BDCD1BCDA3CAA7E79F0F0042120949EA990884D6188CE77AF1 +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ApiDescriptionsWithMatchingGroupName.verified.txt b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ApiDescriptionsWithMatchingGroupName.verified.txt new file mode 100644 index 0000000000..73d6704137 --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.ApiDescriptionsWithMatchingGroupName.verified.txt @@ -0,0 +1,45 @@ +{ + Info: { + Title: Test API, + Version: V1 + }, + Paths: { + /resource: { + Operations: { + Get: { + Tags: [ + { + Name: Fake, + UnresolvedReference: false + } + ], + Responses: { + 200: { + Description: OK, + UnresolvedReference: false + } + }, + Deprecated: false + }, + Post: { + Tags: [ + { + Name: Fake, + UnresolvedReference: false + } + ], + Responses: { + 200: { + Description: OK, + UnresolvedReference: false + } + }, + Deprecated: false + } + }, + UnresolvedReference: false + } + }, + Components: {}, + HashCode: 0F1036F23326E2BD7543491DEC0E03ABCA5BC97AF845BEE30C164155D616F306F6F6E21A77507DA6BE2A85DF1A17B1F07AE23E7608E37C971BAF1CBA2491E899 +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.cs new file mode 100644 index 0000000000..891f3cd308 --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGeneratorVerifyTests/SwaggerGeneratorVerifyTests.cs @@ -0,0 +1,246 @@ +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.AspNetCore.Routing; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.TestSupport; +using VerifyXunit; +using Xunit; + +namespace Swashbuckle.AspNetCore.SwaggerGen.Test; + +public class SwaggerGeneratorVerifyTests +{ + [Fact] + public Task ApiDescriptionsWithMatchingGroupName() + { + var subject = Subject( + apiDescriptions: new[] + { + ApiDescriptionFactory.Create( + c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource"), + + ApiDescriptionFactory.Create( + c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "GET", relativePath: "resource"), + + ApiDescriptionFactory.Create( + c => nameof(c.ActionWithNoParameters), groupName: "v2", httpMethod: "POST", relativePath: "resource"), + }, + options: new SwaggerGeneratorOptions + { + SwaggerDocs = new Dictionary + { + ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } + } + } + ); + + var document = subject.GetSwagger("v1"); + + return Verifier.Verify(document); + } + + [Fact] + public Task ActionWithRouteNameMetadata() + { + var subject = Subject( + apiDescriptions: new[] + { + ApiDescriptionFactory.Create( + c => nameof(c.ActionWithRouteNameMetadata), groupName: "v1", httpMethod: "POST", relativePath: "resource"), + } + ); + + var document = subject.GetSwagger("v1"); + + return Verifier.Verify(document); + } + + [Fact] + public Task ActionWithEndpointNameMetadata() + { + var methodInfo = typeof(FakeController).GetMethod(nameof(FakeController.ActionWithParameter)); + var actionDescriptor = new ActionDescriptor + { + EndpointMetadata = new List() { new EndpointNameMetadata("SomeEndpointName") }, + RouteValues = new Dictionary + { + ["controller"] = methodInfo.DeclaringType.Name.Replace("Controller", string.Empty) + } + }; + var subject = Subject( + apiDescriptions: new[] + { + ApiDescriptionFactory.Create(actionDescriptor, methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource"), + } + ); + + var document = subject.GetSwagger("v1"); + + return Verifier.Verify(document); + } + + [Fact] + public Task ActionWithProvidedOpenApiMetadata() + { + var methodInfo = typeof(FakeController).GetMethod(nameof(FakeController.ActionWithParameter)); + var actionDescriptor = new ActionDescriptor + { + EndpointMetadata = new List() + { + new OpenApiOperation + { + OperationId = "OperationIdSetInMetadata", + Parameters = new List() + { + new OpenApiParameter + { + Name = "ParameterInMetadata" + } + } + } + }, + RouteValues = new Dictionary + { + ["controller"] = methodInfo.DeclaringType.Name.Replace("Controller", string.Empty) + } + }; + var subject = Subject( + apiDescriptions: new[] + { + ApiDescriptionFactory.Create(actionDescriptor, methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource"), + } + ); + + var document = subject.GetSwagger("v1"); + + return Verifier.Verify(document); + } + + [Theory] + [InlineData(nameof(FakeController.ActionWithAcceptFromHeaderParameter))] + [InlineData(nameof(FakeController.ActionWithContentTypeFromHeaderParameter))] + [InlineData(nameof(FakeController.ActionWithAuthorizationFromHeaderParameter))] + public Task ActionsWithIllegalHeaderParameters(string action) + { + var illegalParameter = typeof(FakeController).GetMethod(action).GetParameters()[0]; + var fromHeaderAttribute = illegalParameter.GetCustomAttribute(); + + var subject = Subject( + new[] + { + ApiDescriptionFactory.Create( + c => action, + groupName: "v1", + httpMethod: "GET", + relativePath: "resource", + parameterDescriptions: new[] + { + new ApiParameterDescription + { + Name = fromHeaderAttribute?.Name ?? illegalParameter.Name, + Source = BindingSource.Header, + ModelMetadata = ModelMetadataFactory.CreateForParameter(illegalParameter) + }, + new ApiParameterDescription + { + Name = "param", + Source = BindingSource.Header + } + } + ) + } + ); + + var document = subject.GetSwagger("v1"); + + return Verifier.Verify(document).UseParameters(action); + } + + [Theory] + [InlineData(nameof(FakeController.ActionWithParameterWithRequiredAttribute))] + [InlineData(nameof(FakeController.ActionWithParameterWithBindRequiredAttribute))] + public Task ActionWithRequiredParameter(string action) + { + var subject = Subject( + apiDescriptions: new[] + { + ApiDescriptionFactory.Create( + methodInfo: typeof(FakeController).GetMethod(action), + groupName: "v1", + httpMethod: "POST", + relativePath: "resource", + parameterDescriptions: new [] + { + new ApiParameterDescription + { + Name = "param", + Source = BindingSource.Query + } + }) + } + ); + + var document = subject.GetSwagger("v1"); + + return Verifier.Verify(document).UseParameters(action); + } + +#if NET7_0_OR_GREATER + [Fact] + public Task ActionWithRequiredMember() + { + var subject = Subject( + apiDescriptions: new[] + { + ApiDescriptionFactory.Create( + methodInfo: typeof(FakeController).GetMethod(nameof(FakeController.ActionWithRequiredMember)), + groupName: "v1", + httpMethod: "POST", + relativePath: "resource", + parameterDescriptions: new [] + { + new ApiParameterDescription + { + Name = "param", + Source = BindingSource.Query, + ModelMetadata = ModelMetadataFactory.CreateForProperty(typeof(FakeController.TypeWithRequiredProperty), "RequiredProperty") + } + }) + } + ); + + var document = subject.GetSwagger("v1"); + + return Verifier.Verify(document); + } +#endif + + private static SwaggerGenerator Subject( + IEnumerable apiDescriptions, + SwaggerGeneratorOptions options = null, + IEnumerable authenticationSchemes = null) + { + return new SwaggerGenerator( + options ?? DefaultOptions, + new FakeApiDescriptionGroupCollectionProvider(apiDescriptions), + new SchemaGenerator(new SchemaGeneratorOptions(), new JsonSerializerDataContractResolver(new JsonSerializerOptions())), + new FakeAuthenticationSchemeProvider(authenticationSchemes ?? Enumerable.Empty()) + ); + } + + private static readonly SwaggerGeneratorOptions DefaultOptions = new SwaggerGeneratorOptions + { + SwaggerDocs = new Dictionary + { + ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } + } + }; +} diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/Swashbuckle.AspNetCore.SwaggerGen.Test.csproj b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/Swashbuckle.AspNetCore.SwaggerGen.Test.csproj index e47f4275ef..950eefb2fa 100644 --- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/Swashbuckle.AspNetCore.SwaggerGen.Test.csproj +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/Swashbuckle.AspNetCore.SwaggerGen.Test.csproj @@ -17,6 +17,7 @@ +