diff --git a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/SchemaGenerator.cs b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/SchemaGenerator.cs index 913112040f..33baf5ff29 100644 --- a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/SchemaGenerator.cs +++ b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/SchemaGenerator.cs @@ -49,9 +49,28 @@ private IOpenApiSchema GenerateSchemaForMember( ? GeneratePolymorphicSchema(schemaRepository, knownTypesDataContracts) : GenerateConcreteSchema(dataContract, schemaRepository); - if (_generatorOptions.UseAllOfToExtendReferenceSchemas && schema is OpenApiSchemaReference reference) + if (schema is OpenApiSchemaReference reference) { - schema = new OpenApiSchema() { AllOf = [reference] }; + if (_generatorOptions.UseAllOfToExtendReferenceSchemas) + { + schema = new OpenApiSchema() { AllOf = [reference] }; + } + else + { + var customAttributes = memberInfo.GetInlineAndMetadataAttributes(); + + var defaultValueAttribute = customAttributes.OfType().FirstOrDefault(); + if (defaultValueAttribute != null) + { + reference.Default = GenerateDefaultValue(dataContract, modelType, defaultValueAttribute.Value); + } + + var obsoleteAttribute = customAttributes.OfType().FirstOrDefault(); + if (obsoleteAttribute != null) + { + reference.Deprecated = true; + } + } } if (schema is OpenApiSchema concrete) @@ -96,9 +115,11 @@ private IOpenApiSchema GenerateSchemaForMember( .Where(t => t.IsGenericType) .ToArray(); - var isDictionaryType = - genericTypes.Any(t => t.GetGenericTypeDefinition() == typeof(IDictionary<,>)) || - genericTypes.Any(t => t.GetGenericTypeDefinition() == typeof(IReadOnlyDictionary<,>)); + var isDictionaryType = genericTypes.Any(static (type) => + { + var definition = type.GetGenericTypeDefinition(); + return definition == typeof(IDictionary<,>) || definition == typeof(IReadOnlyDictionary<,>); + }); if (isDictionaryType && schema.AdditionalProperties is OpenApiSchema additionalProperties) { @@ -138,9 +159,25 @@ private IOpenApiSchema GenerateSchemaForParameter( ? GeneratePolymorphicSchema(schemaRepository, knownTypesDataContracts) : GenerateConcreteSchema(dataContract, schemaRepository); - if (_generatorOptions.UseAllOfToExtendReferenceSchemas && schema is OpenApiSchemaReference reference) + if (schema is OpenApiSchemaReference reference) { - schema = new OpenApiSchema() { AllOf = [reference] }; + if (_generatorOptions.UseAllOfToExtendReferenceSchemas) + { + schema = new OpenApiSchema() { AllOf = [reference] }; + } + else + { + var customAttributes = parameterInfo.GetCustomAttributes(); + + var defaultValue = parameterInfo.HasDefaultValue + ? parameterInfo.DefaultValue + : customAttributes.OfType().FirstOrDefault()?.Value; + + if (defaultValue != null) + { + reference.Default = GenerateDefaultValue(dataContract, modelType, defaultValue); + } + } } if (schema is OpenApiSchema concrete) @@ -438,7 +475,7 @@ private OpenApiSchema CreateObjectSchema(DataContract dataContract, SchemaReposi var memberType = dataProperty.MemberType; - schema.Properties[dataProperty.Name] = (dataProperty.MemberInfo != null) + schema.Properties[dataProperty.Name] = dataProperty.MemberInfo != null ? GenerateSchemaForMember(memberType, schemaRepository, dataProperty.MemberInfo, dataProperty) : GenerateSchemaForType(memberType, schemaRepository); diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/CodeGenerationTests.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/CodeGenerationTests.cs index 416acba756..54c7f0be6f 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/CodeGenerationTests.cs +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/CodeGenerationTests.cs @@ -33,10 +33,21 @@ public static TheoryData SnapshotTestCases() foreach (var tool in Enum.GetValues()) { - if (tool is ClientGeneratorTool.NSwag && Path.GetFileNameWithoutExtension(path).Contains("Basic.Startup")) + var fileName = Path.GetFileNameWithoutExtension(path); + + if (fileName.Contains("Basic.Startup")) { - // NSwag doesn't generate valid compilation due to a missing FileResponse type - continue; + if (tool is ClientGeneratorTool.NSwag) + { + // NSwag doesn't generate valid compilation due to a missing FileResponse type + continue; + } + + if (!fileName.Contains("=v1.")) + { + // Ignore duplicative test cases for Swagger 2.0 and OpenAPI 3.1 + continue; + } } if (ClientGenerator.IsSupported(tool, "json", version)) diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs index 333839d2e5..c83f968e57 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs @@ -11,6 +11,8 @@ public class SwaggerIntegrationTests(ITestOutputHelper outputHelper) { [Theory] [InlineData(typeof(Basic.Startup), "/swagger/v1/swagger.json")] + [InlineData(typeof(Basic.Startup), "/swagger/v1/swaggerv2.json")] + [InlineData(typeof(Basic.Startup), "/swagger/v1/swaggerv3_1.json")] [InlineData(typeof(CliExample.Startup), "/swagger/v1/swagger_net10.0.json")] [InlineData(typeof(ConfigFromFile.Startup), "/swagger/v1/swagger.json")] [InlineData(typeof(CustomUIConfig.Startup), "/swagger/v1/swagger.json")] diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/VerifyTests.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/VerifyTests.cs index 972a6ea5ff..1aeca59e1a 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/VerifyTests.cs +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/VerifyTests.cs @@ -10,6 +10,8 @@ public partial class VerifyTests(ITestOutputHelper outputHelper) [Theory] [InlineData(typeof(Basic.Startup), "/swagger/v1/swagger.json")] + [InlineData(typeof(Basic.Startup), "/swagger/v1/swaggerv2.json", "2.0")] + [InlineData(typeof(Basic.Startup), "/swagger/v1/swaggerv3_1.json", "3.1")] [InlineData(typeof(NSwagClientExample.Startup), "/swagger/v1/swagger.json")] [InlineData(typeof(CliExample.Startup), "/swagger/v1/swagger_net10.0.json")] [InlineData(typeof(ConfigFromFile.Startup), "/swagger/v1/swagger.json")] @@ -24,7 +26,8 @@ public partial class VerifyTests(ITestOutputHelper outputHelper) [InlineData(typeof(TestFirst.Startup), "/swagger/v1-generated/openapi.json")] public async Task SwaggerEndpoint_ReturnsValidSwaggerJson( Type startupType, - string swaggerRequestUri) + string swaggerRequestUri, + string openApiVersion = null) { var testSite = new TestSite(startupType, outputHelper); using var client = testSite.BuildClient(); @@ -34,7 +37,7 @@ public async Task SwaggerEndpoint_ReturnsValidSwaggerJson( await Verify(NormalizeLineBreaks(swagger)) .UseDirectory(SnapshotsDirectory) - .UseParameters(startupType, GetVersion(swaggerRequestUri)); + .UseParameters(startupType, openApiVersion ?? GetVersion(swaggerRequestUri)); } [Fact] diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=2.0.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=2.0.verified.txt new file mode 100644 index 0000000000..89109a3055 --- /dev/null +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=2.0.verified.txt @@ -0,0 +1,1474 @@ +{ + "swagger": "2.0", + "info": { + "title": "Test API V1", + "description": "A sample API for testing Swashbuckle", + "termsOfService": "http://tempuri.org/terms", + "version": "v1" + }, + "paths": { + "/products": { + "post": { + "tags": [ + "CrudActions" + ], + "summary": "Creates a product", + "description": "## Heading 1\r\n\r\n POST /products\r\n {\r\n \"id\": \"123\",\r\n \"description\": \"Some product\"\r\n }", + "operationId": "CreateProduct", + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "$ref": "#/definitions/Product" + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Product" + } + } + }, + "x-purpose": "test" + }, + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Searches the collection of products by description key words", + "operationId": "SearchProducts", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "query", + "name": "kw", + "description": "A list of search terms", + "type": "string", + "default": "foobar" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Product" + } + } + } + }, + "x-purpose": "test" + } + }, + "/products/all": { + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Get all products", + "description": "```\r\n{\r\n \"Id\":1,\r\n \"Description\":\"\",\r\n \"Status\": 0,\r\n \"Status2\": 1\r\n}\r\n \r\n```", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Product" + } + } + } + }, + "x-purpose": "test" + } + }, + "/products/{id}": { + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Returns a specific product", + "operationId": "GetProduct", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The product id", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Product" + } + } + }, + "x-purpose": "test" + }, + "put": { + "tags": [ + "CrudActions" + ], + "summary": "Updates all properties of a specific product", + "operationId": "UpdateProduct", + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "", + "required": true, + "type": "integer", + "format": "int32" + }, + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "$ref": "#/definitions/Product" + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "patch": { + "tags": [ + "CrudActions" + ], + "summary": "Updates some properties of a specific product", + "description": "\r\nOnly provided properties will be updated,\r\n other remain unchanged.\r\n\r\nIdentifier must be non-default value\r\n\r\nBody must be specified", + "operationId": "PatchProduct", + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "", + "required": true, + "type": "integer", + "format": "int32" + }, + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "type": "object", + "additionalProperties": { } + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "CrudActions" + ], + "summary": "Deletes a specific product", + "operationId": "DeleteProduct", + "parameters": [ + { + "in": "path", + "name": "id", + "description": "", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/payments/authorize": { + "post": { + "tags": [ + "DataAnnotations" + ], + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/PaymentRequest" + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + }, + "x-purpose": "test" + } + }, + "/payments/{paymentId}/cancel": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "in": "path", + "name": "paymentId", + "required": true, + "type": "string", + "minLength": 6 + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/get-weekly-apppointments": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "in": "query", + "name": "dayOfWeek", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/kittens": { + "post": { + "tags": [ + "DynamicTypes" + ], + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "integer", + "format": "int32" + } + } + }, + "x-purpose": "test" + } + }, + "/unicorns": { + "get": { + "tags": [ + "DynamicTypes" + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { } + } + } + }, + "x-purpose": "test" + } + }, + "/dragons": { + "post": { + "tags": [ + "DynamicTypes" + ], + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/single": { + "post": { + "tags": [ + "Files" + ], + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "file", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/multiple": { + "post": { + "tags": [ + "Files" + ], + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "files", + "type": "array", + "items": { + "type": "string", + "format": "binary" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/form-with-file": { + "post": { + "tags": [ + "Files" + ], + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "name", + "type": "string" + }, + { + "in": "formData", + "name": "file", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/{name}": { + "get": { + "tags": [ + "Files" + ], + "produces": [ + "text/plain", + "application/zip" + ], + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "format": "binary", + "allOf": [ + { + "type": "string", + "format": "binary" + } + ] + } + } + }, + "x-purpose": "test" + } + }, + "/registrations": { + "post": { + "tags": [ + "FromFormParams" + ], + "summary": "Form parameters with description", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "parameters": [ + { + "in": "formData", + "name": "name", + "description": "Summary for Name", + "type": "string" + }, + { + "in": "formData", + "name": "phoneNumbers", + "description": "Summary for PhoneNumbers", + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + }, + { + "in": "formData", + "name": "formFile", + "description": "Description for file", + "type": "string" + }, + { + "in": "formData", + "name": "text", + "description": "Description for Text", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/registrationsWithIgnoreProperties": { + "post": { + "tags": [ + "FromFormParams" + ], + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "phoneNumbers", + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/registrationsWithEnumParameter": { + "post": { + "tags": [ + "FromFormParams" + ], + "summary": "Form parameters with description", + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "name", + "description": "Summary for Name", + "type": "string" + }, + { + "in": "formData", + "name": "phoneNumbers", + "description": "Summary for PhoneNumbers", + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + }, + { + "in": "formData", + "name": "logLevel", + "type": "string" + }, + { + "in": "formData", + "name": "formFile", + "description": "Description for file", + "type": "string" + }, + { + "in": "formData", + "name": "dateTimeKind", + "description": "Description for dateTimeKind", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/country/validate": { + "get": { + "tags": [ + "FromHeaderParams" + ], + "parameters": [ + { + "in": "query", + "name": "country", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/addresses/validate": { + "get": { + "tags": [ + "FromQueryParams" + ], + "parameters": [ + { + "in": "query", + "name": "country", + "description": "3-letter ISO country code", + "required": true, + "type": "string" + }, + { + "in": "query", + "name": "city", + "description": "Name of city", + "type": "string", + "default": "Seattle" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/zip-codes/validate": { + "get": { + "tags": [ + "FromQueryParams" + ], + "parameters": [ + { + "in": "query", + "name": "zipCodes", + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi" + }, + { + "in": "query", + "name": "search", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/Issue3013/Get": { + "get": { + "tags": [ + "Issue3013" + ], + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/TestResponse" + } + } + }, + "x-purpose": "test" + } + }, + "/promotions": { + "get": { + "tags": [ + "JsonAnnotations" + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Promotion" + } + } + } + }, + "x-purpose": "test" + } + }, + "/shapes": { + "post": { + "tags": [ + "PolymorphicTypes" + ], + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/Rectangle" + } + ] + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "integer", + "format": "int32" + } + } + }, + "x-purpose": "test" + } + }, + "/orders": { + "post": { + "tags": [ + "ResponseTypeAnnotations" + ], + "summary": "Creates an order", + "consumes": [ + "application/xml" + ], + "produces": [ + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "$ref": "#/definitions/Order" + }, + "x-purpose": "test" + } + ], + "responses": { + "201": { + "description": "Order created", + "schema": { + "type": "integer", + "format": "int32" + } + }, + "400": { + "description": "Order invalid", + "schema": { + "$ref": "#/definitions/ValidationProblemDetails" + } + } + }, + "x-purpose": "test" + } + }, + "/carts": { + "post": { + "tags": [ + "SwaggerAnnotations" + ], + "operationId": "CreateCart", + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "The cart request body", + "schema": { + "$ref": "#/definitions/Cart" + }, + "x-purpose": "test" + } + ], + "responses": { + "201": { + "description": "The cart was created", + "schema": { + "$ref": "#/definitions/Cart" + } + }, + "400": { + "description": "The cart data is invalid" + } + }, + "x-purpose": "test" + } + }, + "/carts/{id}": { + "get": { + "tags": [ + "SwaggerAnnotations" + ], + "externalDocs": { + "description": "External docs for CartsByIdGet", + "url": "https://tempuri.org/carts-by-id-get" + }, + "operationId": "GetCart", + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The cart identifier", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Cart" + } + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "SwaggerAnnotations" + ], + "summary": "Deletes a specific cart", + "description": "Requires admin privileges", + "operationId": "DeleteCart", + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The cart identifier", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Cart" + } + } + }, + "x-purpose": "test" + } + }, + "/stores": { + "post": { + "tags": [ + "UnboundParams" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "query", + "name": "id", + "type": "integer", + "format": "int32" + }, + { + "in": "query", + "name": "location", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "integer", + "format": "int32" + } + } + }, + "x-purpose": "test" + }, + "get": { + "tags": [ + "UnboundParams" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "query", + "name": "locations", + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Store" + } + } + } + }, + "x-purpose": "test" + } + }, + "/stores/{id}": { + "get": { + "tags": [ + "UnboundParams" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Store" + } + } + }, + "x-purpose": "test" + }, + "put": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "in": "query", + "name": "id", + "type": "integer", + "format": "int32" + }, + { + "in": "path", + "name": "id", + "required": true, + "type": "integer", + "format": "int32" + }, + { + "in": "query", + "name": "location", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + } + }, + "definitions": { + "Cart": { + "type": "object", + "required": [ + "Id" + ], + "properties": { + "id": { + "type": "integer", + "description": "The cart identifier", + "format": "int32", + "readOnly": true + }, + "cartType": { + "$ref": "#/definitions/CartType" + }, + "basketType": { + "$ref": "#/definitions/CartType" + } + }, + "additionalProperties": false + }, + "CartType": { + "type": "integer", + "description": "The cart type", + "format": "int32", + "enum": [ + 0, + 1 + ] + }, + "Circle": { + "allOf": [ + { + "$ref": "#/definitions/Shape" + }, + { + "type": "object", + "properties": { + "radius": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ] + }, + "CreditCard": { + "type": "object", + "required": [ + "cardNumber", + "expMonth", + "expYear" + ], + "properties": { + "cardNumber": { + "type": "string", + "minLength": 1, + "pattern": "^[3-6]?\\d{12,15}$" + }, + "expMonth": { + "type": "integer", + "format": "int32", + "maximum": 12, + "minimum": 1 + }, + "expYear": { + "type": "integer", + "format": "int32", + "maximum": 99, + "minimum": 14 + } + }, + "additionalProperties": false + }, + "DateTimeKind": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1, + 2 + ] + }, + "DayOfWeek": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ] + }, + "DiscountType": { + "type": "string", + "enum": [ + "Percentage", + "Amount" + ] + }, + "LogLevel": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ] + }, + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "description": { + "type": "string", + "x-nullable": true + }, + "total": { + "type": "number", + "format": "double" + } + }, + "additionalProperties": false + }, + "PaymentRequest": { + "type": "object", + "required": [ + "creditCard", + "transaction" + ], + "properties": { + "transaction": { + "$ref": "#/definitions/Transaction" + }, + "creditCard": { + "$ref": "#/definitions/CreditCard" + } + }, + "additionalProperties": false + }, + "Product": { + "type": "object", + "description": "Represents a product", + "properties": { + "id": { + "type": "integer", + "description": "Uniquely identifies the product", + "format": "int32" + }, + "description": { + "type": "string", + "description": "Describes the product", + "x-nullable": true + }, + "status": { + "$ref": "#/definitions/ProductStatus" + }, + "status2": { + "$ref": "#/definitions/ProductStatus" + }, + "price": { + "type": "number", + "format": "double", + "maximum": 122.9, + "exclusiveMaximum": true, + "minimum": 0.1, + "exclusiveMinimum": true, + "x-nullable": true + } + }, + "additionalProperties": false, + "example": { + "id": 123, + "description": "foobar", + "price": 14.37 + } + }, + "ProductStatus": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1, + 2 + ] + }, + "Promotion": { + "type": "object", + "properties": { + "promo-code": { + "type": "string", + "x-nullable": true + }, + "discountType": { + "$ref": "#/definitions/DiscountType" + } + }, + "additionalProperties": false + }, + "Rectangle": { + "allOf": [ + { + "$ref": "#/definitions/Shape" + }, + { + "type": "object", + "properties": { + "height": { + "type": "integer", + "format": "int32" + }, + "width": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ] + }, + "Shape": { + "type": "object", + "required": [ + "TypeName" + ], + "properties": { + "TypeName": { + "type": "string" + }, + "name": { + "type": "string", + "x-nullable": true + } + }, + "additionalProperties": false, + "discriminator": "TypeName" + }, + "Store": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "location": { + "type": "string", + "x-nullable": true + } + }, + "additionalProperties": false + }, + "TestResponse": { + "type": "object", + "properties": { + "foo": { + "$ref": "#/definitions/TestStruct" + } + }, + "additionalProperties": false + }, + "TestStruct": { + "type": "object", + "properties": { + "a": { + "type": "integer", + "format": "int32" + }, + "b": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + }, + "Transaction": { + "type": "object", + "required": [ + "amount" + ], + "properties": { + "amount": { + "type": "number", + "format": "double" + }, + "note": { + "type": "string", + "x-nullable": true + } + }, + "additionalProperties": false + }, + "ValidationProblemDetails": { + "type": "object", + "properties": { + "type": { + "type": "string", + "x-nullable": true + }, + "title": { + "type": "string", + "x-nullable": true + }, + "status": { + "type": "integer", + "format": "int32", + "x-nullable": true + }, + "detail": { + "type": "string", + "x-nullable": true + }, + "instance": { + "type": "string", + "x-nullable": true + }, + "errors": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "x-nullable": true + } + }, + "additionalProperties": { } + } + }, + "tags": [ + { + "name": "CrudActions" + }, + { + "name": "DataAnnotations" + }, + { + "name": "DynamicTypes" + }, + { + "name": "Files" + }, + { + "name": "FromFormParams" + }, + { + "name": "FromHeaderParams" + }, + { + "name": "FromQueryParams" + }, + { + "name": "Issue3013" + }, + { + "name": "JsonAnnotations" + }, + { + "name": "PolymorphicTypes" + }, + { + "name": "ResponseTypeAnnotations" + }, + { + "name": "SwaggerAnnotations", + "description": "Manipulate Carts to your heart's content", + "externalDocs": { + "url": "http://www.tempuri.org" + } + }, + { + "name": "UnboundParams" + } + ] +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=3.1.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=3.1.verified.txt new file mode 100644 index 0000000000..5b9d29ef14 --- /dev/null +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=3.1.verified.txt @@ -0,0 +1,1786 @@ +{ + "openapi": "3.1.1", + "info": { + "title": "Test API V1", + "description": "A sample API for testing Swashbuckle", + "termsOfService": "http://tempuri.org/terms", + "version": "v1" + }, + "paths": { + "/products": { + "post": { + "tags": [ + "CrudActions" + ], + "summary": "Creates a product", + "description": "## Heading 1\r\n\r\n POST /products\r\n {\r\n \"id\": \"123\",\r\n \"description\": \"Some product\"\r\n }", + "operationId": "CreateProduct", + "requestBody": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + } + } + } + }, + "x-purpose": "test" + }, + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Searches the collection of products by description key words", + "operationId": "SearchProducts", + "parameters": [ + { + "name": "kw", + "in": "query", + "description": "A list of search terms", + "schema": { + "type": "string", + "default": "foobar" + }, + "example": "hello" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Product" + } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/products/all": { + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Get all products", + "description": "```\r\n{\r\n \"Id\":1,\r\n \"Description\":\"\",\r\n \"Status\": 0,\r\n \"Status2\": 1\r\n}\r\n \r\n```", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Product" + } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/products/{id}": { + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Returns a specific product", + "operationId": "GetProduct", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The product id", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "example": 111 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + } + } + } + }, + "x-purpose": "test" + }, + "put": { + "tags": [ + "CrudActions" + ], + "summary": "Updates all properties of a specific product", + "operationId": "UpdateProduct", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "example": 222 + } + ], + "requestBody": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "patch": { + "tags": [ + "CrudActions" + ], + "summary": "Updates some properties of a specific product", + "description": "\r\nOnly provided properties will be updated,\r\n other remain unchanged.\r\n\r\nIdentifier must be non-default value\r\n\r\nBody must be specified", + "operationId": "PatchProduct", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "example": 333 + } + ], + "requestBody": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { } + } + }, + "text/json": { + "schema": { + "type": "object", + "additionalProperties": { } + } + }, + "application/*+json": { + "schema": { + "type": "object", + "additionalProperties": { } + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "CrudActions" + ], + "summary": "Deletes a specific product", + "operationId": "DeleteProduct", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "example": 444 + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/payments/authorize": { + "post": { + "tags": [ + "DataAnnotations" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentRequest" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/PaymentRequest" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/PaymentRequest" + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/payments/{paymentId}/cancel": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "name": "paymentId", + "in": "path", + "required": true, + "schema": { + "minLength": 6, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/get-weekly-apppointments": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "name": "dayOfWeek", + "in": "query", + "schema": { + "default": 4, + "$ref": "#/components/schemas/DayOfWeek" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/kittens": { + "post": { + "tags": [ + "DynamicTypes" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { } + }, + "text/json": { + "schema": { } + }, + "application/*+json": { + "schema": { } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/unicorns": { + "get": { + "tags": [ + "DynamicTypes" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/dragons": { + "post": { + "tags": [ + "DynamicTypes" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { } + }, + "text/json": { + "schema": { } + }, + "application/*+json": { + "schema": { } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/single": { + "post": { + "tags": [ + "Files" + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "file": { + "type": "string", + "format": "binary" + } + } + }, + "encoding": { + "file": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/multiple": { + "post": { + "tags": [ + "Files" + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "files": { + "type": "array", + "items": { + "type": "string", + "format": "binary" + } + } + } + }, + "encoding": { + "files": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/form-with-file": { + "post": { + "tags": [ + "Files" + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "file": { + "type": "string", + "format": "binary" + } + } + }, + "encoding": { + "name": { + "style": "form" + }, + "file": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/{name}": { + "get": { + "tags": [ + "Files" + ], + "parameters": [ + { + "name": "name", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "oneOf": [ + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + } + ] + } + }, + "application/zip": { + "schema": { + "oneOf": [ + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + } + ] + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/registrations": { + "post": { + "tags": [ + "FromFormParams" + ], + "summary": "Form parameters with description", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Summary for Name", + "example": "MyName" + }, + "phoneNumbers": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + }, + "description": "Summary for PhoneNumbers" + }, + "formFile": { + "type": "string", + "description": "Description for file", + "format": "binary" + }, + "text": { + "type": "string", + "description": "Description for Text" + } + } + }, + "encoding": { + "name": { + "style": "form" + }, + "phoneNumbers": { + "style": "form" + }, + "formFile": { + "style": "form" + }, + "text": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/registrationsWithIgnoreProperties": { + "post": { + "tags": [ + "FromFormParams" + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "phoneNumbers": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + } + } + }, + "encoding": { + "phoneNumbers": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/registrationsWithEnumParameter": { + "post": { + "tags": [ + "FromFormParams" + ], + "summary": "Form parameters with description", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Summary for Name", + "example": "MyName" + }, + "phoneNumbers": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + }, + "description": "Summary for PhoneNumbers" + }, + "logLevel": { + "$ref": "#/components/schemas/LogLevel" + }, + "formFile": { + "type": "string", + "description": "Description for file", + "format": "binary" + }, + "dateTimeKind": { + "description": "Description for dateTimeKind", + "$ref": "#/components/schemas/DateTimeKind" + } + } + }, + "encoding": { + "name": { + "style": "form" + }, + "phoneNumbers": { + "style": "form" + }, + "logLevel": { + "style": "form" + }, + "formFile": { + "style": "form" + }, + "dateTimeKind": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/country/validate": { + "get": { + "tags": [ + "FromHeaderParams" + ], + "parameters": [ + { + "name": "country", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/addresses/validate": { + "get": { + "tags": [ + "FromQueryParams" + ], + "parameters": [ + { + "name": "country", + "in": "query", + "description": "3-letter ISO country code", + "required": true, + "schema": { + "type": "string", + "example": null + }, + "example": null + }, + { + "name": "city", + "in": "query", + "description": "Name of city", + "schema": { + "type": "string", + "default": "Seattle" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/zip-codes/validate": { + "get": { + "tags": [ + "FromQueryParams" + ], + "parameters": [ + { + "name": "zipCodes", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "search", + "in": "query", + "required": true, + "style": "deepObject", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/Issue3013/Get": { + "get": { + "tags": [ + "Issue3013" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/TestResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/TestResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/TestResponse" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/promotions": { + "get": { + "tags": [ + "JsonAnnotations" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Promotion" + } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/shapes": { + "post": { + "tags": [ + "PolymorphicTypes" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/Rectangle" + }, + { + "$ref": "#/components/schemas/Circle" + } + ] + } + }, + "text/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/Rectangle" + }, + { + "$ref": "#/components/schemas/Circle" + } + ] + } + }, + "application/*+json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/Rectangle" + }, + { + "$ref": "#/components/schemas/Circle" + } + ] + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "type": "integer", + "format": "int32" + } + }, + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + }, + "text/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/orders": { + "post": { + "tags": [ + "ResponseTypeAnnotations" + ], + "summary": "Creates an order", + "requestBody": { + "description": "", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "201": { + "description": "Order created", + "content": { + "application/xml": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + }, + "400": { + "description": "Order invalid", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/ValidationProblemDetails" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/carts": { + "post": { + "tags": [ + "SwaggerAnnotations" + ], + "operationId": "CreateCart", + "requestBody": { + "description": "The cart request body", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + } + }, + "x-purpose": "test" + }, + "responses": { + "201": { + "description": "The cart was created", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + } + } + }, + "400": { + "description": "The cart data is invalid" + } + }, + "x-purpose": "test" + } + }, + "/carts/{id}": { + "get": { + "tags": [ + "SwaggerAnnotations" + ], + "externalDocs": { + "description": "External docs for CartsByIdGet", + "url": "https://tempuri.org/carts-by-id-get" + }, + "operationId": "GetCart", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The cart identifier", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + } + } + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "SwaggerAnnotations" + ], + "summary": "Deletes a specific cart", + "description": "Requires admin privileges", + "operationId": "DeleteCart", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The cart identifier", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/stores": { + "post": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "id", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "location", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + } + }, + "x-purpose": "test" + }, + "get": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "locations", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Store" + } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/stores/{id}": { + "get": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Store" + } + } + } + } + }, + "x-purpose": "test" + }, + "put": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "id", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "location", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + } + }, + "components": { + "schemas": { + "Cart": { + "required": [ + "Id" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The cart identifier", + "format": "int32", + "readOnly": true + }, + "cartType": { + "default": 0, + "$ref": "#/components/schemas/CartType" + }, + "basketType": { + "deprecated": true, + "$ref": "#/components/schemas/CartType" + } + }, + "additionalProperties": false + }, + "CartType": { + "enum": [ + 0, + 1 + ], + "type": "integer", + "description": "The cart type", + "format": "int32" + }, + "Circle": { + "allOf": [ + { + "$ref": "#/components/schemas/Shape" + }, + { + "type": "object", + "properties": { + "radius": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ] + }, + "CreditCard": { + "required": [ + "cardNumber", + "expMonth", + "expYear" + ], + "type": "object", + "properties": { + "cardNumber": { + "minLength": 1, + "pattern": "^[3-6]?\\d{12,15}$", + "type": "string" + }, + "expMonth": { + "maximum": 12, + "minimum": 1, + "type": "integer", + "format": "int32" + }, + "expYear": { + "maximum": 99, + "minimum": 14, + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + }, + "DateTimeKind": { + "enum": [ + 0, + 1, + 2 + ], + "type": "integer", + "format": "int32" + }, + "DayOfWeek": { + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "type": "integer", + "format": "int32" + }, + "DiscountType": { + "enum": [ + "Percentage", + "Amount" + ], + "type": "string" + }, + "LogLevel": { + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "type": "integer", + "format": "int32" + }, + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "total": { + "type": "number", + "format": "double" + } + }, + "additionalProperties": false + }, + "PaymentRequest": { + "required": [ + "creditCard", + "transaction" + ], + "type": "object", + "properties": { + "transaction": { + "$ref": "#/components/schemas/Transaction" + }, + "creditCard": { + "$ref": "#/components/schemas/CreditCard" + } + }, + "additionalProperties": false + }, + "Product": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Uniquely identifies the product", + "format": "int32" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "Describes the product" + }, + "status": { + "$ref": "#/components/schemas/ProductStatus" + }, + "status2": { + "$ref": "#/components/schemas/ProductStatus" + }, + "price": { + "exclusiveMaximum": 122.9, + "exclusiveMinimum": 0.1, + "type": [ + "null", + "number" + ], + "format": "double" + } + }, + "additionalProperties": false, + "description": "Represents a product", + "example": { + "id": 123, + "description": "foobar", + "price": 14.37 + } + }, + "ProductStatus": { + "enum": [ + 0, + 1, + 2 + ], + "type": "integer", + "format": "int32" + }, + "Promotion": { + "type": "object", + "properties": { + "promo-code": { + "type": [ + "null", + "string" + ] + }, + "discountType": { + "$ref": "#/components/schemas/DiscountType" + } + }, + "additionalProperties": false + }, + "Rectangle": { + "allOf": [ + { + "$ref": "#/components/schemas/Shape" + }, + { + "type": "object", + "properties": { + "height": { + "type": "integer", + "format": "int32" + }, + "width": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ] + }, + "Shape": { + "required": [ + "TypeName" + ], + "type": "object", + "properties": { + "TypeName": { + "type": "string" + }, + "name": { + "type": [ + "null", + "string" + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "TypeName", + "mapping": { + "Rectangle": "#/components/schemas/Rectangle", + "Circle": "#/components/schemas/Circle" + } + } + }, + "Store": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "location": { + "type": [ + "null", + "string" + ] + } + }, + "additionalProperties": false + }, + "TestResponse": { + "type": "object", + "properties": { + "foo": { + "$ref": "#/components/schemas/TestStruct" + } + }, + "additionalProperties": false + }, + "TestStruct": { + "type": "object", + "properties": { + "a": { + "type": "integer", + "format": "int32" + }, + "b": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + }, + "Transaction": { + "required": [ + "amount" + ], + "type": "object", + "properties": { + "amount": { + "type": "number", + "format": "double" + }, + "note": { + "type": [ + "null", + "string" + ] + } + }, + "additionalProperties": false + }, + "ValidationProblemDetails": { + "type": "object", + "properties": { + "type": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "status": { + "type": [ + "null", + "integer" + ], + "format": "int32" + }, + "detail": { + "type": [ + "null", + "string" + ] + }, + "instance": { + "type": [ + "null", + "string" + ] + }, + "errors": { + "type": [ + "null", + "object" + ], + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "additionalProperties": { } + } + } + }, + "tags": [ + { + "name": "CrudActions" + }, + { + "name": "DataAnnotations" + }, + { + "name": "DynamicTypes" + }, + { + "name": "Files" + }, + { + "name": "FromFormParams" + }, + { + "name": "FromHeaderParams" + }, + { + "name": "FromQueryParams" + }, + { + "name": "Issue3013" + }, + { + "name": "JsonAnnotations" + }, + { + "name": "PolymorphicTypes" + }, + { + "name": "ResponseTypeAnnotations" + }, + { + "name": "SwaggerAnnotations", + "description": "Manipulate Carts to your heart's content", + "externalDocs": { + "url": "http://www.tempuri.org" + } + }, + { + "name": "UnboundParams" + } + ] +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=v1.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=v1.verified.txt index a4b09a31e5..ce88b8a9b6 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=v1.verified.txt +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=v1.verified.txt @@ -338,6 +338,28 @@ "x-purpose": "test" } }, + "/get-weekly-apppointments": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "name": "dayOfWeek", + "in": "query", + "schema": { + "$ref": "#/components/schemas/DayOfWeek" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, "/kittens": { "post": { "tags": [ @@ -1355,6 +1377,9 @@ }, "cartType": { "$ref": "#/components/schemas/CartType" + }, + "basketType": { + "$ref": "#/components/schemas/CartType" } }, "additionalProperties": false @@ -1422,6 +1447,19 @@ "type": "integer", "format": "int32" }, + "DayOfWeek": { + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "type": "integer", + "format": "int32" + }, "DiscountType": { "enum": [ "Percentage", diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=2.0.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=2.0.verified.txt new file mode 100644 index 0000000000..89109a3055 --- /dev/null +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=2.0.verified.txt @@ -0,0 +1,1474 @@ +{ + "swagger": "2.0", + "info": { + "title": "Test API V1", + "description": "A sample API for testing Swashbuckle", + "termsOfService": "http://tempuri.org/terms", + "version": "v1" + }, + "paths": { + "/products": { + "post": { + "tags": [ + "CrudActions" + ], + "summary": "Creates a product", + "description": "## Heading 1\r\n\r\n POST /products\r\n {\r\n \"id\": \"123\",\r\n \"description\": \"Some product\"\r\n }", + "operationId": "CreateProduct", + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "$ref": "#/definitions/Product" + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Product" + } + } + }, + "x-purpose": "test" + }, + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Searches the collection of products by description key words", + "operationId": "SearchProducts", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "query", + "name": "kw", + "description": "A list of search terms", + "type": "string", + "default": "foobar" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Product" + } + } + } + }, + "x-purpose": "test" + } + }, + "/products/all": { + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Get all products", + "description": "```\r\n{\r\n \"Id\":1,\r\n \"Description\":\"\",\r\n \"Status\": 0,\r\n \"Status2\": 1\r\n}\r\n \r\n```", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Product" + } + } + } + }, + "x-purpose": "test" + } + }, + "/products/{id}": { + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Returns a specific product", + "operationId": "GetProduct", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The product id", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Product" + } + } + }, + "x-purpose": "test" + }, + "put": { + "tags": [ + "CrudActions" + ], + "summary": "Updates all properties of a specific product", + "operationId": "UpdateProduct", + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "", + "required": true, + "type": "integer", + "format": "int32" + }, + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "$ref": "#/definitions/Product" + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "patch": { + "tags": [ + "CrudActions" + ], + "summary": "Updates some properties of a specific product", + "description": "\r\nOnly provided properties will be updated,\r\n other remain unchanged.\r\n\r\nIdentifier must be non-default value\r\n\r\nBody must be specified", + "operationId": "PatchProduct", + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "", + "required": true, + "type": "integer", + "format": "int32" + }, + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "type": "object", + "additionalProperties": { } + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "CrudActions" + ], + "summary": "Deletes a specific product", + "operationId": "DeleteProduct", + "parameters": [ + { + "in": "path", + "name": "id", + "description": "", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/payments/authorize": { + "post": { + "tags": [ + "DataAnnotations" + ], + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/PaymentRequest" + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + }, + "x-purpose": "test" + } + }, + "/payments/{paymentId}/cancel": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "in": "path", + "name": "paymentId", + "required": true, + "type": "string", + "minLength": 6 + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/get-weekly-apppointments": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "in": "query", + "name": "dayOfWeek", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/kittens": { + "post": { + "tags": [ + "DynamicTypes" + ], + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "integer", + "format": "int32" + } + } + }, + "x-purpose": "test" + } + }, + "/unicorns": { + "get": { + "tags": [ + "DynamicTypes" + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { } + } + } + }, + "x-purpose": "test" + } + }, + "/dragons": { + "post": { + "tags": [ + "DynamicTypes" + ], + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/single": { + "post": { + "tags": [ + "Files" + ], + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "file", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/multiple": { + "post": { + "tags": [ + "Files" + ], + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "files", + "type": "array", + "items": { + "type": "string", + "format": "binary" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/form-with-file": { + "post": { + "tags": [ + "Files" + ], + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "name", + "type": "string" + }, + { + "in": "formData", + "name": "file", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/{name}": { + "get": { + "tags": [ + "Files" + ], + "produces": [ + "text/plain", + "application/zip" + ], + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "format": "binary", + "allOf": [ + { + "type": "string", + "format": "binary" + } + ] + } + } + }, + "x-purpose": "test" + } + }, + "/registrations": { + "post": { + "tags": [ + "FromFormParams" + ], + "summary": "Form parameters with description", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "parameters": [ + { + "in": "formData", + "name": "name", + "description": "Summary for Name", + "type": "string" + }, + { + "in": "formData", + "name": "phoneNumbers", + "description": "Summary for PhoneNumbers", + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + }, + { + "in": "formData", + "name": "formFile", + "description": "Description for file", + "type": "string" + }, + { + "in": "formData", + "name": "text", + "description": "Description for Text", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/registrationsWithIgnoreProperties": { + "post": { + "tags": [ + "FromFormParams" + ], + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "phoneNumbers", + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/registrationsWithEnumParameter": { + "post": { + "tags": [ + "FromFormParams" + ], + "summary": "Form parameters with description", + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "name", + "description": "Summary for Name", + "type": "string" + }, + { + "in": "formData", + "name": "phoneNumbers", + "description": "Summary for PhoneNumbers", + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + }, + { + "in": "formData", + "name": "logLevel", + "type": "string" + }, + { + "in": "formData", + "name": "formFile", + "description": "Description for file", + "type": "string" + }, + { + "in": "formData", + "name": "dateTimeKind", + "description": "Description for dateTimeKind", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/country/validate": { + "get": { + "tags": [ + "FromHeaderParams" + ], + "parameters": [ + { + "in": "query", + "name": "country", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/addresses/validate": { + "get": { + "tags": [ + "FromQueryParams" + ], + "parameters": [ + { + "in": "query", + "name": "country", + "description": "3-letter ISO country code", + "required": true, + "type": "string" + }, + { + "in": "query", + "name": "city", + "description": "Name of city", + "type": "string", + "default": "Seattle" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/zip-codes/validate": { + "get": { + "tags": [ + "FromQueryParams" + ], + "parameters": [ + { + "in": "query", + "name": "zipCodes", + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi" + }, + { + "in": "query", + "name": "search", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/Issue3013/Get": { + "get": { + "tags": [ + "Issue3013" + ], + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/TestResponse" + } + } + }, + "x-purpose": "test" + } + }, + "/promotions": { + "get": { + "tags": [ + "JsonAnnotations" + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Promotion" + } + } + } + }, + "x-purpose": "test" + } + }, + "/shapes": { + "post": { + "tags": [ + "PolymorphicTypes" + ], + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/Rectangle" + } + ] + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "integer", + "format": "int32" + } + } + }, + "x-purpose": "test" + } + }, + "/orders": { + "post": { + "tags": [ + "ResponseTypeAnnotations" + ], + "summary": "Creates an order", + "consumes": [ + "application/xml" + ], + "produces": [ + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "$ref": "#/definitions/Order" + }, + "x-purpose": "test" + } + ], + "responses": { + "201": { + "description": "Order created", + "schema": { + "type": "integer", + "format": "int32" + } + }, + "400": { + "description": "Order invalid", + "schema": { + "$ref": "#/definitions/ValidationProblemDetails" + } + } + }, + "x-purpose": "test" + } + }, + "/carts": { + "post": { + "tags": [ + "SwaggerAnnotations" + ], + "operationId": "CreateCart", + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "The cart request body", + "schema": { + "$ref": "#/definitions/Cart" + }, + "x-purpose": "test" + } + ], + "responses": { + "201": { + "description": "The cart was created", + "schema": { + "$ref": "#/definitions/Cart" + } + }, + "400": { + "description": "The cart data is invalid" + } + }, + "x-purpose": "test" + } + }, + "/carts/{id}": { + "get": { + "tags": [ + "SwaggerAnnotations" + ], + "externalDocs": { + "description": "External docs for CartsByIdGet", + "url": "https://tempuri.org/carts-by-id-get" + }, + "operationId": "GetCart", + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The cart identifier", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Cart" + } + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "SwaggerAnnotations" + ], + "summary": "Deletes a specific cart", + "description": "Requires admin privileges", + "operationId": "DeleteCart", + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The cart identifier", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Cart" + } + } + }, + "x-purpose": "test" + } + }, + "/stores": { + "post": { + "tags": [ + "UnboundParams" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "query", + "name": "id", + "type": "integer", + "format": "int32" + }, + { + "in": "query", + "name": "location", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "integer", + "format": "int32" + } + } + }, + "x-purpose": "test" + }, + "get": { + "tags": [ + "UnboundParams" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "query", + "name": "locations", + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Store" + } + } + } + }, + "x-purpose": "test" + } + }, + "/stores/{id}": { + "get": { + "tags": [ + "UnboundParams" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Store" + } + } + }, + "x-purpose": "test" + }, + "put": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "in": "query", + "name": "id", + "type": "integer", + "format": "int32" + }, + { + "in": "path", + "name": "id", + "required": true, + "type": "integer", + "format": "int32" + }, + { + "in": "query", + "name": "location", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + } + }, + "definitions": { + "Cart": { + "type": "object", + "required": [ + "Id" + ], + "properties": { + "id": { + "type": "integer", + "description": "The cart identifier", + "format": "int32", + "readOnly": true + }, + "cartType": { + "$ref": "#/definitions/CartType" + }, + "basketType": { + "$ref": "#/definitions/CartType" + } + }, + "additionalProperties": false + }, + "CartType": { + "type": "integer", + "description": "The cart type", + "format": "int32", + "enum": [ + 0, + 1 + ] + }, + "Circle": { + "allOf": [ + { + "$ref": "#/definitions/Shape" + }, + { + "type": "object", + "properties": { + "radius": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ] + }, + "CreditCard": { + "type": "object", + "required": [ + "cardNumber", + "expMonth", + "expYear" + ], + "properties": { + "cardNumber": { + "type": "string", + "minLength": 1, + "pattern": "^[3-6]?\\d{12,15}$" + }, + "expMonth": { + "type": "integer", + "format": "int32", + "maximum": 12, + "minimum": 1 + }, + "expYear": { + "type": "integer", + "format": "int32", + "maximum": 99, + "minimum": 14 + } + }, + "additionalProperties": false + }, + "DateTimeKind": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1, + 2 + ] + }, + "DayOfWeek": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ] + }, + "DiscountType": { + "type": "string", + "enum": [ + "Percentage", + "Amount" + ] + }, + "LogLevel": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ] + }, + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "description": { + "type": "string", + "x-nullable": true + }, + "total": { + "type": "number", + "format": "double" + } + }, + "additionalProperties": false + }, + "PaymentRequest": { + "type": "object", + "required": [ + "creditCard", + "transaction" + ], + "properties": { + "transaction": { + "$ref": "#/definitions/Transaction" + }, + "creditCard": { + "$ref": "#/definitions/CreditCard" + } + }, + "additionalProperties": false + }, + "Product": { + "type": "object", + "description": "Represents a product", + "properties": { + "id": { + "type": "integer", + "description": "Uniquely identifies the product", + "format": "int32" + }, + "description": { + "type": "string", + "description": "Describes the product", + "x-nullable": true + }, + "status": { + "$ref": "#/definitions/ProductStatus" + }, + "status2": { + "$ref": "#/definitions/ProductStatus" + }, + "price": { + "type": "number", + "format": "double", + "maximum": 122.9, + "exclusiveMaximum": true, + "minimum": 0.1, + "exclusiveMinimum": true, + "x-nullable": true + } + }, + "additionalProperties": false, + "example": { + "id": 123, + "description": "foobar", + "price": 14.37 + } + }, + "ProductStatus": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1, + 2 + ] + }, + "Promotion": { + "type": "object", + "properties": { + "promo-code": { + "type": "string", + "x-nullable": true + }, + "discountType": { + "$ref": "#/definitions/DiscountType" + } + }, + "additionalProperties": false + }, + "Rectangle": { + "allOf": [ + { + "$ref": "#/definitions/Shape" + }, + { + "type": "object", + "properties": { + "height": { + "type": "integer", + "format": "int32" + }, + "width": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ] + }, + "Shape": { + "type": "object", + "required": [ + "TypeName" + ], + "properties": { + "TypeName": { + "type": "string" + }, + "name": { + "type": "string", + "x-nullable": true + } + }, + "additionalProperties": false, + "discriminator": "TypeName" + }, + "Store": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "location": { + "type": "string", + "x-nullable": true + } + }, + "additionalProperties": false + }, + "TestResponse": { + "type": "object", + "properties": { + "foo": { + "$ref": "#/definitions/TestStruct" + } + }, + "additionalProperties": false + }, + "TestStruct": { + "type": "object", + "properties": { + "a": { + "type": "integer", + "format": "int32" + }, + "b": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + }, + "Transaction": { + "type": "object", + "required": [ + "amount" + ], + "properties": { + "amount": { + "type": "number", + "format": "double" + }, + "note": { + "type": "string", + "x-nullable": true + } + }, + "additionalProperties": false + }, + "ValidationProblemDetails": { + "type": "object", + "properties": { + "type": { + "type": "string", + "x-nullable": true + }, + "title": { + "type": "string", + "x-nullable": true + }, + "status": { + "type": "integer", + "format": "int32", + "x-nullable": true + }, + "detail": { + "type": "string", + "x-nullable": true + }, + "instance": { + "type": "string", + "x-nullable": true + }, + "errors": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "x-nullable": true + } + }, + "additionalProperties": { } + } + }, + "tags": [ + { + "name": "CrudActions" + }, + { + "name": "DataAnnotations" + }, + { + "name": "DynamicTypes" + }, + { + "name": "Files" + }, + { + "name": "FromFormParams" + }, + { + "name": "FromHeaderParams" + }, + { + "name": "FromQueryParams" + }, + { + "name": "Issue3013" + }, + { + "name": "JsonAnnotations" + }, + { + "name": "PolymorphicTypes" + }, + { + "name": "ResponseTypeAnnotations" + }, + { + "name": "SwaggerAnnotations", + "description": "Manipulate Carts to your heart's content", + "externalDocs": { + "url": "http://www.tempuri.org" + } + }, + { + "name": "UnboundParams" + } + ] +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=3.1.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=3.1.verified.txt new file mode 100644 index 0000000000..5b9d29ef14 --- /dev/null +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=3.1.verified.txt @@ -0,0 +1,1786 @@ +{ + "openapi": "3.1.1", + "info": { + "title": "Test API V1", + "description": "A sample API for testing Swashbuckle", + "termsOfService": "http://tempuri.org/terms", + "version": "v1" + }, + "paths": { + "/products": { + "post": { + "tags": [ + "CrudActions" + ], + "summary": "Creates a product", + "description": "## Heading 1\r\n\r\n POST /products\r\n {\r\n \"id\": \"123\",\r\n \"description\": \"Some product\"\r\n }", + "operationId": "CreateProduct", + "requestBody": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + } + } + } + }, + "x-purpose": "test" + }, + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Searches the collection of products by description key words", + "operationId": "SearchProducts", + "parameters": [ + { + "name": "kw", + "in": "query", + "description": "A list of search terms", + "schema": { + "type": "string", + "default": "foobar" + }, + "example": "hello" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Product" + } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/products/all": { + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Get all products", + "description": "```\r\n{\r\n \"Id\":1,\r\n \"Description\":\"\",\r\n \"Status\": 0,\r\n \"Status2\": 1\r\n}\r\n \r\n```", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Product" + } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/products/{id}": { + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Returns a specific product", + "operationId": "GetProduct", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The product id", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "example": 111 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + } + } + } + }, + "x-purpose": "test" + }, + "put": { + "tags": [ + "CrudActions" + ], + "summary": "Updates all properties of a specific product", + "operationId": "UpdateProduct", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "example": 222 + } + ], + "requestBody": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "patch": { + "tags": [ + "CrudActions" + ], + "summary": "Updates some properties of a specific product", + "description": "\r\nOnly provided properties will be updated,\r\n other remain unchanged.\r\n\r\nIdentifier must be non-default value\r\n\r\nBody must be specified", + "operationId": "PatchProduct", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "example": 333 + } + ], + "requestBody": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { } + } + }, + "text/json": { + "schema": { + "type": "object", + "additionalProperties": { } + } + }, + "application/*+json": { + "schema": { + "type": "object", + "additionalProperties": { } + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "CrudActions" + ], + "summary": "Deletes a specific product", + "operationId": "DeleteProduct", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "example": 444 + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/payments/authorize": { + "post": { + "tags": [ + "DataAnnotations" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentRequest" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/PaymentRequest" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/PaymentRequest" + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/payments/{paymentId}/cancel": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "name": "paymentId", + "in": "path", + "required": true, + "schema": { + "minLength": 6, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/get-weekly-apppointments": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "name": "dayOfWeek", + "in": "query", + "schema": { + "default": 4, + "$ref": "#/components/schemas/DayOfWeek" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/kittens": { + "post": { + "tags": [ + "DynamicTypes" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { } + }, + "text/json": { + "schema": { } + }, + "application/*+json": { + "schema": { } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/unicorns": { + "get": { + "tags": [ + "DynamicTypes" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/dragons": { + "post": { + "tags": [ + "DynamicTypes" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { } + }, + "text/json": { + "schema": { } + }, + "application/*+json": { + "schema": { } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/single": { + "post": { + "tags": [ + "Files" + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "file": { + "type": "string", + "format": "binary" + } + } + }, + "encoding": { + "file": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/multiple": { + "post": { + "tags": [ + "Files" + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "files": { + "type": "array", + "items": { + "type": "string", + "format": "binary" + } + } + } + }, + "encoding": { + "files": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/form-with-file": { + "post": { + "tags": [ + "Files" + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "file": { + "type": "string", + "format": "binary" + } + } + }, + "encoding": { + "name": { + "style": "form" + }, + "file": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/{name}": { + "get": { + "tags": [ + "Files" + ], + "parameters": [ + { + "name": "name", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "oneOf": [ + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + } + ] + } + }, + "application/zip": { + "schema": { + "oneOf": [ + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + } + ] + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/registrations": { + "post": { + "tags": [ + "FromFormParams" + ], + "summary": "Form parameters with description", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Summary for Name", + "example": "MyName" + }, + "phoneNumbers": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + }, + "description": "Summary for PhoneNumbers" + }, + "formFile": { + "type": "string", + "description": "Description for file", + "format": "binary" + }, + "text": { + "type": "string", + "description": "Description for Text" + } + } + }, + "encoding": { + "name": { + "style": "form" + }, + "phoneNumbers": { + "style": "form" + }, + "formFile": { + "style": "form" + }, + "text": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/registrationsWithIgnoreProperties": { + "post": { + "tags": [ + "FromFormParams" + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "phoneNumbers": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + } + } + }, + "encoding": { + "phoneNumbers": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/registrationsWithEnumParameter": { + "post": { + "tags": [ + "FromFormParams" + ], + "summary": "Form parameters with description", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Summary for Name", + "example": "MyName" + }, + "phoneNumbers": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + }, + "description": "Summary for PhoneNumbers" + }, + "logLevel": { + "$ref": "#/components/schemas/LogLevel" + }, + "formFile": { + "type": "string", + "description": "Description for file", + "format": "binary" + }, + "dateTimeKind": { + "description": "Description for dateTimeKind", + "$ref": "#/components/schemas/DateTimeKind" + } + } + }, + "encoding": { + "name": { + "style": "form" + }, + "phoneNumbers": { + "style": "form" + }, + "logLevel": { + "style": "form" + }, + "formFile": { + "style": "form" + }, + "dateTimeKind": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/country/validate": { + "get": { + "tags": [ + "FromHeaderParams" + ], + "parameters": [ + { + "name": "country", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/addresses/validate": { + "get": { + "tags": [ + "FromQueryParams" + ], + "parameters": [ + { + "name": "country", + "in": "query", + "description": "3-letter ISO country code", + "required": true, + "schema": { + "type": "string", + "example": null + }, + "example": null + }, + { + "name": "city", + "in": "query", + "description": "Name of city", + "schema": { + "type": "string", + "default": "Seattle" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/zip-codes/validate": { + "get": { + "tags": [ + "FromQueryParams" + ], + "parameters": [ + { + "name": "zipCodes", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "search", + "in": "query", + "required": true, + "style": "deepObject", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/Issue3013/Get": { + "get": { + "tags": [ + "Issue3013" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/TestResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/TestResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/TestResponse" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/promotions": { + "get": { + "tags": [ + "JsonAnnotations" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Promotion" + } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/shapes": { + "post": { + "tags": [ + "PolymorphicTypes" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/Rectangle" + }, + { + "$ref": "#/components/schemas/Circle" + } + ] + } + }, + "text/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/Rectangle" + }, + { + "$ref": "#/components/schemas/Circle" + } + ] + } + }, + "application/*+json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/Rectangle" + }, + { + "$ref": "#/components/schemas/Circle" + } + ] + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "type": "integer", + "format": "int32" + } + }, + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + }, + "text/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/orders": { + "post": { + "tags": [ + "ResponseTypeAnnotations" + ], + "summary": "Creates an order", + "requestBody": { + "description": "", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "201": { + "description": "Order created", + "content": { + "application/xml": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + }, + "400": { + "description": "Order invalid", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/ValidationProblemDetails" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/carts": { + "post": { + "tags": [ + "SwaggerAnnotations" + ], + "operationId": "CreateCart", + "requestBody": { + "description": "The cart request body", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + } + }, + "x-purpose": "test" + }, + "responses": { + "201": { + "description": "The cart was created", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + } + } + }, + "400": { + "description": "The cart data is invalid" + } + }, + "x-purpose": "test" + } + }, + "/carts/{id}": { + "get": { + "tags": [ + "SwaggerAnnotations" + ], + "externalDocs": { + "description": "External docs for CartsByIdGet", + "url": "https://tempuri.org/carts-by-id-get" + }, + "operationId": "GetCart", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The cart identifier", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + } + } + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "SwaggerAnnotations" + ], + "summary": "Deletes a specific cart", + "description": "Requires admin privileges", + "operationId": "DeleteCart", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The cart identifier", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/stores": { + "post": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "id", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "location", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + } + }, + "x-purpose": "test" + }, + "get": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "locations", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Store" + } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/stores/{id}": { + "get": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Store" + } + } + } + } + }, + "x-purpose": "test" + }, + "put": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "id", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "location", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + } + }, + "components": { + "schemas": { + "Cart": { + "required": [ + "Id" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The cart identifier", + "format": "int32", + "readOnly": true + }, + "cartType": { + "default": 0, + "$ref": "#/components/schemas/CartType" + }, + "basketType": { + "deprecated": true, + "$ref": "#/components/schemas/CartType" + } + }, + "additionalProperties": false + }, + "CartType": { + "enum": [ + 0, + 1 + ], + "type": "integer", + "description": "The cart type", + "format": "int32" + }, + "Circle": { + "allOf": [ + { + "$ref": "#/components/schemas/Shape" + }, + { + "type": "object", + "properties": { + "radius": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ] + }, + "CreditCard": { + "required": [ + "cardNumber", + "expMonth", + "expYear" + ], + "type": "object", + "properties": { + "cardNumber": { + "minLength": 1, + "pattern": "^[3-6]?\\d{12,15}$", + "type": "string" + }, + "expMonth": { + "maximum": 12, + "minimum": 1, + "type": "integer", + "format": "int32" + }, + "expYear": { + "maximum": 99, + "minimum": 14, + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + }, + "DateTimeKind": { + "enum": [ + 0, + 1, + 2 + ], + "type": "integer", + "format": "int32" + }, + "DayOfWeek": { + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "type": "integer", + "format": "int32" + }, + "DiscountType": { + "enum": [ + "Percentage", + "Amount" + ], + "type": "string" + }, + "LogLevel": { + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "type": "integer", + "format": "int32" + }, + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "total": { + "type": "number", + "format": "double" + } + }, + "additionalProperties": false + }, + "PaymentRequest": { + "required": [ + "creditCard", + "transaction" + ], + "type": "object", + "properties": { + "transaction": { + "$ref": "#/components/schemas/Transaction" + }, + "creditCard": { + "$ref": "#/components/schemas/CreditCard" + } + }, + "additionalProperties": false + }, + "Product": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Uniquely identifies the product", + "format": "int32" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "Describes the product" + }, + "status": { + "$ref": "#/components/schemas/ProductStatus" + }, + "status2": { + "$ref": "#/components/schemas/ProductStatus" + }, + "price": { + "exclusiveMaximum": 122.9, + "exclusiveMinimum": 0.1, + "type": [ + "null", + "number" + ], + "format": "double" + } + }, + "additionalProperties": false, + "description": "Represents a product", + "example": { + "id": 123, + "description": "foobar", + "price": 14.37 + } + }, + "ProductStatus": { + "enum": [ + 0, + 1, + 2 + ], + "type": "integer", + "format": "int32" + }, + "Promotion": { + "type": "object", + "properties": { + "promo-code": { + "type": [ + "null", + "string" + ] + }, + "discountType": { + "$ref": "#/components/schemas/DiscountType" + } + }, + "additionalProperties": false + }, + "Rectangle": { + "allOf": [ + { + "$ref": "#/components/schemas/Shape" + }, + { + "type": "object", + "properties": { + "height": { + "type": "integer", + "format": "int32" + }, + "width": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ] + }, + "Shape": { + "required": [ + "TypeName" + ], + "type": "object", + "properties": { + "TypeName": { + "type": "string" + }, + "name": { + "type": [ + "null", + "string" + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "TypeName", + "mapping": { + "Rectangle": "#/components/schemas/Rectangle", + "Circle": "#/components/schemas/Circle" + } + } + }, + "Store": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "location": { + "type": [ + "null", + "string" + ] + } + }, + "additionalProperties": false + }, + "TestResponse": { + "type": "object", + "properties": { + "foo": { + "$ref": "#/components/schemas/TestStruct" + } + }, + "additionalProperties": false + }, + "TestStruct": { + "type": "object", + "properties": { + "a": { + "type": "integer", + "format": "int32" + }, + "b": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + }, + "Transaction": { + "required": [ + "amount" + ], + "type": "object", + "properties": { + "amount": { + "type": "number", + "format": "double" + }, + "note": { + "type": [ + "null", + "string" + ] + } + }, + "additionalProperties": false + }, + "ValidationProblemDetails": { + "type": "object", + "properties": { + "type": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "status": { + "type": [ + "null", + "integer" + ], + "format": "int32" + }, + "detail": { + "type": [ + "null", + "string" + ] + }, + "instance": { + "type": [ + "null", + "string" + ] + }, + "errors": { + "type": [ + "null", + "object" + ], + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "additionalProperties": { } + } + } + }, + "tags": [ + { + "name": "CrudActions" + }, + { + "name": "DataAnnotations" + }, + { + "name": "DynamicTypes" + }, + { + "name": "Files" + }, + { + "name": "FromFormParams" + }, + { + "name": "FromHeaderParams" + }, + { + "name": "FromQueryParams" + }, + { + "name": "Issue3013" + }, + { + "name": "JsonAnnotations" + }, + { + "name": "PolymorphicTypes" + }, + { + "name": "ResponseTypeAnnotations" + }, + { + "name": "SwaggerAnnotations", + "description": "Manipulate Carts to your heart's content", + "externalDocs": { + "url": "http://www.tempuri.org" + } + }, + { + "name": "UnboundParams" + } + ] +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=v1.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=v1.verified.txt index a4b09a31e5..ce88b8a9b6 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=v1.verified.txt +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=v1.verified.txt @@ -338,6 +338,28 @@ "x-purpose": "test" } }, + "/get-weekly-apppointments": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "name": "dayOfWeek", + "in": "query", + "schema": { + "$ref": "#/components/schemas/DayOfWeek" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, "/kittens": { "post": { "tags": [ @@ -1355,6 +1377,9 @@ }, "cartType": { "$ref": "#/components/schemas/CartType" + }, + "basketType": { + "$ref": "#/components/schemas/CartType" } }, "additionalProperties": false @@ -1422,6 +1447,19 @@ "type": "integer", "format": "int32" }, + "DayOfWeek": { + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "type": "integer", + "format": "int32" + }, "DiscountType": { "enum": [ "Percentage", diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=2.0.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=2.0.verified.txt new file mode 100644 index 0000000000..89109a3055 --- /dev/null +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=2.0.verified.txt @@ -0,0 +1,1474 @@ +{ + "swagger": "2.0", + "info": { + "title": "Test API V1", + "description": "A sample API for testing Swashbuckle", + "termsOfService": "http://tempuri.org/terms", + "version": "v1" + }, + "paths": { + "/products": { + "post": { + "tags": [ + "CrudActions" + ], + "summary": "Creates a product", + "description": "## Heading 1\r\n\r\n POST /products\r\n {\r\n \"id\": \"123\",\r\n \"description\": \"Some product\"\r\n }", + "operationId": "CreateProduct", + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "$ref": "#/definitions/Product" + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Product" + } + } + }, + "x-purpose": "test" + }, + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Searches the collection of products by description key words", + "operationId": "SearchProducts", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "query", + "name": "kw", + "description": "A list of search terms", + "type": "string", + "default": "foobar" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Product" + } + } + } + }, + "x-purpose": "test" + } + }, + "/products/all": { + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Get all products", + "description": "```\r\n{\r\n \"Id\":1,\r\n \"Description\":\"\",\r\n \"Status\": 0,\r\n \"Status2\": 1\r\n}\r\n \r\n```", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Product" + } + } + } + }, + "x-purpose": "test" + } + }, + "/products/{id}": { + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Returns a specific product", + "operationId": "GetProduct", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The product id", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Product" + } + } + }, + "x-purpose": "test" + }, + "put": { + "tags": [ + "CrudActions" + ], + "summary": "Updates all properties of a specific product", + "operationId": "UpdateProduct", + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "", + "required": true, + "type": "integer", + "format": "int32" + }, + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "$ref": "#/definitions/Product" + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "patch": { + "tags": [ + "CrudActions" + ], + "summary": "Updates some properties of a specific product", + "description": "\r\nOnly provided properties will be updated,\r\n other remain unchanged.\r\n\r\nIdentifier must be non-default value\r\n\r\nBody must be specified", + "operationId": "PatchProduct", + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "", + "required": true, + "type": "integer", + "format": "int32" + }, + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "type": "object", + "additionalProperties": { } + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "CrudActions" + ], + "summary": "Deletes a specific product", + "operationId": "DeleteProduct", + "parameters": [ + { + "in": "path", + "name": "id", + "description": "", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/payments/authorize": { + "post": { + "tags": [ + "DataAnnotations" + ], + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/PaymentRequest" + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + }, + "x-purpose": "test" + } + }, + "/payments/{paymentId}/cancel": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "in": "path", + "name": "paymentId", + "required": true, + "type": "string", + "minLength": 6 + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/get-weekly-apppointments": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "in": "query", + "name": "dayOfWeek", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/kittens": { + "post": { + "tags": [ + "DynamicTypes" + ], + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "integer", + "format": "int32" + } + } + }, + "x-purpose": "test" + } + }, + "/unicorns": { + "get": { + "tags": [ + "DynamicTypes" + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { } + } + } + }, + "x-purpose": "test" + } + }, + "/dragons": { + "post": { + "tags": [ + "DynamicTypes" + ], + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/single": { + "post": { + "tags": [ + "Files" + ], + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "file", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/multiple": { + "post": { + "tags": [ + "Files" + ], + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "files", + "type": "array", + "items": { + "type": "string", + "format": "binary" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/form-with-file": { + "post": { + "tags": [ + "Files" + ], + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "name", + "type": "string" + }, + { + "in": "formData", + "name": "file", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/{name}": { + "get": { + "tags": [ + "Files" + ], + "produces": [ + "text/plain", + "application/zip" + ], + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "format": "binary", + "allOf": [ + { + "type": "string", + "format": "binary" + } + ] + } + } + }, + "x-purpose": "test" + } + }, + "/registrations": { + "post": { + "tags": [ + "FromFormParams" + ], + "summary": "Form parameters with description", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "parameters": [ + { + "in": "formData", + "name": "name", + "description": "Summary for Name", + "type": "string" + }, + { + "in": "formData", + "name": "phoneNumbers", + "description": "Summary for PhoneNumbers", + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + }, + { + "in": "formData", + "name": "formFile", + "description": "Description for file", + "type": "string" + }, + { + "in": "formData", + "name": "text", + "description": "Description for Text", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/registrationsWithIgnoreProperties": { + "post": { + "tags": [ + "FromFormParams" + ], + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "phoneNumbers", + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/registrationsWithEnumParameter": { + "post": { + "tags": [ + "FromFormParams" + ], + "summary": "Form parameters with description", + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "in": "formData", + "name": "name", + "description": "Summary for Name", + "type": "string" + }, + { + "in": "formData", + "name": "phoneNumbers", + "description": "Summary for PhoneNumbers", + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + }, + { + "in": "formData", + "name": "logLevel", + "type": "string" + }, + { + "in": "formData", + "name": "formFile", + "description": "Description for file", + "type": "string" + }, + { + "in": "formData", + "name": "dateTimeKind", + "description": "Description for dateTimeKind", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/country/validate": { + "get": { + "tags": [ + "FromHeaderParams" + ], + "parameters": [ + { + "in": "query", + "name": "country", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/addresses/validate": { + "get": { + "tags": [ + "FromQueryParams" + ], + "parameters": [ + { + "in": "query", + "name": "country", + "description": "3-letter ISO country code", + "required": true, + "type": "string" + }, + { + "in": "query", + "name": "city", + "description": "Name of city", + "type": "string", + "default": "Seattle" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/zip-codes/validate": { + "get": { + "tags": [ + "FromQueryParams" + ], + "parameters": [ + { + "in": "query", + "name": "zipCodes", + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi" + }, + { + "in": "query", + "name": "search", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/Issue3013/Get": { + "get": { + "tags": [ + "Issue3013" + ], + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/TestResponse" + } + } + }, + "x-purpose": "test" + } + }, + "/promotions": { + "get": { + "tags": [ + "JsonAnnotations" + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Promotion" + } + } + } + }, + "x-purpose": "test" + } + }, + "/shapes": { + "post": { + "tags": [ + "PolymorphicTypes" + ], + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/Rectangle" + } + ] + }, + "x-purpose": "test" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "integer", + "format": "int32" + } + } + }, + "x-purpose": "test" + } + }, + "/orders": { + "post": { + "tags": [ + "ResponseTypeAnnotations" + ], + "summary": "Creates an order", + "consumes": [ + "application/xml" + ], + "produces": [ + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "", + "required": true, + "schema": { + "$ref": "#/definitions/Order" + }, + "x-purpose": "test" + } + ], + "responses": { + "201": { + "description": "Order created", + "schema": { + "type": "integer", + "format": "int32" + } + }, + "400": { + "description": "Order invalid", + "schema": { + "$ref": "#/definitions/ValidationProblemDetails" + } + } + }, + "x-purpose": "test" + } + }, + "/carts": { + "post": { + "tags": [ + "SwaggerAnnotations" + ], + "operationId": "CreateCart", + "consumes": [ + "application/json", + "text/json", + "application/*+json" + ], + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "The cart request body", + "schema": { + "$ref": "#/definitions/Cart" + }, + "x-purpose": "test" + } + ], + "responses": { + "201": { + "description": "The cart was created", + "schema": { + "$ref": "#/definitions/Cart" + } + }, + "400": { + "description": "The cart data is invalid" + } + }, + "x-purpose": "test" + } + }, + "/carts/{id}": { + "get": { + "tags": [ + "SwaggerAnnotations" + ], + "externalDocs": { + "description": "External docs for CartsByIdGet", + "url": "https://tempuri.org/carts-by-id-get" + }, + "operationId": "GetCart", + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The cart identifier", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Cart" + } + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "SwaggerAnnotations" + ], + "summary": "Deletes a specific cart", + "description": "Requires admin privileges", + "operationId": "DeleteCart", + "produces": [ + "text/plain", + "application/json", + "text/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The cart identifier", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Cart" + } + } + }, + "x-purpose": "test" + } + }, + "/stores": { + "post": { + "tags": [ + "UnboundParams" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "query", + "name": "id", + "type": "integer", + "format": "int32" + }, + { + "in": "query", + "name": "location", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "integer", + "format": "int32" + } + } + }, + "x-purpose": "test" + }, + "get": { + "tags": [ + "UnboundParams" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "query", + "name": "locations", + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Store" + } + } + } + }, + "x-purpose": "test" + } + }, + "/stores/{id}": { + "get": { + "tags": [ + "UnboundParams" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Store" + } + } + }, + "x-purpose": "test" + }, + "put": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "in": "query", + "name": "id", + "type": "integer", + "format": "int32" + }, + { + "in": "path", + "name": "id", + "required": true, + "type": "integer", + "format": "int32" + }, + { + "in": "query", + "name": "location", + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + } + }, + "definitions": { + "Cart": { + "type": "object", + "required": [ + "Id" + ], + "properties": { + "id": { + "type": "integer", + "description": "The cart identifier", + "format": "int32", + "readOnly": true + }, + "cartType": { + "$ref": "#/definitions/CartType" + }, + "basketType": { + "$ref": "#/definitions/CartType" + } + }, + "additionalProperties": false + }, + "CartType": { + "type": "integer", + "description": "The cart type", + "format": "int32", + "enum": [ + 0, + 1 + ] + }, + "Circle": { + "allOf": [ + { + "$ref": "#/definitions/Shape" + }, + { + "type": "object", + "properties": { + "radius": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ] + }, + "CreditCard": { + "type": "object", + "required": [ + "cardNumber", + "expMonth", + "expYear" + ], + "properties": { + "cardNumber": { + "type": "string", + "minLength": 1, + "pattern": "^[3-6]?\\d{12,15}$" + }, + "expMonth": { + "type": "integer", + "format": "int32", + "maximum": 12, + "minimum": 1 + }, + "expYear": { + "type": "integer", + "format": "int32", + "maximum": 99, + "minimum": 14 + } + }, + "additionalProperties": false + }, + "DateTimeKind": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1, + 2 + ] + }, + "DayOfWeek": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ] + }, + "DiscountType": { + "type": "string", + "enum": [ + "Percentage", + "Amount" + ] + }, + "LogLevel": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ] + }, + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "description": { + "type": "string", + "x-nullable": true + }, + "total": { + "type": "number", + "format": "double" + } + }, + "additionalProperties": false + }, + "PaymentRequest": { + "type": "object", + "required": [ + "creditCard", + "transaction" + ], + "properties": { + "transaction": { + "$ref": "#/definitions/Transaction" + }, + "creditCard": { + "$ref": "#/definitions/CreditCard" + } + }, + "additionalProperties": false + }, + "Product": { + "type": "object", + "description": "Represents a product", + "properties": { + "id": { + "type": "integer", + "description": "Uniquely identifies the product", + "format": "int32" + }, + "description": { + "type": "string", + "description": "Describes the product", + "x-nullable": true + }, + "status": { + "$ref": "#/definitions/ProductStatus" + }, + "status2": { + "$ref": "#/definitions/ProductStatus" + }, + "price": { + "type": "number", + "format": "double", + "maximum": 122.9, + "exclusiveMaximum": true, + "minimum": 0.1, + "exclusiveMinimum": true, + "x-nullable": true + } + }, + "additionalProperties": false, + "example": { + "id": 123, + "description": "foobar", + "price": 14.37 + } + }, + "ProductStatus": { + "type": "integer", + "format": "int32", + "enum": [ + 0, + 1, + 2 + ] + }, + "Promotion": { + "type": "object", + "properties": { + "promo-code": { + "type": "string", + "x-nullable": true + }, + "discountType": { + "$ref": "#/definitions/DiscountType" + } + }, + "additionalProperties": false + }, + "Rectangle": { + "allOf": [ + { + "$ref": "#/definitions/Shape" + }, + { + "type": "object", + "properties": { + "height": { + "type": "integer", + "format": "int32" + }, + "width": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ] + }, + "Shape": { + "type": "object", + "required": [ + "TypeName" + ], + "properties": { + "TypeName": { + "type": "string" + }, + "name": { + "type": "string", + "x-nullable": true + } + }, + "additionalProperties": false, + "discriminator": "TypeName" + }, + "Store": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "location": { + "type": "string", + "x-nullable": true + } + }, + "additionalProperties": false + }, + "TestResponse": { + "type": "object", + "properties": { + "foo": { + "$ref": "#/definitions/TestStruct" + } + }, + "additionalProperties": false + }, + "TestStruct": { + "type": "object", + "properties": { + "a": { + "type": "integer", + "format": "int32" + }, + "b": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + }, + "Transaction": { + "type": "object", + "required": [ + "amount" + ], + "properties": { + "amount": { + "type": "number", + "format": "double" + }, + "note": { + "type": "string", + "x-nullable": true + } + }, + "additionalProperties": false + }, + "ValidationProblemDetails": { + "type": "object", + "properties": { + "type": { + "type": "string", + "x-nullable": true + }, + "title": { + "type": "string", + "x-nullable": true + }, + "status": { + "type": "integer", + "format": "int32", + "x-nullable": true + }, + "detail": { + "type": "string", + "x-nullable": true + }, + "instance": { + "type": "string", + "x-nullable": true + }, + "errors": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "x-nullable": true + } + }, + "additionalProperties": { } + } + }, + "tags": [ + { + "name": "CrudActions" + }, + { + "name": "DataAnnotations" + }, + { + "name": "DynamicTypes" + }, + { + "name": "Files" + }, + { + "name": "FromFormParams" + }, + { + "name": "FromHeaderParams" + }, + { + "name": "FromQueryParams" + }, + { + "name": "Issue3013" + }, + { + "name": "JsonAnnotations" + }, + { + "name": "PolymorphicTypes" + }, + { + "name": "ResponseTypeAnnotations" + }, + { + "name": "SwaggerAnnotations", + "description": "Manipulate Carts to your heart's content", + "externalDocs": { + "url": "http://www.tempuri.org" + } + }, + { + "name": "UnboundParams" + } + ] +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=3.1.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=3.1.verified.txt new file mode 100644 index 0000000000..5b9d29ef14 --- /dev/null +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=3.1.verified.txt @@ -0,0 +1,1786 @@ +{ + "openapi": "3.1.1", + "info": { + "title": "Test API V1", + "description": "A sample API for testing Swashbuckle", + "termsOfService": "http://tempuri.org/terms", + "version": "v1" + }, + "paths": { + "/products": { + "post": { + "tags": [ + "CrudActions" + ], + "summary": "Creates a product", + "description": "## Heading 1\r\n\r\n POST /products\r\n {\r\n \"id\": \"123\",\r\n \"description\": \"Some product\"\r\n }", + "operationId": "CreateProduct", + "requestBody": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + } + } + } + }, + "x-purpose": "test" + }, + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Searches the collection of products by description key words", + "operationId": "SearchProducts", + "parameters": [ + { + "name": "kw", + "in": "query", + "description": "A list of search terms", + "schema": { + "type": "string", + "default": "foobar" + }, + "example": "hello" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Product" + } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/products/all": { + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Get all products", + "description": "```\r\n{\r\n \"Id\":1,\r\n \"Description\":\"\",\r\n \"Status\": 0,\r\n \"Status2\": 1\r\n}\r\n \r\n```", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Product" + } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/products/{id}": { + "get": { + "tags": [ + "CrudActions" + ], + "summary": "Returns a specific product", + "operationId": "GetProduct", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The product id", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "example": 111 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + } + } + } + }, + "x-purpose": "test" + }, + "put": { + "tags": [ + "CrudActions" + ], + "summary": "Updates all properties of a specific product", + "operationId": "UpdateProduct", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "example": 222 + } + ], + "requestBody": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/Product" + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "patch": { + "tags": [ + "CrudActions" + ], + "summary": "Updates some properties of a specific product", + "description": "\r\nOnly provided properties will be updated,\r\n other remain unchanged.\r\n\r\nIdentifier must be non-default value\r\n\r\nBody must be specified", + "operationId": "PatchProduct", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "example": 333 + } + ], + "requestBody": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { } + } + }, + "text/json": { + "schema": { + "type": "object", + "additionalProperties": { } + } + }, + "application/*+json": { + "schema": { + "type": "object", + "additionalProperties": { } + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "CrudActions" + ], + "summary": "Deletes a specific product", + "operationId": "DeleteProduct", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "example": 444 + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/payments/authorize": { + "post": { + "tags": [ + "DataAnnotations" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentRequest" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/PaymentRequest" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/PaymentRequest" + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/payments/{paymentId}/cancel": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "name": "paymentId", + "in": "path", + "required": true, + "schema": { + "minLength": 6, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/get-weekly-apppointments": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "name": "dayOfWeek", + "in": "query", + "schema": { + "default": 4, + "$ref": "#/components/schemas/DayOfWeek" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/kittens": { + "post": { + "tags": [ + "DynamicTypes" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { } + }, + "text/json": { + "schema": { } + }, + "application/*+json": { + "schema": { } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/unicorns": { + "get": { + "tags": [ + "DynamicTypes" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/dragons": { + "post": { + "tags": [ + "DynamicTypes" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { } + }, + "text/json": { + "schema": { } + }, + "application/*+json": { + "schema": { } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/single": { + "post": { + "tags": [ + "Files" + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "file": { + "type": "string", + "format": "binary" + } + } + }, + "encoding": { + "file": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/multiple": { + "post": { + "tags": [ + "Files" + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "files": { + "type": "array", + "items": { + "type": "string", + "format": "binary" + } + } + } + }, + "encoding": { + "files": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/form-with-file": { + "post": { + "tags": [ + "Files" + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "file": { + "type": "string", + "format": "binary" + } + } + }, + "encoding": { + "name": { + "style": "form" + }, + "file": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/files/{name}": { + "get": { + "tags": [ + "Files" + ], + "parameters": [ + { + "name": "name", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "oneOf": [ + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + } + ] + } + }, + "application/zip": { + "schema": { + "oneOf": [ + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + }, + { + "type": "string", + "format": "binary" + } + ] + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/registrations": { + "post": { + "tags": [ + "FromFormParams" + ], + "summary": "Form parameters with description", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Summary for Name", + "example": "MyName" + }, + "phoneNumbers": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + }, + "description": "Summary for PhoneNumbers" + }, + "formFile": { + "type": "string", + "description": "Description for file", + "format": "binary" + }, + "text": { + "type": "string", + "description": "Description for Text" + } + } + }, + "encoding": { + "name": { + "style": "form" + }, + "phoneNumbers": { + "style": "form" + }, + "formFile": { + "style": "form" + }, + "text": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/registrationsWithIgnoreProperties": { + "post": { + "tags": [ + "FromFormParams" + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "phoneNumbers": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + } + } + }, + "encoding": { + "phoneNumbers": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/registrationsWithEnumParameter": { + "post": { + "tags": [ + "FromFormParams" + ], + "summary": "Form parameters with description", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Summary for Name", + "example": "MyName" + }, + "phoneNumbers": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + }, + "description": "Summary for PhoneNumbers" + }, + "logLevel": { + "$ref": "#/components/schemas/LogLevel" + }, + "formFile": { + "type": "string", + "description": "Description for file", + "format": "binary" + }, + "dateTimeKind": { + "description": "Description for dateTimeKind", + "$ref": "#/components/schemas/DateTimeKind" + } + } + }, + "encoding": { + "name": { + "style": "form" + }, + "phoneNumbers": { + "style": "form" + }, + "logLevel": { + "style": "form" + }, + "formFile": { + "style": "form" + }, + "dateTimeKind": { + "style": "form" + } + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/country/validate": { + "get": { + "tags": [ + "FromHeaderParams" + ], + "parameters": [ + { + "name": "country", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/addresses/validate": { + "get": { + "tags": [ + "FromQueryParams" + ], + "parameters": [ + { + "name": "country", + "in": "query", + "description": "3-letter ISO country code", + "required": true, + "schema": { + "type": "string", + "example": null + }, + "example": null + }, + { + "name": "city", + "in": "query", + "description": "Name of city", + "schema": { + "type": "string", + "default": "Seattle" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/zip-codes/validate": { + "get": { + "tags": [ + "FromQueryParams" + ], + "parameters": [ + { + "name": "zipCodes", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "search", + "in": "query", + "required": true, + "style": "deepObject", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, + "/Issue3013/Get": { + "get": { + "tags": [ + "Issue3013" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/TestResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/TestResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/TestResponse" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/promotions": { + "get": { + "tags": [ + "JsonAnnotations" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Promotion" + } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/shapes": { + "post": { + "tags": [ + "PolymorphicTypes" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/Rectangle" + }, + { + "$ref": "#/components/schemas/Circle" + } + ] + } + }, + "text/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/Rectangle" + }, + { + "$ref": "#/components/schemas/Circle" + } + ] + } + }, + "application/*+json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/Rectangle" + }, + { + "$ref": "#/components/schemas/Circle" + } + ] + } + } + }, + "x-purpose": "test" + }, + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "type": "integer", + "format": "int32" + } + }, + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + }, + "text/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/orders": { + "post": { + "tags": [ + "ResponseTypeAnnotations" + ], + "summary": "Creates an order", + "requestBody": { + "description": "", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + }, + "required": true, + "x-purpose": "test" + }, + "responses": { + "201": { + "description": "Order created", + "content": { + "application/xml": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + }, + "400": { + "description": "Order invalid", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/ValidationProblemDetails" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/carts": { + "post": { + "tags": [ + "SwaggerAnnotations" + ], + "operationId": "CreateCart", + "requestBody": { + "description": "The cart request body", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + } + }, + "x-purpose": "test" + }, + "responses": { + "201": { + "description": "The cart was created", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + } + } + }, + "400": { + "description": "The cart data is invalid" + } + }, + "x-purpose": "test" + } + }, + "/carts/{id}": { + "get": { + "tags": [ + "SwaggerAnnotations" + ], + "externalDocs": { + "description": "External docs for CartsByIdGet", + "url": "https://tempuri.org/carts-by-id-get" + }, + "operationId": "GetCart", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The cart identifier", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + } + } + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "SwaggerAnnotations" + ], + "summary": "Deletes a specific cart", + "description": "Requires admin privileges", + "operationId": "DeleteCart", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The cart identifier", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/Cart" + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/stores": { + "post": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "id", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "location", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + } + }, + "x-purpose": "test" + }, + "get": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "locations", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Store" + } + } + } + } + } + }, + "x-purpose": "test" + } + }, + "/stores/{id}": { + "get": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Store" + } + } + } + } + }, + "x-purpose": "test" + }, + "put": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "id", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "location", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + }, + "delete": { + "tags": [ + "UnboundParams" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + } + }, + "components": { + "schemas": { + "Cart": { + "required": [ + "Id" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The cart identifier", + "format": "int32", + "readOnly": true + }, + "cartType": { + "default": 0, + "$ref": "#/components/schemas/CartType" + }, + "basketType": { + "deprecated": true, + "$ref": "#/components/schemas/CartType" + } + }, + "additionalProperties": false + }, + "CartType": { + "enum": [ + 0, + 1 + ], + "type": "integer", + "description": "The cart type", + "format": "int32" + }, + "Circle": { + "allOf": [ + { + "$ref": "#/components/schemas/Shape" + }, + { + "type": "object", + "properties": { + "radius": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ] + }, + "CreditCard": { + "required": [ + "cardNumber", + "expMonth", + "expYear" + ], + "type": "object", + "properties": { + "cardNumber": { + "minLength": 1, + "pattern": "^[3-6]?\\d{12,15}$", + "type": "string" + }, + "expMonth": { + "maximum": 12, + "minimum": 1, + "type": "integer", + "format": "int32" + }, + "expYear": { + "maximum": 99, + "minimum": 14, + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + }, + "DateTimeKind": { + "enum": [ + 0, + 1, + 2 + ], + "type": "integer", + "format": "int32" + }, + "DayOfWeek": { + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "type": "integer", + "format": "int32" + }, + "DiscountType": { + "enum": [ + "Percentage", + "Amount" + ], + "type": "string" + }, + "LogLevel": { + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "type": "integer", + "format": "int32" + }, + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "total": { + "type": "number", + "format": "double" + } + }, + "additionalProperties": false + }, + "PaymentRequest": { + "required": [ + "creditCard", + "transaction" + ], + "type": "object", + "properties": { + "transaction": { + "$ref": "#/components/schemas/Transaction" + }, + "creditCard": { + "$ref": "#/components/schemas/CreditCard" + } + }, + "additionalProperties": false + }, + "Product": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Uniquely identifies the product", + "format": "int32" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "Describes the product" + }, + "status": { + "$ref": "#/components/schemas/ProductStatus" + }, + "status2": { + "$ref": "#/components/schemas/ProductStatus" + }, + "price": { + "exclusiveMaximum": 122.9, + "exclusiveMinimum": 0.1, + "type": [ + "null", + "number" + ], + "format": "double" + } + }, + "additionalProperties": false, + "description": "Represents a product", + "example": { + "id": 123, + "description": "foobar", + "price": 14.37 + } + }, + "ProductStatus": { + "enum": [ + 0, + 1, + 2 + ], + "type": "integer", + "format": "int32" + }, + "Promotion": { + "type": "object", + "properties": { + "promo-code": { + "type": [ + "null", + "string" + ] + }, + "discountType": { + "$ref": "#/components/schemas/DiscountType" + } + }, + "additionalProperties": false + }, + "Rectangle": { + "allOf": [ + { + "$ref": "#/components/schemas/Shape" + }, + { + "type": "object", + "properties": { + "height": { + "type": "integer", + "format": "int32" + }, + "width": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + } + ] + }, + "Shape": { + "required": [ + "TypeName" + ], + "type": "object", + "properties": { + "TypeName": { + "type": "string" + }, + "name": { + "type": [ + "null", + "string" + ] + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "TypeName", + "mapping": { + "Rectangle": "#/components/schemas/Rectangle", + "Circle": "#/components/schemas/Circle" + } + } + }, + "Store": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "location": { + "type": [ + "null", + "string" + ] + } + }, + "additionalProperties": false + }, + "TestResponse": { + "type": "object", + "properties": { + "foo": { + "$ref": "#/components/schemas/TestStruct" + } + }, + "additionalProperties": false + }, + "TestStruct": { + "type": "object", + "properties": { + "a": { + "type": "integer", + "format": "int32" + }, + "b": { + "type": "integer", + "format": "int32" + } + }, + "additionalProperties": false + }, + "Transaction": { + "required": [ + "amount" + ], + "type": "object", + "properties": { + "amount": { + "type": "number", + "format": "double" + }, + "note": { + "type": [ + "null", + "string" + ] + } + }, + "additionalProperties": false + }, + "ValidationProblemDetails": { + "type": "object", + "properties": { + "type": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "status": { + "type": [ + "null", + "integer" + ], + "format": "int32" + }, + "detail": { + "type": [ + "null", + "string" + ] + }, + "instance": { + "type": [ + "null", + "string" + ] + }, + "errors": { + "type": [ + "null", + "object" + ], + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "additionalProperties": { } + } + } + }, + "tags": [ + { + "name": "CrudActions" + }, + { + "name": "DataAnnotations" + }, + { + "name": "DynamicTypes" + }, + { + "name": "Files" + }, + { + "name": "FromFormParams" + }, + { + "name": "FromHeaderParams" + }, + { + "name": "FromQueryParams" + }, + { + "name": "Issue3013" + }, + { + "name": "JsonAnnotations" + }, + { + "name": "PolymorphicTypes" + }, + { + "name": "ResponseTypeAnnotations" + }, + { + "name": "SwaggerAnnotations", + "description": "Manipulate Carts to your heart's content", + "externalDocs": { + "url": "http://www.tempuri.org" + } + }, + { + "name": "UnboundParams" + } + ] +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=v1.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=v1.verified.txt index a4b09a31e5..ce88b8a9b6 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=v1.verified.txt +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.SwaggerEndpoint_ReturnsValidSwaggerJson_startupType=Basic.Startup_swaggerRequestUri=v1.verified.txt @@ -338,6 +338,28 @@ "x-purpose": "test" } }, + "/get-weekly-apppointments": { + "put": { + "tags": [ + "DataAnnotations" + ], + "parameters": [ + { + "name": "dayOfWeek", + "in": "query", + "schema": { + "$ref": "#/components/schemas/DayOfWeek" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-purpose": "test" + } + }, "/kittens": { "post": { "tags": [ @@ -1355,6 +1377,9 @@ }, "cartType": { "$ref": "#/components/schemas/CartType" + }, + "basketType": { + "$ref": "#/components/schemas/CartType" } }, "additionalProperties": false @@ -1422,6 +1447,19 @@ "type": "integer", "format": "int32" }, + "DayOfWeek": { + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "type": "integer", + "format": "int32" + }, "DiscountType": { "enum": [ "Percentage", diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_6548ff89f26311aa/GetWeeklyApppointments/GetWeeklyApppointmentsRequestBuilder.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_6548ff89f26311aa/GetWeeklyApppointments/GetWeeklyApppointmentsRequestBuilder.verified.cs new file mode 100644 index 0000000000..b8f23d6113 --- /dev/null +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_6548ff89f26311aa/GetWeeklyApppointments/GetWeeklyApppointmentsRequestBuilder.verified.cs @@ -0,0 +1,92 @@ +// +#pragma warning disable CS0618 +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System; +namespace Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.GetWeeklyApppointments +{ + /// + /// Builds and executes requests for operations under \get-weekly-apppointments + /// + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class GetWeeklyApppointmentsRequestBuilder : BaseRequestBuilder + { + /// + /// Instantiates a new and sets the default values. + /// + /// Path parameters for the request + /// The request adapter to use to execute the requests. + public GetWeeklyApppointmentsRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/get-weekly-apppointments{?dayOfWeek*}", pathParameters) + { + } + /// + /// Instantiates a new and sets the default values. + /// + /// The raw URL to use for the request builder. + /// The request adapter to use to execute the requests. + public GetWeeklyApppointmentsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/get-weekly-apppointments{?dayOfWeek*}", rawUrl) + { + } + /// A + /// Cancellation token to use when cancelling requests + /// Configuration for the request such as headers, query parameters, and middleware options. +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER +#nullable enable + public async Task PutAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default) + { +#nullable restore +#else + public async Task PutAsync(Action> requestConfiguration = default, CancellationToken cancellationToken = default) + { +#endif + var requestInfo = ToPutRequestInformation(requestConfiguration); + return await RequestAdapter.SendPrimitiveAsync(requestInfo, default, cancellationToken).ConfigureAwait(false); + } + /// A + /// Configuration for the request such as headers, query parameters, and middleware options. +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER +#nullable enable + public RequestInformation ToPutRequestInformation(Action>? requestConfiguration = default) + { +#nullable restore +#else + public RequestInformation ToPutRequestInformation(Action> requestConfiguration = default) + { +#endif + var requestInfo = new RequestInformation(Method.PUT, UrlTemplate, PathParameters); + requestInfo.Configure(requestConfiguration); + return requestInfo; + } + /// + /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored. + /// + /// A + /// The raw URL to use for the request builder. + public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.GetWeeklyApppointments.GetWeeklyApppointmentsRequestBuilder WithUrl(string rawUrl) + { + return new global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.GetWeeklyApppointments.GetWeeklyApppointmentsRequestBuilder(rawUrl, RequestAdapter); + } + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public partial class GetWeeklyApppointmentsRequestBuilderPutQueryParameters + #pragma warning restore CS1591 + { + [QueryParameter("dayOfWeek")] + public int? DayOfWeek { get; set; } + } + /// + /// Configuration for the request such as headers, query parameters, and middleware options. + /// + [Obsolete("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.")] + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + public partial class GetWeeklyApppointmentsRequestBuilderPutRequestConfiguration : RequestConfiguration + { + } + } +} +#pragma warning restore CS0618 diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_6548ff89f26311aa/KiotaOpenApiClient.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_6548ff89f26311aa/KiotaOpenApiClient.verified.cs index a964f8c532..fe74962715 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_6548ff89f26311aa/KiotaOpenApiClient.verified.cs +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_6548ff89f26311aa/KiotaOpenApiClient.verified.cs @@ -11,6 +11,7 @@ using Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Country; using Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Dragons; using Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Files; +using Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.GetWeeklyApppointments; using Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Issue3013; using Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Kittens; using Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Orders; @@ -61,6 +62,11 @@ public partial class KiotaOpenApiClient : BaseRequestBuilder { get => new global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Files.FilesRequestBuilder(PathParameters, RequestAdapter); } + /// The getWeeklyApppointments property + public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.GetWeeklyApppointments.GetWeeklyApppointmentsRequestBuilder GetWeeklyApppointments + { + get => new global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.GetWeeklyApppointments.GetWeeklyApppointmentsRequestBuilder(PathParameters, RequestAdapter); + } /// The Issue3013 property public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Issue3013.Issue3013RequestBuilder Issue3013 { diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_6548ff89f26311aa/Models/Cart.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_6548ff89f26311aa/Models/Cart.verified.cs index ba75b1190f..818cacb043 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_6548ff89f26311aa/Models/Cart.verified.cs +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_6548ff89f26311aa/Models/Cart.verified.cs @@ -12,6 +12,8 @@ namespace Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models public partial class Cart : IParsable #pragma warning restore CS1591 { + /// The cart type + public int? BasketType { get; set; } /// The cart type public int? CartType { get; set; } /// The cart identifier @@ -34,6 +36,7 @@ public virtual IDictionary> GetFieldDeserializers() { return new Dictionary> { + { "basketType", n => { BasketType = n.GetIntValue(); } }, { "cartType", n => { CartType = n.GetIntValue(); } }, { "id", n => { Id = n.GetIntValue(); } }, }; @@ -45,6 +48,7 @@ public virtual IDictionary> GetFieldDeserializers() public virtual void Serialize(ISerializationWriter writer) { if(ReferenceEquals(writer, null)) throw new ArgumentNullException(nameof(writer)); + writer.WriteIntValue("basketType", BasketType); writer.WriteIntValue("cartType", CartType); } } diff --git a/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs b/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs index 1e3a76f7b4..6c0fbb3552 100644 --- a/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs +++ b/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs @@ -225,7 +225,7 @@ public void GenerateSchema_GeneratesReferencedArraySchema_IfEnumerableTypeIsSelf } [Theory] - [InlineData(typeof(ComplexType), "ComplexType", new[] { "Property1", "Property2" })] + [InlineData(typeof(ComplexType), "ComplexType", new[] { "Property1", "Property2", "Property3" })] [InlineData(typeof(GenericType), "BooleanInt32GenericType", new[] { "Property1", "Property2" })] [InlineData(typeof(GenericType), "BooleanInt32ArrayGenericType", new[] { "Property1", "Property2" })] [InlineData(typeof(ContainingType.NestedType), "NestedType", new[] { "Property2" })] diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/Fixtures/FakeController.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/Fixtures/FakeController.cs index 9c87c07dd3..f08b229f36 100644 --- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/Fixtures/FakeController.cs +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/Fixtures/FakeController.cs @@ -49,6 +49,9 @@ public void ActionWithIntParameterWithDefaultValue(int param = 1) public void ActionWithIntParameterWithDefaultValueAttribute([DefaultValue(3)] int param) { } + public void ActionWithEnumParameterWithDefaultValueAttribute([DefaultValue(DayOfWeek.Thursday)] DayOfWeek param) + { } + public void ActionWithIntFromQueryParameter([FromQuery] int param) { } diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs index 7f06e79fd4..d866a7b40c 100644 --- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs @@ -216,7 +216,7 @@ public void GenerateSchema_GeneratesReferencedArraySchema_IfEnumerableTypeIsSelf } [Theory] - [InlineData(typeof(ComplexType), "ComplexType", new[] { "Property1", "Property2" })] + [InlineData(typeof(ComplexType), "ComplexType", new[] { "Property1", "Property2", "Property3" })] [InlineData(typeof(GenericType), "BooleanInt32GenericType", new[] { "Property1", "Property2" })] [InlineData(typeof(GenericType), "BooleanInt32ArrayGenericType", new[] { "Property1", "Property2" })] [InlineData(typeof(ContainingType.NestedType), "NestedType", new[] { "Property2" })] @@ -324,6 +324,7 @@ public void GenerateSchema_SetsNullableFlag_IfPropertyIsReferenceOrNullableType( [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.StringArrayWithDefault), "[\n \"foo\",\n \"bar\"\n]")] [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.NullableIntWithDefaultNullValue), null)] [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.NullableIntWithDefaultValue), "2147483647")] + [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.EnumWithDefaultValue), "4")] public void GenerateSchema_SetsDefault_IfPropertyHasDefaultValueAttribute( Type declaringType, string propertyName, @@ -519,6 +520,22 @@ public void GenerateSchema_SetsDefault_IfParameterHasDefaultValueAttribute() Assert.Equal("3", schema.Default.ToJson()); } + [Fact] + public void GenerateSchema_SetsDefault_IfParameterHasEnumDefaultValueAttribute() + { + var schemaRepository = new SchemaRepository(); + + var parameterInfo = typeof(FakeController) + .GetMethod(nameof(FakeController.ActionWithEnumParameterWithDefaultValueAttribute)) + .GetParameters() + .First(); + + var schema = Subject().GenerateSchema(parameterInfo.ParameterType, schemaRepository, parameterInfo: parameterInfo); + + Assert.NotNull(schema.Default); + Assert.Equal("4", schema.Default.ToJson()); + } + [Theory] [InlineData(typeof(ComplexType), typeof(ComplexType))] [InlineData(typeof(GenericType), typeof(GenericType))] @@ -1237,7 +1254,7 @@ public void GenerateSchema_HonorsSerializerOption_PropertyNamingPolicy() var reference = Assert.IsType(referenceSchema); var schema = schemaRepository.Schemas[reference.Reference.Id]; - Assert.Equal(["property1", "property2"], schema.Properties.Keys); + Assert.Equal(["property1", "property2", "property3"], schema.Properties.Keys); } [Theory] @@ -1250,7 +1267,7 @@ public void GenerateSchema_HonorsSerializerOption_StringEnumConverter( { var subject = Subject( configureGenerator: c => { c.UseInlineDefinitionsForEnums = true; }, - configureSerializer: c => { c.Converters.Add(new JsonStringEnumConverter(namingPolicy: (camelCaseText ? JsonNamingPolicy.CamelCase : null), true)); } + configureSerializer: c => { c.Converters.Add(new JsonStringEnumConverter(namingPolicy: camelCaseText ? JsonNamingPolicy.CamelCase : null, true)); } ); var schemaRepository = new SchemaRepository(); diff --git a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/ComplexType.cs b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/ComplexType.cs index e4a735b9a7..9d9850a7ba 100644 --- a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/ComplexType.cs +++ b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/ComplexType.cs @@ -1,8 +1,13 @@ -namespace Swashbuckle.AspNetCore.TestSupport; +using System.ComponentModel; + +namespace Swashbuckle.AspNetCore.TestSupport; public class ComplexType { public bool Property1 { get; set; } public int Property2 { get; set; } + + [DefaultValue(DayOfWeek.Thursday)] + public DayOfWeek Property3 { get; set; } } diff --git a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithDefaultAttributeOnEnum.cs b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithDefaultAttributeOnEnum.cs index 26bd21c522..ea95d9da7a 100644 --- a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithDefaultAttributeOnEnum.cs +++ b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithDefaultAttributeOnEnum.cs @@ -6,6 +6,7 @@ public class TypeWithDefaultAttributeOnEnum { [DefaultValue(IntEnum.Value4)] public IntEnum EnumWithDefault { get; set; } + [DefaultValue(new IntEnum[] { IntEnum.Value4 })] public IntEnum[] EnumArrayWithDefault { get; set; } } diff --git a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithDefaultAttributes.cs b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithDefaultAttributes.cs index 7671a46945..cb9ae319fb 100644 --- a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithDefaultAttributes.cs +++ b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithDefaultAttributes.cs @@ -36,4 +36,7 @@ public class TypeWithDefaultAttributes [DefaultValue(int.MaxValue)] public int? NullableIntWithDefaultValue { get; set; } + + [DefaultValue(DayOfWeek.Thursday)] + public DayOfWeek EnumWithDefaultValue { get; set; } } diff --git a/test/WebSites/Basic/Controllers/DataAnnotationsController.cs b/test/WebSites/Basic/Controllers/DataAnnotationsController.cs index 04f62aefba..de328dab92 100644 --- a/test/WebSites/Basic/Controllers/DataAnnotationsController.cs +++ b/test/WebSites/Basic/Controllers/DataAnnotationsController.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; using System.Diagnostics; using Microsoft.AspNetCore.Mvc; @@ -27,6 +28,13 @@ public IActionResult CancelPayment([MinLength(6)] string paymentId) Debug.Assert(paymentId is not null); return Ok(); } + + [HttpPut("get-weekly-apppointments")] + public IActionResult GetWeeklyAppointments([DefaultValue(DayOfWeek.Thursday)] DayOfWeek? dayOfWeek) + { + Debug.Assert(dayOfWeek is null || Enum.IsDefined(dayOfWeek.Value)); + return Ok(); + } } public class PaymentRequest diff --git a/test/WebSites/Basic/Controllers/DefaultValuesAttribute.cs b/test/WebSites/Basic/Controllers/DefaultValuesAttribute.cs deleted file mode 100644 index a8777386d0..0000000000 --- a/test/WebSites/Basic/Controllers/DefaultValuesAttribute.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Basic.Controllers; - -internal class DefaultValuesAttribute : Attribute; diff --git a/test/WebSites/Basic/Controllers/SwaggerAnnotationsController.cs b/test/WebSites/Basic/Controllers/SwaggerAnnotationsController.cs index a97442bc60..aecc062aec 100644 --- a/test/WebSites/Basic/Controllers/SwaggerAnnotationsController.cs +++ b/test/WebSites/Basic/Controllers/SwaggerAnnotationsController.cs @@ -1,4 +1,5 @@ -using System.Diagnostics; +using System.ComponentModel; +using System.Diagnostics; using Basic.Swagger; using Microsoft.AspNetCore.Mvc; using Swashbuckle.AspNetCore.Annotations; @@ -45,7 +46,11 @@ public class Cart [SwaggerSchema("The cart identifier", ReadOnly = true)] public int Id { get; set; } + [DefaultValue(CartType.Anonymous)] public CartType CartType { get; set; } + + [Obsolete("Use CartType instead.")] + public CartType BasketType { get; set; } } [SwaggerSchema(Description = "The cart type")]