diff --git a/src/Swashbuckle.AspNetCore.Annotations/AnnotationsOperationFilter.cs b/src/Swashbuckle.AspNetCore.Annotations/AnnotationsOperationFilter.cs index 4904858be1..1d0e54eb7a 100644 --- a/src/Swashbuckle.AspNetCore.Annotations/AnnotationsOperationFilter.cs +++ b/src/Swashbuckle.AspNetCore.Annotations/AnnotationsOperationFilter.cs @@ -10,9 +10,9 @@ public class AnnotationsOperationFilter : IOperationFilter { public void Apply(OpenApiOperation operation, OperationFilterContext context) { - IEnumerable controllerAttributes = Array.Empty(); - IEnumerable actionAttributes = Array.Empty(); - IEnumerable metadataAttributes = Array.Empty(); + IEnumerable controllerAttributes = []; + IEnumerable actionAttributes = []; + IEnumerable metadataAttributes = []; if (context.MethodInfo != null) { @@ -86,7 +86,7 @@ public static void ApplySwaggerOperationFilterAttributes( } } - private void ApplySwaggerResponseAttributes( + private static void ApplySwaggerResponseAttributes( OpenApiOperation operation, OperationFilterContext context, IEnumerable controllerAndActionAttributes) @@ -97,10 +97,7 @@ private void ApplySwaggerResponseAttributes( { var statusCode = swaggerResponseAttribute.StatusCode.ToString(); - if (operation.Responses == null) - { - operation.Responses = new OpenApiResponses(); - } + operation.Responses ??= []; if (!operation.Responses.TryGetValue(statusCode, out OpenApiResponse response)) { diff --git a/src/Swashbuckle.AspNetCore.ApiTesting/ApiTestRunnerOptionsExtensions.cs b/src/Swashbuckle.AspNetCore.ApiTesting/ApiTestRunnerOptionsExtensions.cs index 300a316b1c..97df705d66 100644 --- a/src/Swashbuckle.AspNetCore.ApiTesting/ApiTestRunnerOptionsExtensions.cs +++ b/src/Swashbuckle.AspNetCore.ApiTesting/ApiTestRunnerOptionsExtensions.cs @@ -1,7 +1,7 @@ -using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.Readers; -using System; +using System; using System.IO; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Readers; namespace Swashbuckle.AspNetCore.ApiTesting { @@ -9,17 +9,18 @@ public static class ApiTestRunnerOptionsExtensions { public static void AddOpenApiFile(this ApiTestRunnerOptions options, string documentName, string filePath) { - using (var fileStream = File.OpenRead(filePath)) - { - var openApiDocument = new OpenApiStreamReader().Read(fileStream, out OpenApiDiagnostic diagnostic); - options.OpenApiDocs.Add(documentName, openApiDocument); - } + using var fileStream = File.OpenRead(filePath); + + var openApiDocument = new OpenApiStreamReader().Read(fileStream, out var diagnostic); + options.OpenApiDocs.Add(documentName, openApiDocument); } public static OpenApiDocument GetOpenApiDocument(this ApiTestRunnerOptions options, string documentName) { if (!options.OpenApiDocs.TryGetValue(documentName, out OpenApiDocument document)) + { throw new InvalidOperationException($"Document with name '{documentName}' not found"); + } return document; } diff --git a/src/Swashbuckle.AspNetCore.ApiTesting/JsonContentValidator.cs b/src/Swashbuckle.AspNetCore.ApiTesting/JsonContentValidator.cs index e1c53d1671..c818db1bf0 100644 --- a/src/Swashbuckle.AspNetCore.ApiTesting/JsonContentValidator.cs +++ b/src/Swashbuckle.AspNetCore.ApiTesting/JsonContentValidator.cs @@ -8,25 +8,22 @@ namespace Swashbuckle.AspNetCore.ApiTesting { public class JsonContentValidator : IContentValidator { - private readonly JsonValidator _jsonValidator; + private readonly JsonValidator _jsonValidator = new(); - public JsonContentValidator() - { - _jsonValidator = new JsonValidator(); - } - - public bool CanValidate(string mediaType) - { - return mediaType.Contains("json"); - } + public bool CanValidate(string mediaType) => mediaType.Contains("json"); public void Validate(OpenApiMediaType mediaTypeSpec, OpenApiDocument openApiDocument, HttpContent content) { - if (mediaTypeSpec?.Schema == null) return; + if (mediaTypeSpec?.Schema == null) + { + return; + } var instance = JToken.Parse(content.ReadAsStringAsync().Result); if (!_jsonValidator.Validate(mediaTypeSpec.Schema, openApiDocument, instance, out IEnumerable errorMessages)) + { throw new ContentDoesNotMatchSpecException(string.Join(Environment.NewLine, errorMessages)); + } } } } diff --git a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonAllOfValidator.cs b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonAllOfValidator.cs index 36680b3747..ff596f9b4a 100644 --- a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonAllOfValidator.cs +++ b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonAllOfValidator.cs @@ -5,14 +5,9 @@ namespace Swashbuckle.AspNetCore.ApiTesting { - public class JsonAllOfValidator : IJsonValidator + public class JsonAllOfValidator(JsonValidator jsonValidator) : IJsonValidator { - private JsonValidator _jsonValidator; - - public JsonAllOfValidator(JsonValidator jsonValidator) - { - _jsonValidator = jsonValidator; - } + private JsonValidator _jsonValidator = jsonValidator; public bool CanValidate(OpenApiSchema schema) => schema.AllOf != null && schema.AllOf.Any(); @@ -26,14 +21,16 @@ public bool Validate( var allOfArray = schema.AllOf.ToArray(); - for (int i=0;i subErrorMessages)) + { errorMessagesList.AddRange(subErrorMessages.Select(msg => $"{msg} (allOf[{i}])")); + } } errorMessages = errorMessagesList; return !errorMessages.Any(); } } -} \ No newline at end of file +} diff --git a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonAnyOfValidator.cs b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonAnyOfValidator.cs index c761a4069e..411b4d3f0a 100644 --- a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonAnyOfValidator.cs +++ b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonAnyOfValidator.cs @@ -1,18 +1,13 @@ -using System.Linq; using System.Collections.Generic; +using System.Linq; using Microsoft.OpenApi.Models; using Newtonsoft.Json.Linq; namespace Swashbuckle.AspNetCore.ApiTesting { - public class JsonAnyOfValidator : IJsonValidator + public class JsonAnyOfValidator(JsonValidator jsonValidator) : IJsonValidator { - private JsonValidator _jsonValidator; - - public JsonAnyOfValidator(JsonValidator jsonValidator) - { - _jsonValidator = jsonValidator; - } + private JsonValidator _jsonValidator = jsonValidator; public bool CanValidate(OpenApiSchema schema) => schema.AnyOf != null && schema.AnyOf.Any(); @@ -26,11 +21,11 @@ public bool Validate( var anyOfArray = schema.AnyOf.ToArray(); - for (int i=0;i subErrorMessages)) { - errorMessages = Enumerable.Empty(); + errorMessages = []; return true; } @@ -41,4 +36,4 @@ public bool Validate( return !errorMessages.Any(); } } -} \ No newline at end of file +} diff --git a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonArrayValidator.cs b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonArrayValidator.cs index f486fd5593..72978e3b46 100644 --- a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonArrayValidator.cs +++ b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonArrayValidator.cs @@ -1,19 +1,13 @@ -using System; -using System.Linq; using System.Collections.Generic; +using System.Linq; using Microsoft.OpenApi.Models; using Newtonsoft.Json.Linq; namespace Swashbuckle.AspNetCore.ApiTesting { - public class JsonArrayValidator : IJsonValidator + public class JsonArrayValidator(IJsonValidator jsonValidator) : IJsonValidator { - private readonly IJsonValidator _jsonValidator; - - public JsonArrayValidator(IJsonValidator jsonValidator) - { - _jsonValidator = jsonValidator; - } + private readonly IJsonValidator _jsonValidator = jsonValidator; public bool CanValidate(OpenApiSchema schema) => schema.Type == "array"; @@ -25,7 +19,7 @@ public bool Validate( { if (instance.Type != JTokenType.Array) { - errorMessages = new[] { $"Path: {instance.Path}. Instance is not of type 'array'" }; + errorMessages = [$"Path: {instance.Path}. Instance is not of type 'array'"]; return false; } @@ -38,24 +32,32 @@ public bool Validate( foreach (var itemInstance in arrayInstance) { if (!_jsonValidator.Validate(schema.Items, openApiDocument, itemInstance, out IEnumerable itemErrorMessages)) + { errorMessagesList.AddRange(itemErrorMessages); + } } } // maxItems - if (schema.MaxItems.HasValue && (arrayInstance.Count() > schema.MaxItems.Value)) + if (schema.MaxItems.HasValue && (arrayInstance.Count > schema.MaxItems.Value)) + { errorMessagesList.Add($"Path: {instance.Path}. Array size is greater than maxItems"); + } // minItems - if (schema.MinItems.HasValue && (arrayInstance.Count() < schema.MinItems.Value)) + if (schema.MinItems.HasValue && (arrayInstance.Count < schema.MinItems.Value)) + { errorMessagesList.Add($"Path: {instance.Path}. Array size is less than minItems"); + } // uniqueItems - if (schema.UniqueItems.HasValue && (arrayInstance.Count() != arrayInstance.Distinct().Count())) + if (schema.UniqueItems.HasValue && (arrayInstance.Count != arrayInstance.Distinct().Count())) + { errorMessagesList.Add($"Path: {instance.Path}. Array does not contain uniqueItems"); + } errorMessages = errorMessagesList; return !errorMessages.Any(); } } -} \ No newline at end of file +} diff --git a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonBooleanValidator.cs b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonBooleanValidator.cs index 11def7930d..2277f95357 100644 --- a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonBooleanValidator.cs +++ b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonBooleanValidator.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using Microsoft.OpenApi.Models; using Newtonsoft.Json.Linq; @@ -17,12 +16,12 @@ public bool Validate( { if (instance.Type != JTokenType.Boolean) { - errorMessages = new[] { $"Path: {instance.Path}. Instance is not of type 'boolean'" }; + errorMessages = [$"Path: {instance.Path}. Instance is not of type 'boolean'"]; return false; } - errorMessages = Enumerable.Empty(); + errorMessages = []; return true; } } -} \ No newline at end of file +} diff --git a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonNullValidator.cs b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonNullValidator.cs index e17633a149..0472225852 100644 --- a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonNullValidator.cs +++ b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonNullValidator.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using Microsoft.OpenApi.Models; using Newtonsoft.Json.Linq; @@ -17,12 +16,12 @@ public bool Validate( { if (instance.Type != JTokenType.Null) { - errorMessages = new[] { $"Path: {instance.Path}. Instance is not of type 'null'" }; + errorMessages = [$"Path: {instance.Path}. Instance is not of type 'null'"]; return false; } - errorMessages = Enumerable.Empty(); + errorMessages = []; return true; } } -} \ No newline at end of file +} diff --git a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonNumberValidator.cs b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonNumberValidator.cs index 4467ad9d02..85b6151621 100644 --- a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonNumberValidator.cs +++ b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonNumberValidator.cs @@ -1,5 +1,5 @@ -using System.Linq; using System.Collections.Generic; +using System.Linq; using Microsoft.OpenApi.Models; using Newtonsoft.Json.Linq; @@ -15,9 +15,9 @@ public bool Validate( JToken instance, out IEnumerable errorMessages) { - if (!new[] { JTokenType.Float, JTokenType.Integer }.Contains(instance.Type)) + if (instance.Type is not JTokenType.Float and not JTokenType.Integer) { - errorMessages = new[] { $"Path: {instance.Path}. Instance is not of type 'number'" }; + errorMessages = [$"Path: {instance.Path}. Instance is not of type 'number'"]; return false; } @@ -26,32 +26,42 @@ public bool Validate( // multipleOf if (schema.MultipleOf.HasValue && ((numberValue % schema.MultipleOf.Value) != 0)) + { errorMessagesList.Add($"Path: {instance.Path}. Number is not evenly divisible by multipleOf"); + } // maximum & exclusiveMaximum if (schema.Maximum.HasValue) { - var exclusiveMaximum = schema.ExclusiveMaximum.HasValue ? schema.ExclusiveMaximum.Value : false; + var exclusiveMaximum = schema.ExclusiveMaximum ?? false; if (exclusiveMaximum && (numberValue >= schema.Maximum.Value)) + { errorMessagesList.Add($"Path: {instance.Path}. Number is greater than, or equal to, maximum"); + } else if (numberValue > schema.Maximum.Value) + { errorMessagesList.Add($"Path: {instance.Path}. Number is greater than maximum"); + } } // minimum & exclusiveMinimum if (schema.Minimum.HasValue) { - var exclusiveMinimum = schema.ExclusiveMinimum.HasValue ? schema.ExclusiveMinimum.Value : false; + var exclusiveMinimum = schema.ExclusiveMinimum ?? false; if (exclusiveMinimum && (numberValue <= schema.Minimum.Value)) + { errorMessagesList.Add($"Path: {instance.Path}. Number is less than, or equal to, minimum"); + } else if (numberValue < schema.Minimum.Value) + { errorMessagesList.Add($"Path: {instance.Path}. Number is less than minimum"); + } } errorMessages = errorMessagesList; return !errorMessages.Any(); } } -} \ No newline at end of file +} diff --git a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonObjectValidator.cs b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonObjectValidator.cs index 4cebb7c4d8..6a7787cd97 100644 --- a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonObjectValidator.cs +++ b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonObjectValidator.cs @@ -1,19 +1,13 @@ -using System; -using System.Linq; using System.Collections.Generic; +using System.Linq; using Microsoft.OpenApi.Models; using Newtonsoft.Json.Linq; namespace Swashbuckle.AspNetCore.ApiTesting { - public class JsonObjectValidator : IJsonValidator + public class JsonObjectValidator(IJsonValidator jsonValidator) : IJsonValidator { - private readonly IJsonValidator _jsonValidator; - - public JsonObjectValidator(IJsonValidator jsonValidator) - { - _jsonValidator = jsonValidator; - } + private readonly IJsonValidator _jsonValidator = jsonValidator; public bool CanValidate(OpenApiSchema schema) => schema.Type == "object"; @@ -25,7 +19,7 @@ public bool Validate( { if (instance.Type != JTokenType.Object) { - errorMessages = new[] { $"Path: {instance.Path}. Instance is not of type 'object'" }; + errorMessages = [$"Path: {instance.Path}. Instance is not of type 'object'"]; return false; } @@ -35,35 +29,47 @@ public bool Validate( // maxProperties if (schema.MaxProperties.HasValue && properties.Count() > schema.MaxProperties.Value) + { errorMessagesList.Add($"Path: {instance.Path}. Number of properties is greater than maxProperties"); + } // minProperties if (schema.MinProperties.HasValue && properties.Count() < schema.MinProperties.Value) + { errorMessagesList.Add($"Path: {instance.Path}. Number of properties is less than minProperties"); + } // required if (schema.Required != null && schema.Required.Except(properties.Select(p => p.Name)).Any()) + { errorMessagesList.Add($"Path: {instance.Path}. Required property(s) not present"); + } foreach (var property in properties) { // properties + IEnumerable propertyErrorMessages; + if (schema.Properties != null && schema.Properties.TryGetValue(property.Name, out OpenApiSchema propertySchema)) { - if (!_jsonValidator.Validate(propertySchema, openApiDocument, property.Value, out IEnumerable propertyErrorMessages)) + if (!_jsonValidator.Validate(propertySchema, openApiDocument, property.Value, out propertyErrorMessages)) + { errorMessagesList.AddRange(propertyErrorMessages); + } continue; } if (!schema.AdditionalPropertiesAllowed) + { errorMessagesList.Add($"Path: {instance.Path}. Additional properties not allowed"); + } // additionalProperties - if (schema.AdditionalProperties != null) + if (schema.AdditionalProperties != null && + !_jsonValidator.Validate(schema.AdditionalProperties, openApiDocument, property.Value, out propertyErrorMessages)) { - if (!_jsonValidator.Validate(schema.AdditionalProperties, openApiDocument, property.Value, out IEnumerable propertyErrorMessages)) - errorMessagesList.AddRange(propertyErrorMessages); + errorMessagesList.AddRange(propertyErrorMessages); } } @@ -71,4 +77,4 @@ public bool Validate( return !errorMessages.Any(); } } -} \ No newline at end of file +} diff --git a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonOneOfValidator.cs b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonOneOfValidator.cs index ba84807883..8f596c5721 100644 --- a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonOneOfValidator.cs +++ b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonOneOfValidator.cs @@ -1,18 +1,13 @@ -using System.Linq; using System.Collections.Generic; +using System.Linq; using Microsoft.OpenApi.Models; using Newtonsoft.Json.Linq; namespace Swashbuckle.AspNetCore.ApiTesting { - public class JsonOneOfValidator : IJsonValidator + public class JsonOneOfValidator(JsonValidator jsonValidator) : IJsonValidator { - private JsonValidator _jsonValidator; - - public JsonOneOfValidator(JsonValidator jsonValidator) - { - _jsonValidator = jsonValidator; - } + private readonly JsonValidator _jsonValidator = jsonValidator; public bool CanValidate(OpenApiSchema schema) => schema.OneOf != null && schema.OneOf.Any(); @@ -27,12 +22,16 @@ public bool Validate( var oneOfArray = schema.OneOf.ToArray(); int matched = 0; - for (int i=0;i subErrorMessages)) + { matched++; + } else + { errorMessagesList.AddRange(subErrorMessages.Select(msg => $"{msg} (oneOf[{i}])")); + } } if (matched == 0) @@ -43,12 +42,12 @@ public bool Validate( if (matched > 1) { - errorMessages = new[] { $"Path: {instance.Path}. Instance matches multiple schemas in oneOf array" }; + errorMessages = [$"Path: {instance.Path}. Instance matches multiple schemas in oneOf array"]; return false; } - errorMessages = Enumerable.Empty(); + errorMessages = []; return true; } } -} \ No newline at end of file +} diff --git a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonStringValidator.cs b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonStringValidator.cs index bc65af5428..69d1b95f94 100644 --- a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonStringValidator.cs +++ b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonStringValidator.cs @@ -16,9 +16,9 @@ public bool Validate( JToken instance, out IEnumerable errorMessages) { - if (!new JTokenType[] { JTokenType.Date, JTokenType.Guid, JTokenType.String }.Contains(instance.Type)) + if (instance.Type is not JTokenType.Date and not JTokenType.Guid and not JTokenType.String) { - errorMessages = new[] { $"Path: {instance.Path}. Instance is not of type 'string'" }; + errorMessages = [$"Path: {instance.Path}. Instance is not of type 'string'"]; return false; } @@ -27,18 +27,24 @@ public bool Validate( // maxLength if (schema.MaxLength.HasValue && (stringValue.Length > schema.MaxLength.Value)) + { errorMessagesList.Add($"Path: {instance.Path}. String length is greater than maxLength"); + } // minLength if (schema.MinLength.HasValue && (stringValue.Length < schema.MinLength.Value)) + { errorMessagesList.Add($"Path: {instance.Path}. String length is less than minLength"); + } // pattern if ((schema.Pattern != null) && !Regex.IsMatch(stringValue, schema.Pattern)) + { errorMessagesList.Add($"Path: {instance.Path}. String does not match pattern"); + } errorMessages = errorMessagesList; return !errorMessages.Any(); } } -} \ No newline at end of file +} diff --git a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonValidator.cs b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonValidator.cs index cebffc5c6d..f684b59223 100644 --- a/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonValidator.cs +++ b/src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonValidator.cs @@ -1,5 +1,5 @@ -using System.Linq; using System.Collections.Generic; +using System.Linq; using Microsoft.OpenApi.Models; using Newtonsoft.Json.Linq; @@ -11,8 +11,8 @@ public class JsonValidator : IJsonValidator public JsonValidator() { - _subValidators = new IJsonValidator[] - { + _subValidators = + [ new JsonNullValidator(), new JsonBooleanValidator(), new JsonObjectValidator(this), @@ -22,7 +22,7 @@ public JsonValidator() new JsonAllOfValidator(this), new JsonAnyOfValidator(this), new JsonOneOfValidator(this), - }; + ]; } public bool CanValidate(OpenApiSchema schema) => true; @@ -33,7 +33,7 @@ public bool Validate( JToken instance, out IEnumerable errorMessages) { - schema = (schema.Reference != null) + schema = schema.Reference != null ? (OpenApiSchema)openApiDocument.ResolveReference(schema.Reference) : schema; @@ -41,14 +41,19 @@ public bool Validate( foreach (var subValidator in _subValidators) { - if (!subValidator.CanValidate(schema)) continue; + if (!subValidator.CanValidate(schema)) + { + continue; + } if (!subValidator.Validate(schema, openApiDocument, instance, out IEnumerable subErrorMessages)) + { errorMessagesList.AddRange(subErrorMessages); + } } errorMessages = errorMessagesList; return !errorMessages.Any(); } } -} \ No newline at end of file +} diff --git a/src/Swashbuckle.AspNetCore.ApiTesting/RequestValidator.cs b/src/Swashbuckle.AspNetCore.ApiTesting/RequestValidator.cs index 5dbc18534b..a09e1afdf6 100644 --- a/src/Swashbuckle.AspNetCore.ApiTesting/RequestValidator.cs +++ b/src/Swashbuckle.AspNetCore.ApiTesting/RequestValidator.cs @@ -11,14 +11,9 @@ namespace Swashbuckle.AspNetCore.ApiTesting { - public class RequestValidator + public class RequestValidator(IEnumerable contentValidators) { - private readonly IEnumerable _contentValidators; - - public RequestValidator(IEnumerable contentValidators) - { - _contentValidators = contentValidators; - } + private readonly IEnumerable _contentValidators = contentValidators; public void Validate( HttpRequestMessage request, @@ -33,17 +28,23 @@ public void Validate( var requestUri = new Uri(new Uri("http://tempuri.org"), request.RequestUri); if (!TryParsePathNameValues(pathTemplate, requestUri.AbsolutePath, out NameValueCollection pathNameValues)) + { throw new RequestDoesNotMatchSpecException($"Request URI '{requestUri.AbsolutePath}' does not match specified template '{pathTemplate}'"); + } if (request.Method != new HttpMethod(operationType.ToString())) + { throw new RequestDoesNotMatchSpecException($"Request method '{request.Method}' does not match specified operation type '{operationType}'"); + } ValidateParameters(parameterSpecs.Where(p => p.In == ParameterLocation.Path), openApiDocument, pathNameValues); ValidateParameters(parameterSpecs.Where(p => p.In == ParameterLocation.Query), openApiDocument, HttpUtility.ParseQueryString(requestUri.Query)); ValidateParameters(parameterSpecs.Where(p => p.In == ParameterLocation.Header), openApiDocument, request.Headers.ToNameValueCollection()); if (operationSpec.RequestBody != null) + { ValidateContent(operationSpec.RequestBody, openApiDocument, request.Content); + } } private static IEnumerable ExpandParameterSpecs( @@ -58,7 +59,7 @@ private static IEnumerable ExpandParameterSpecs( .Concat(operationSpec.Parameters) .Select(p => { - return (p.Reference != null) + return p.Reference != null ? (OpenApiParameter)openApiDocument.ResolveReference(p.Reference) : p; }); @@ -69,27 +70,30 @@ private static IEnumerable DeriveSecurityParameterSpecs( OpenApiDocument openApiDocument) { // TODO - return new OpenApiParameter[] { }; + return []; } - private bool TryParsePathNameValues(string pathTemplate, string requestUri, out NameValueCollection pathNameValues) + private static bool TryParsePathNameValues(string pathTemplate, string requestUri, out NameValueCollection pathNameValues) { - pathNameValues = new NameValueCollection(); + pathNameValues = []; var templateMatcher = new TemplateMatcher(TemplateParser.Parse(pathTemplate), null); var routeValues = new RouteValueDictionary(); if (!templateMatcher.TryMatch(new PathString(requestUri), routeValues)) + { return false; + } foreach (var entry in routeValues) { pathNameValues.Add(entry.Key, entry.Value.ToString()); } + return true; } - private void ValidateParameters( + private static void ValidateParameters( IEnumerable parameterSpecs, OpenApiDocument openApiDocument, NameValueCollection parameterNameValues) @@ -99,39 +103,55 @@ private void ValidateParameters( var value = parameterNameValues[parameterSpec.Name]; if ((parameterSpec.In == ParameterLocation.Path || parameterSpec.Required) && value == null) + { throw new RequestDoesNotMatchSpecException($"Required parameter '{parameterSpec.Name}' is not present"); + } - if (value == null || parameterSpec.Schema == null) continue; + if (value == null || parameterSpec.Schema == null) + { + continue; + } var schema = (parameterSpec.Schema.Reference != null) ? (OpenApiSchema)openApiDocument.ResolveReference(parameterSpec.Schema.Reference) : parameterSpec.Schema; if (!schema.TryParse(value, out object typedValue)) + { throw new RequestDoesNotMatchSpecException($"Parameter '{parameterSpec.Name}' is not of type '{parameterSpec.Schema.TypeIdentifier()}'"); + } } } private void ValidateContent(OpenApiRequestBody requestBodySpec, OpenApiDocument openApiDocument, HttpContent content) { - requestBodySpec = (requestBodySpec.Reference != null) + requestBodySpec = requestBodySpec.Reference != null ? (OpenApiRequestBody)openApiDocument.ResolveReference(requestBodySpec.Reference) : requestBodySpec; if (requestBodySpec.Required && content == null) + { throw new RequestDoesNotMatchSpecException("Required content is not present"); + } - if (content == null) return; + if (content == null) + { + return; + } if (!requestBodySpec.Content.TryGetValue(content.Headers.ContentType.MediaType, out OpenApiMediaType mediaTypeSpec)) + { throw new RequestDoesNotMatchSpecException($"Content media type '{content.Headers.ContentType.MediaType}' is not specified"); + } try { foreach (var contentValidator in _contentValidators) { if (contentValidator.CanValidate(content.Headers.ContentType.MediaType)) + { contentValidator.Validate(mediaTypeSpec, openApiDocument, content); + } } } catch (ContentDoesNotMatchSpecException contentException) @@ -141,10 +161,5 @@ private void ValidateContent(OpenApiRequestBody requestBodySpec, OpenApiDocument } } - public class RequestDoesNotMatchSpecException : Exception - { - public RequestDoesNotMatchSpecException(string message) - : base(message) - { } - } -} \ No newline at end of file + public class RequestDoesNotMatchSpecException(string message) : Exception(message); +} diff --git a/src/Swashbuckle.AspNetCore.ApiTesting/ResponseValidator.cs b/src/Swashbuckle.AspNetCore.ApiTesting/ResponseValidator.cs index 2dfb5ac0db..ea056f8b52 100644 --- a/src/Swashbuckle.AspNetCore.ApiTesting/ResponseValidator.cs +++ b/src/Swashbuckle.AspNetCore.ApiTesting/ResponseValidator.cs @@ -1,20 +1,14 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; -using System.Linq; using System.Net.Http; using Microsoft.OpenApi.Models; namespace Swashbuckle.AspNetCore.ApiTesting { - public class ResponseValidator + public class ResponseValidator(IEnumerable contentValidators) { - private readonly IEnumerable _contentValidators; - - public ResponseValidator(IEnumerable contentValidators) - { - _contentValidators = contentValidators; - } + private readonly IEnumerable _contentValidators = contentValidators; public void Validate( HttpResponseMessage response, @@ -23,21 +17,27 @@ public void Validate( OperationType operationType, string expectedStatusCode) { - var operationSpec = openApiDocument.GetOperationByPathAndType(pathTemplate, operationType, out OpenApiPathItem pathSpec); + var operationSpec = openApiDocument.GetOperationByPathAndType(pathTemplate, operationType, out _); if (!operationSpec.Responses.TryGetValue(expectedStatusCode, out OpenApiResponse responseSpec)) + { throw new InvalidOperationException($"Response for status '{expectedStatusCode}' not found for operation '{operationSpec.OperationId}'"); + } var statusCode = (int)response.StatusCode; if (statusCode.ToString() != expectedStatusCode) + { throw new ResponseDoesNotMatchSpecException($"Status code '{statusCode}' does not match expected value '{expectedStatusCode}'"); + } ValidateHeaders(responseSpec.Headers, openApiDocument, response.Headers.ToNameValueCollection()); - if (responseSpec.Content != null && responseSpec.Content.Keys.Any()) + if (responseSpec.Content != null && responseSpec.Content.Keys.Count != 0) + { ValidateContent(responseSpec.Content, openApiDocument, response.Content); + } } - private void ValidateHeaders( + private static void ValidateHeaders( IDictionary headerSpecs, OpenApiDocument openApiDocument, NameValueCollection headerValues) @@ -48,18 +48,28 @@ private void ValidateHeaders( var headerSpec = entry.Value; if (headerSpec.Required && value == null) + { throw new ResponseDoesNotMatchSpecException($"Required header '{entry.Key}' is not present"); + } - if (value == null || headerSpec.Schema == null) continue; + if (value == null || headerSpec.Schema == null) + { + continue; + } var schema = (headerSpec.Schema.Reference != null) ? (OpenApiSchema)openApiDocument.ResolveReference(headerSpec.Schema.Reference) : headerSpec.Schema; - if (value == null) continue; + if (value == null) + { + continue; + } if (!schema.TryParse(value, out object typedValue)) + { throw new ResponseDoesNotMatchSpecException($"Header '{entry.Key}' is not of type '{headerSpec.Schema.TypeIdentifier()}'"); + } } } @@ -69,17 +79,23 @@ private void ValidateContent( HttpContent content) { if (content == null || content?.Headers?.ContentLength == 0) + { throw new RequestDoesNotMatchSpecException("Expected content is not present"); + } if (!contentSpecs.TryGetValue(content.Headers.ContentType.MediaType, out OpenApiMediaType mediaTypeSpec)) + { throw new ResponseDoesNotMatchSpecException($"Content media type '{content.Headers.ContentType.MediaType}' is not specified"); + } try { foreach (var contentValidator in _contentValidators) { if (contentValidator.CanValidate(content.Headers.ContentType.MediaType)) + { contentValidator.Validate(mediaTypeSpec, openApiDocument, content); + } } } catch (ContentDoesNotMatchSpecException contentException) @@ -89,10 +105,5 @@ private void ValidateContent( } } - public class ResponseDoesNotMatchSpecException : Exception - { - public ResponseDoesNotMatchSpecException(string message) - : base(message) - { } - } + public class ResponseDoesNotMatchSpecException(string message) : Exception(message); } diff --git a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs index e570bb28ab..225689fbd4 100644 --- a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs +++ b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs @@ -113,12 +113,17 @@ public static void ApplyRouteConstraints(this OpenApiSchema schema, ApiParameter public static string ResolveType(this OpenApiSchema schema, SchemaRepository schemaRepository) { if (schema.Reference != null && schemaRepository.Schemas.TryGetValue(schema.Reference.Id, out OpenApiSchema definitionSchema)) + { return definitionSchema.ResolveType(schemaRepository); + } foreach (var subSchema in schema.AllOf) { var type = subSchema.ResolveType(schemaRepository); - if (type != null) return type; + if (type != null) + { + return type; + } } return schema.Type; diff --git a/src/Swashbuckle.AspNetCore.SwaggerGen/SwaggerGenerator/SwaggerGenerator.cs b/src/Swashbuckle.AspNetCore.SwaggerGen/SwaggerGenerator/SwaggerGenerator.cs index 1fa5c3db11..6f2445d466 100644 --- a/src/Swashbuckle.AspNetCore.SwaggerGen/SwaggerGenerator/SwaggerGenerator.cs +++ b/src/Swashbuckle.AspNetCore.SwaggerGen/SwaggerGenerator/SwaggerGenerator.cs @@ -20,23 +20,16 @@ namespace Swashbuckle.AspNetCore.SwaggerGen { - public class SwaggerGenerator : ISwaggerProvider, IAsyncSwaggerProvider, ISwaggerDocumentMetadataProvider + public class SwaggerGenerator( + SwaggerGeneratorOptions options, + IApiDescriptionGroupCollectionProvider apiDescriptionsProvider, + ISchemaGenerator schemaGenerator) : ISwaggerProvider, IAsyncSwaggerProvider, ISwaggerDocumentMetadataProvider { - private readonly IApiDescriptionGroupCollectionProvider _apiDescriptionsProvider; - private readonly ISchemaGenerator _schemaGenerator; - private readonly SwaggerGeneratorOptions _options; + private readonly IApiDescriptionGroupCollectionProvider _apiDescriptionsProvider = apiDescriptionsProvider; + private readonly ISchemaGenerator _schemaGenerator = schemaGenerator; + private readonly SwaggerGeneratorOptions _options = options ?? new(); private readonly IAuthenticationSchemeProvider _authenticationSchemeProvider; - public SwaggerGenerator( - SwaggerGeneratorOptions options, - IApiDescriptionGroupCollectionProvider apiDescriptionsProvider, - ISchemaGenerator schemaGenerator) - { - _options = options ?? new SwaggerGeneratorOptions(); - _apiDescriptionsProvider = apiDescriptionsProvider; - _schemaGenerator = schemaGenerator; - } - public SwaggerGenerator( SwaggerGeneratorOptions options, IApiDescriptionGroupCollectionProvider apiDescriptionsProvider, diff --git a/src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XmlCommentsExampleHelper.cs b/src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XmlCommentsExampleHelper.cs index 40a2271723..f5aacd2125 100644 --- a/src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XmlCommentsExampleHelper.cs +++ b/src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XmlCommentsExampleHelper.cs @@ -12,7 +12,7 @@ public static IOpenApiAny Create( string exampleString) { var isStringType = - (schema?.ResolveType(schemaRepository) == "string") && + schema?.ResolveType(schemaRepository) == "string" && !string.Equals(exampleString, "null"); var exampleAsJson = isStringType diff --git a/test/Swashbuckle.AspNetCore.Annotations.Test/AnnotationsOperationFilterTests.cs b/test/Swashbuckle.AspNetCore.Annotations.Test/AnnotationsOperationFilterTests.cs index cee1575558..58e73b06a7 100644 --- a/test/Swashbuckle.AspNetCore.Annotations.Test/AnnotationsOperationFilterTests.cs +++ b/test/Swashbuckle.AspNetCore.Annotations.Test/AnnotationsOperationFilterTests.cs @@ -4,8 +4,6 @@ using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.OpenApi.Models; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Options; using Swashbuckle.AspNetCore.SwaggerGen; using Xunit; @@ -30,7 +28,7 @@ public void Apply_EnrichesOperationMetadata_IfActionDecoratedWithSwaggerOperatio Assert.Equal("Summary for ActionWithSwaggerOperationAttribute", operation.Summary); Assert.Equal("Description for ActionWithSwaggerOperationAttribute", operation.Description); Assert.Equal("actionWithSwaggerOperationAttribute", operation.OperationId); - Assert.Equal(new[] { "foobar" }, operation.Tags.Cast().Select(t => t.Name)); + Assert.Equal(["foobar"], [.. operation.Tags.Select(t => t.Name)]); } [Fact] @@ -54,7 +52,7 @@ public void Apply_EnrichesResponseMetadata_IfActionDecoratedWithSwaggerResponseA Subject().Apply(operation, filterContext); - Assert.Equal(new[] { "204", "400", "500" }, operation.Responses.Keys.ToArray()); + Assert.Equal(["204", "400", "500"], [.. operation.Responses.Keys]); var response1 = operation.Responses["204"]; Assert.Equal("Description for 204 response", response1.Description); var response2 = operation.Responses["400"]; @@ -83,7 +81,7 @@ public void Apply_EnrichesResponseMetadata_IfActionDecoratedWithSwaggerResponseC Subject().Apply(operation, filterContext); - Assert.Equal(new[] { "200", "500" }, operation.Responses.Keys.ToArray()); + Assert.Equal(["200", "500"], [.. operation.Responses.Keys]); var response1 = operation.Responses["200"]; Assert.Equal("Description for 200 response", response1.Description); Assert.NotNull(response1.Content); @@ -135,7 +133,7 @@ public void Apply_EnrichesOperationMetadata_IfMinimalActionDecoratedWithSwaggerO { Description = "Description for ActionWithSwaggerOperationAttribute", OperationId = "actionWithSwaggerOperationAttribute", - Tags = new[] { "foobar" } + Tags = ["foobar"] }; var action = RequestDelegateFactory.Create((string parameter) => "{}"); @@ -147,7 +145,7 @@ public void Apply_EnrichesOperationMetadata_IfMinimalActionDecoratedWithSwaggerO { ActionDescriptor = new ActionDescriptor() { - EndpointMetadata = new[] { operationAttribute } + EndpointMetadata = [operationAttribute] } }; @@ -162,12 +160,12 @@ public void Apply_EnrichesOperationMetadata_IfMinimalActionDecoratedWithSwaggerO Assert.Equal("Summary for ActionWithSwaggerOperationAttribute", operation.Summary); Assert.Equal("Description for ActionWithSwaggerOperationAttribute", operation.Description); Assert.Equal("actionWithSwaggerOperationAttribute", operation.OperationId); - Assert.Equal(new[] { "foobar" }, operation.Tags.Cast().Select(t => t.Name)); + Assert.Equal(["foobar"], [.. operation.Tags.Select(t => t.Name)]); } - private AnnotationsOperationFilter Subject() + private static AnnotationsOperationFilter Subject() { - return new AnnotationsOperationFilter(); + return new(); } } } diff --git a/test/Swashbuckle.AspNetCore.ApiTesting.Test/JsonValidatorTests.cs b/test/Swashbuckle.AspNetCore.ApiTesting.Test/JsonValidatorTests.cs index ed9d090dbc..024928cad4 100644 --- a/test/Swashbuckle.AspNetCore.ApiTesting.Test/JsonValidatorTests.cs +++ b/test/Swashbuckle.AspNetCore.ApiTesting.Test/JsonValidatorTests.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; -using Xunit; +using System.Linq; using Microsoft.OpenApi.Models; using Newtonsoft.Json.Linq; -using System.Linq; +using Xunit; namespace Swashbuckle.AspNetCore.ApiTesting.Test { @@ -51,7 +51,7 @@ public void Validate_ReturnsError_IfNumberNotEvenlyDivisibleByMultipleOf( { var openApiSchema = new OpenApiSchema { Type = "number", MultipleOf = schemaMultipleOf }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -73,7 +73,7 @@ public void Validate_ReturnsError_IfNumberGreaterThanMaximum( { var openApiSchema = new OpenApiSchema { Type = "number", Maximum = schemaMaximum }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -100,7 +100,7 @@ public void Validate_ReturnsError_IfNumberGreaterThanOrEqualToMaximumAndExclusiv ExclusiveMaximum = true }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -122,7 +122,7 @@ public void Validate_ReturnsError_IfNumberLessThanMinimum( { var openApiSchema = new OpenApiSchema { Type = "number", Minimum = schemaMinimum }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -149,7 +149,7 @@ public void Validate_ReturnsError_IfNumberLessThanOrEqualToMinimumAndExclusiveMi ExclusiveMinimum = true }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -175,7 +175,7 @@ public void Validate_ReturnsError_IfStringLengthGreaterThanMaxLength( MaxLength = schemaMaxLength }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -201,7 +201,7 @@ public void Validate_ReturnsError_IfStringLengthLessThanMinLength( MinLength = schemaMinLength }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -227,7 +227,7 @@ public void Validate_ReturnsError_IfStringDoesNotMatchPattern( Pattern = schemaPattern }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -254,7 +254,7 @@ public void Validate_ReturnsError_IfArrayItemDoesNotMatchItemsSchema( Items = new OpenApiSchema { Type = itemsSchemaType } }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -280,7 +280,7 @@ public void Validate_ReturnsError_IfArraySizeGreaterThanMaxItems( MaxItems = schemaMaxItems }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -306,7 +306,7 @@ public void Validate_ReturnsError_IfArraySizeLessThanMinItems( MinItems = schemaMinItems }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -331,7 +331,7 @@ public void Validate_ReturnsError_IfArrayDoesNotContainUniqueItemsAndUniqueItems UniqueItems = true }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -357,7 +357,7 @@ public void Validate_ReturnsError_IfNumberOfPropertiesGreaterThanMaxProperties( MaxProperties = schemaMaxProperties }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -383,7 +383,7 @@ public void Validate_ReturnsError_IfNumberOfPropertiesLessThanMinProperties( MinProperties = schemaMinProperties }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -409,7 +409,7 @@ public void Validate_ReturnsError_IfRequiredPropertyNotPresent( Required = new SortedSet(schemaRequired) }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -439,7 +439,7 @@ public void Validate_ReturnsError_IfKnownPropertyDoesNotMatchPropertySchema( } }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -466,7 +466,7 @@ public void Validate_ReturnsError_IfAdditionalPropertyDoesNotMatchAdditionalProp AdditionalProperties = new OpenApiSchema { Type = additionalPropertiesType } }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -492,7 +492,7 @@ public void Validate_ReturnsError_IfAdditionalPropertiesPresentAndAdditionalProp AdditionalPropertiesAllowed = additionalPropertiesAllowed }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -513,15 +513,15 @@ public void Validate_ReturnsError_IfInstanceDoesNotMatchAllSchemasSpecifiedByAll { var openApiSchema = new OpenApiSchema { - AllOf = new List - { + AllOf = + [ new OpenApiSchema { Type = "object", Required = new SortedSet { "p1" } }, new OpenApiSchema { Type = "object", Required = new SortedSet { "p2" } }, new OpenApiSchema { Type = "object", Required = new SortedSet { "p3" } } - } + ] }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -542,15 +542,15 @@ public void Validate_ReturnsError_IfInstanceDoesNotMatchAnySchemaSpecifiedByAnyO { var openApiSchema = new OpenApiSchema { - AnyOf = new List - { + AnyOf = + [ new OpenApiSchema { Type = "object", Required = new SortedSet { "p1" } }, new OpenApiSchema { Type = "object", Required = new SortedSet { "p2" } }, new OpenApiSchema { Type = "object", Required = new SortedSet { "p3" } } - } + ] }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -572,15 +572,15 @@ public void Validate_ReturnsError_IfInstanceDoesNotMatchExactlyOneSchemaSpecifie { var openApiSchema = new OpenApiSchema { - OneOf = new List - { + OneOf = + [ new OpenApiSchema { Type = "object", Required = new SortedSet { "p1" } }, new OpenApiSchema { Type = "object", Required = new SortedSet { "p2" } }, new OpenApiSchema { Type = "object", Required = new SortedSet { "p3" } } - } + ] }; var instance = JToken.Parse(instanceText); - + var returnValue = Subject().Validate( openApiSchema, new OpenApiDocument(), @@ -628,9 +628,6 @@ public void Validate_SupportsReferencedSchemas_IfDefinedInProvidedOpenApiDocumen Assert.Equal(expectedExceptionMessage, exception?.Message); } - private JsonValidator Subject() - { - return new JsonValidator(); - } + private static JsonValidator Subject() => new(); } } diff --git a/test/Swashbuckle.AspNetCore.ApiTesting.Test/RequestValidatorTests.cs b/test/Swashbuckle.AspNetCore.ApiTesting.Test/RequestValidatorTests.cs index f1609c4042..10da34b01c 100644 --- a/test/Swashbuckle.AspNetCore.ApiTesting.Test/RequestValidatorTests.cs +++ b/test/Swashbuckle.AspNetCore.ApiTesting.Test/RequestValidatorTests.cs @@ -186,7 +186,7 @@ public void Validate_ThrowsException_IfQueryParameterIsNotOfSpecifiedType( Schema = new OpenApiSchema { Type = specifiedType, - Items = (specifiedItemsType != null) ? new OpenApiSchema { Type = specifiedItemsType } : null + Items = specifiedItemsType != null ? new OpenApiSchema { Type = specifiedItemsType } : null } } } @@ -348,13 +348,13 @@ public void Validate_DelegatesContentValidationToInjectedContentValidators( var exception = Record.Exception(() => { - Subject(new[] { new JsonContentValidator() }).Validate(request, openApiDocument, "/api/products", OperationType.Post); + Subject([new JsonContentValidator()]).Validate(request, openApiDocument, "/api/products", OperationType.Post); }); Assert.Equal(expectedErrorMessage, exception?.Message); } - private OpenApiDocument DocumentWithOperation(string pathTemplate, OperationType operationType, OpenApiOperation operationSpec) + private static OpenApiDocument DocumentWithOperation(string pathTemplate, OperationType operationType, OpenApiOperation operationSpec) { return new OpenApiDocument { @@ -375,9 +375,9 @@ private OpenApiDocument DocumentWithOperation(string pathTemplate, OperationType }; } - private RequestValidator Subject(IEnumerable contentValidators = null) + private static RequestValidator Subject(IEnumerable contentValidators = null) { - return new RequestValidator(contentValidators ?? new IContentValidator[] { }); + return new RequestValidator(contentValidators ?? []); } } } diff --git a/test/Swashbuckle.AspNetCore.ApiTesting.Test/ResponseValidatorTests.cs b/test/Swashbuckle.AspNetCore.ApiTesting.Test/ResponseValidatorTests.cs index 4a0de98c6e..acfe0249d0 100644 --- a/test/Swashbuckle.AspNetCore.ApiTesting.Test/ResponseValidatorTests.cs +++ b/test/Swashbuckle.AspNetCore.ApiTesting.Test/ResponseValidatorTests.cs @@ -222,14 +222,14 @@ public void Validate_DelegatesContentValidationToInjectedContentValidators( var exception = Record.Exception(() => { - Subject(new[] { new JsonContentValidator() }).Validate(response, openApiDocument, "/api/products/1", OperationType.Get, "200"); + Subject([new JsonContentValidator()]).Validate(response, openApiDocument, "/api/products/1", OperationType.Get, "200"); }); Assert.Equal(expectedErrorMessage, exception?.Message); } - private OpenApiDocument DocumentWithOperation(string pathTemplate, OperationType operationType, OpenApiOperation operationSpec) + private static OpenApiDocument DocumentWithOperation(string pathTemplate, OperationType operationType, OpenApiOperation operationSpec) { return new OpenApiDocument { @@ -250,9 +250,9 @@ private OpenApiDocument DocumentWithOperation(string pathTemplate, OperationType }; } - private ResponseValidator Subject(IEnumerable contentValidators = null) + private static ResponseValidator Subject(IEnumerable contentValidators = null) { - return new ResponseValidator(contentValidators ?? new IContentValidator[] { }); + return new ResponseValidator(contentValidators ?? []); } } } diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/DocumentProviderTests.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/DocumentProviderTests.cs index a052fa32d2..df18d9f05b 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/DocumentProviderTests.cs +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/DocumentProviderTests.cs @@ -45,19 +45,17 @@ public async Task DocumentProvider_ExposesGeneratedSwagger(Type startupType, str var services = server.Host.Services; var documentProvider = (IDocumentProvider)services.GetService(typeof(IDocumentProvider)); - using (var stream = new MemoryStream()) + using var stream = new MemoryStream(); + using (var writer = new StreamWriter(stream, Encoding.UTF8, bufferSize: 2048, leaveOpen: true)) { - using (var writer = new StreamWriter(stream, Encoding.UTF8, bufferSize: 2048, leaveOpen: true)) - { - await documentProvider.GenerateAsync(documentName, writer); - await writer.FlushAsync(); - } - - stream.Position = 0L; - new OpenApiStreamReader().Read(stream, out var diagnostic); - Assert.NotNull(diagnostic); - Assert.Empty(diagnostic.Errors); + await documentProvider.GenerateAsync(documentName, writer); + await writer.FlushAsync(); } + + stream.Position = 0L; + new OpenApiStreamReader().Read(stream, out var diagnostic); + Assert.NotNull(diagnostic); + Assert.Empty(diagnostic.Errors); } [Fact] @@ -68,11 +66,9 @@ public async Task DocumentProvider_ThrowsUnknownDocument_IfUnknownDocumentName() var services = server.Host.Services; var documentProvider = (IDocumentProvider)services.GetService(typeof(IDocumentProvider)); - using (var writer = new StringWriter()) - { - await Assert.ThrowsAsync( - () => documentProvider.GenerateAsync("NotADocument", writer)); - } + using var writer = new StringWriter(); + await Assert.ThrowsAsync( + () => documentProvider.GenerateAsync("NotADocument", writer)); } } } diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs index 35ee4af447..37c066ac83 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs @@ -9,10 +9,11 @@ using System.Text; using System.Text.Json; using System.Threading.Tasks; -using Microsoft.OpenApi.Any; -using Microsoft.OpenApi.Readers; using Xunit; using ReDocApp = ReDoc; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Readers; +using Microsoft.OpenApi.Any; namespace Swashbuckle.AspNetCore.IntegrationTests { @@ -145,7 +146,13 @@ public async Task TypesAreRenderedCorrectly() using var application = new TestApplication(); using var client = application.CreateDefaultClient(); - using var swaggerResponse = await client.GetFromJsonAsync("/swagger/v1/swagger.json"); + using var response = await client.GetAsync("/swagger/v1/swagger.json"); + + var content = await response.Content.ReadAsStringAsync(); + + Assert.True(response.IsSuccessStatusCode, content); + + using var swaggerResponse = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync()); var weatherForecase = swaggerResponse.RootElement .GetProperty("components") @@ -186,11 +193,8 @@ internal static HttpClient GetHttpClientForTestApplication(Type entryPointType) var createClientMethod = applicationType .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) - .FirstOrDefault(m => m.Name == "CreateDefaultClient" && m.GetParameters().Length == 1); - if (createClientMethod == null) - { - throw new InvalidOperationException($"The method CreateDefaultClient was not found on TestApplication<{entryPointType.FullName}>."); - } + .FirstOrDefault(m => m.Name == "CreateDefaultClient" && m.GetParameters().Length == 1) + ?? throw new InvalidOperationException($"The method CreateDefaultClient was not found on TestApplication<{entryPointType.FullName}>."); // Pass null for DelegatingHandler[] var parameters = new object[] { null }; diff --git a/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs b/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs index 54b25a2b52..fd20157b85 100644 --- a/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs +++ b/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs @@ -7,7 +7,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.NewtonsoftJson; -using Microsoft.Extensions.Options; using Microsoft.OpenApi.Models; using Newtonsoft.Json; using Newtonsoft.Json.Converters; @@ -140,7 +139,7 @@ public void GenerateSchema_GeneratesObjectSchema_IfDictionaryTypeHasEnumKey() var schema = Subject().GenerateSchema(typeof(IDictionary), new SchemaRepository()); Assert.Equal("object", schema.Type); - Assert.Equal(new[] { "Value2", "Value4", "Value8" }, schema.Properties.Keys); + Assert.Equal(["Value2", "Value4", "Value8"], schema.Properties.Keys); } [Fact] @@ -233,7 +232,7 @@ public void GenerateSchema_IncludesInheritedProperties_IfComplexTypeIsDerived() var schema = schemaRepository.Schemas[referenceSchema.Reference.Id]; Assert.Equal("object", schema.Type); - Assert.Equal(new[] { "Property1", "BaseProperty" }, schema.Properties.Keys); + Assert.Equal(["Property1", "BaseProperty"], schema.Properties.Keys); } [Fact] @@ -245,7 +244,7 @@ public void GenerateSchema_ExcludesIndexerProperties_IfComplexTypeIsIndexed() var schema = schemaRepository.Schemas[referenceSchema.Reference.Id]; Assert.Equal("object", schema.Type); - Assert.Equal(new[] { "Property1" }, schema.Properties.Keys); + Assert.Equal(["Property1"], schema.Properties.Keys); } [Theory] @@ -374,20 +373,19 @@ public void GenerateSchema_DoesNotSetReadOnlyFlag_IfPropertyIsReadOnlyButCanBeSe } [Theory] - [InlineData(typeof(ComplexType), typeof(ComplexType), "string")] - [InlineData(typeof(GenericType), typeof(GenericType), "string")] - [InlineData(typeof(GenericType<,>), typeof(GenericType), "string")] + [InlineData(typeof(ComplexType), typeof(ComplexType))] + [InlineData(typeof(GenericType), typeof(GenericType))] + [InlineData(typeof(GenericType<,>), typeof(GenericType))] public void GenerateSchema_SupportsOption_CustomTypeMappings( Type mappingType, - Type type, - string expectedSchemaType) + Type type) { var subject = Subject( configureGenerator: c => c.CustomTypeMappings.Add(mappingType, () => new OpenApiSchema { Type = "string" }) ); var schema = subject.GenerateSchema(type, new SchemaRepository()); - Assert.Equal(expectedSchemaType, schema.Type); + Assert.Equal("string", schema.Type); Assert.Empty(schema.Properties); } @@ -456,11 +454,11 @@ public void GenerateSchema_SupportsOption_UseAllOfForInheritance() Assert.Equal("BaseType", baseSchema.Reference.Id); Assert.NotNull(baseSchema.Reference); var subSchema = schema.AllOf[1]; - Assert.Equal(new[] { "Property1" }, subSchema.Properties.Keys); + Assert.Equal(["Property1"], subSchema.Properties.Keys); // The base type schema var baseTypeSchema = schemaRepository.Schemas[baseSchema.Reference.Id]; Assert.Equal("object", baseTypeSchema.Type); - Assert.Equal(new[] { "BaseProperty" }, baseTypeSchema.Properties.Keys); + Assert.Equal(["BaseProperty"], baseTypeSchema.Properties.Keys); } [Fact] @@ -469,13 +467,13 @@ public void GenerateSchema_SupportsOption_SubTypesSelector() var subject = Subject(configureGenerator: c => { c.UseAllOfForInheritance = true; - c.SubTypesSelector = (type) => new[] { typeof(SubType1) }; + c.SubTypesSelector = (type) => [typeof(SubType1)]; }); var schemaRepository = new SchemaRepository(); var schema = subject.GenerateSchema(typeof(BaseType), schemaRepository); - Assert.Equal(new[] { "SubType1", "BaseType" }, schemaRepository.Schemas.Keys); + Assert.Equal(["SubType1", "BaseType"], schemaRepository.Schemas.Keys); } [Fact] @@ -517,7 +515,7 @@ public void GenerateSchema_SupportsOption_UseAllOfForPolymorphism() Assert.NotNull(schema.OneOf[0].Reference); var baseSchema = schemaRepository.Schemas[schema.OneOf[0].Reference.Id]; Assert.Equal("object", baseSchema.Type); - Assert.Equal(new[] { "BaseProperty" }, baseSchema.Properties.Keys); + Assert.Equal(["BaseProperty"], baseSchema.Properties.Keys); // The first sub type schema Assert.NotNull(schema.OneOf[1].Reference); var subType1Schema = schemaRepository.Schemas[schema.OneOf[1].Reference.Id]; @@ -526,7 +524,7 @@ public void GenerateSchema_SupportsOption_UseAllOfForPolymorphism() var allOf = Assert.Single(subType1Schema.AllOf); Assert.NotNull(allOf.Reference); Assert.Equal("BaseType", allOf.Reference.Id); - Assert.Equal(new[] { "Property1" }, subType1Schema.Properties.Keys); + Assert.Equal(["Property1"], subType1Schema.Properties.Keys); // The second sub type schema Assert.NotNull(schema.OneOf[2].Reference); var subType2Schema = schemaRepository.Schemas[schema.OneOf[2].Reference.Id]; @@ -535,7 +533,7 @@ public void GenerateSchema_SupportsOption_UseAllOfForPolymorphism() allOf = Assert.Single(subType2Schema.AllOf); Assert.NotNull(allOf.Reference); Assert.Equal("BaseType", allOf.Reference.Id); - Assert.Equal(new[] { "Property2" }, subType2Schema.Properties.Keys); + Assert.Equal(["Property2"], subType2Schema.Properties.Keys); } [Fact] @@ -739,7 +737,7 @@ public void GenerateSchema_HonorsSerializerAttribute_StringEnumConverter() var schema = schemaRepository.Schemas[referenceSchema.Reference.Id]; Assert.Equal("string", schema.Type); - Assert.Equal(new[] { "\"Value1\"", "\"Value2\"", "\"X-foo\"" }, schema.Enum.Select(openApiAny => openApiAny.ToJson())); + Assert.Equal(["\"Value1\"", "\"Value2\"", "\"X-foo\""], schema.Enum.Select(openApiAny => openApiAny.ToJson())); } [Fact] diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs index fddcd8825d..8ff212a8d5 100644 --- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs @@ -85,13 +85,12 @@ public void GenerateSchema_GeneratesPrimitiveSchema_IfPrimitiveOrNullablePrimiti } [Theory] - [InlineData(typeof(IntEnum), "integer", "int32", "2", "4", "8")] - [InlineData(typeof(LongEnum), "integer", "int64", "2", "4", "8")] - [InlineData(typeof(IntEnum?), "integer", "int32", "2", "4", "8")] - [InlineData(typeof(LongEnum?), "integer", "int64", "2", "4", "8")] + [InlineData(typeof(IntEnum), "int32", "2", "4", "8")] + [InlineData(typeof(LongEnum), "int64", "2", "4", "8")] + [InlineData(typeof(IntEnum?), "int32", "2", "4", "8")] + [InlineData(typeof(LongEnum?), "int64", "2", "4", "8")] public void GenerateSchema_GeneratesReferencedEnumSchema_IfEnumOrNullableEnumType( Type type, - string expectedSchemaType, string expectedFormat, params string[] expectedEnumAsJson) { @@ -101,7 +100,7 @@ public void GenerateSchema_GeneratesReferencedEnumSchema_IfEnumOrNullableEnumTyp Assert.NotNull(referenceSchema.Reference); var schema = schemaRepository.Schemas[referenceSchema.Reference.Id]; - Assert.Equal(expectedSchemaType, schema.Type); + Assert.Equal("integer", schema.Type); Assert.Equal(expectedFormat, schema.Format); Assert.NotNull(schema.Enum); Assert.Equal(expectedEnumAsJson, schema.Enum.Select(openApiAny => openApiAny.ToJson())); @@ -228,7 +227,7 @@ public void GenerateSchema_IncludesInheritedProperties_IfComplexTypeIsDerived() var schema = schemaRepository.Schemas[referenceSchema.Reference.Id]; Assert.Equal("object", schema.Type); - Assert.Equal(new[] { "BaseProperty", "Property1" }, schema.Properties.Keys); + Assert.Equal(["BaseProperty", "Property1"], schema.Properties.Keys); } [Theory] @@ -269,7 +268,7 @@ public void GenerateSchema_ExcludesIndexerProperties_IfComplexTypeIsIndexed() var schema = schemaRepository.Schemas[referenceSchema.Reference.Id]; Assert.Equal("object", schema.Type); - Assert.Equal(new[] { "Property1" }, schema.Properties.Keys); + Assert.Equal(["Property1"], schema.Properties.Keys); } [Theory] @@ -483,20 +482,19 @@ public void GenerateSchema_SetsDefault_IfParameterHasDefaultValueAttribute() } [Theory] - [InlineData(typeof(ComplexType), typeof(ComplexType), "string")] - [InlineData(typeof(GenericType), typeof(GenericType), "string")] - [InlineData(typeof(GenericType<,>), typeof(GenericType), "string")] + [InlineData(typeof(ComplexType), typeof(ComplexType))] + [InlineData(typeof(GenericType), typeof(GenericType))] + [InlineData(typeof(GenericType<,>), typeof(GenericType))] public void GenerateSchema_SupportsOption_CustomTypeMappings( Type mappingType, - Type type, - string expectedSchemaType) + Type type) { var subject = Subject( configureGenerator: c => c.CustomTypeMappings.Add(mappingType, () => new OpenApiSchema { Type = "string" }) ); var schema = subject.GenerateSchema(type, new SchemaRepository()); - Assert.Equal(expectedSchemaType, schema.Type); + Assert.Equal("string", schema.Type); Assert.Empty(schema.Properties); } @@ -564,11 +562,11 @@ public void GenerateSchema_SupportsOption_UseAllOfForInheritance() Assert.Equal("BaseType", baseSchema.Reference.Id); Assert.NotNull(baseSchema.Reference); var subSchema = schema.AllOf[1]; - Assert.Equal(new[] { "Property1" }, subSchema.Properties.Keys); + Assert.Equal(["Property1"], subSchema.Properties.Keys); // The base type schema var baseTypeSchema = schemaRepository.Schemas[baseSchema.Reference.Id]; Assert.Equal("object", baseTypeSchema.Type); - Assert.Equal(new[] { "BaseProperty" }, baseTypeSchema.Properties.Keys); + Assert.Equal(["BaseProperty"], baseTypeSchema.Properties.Keys); } [Fact] @@ -577,13 +575,13 @@ public void GenerateSchema_SupportsOption_SubTypesSelector() var subject = Subject(configureGenerator: c => { c.UseAllOfForInheritance = true; - c.SubTypesSelector = (type) => new[] { typeof(SubType1) }; + c.SubTypesSelector = (type) => [typeof(SubType1)]; }); var schemaRepository = new SchemaRepository(); var schema = subject.GenerateSchema(typeof(BaseType), schemaRepository); - Assert.Equal(new[] { "SubType1", "BaseType" }, schemaRepository.Schemas.Keys); + Assert.Equal(["SubType1", "BaseType"], schemaRepository.Schemas.Keys); var subSchema = schemaRepository.Schemas["SubType1"]; Assert.NotNull(subSchema.AllOf); @@ -596,13 +594,13 @@ public void GenerateSchema_SecondLevelInheritance_SubTypesSelector() var subject = Subject(configureGenerator: c => { c.UseAllOfForInheritance = true; - c.SubTypesSelector = (type) => type == typeof(BaseSecondLevelType) ? new[] { typeof(SubSubSecondLevelType) } : Array.Empty(); + c.SubTypesSelector = (type) => type == typeof(BaseSecondLevelType) ? [typeof(SubSubSecondLevelType)] : Array.Empty(); }); var schemaRepository = new SchemaRepository(); var schema = subject.GenerateSchema(typeof(BaseSecondLevelType), schemaRepository); - Assert.Equal(new[] { "SubSubSecondLevelType", "BaseSecondLevelType" }, schemaRepository.Schemas.Keys); + Assert.Equal(["SubSubSecondLevelType", "BaseSecondLevelType"], schemaRepository.Schemas.Keys); var subSchema = schemaRepository.Schemas["SubSubSecondLevelType"]; Assert.NotNull(subSchema.AllOf); @@ -648,7 +646,7 @@ public void GenerateSchema_SupportsOption_UseAllOfForPolymorphism() Assert.NotNull(schema.OneOf[0].Reference); var baseSchema = schemaRepository.Schemas[schema.OneOf[0].Reference.Id]; Assert.Equal("object", baseSchema.Type); - Assert.Equal(new[] { "BaseProperty" }, baseSchema.Properties.Keys); + Assert.Equal(["BaseProperty"], baseSchema.Properties.Keys); // The first sub type schema Assert.NotNull(schema.OneOf[1].Reference); var subType1Schema = schemaRepository.Schemas[schema.OneOf[1].Reference.Id]; @@ -657,7 +655,7 @@ public void GenerateSchema_SupportsOption_UseAllOfForPolymorphism() var allOf = Assert.Single(subType1Schema.AllOf); Assert.NotNull(allOf.Reference); Assert.Equal("BaseType", allOf.Reference.Id); - Assert.Equal(new[] { "Property1" }, subType1Schema.Properties.Keys); + Assert.Equal(["Property1"], subType1Schema.Properties.Keys); // The second sub type schema Assert.NotNull(schema.OneOf[2].Reference); var subType2Schema = schemaRepository.Schemas[schema.OneOf[2].Reference.Id]; @@ -666,7 +664,7 @@ public void GenerateSchema_SupportsOption_UseAllOfForPolymorphism() allOf = Assert.Single(subType2Schema.AllOf); Assert.NotNull(allOf.Reference); Assert.Equal("BaseType", allOf.Reference.Id); - Assert.Equal(new[] { "Property2" }, subType2Schema.Properties.Keys); + Assert.Equal(["Property2"], subType2Schema.Properties.Keys); } [Fact] @@ -1132,7 +1130,7 @@ public void GenerateSchema_HonorsSerializerOption_PropertyNamingPolicy() Assert.NotNull(referenceSchema.Reference); var schema = schemaRepository.Schemas[referenceSchema.Reference.Id]; - Assert.Equal(new[] { "property1", "property2" }, schema.Properties.Keys); + Assert.Equal(["property1", "property2"], schema.Properties.Keys); } [Theory] @@ -1178,7 +1176,7 @@ public void GenerateSchema_HonorsSerializerAttribute_StringEnumConverter() var schema = schemaRepository.Schemas[referenceSchema.Reference.Id]; Assert.Equal("string", schema.Type); - Assert.Equal(new[] { "\"Value1\"", "\"Value2\"", "\"X\"" }, schema.Enum.Select(openApiAny => openApiAny.ToJson())); + Assert.Equal(["\"Value1\"", "\"Value2\"", "\"X\""], schema.Enum.Select(openApiAny => openApiAny.ToJson())); } [Fact] diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGenerator/SwaggerGeneratorTests.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGenerator/SwaggerGeneratorTests.cs index 3ce7d687d8..35acf3722f 100644 --- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGenerator/SwaggerGeneratorTests.cs +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGenerator/SwaggerGeneratorTests.cs @@ -13,7 +13,6 @@ using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.Options; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.Swagger; @@ -29,8 +28,8 @@ public class SwaggerGeneratorTests public void GetSwagger_GeneratesSwaggerDocument_ForApiDescriptionsWithMatchingGroupName() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource"), @@ -38,8 +37,8 @@ public void GetSwagger_GeneratesSwaggerDocument_ForApiDescriptionsWithMatchingGr c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "GET", relativePath: "resource"), ApiDescriptionFactory.Create( - c => nameof(c.ActionWithNoParameters), groupName: "v2", httpMethod: "POST", relativePath: "resource") - }, + c => nameof(c.ActionWithNoParameters), groupName: "v2", httpMethod: "POST", relativePath: "resource"), + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary @@ -58,15 +57,15 @@ public void GetSwagger_GeneratesSwaggerDocument_ForApiDescriptionsWithMatchingGr Assert.Equal("V1", document.Info.Version); Assert.Equal("Test API", document.Info.Title); - Assert.Equal(new[] { "/resource" }, document.Paths.Keys.ToArray()); - Assert.Equal(new[] { OperationType.Post, OperationType.Get }, document.Paths["/resource"].Operations.Keys); + Assert.Equal(["/resource"], [.. document.Paths.Keys]); + Assert.Equal([OperationType.Post, OperationType.Get], document.Paths["/resource"].Operations.Keys); Assert.Equal(2, document.Paths["/resource"].Operations.Count); var documentV2 = subject.GetSwagger("v2"); Assert.Equal("V2", documentV2.Info.Version); Assert.Equal("Test API 2", documentV2.Info.Title); - Assert.Equal(new[] { "/resource" }, documentV2.Paths.Keys.ToArray()); - Assert.Equal(new[] { OperationType.Post }, documentV2.Paths["/resource"].Operations.Keys); + Assert.Equal(["/resource"], [.. documentV2.Paths.Keys]); + Assert.Equal([OperationType.Post], documentV2.Paths["/resource"].Operations.Keys); Assert.Single(documentV2.Paths["/resource"].Operations); } @@ -83,12 +82,12 @@ public void GetSwagger_GeneratesSwaggerDocument_ForApiDescriptionsWithMatchingGr public void GetSwagger_GeneratesSwaggerDocument_ForApiDescriptionsWithConstrainedRelativePaths(string path, string expectedPath) { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: path), - }, + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary @@ -110,11 +109,11 @@ public void GetSwagger_GeneratesSwaggerDocument_ForApiDescriptionsWithConstraine public void GetSwagger_SetsOperationIdToNull_ByDefault() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource"), - } + ] ); var document = subject.GetSwagger("v1"); @@ -126,11 +125,11 @@ public void GetSwagger_SetsOperationIdToNull_ByDefault() public void GetSwagger_SetsOperationIdToRouteName_IfActionHasRouteNameMetadata() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithRouteNameMetadata), groupName: "v1", httpMethod: "POST", relativePath: "resource"), - } + ] ); var document = subject.GetSwagger("v1"); @@ -144,17 +143,17 @@ public void GetSwagger_SetsOperationIdToEndpointName_IfActionHasEndpointNameMeta var methodInfo = typeof(FakeController).GetMethod(nameof(FakeController.ActionWithParameter)); var actionDescriptor = new ActionDescriptor { - EndpointMetadata = new List() { new EndpointNameMetadata("SomeEndpointName") }, + EndpointMetadata = [new EndpointNameMetadata("SomeEndpointName")], RouteValues = new Dictionary { ["controller"] = methodInfo.DeclaringType.Name.Replace("Controller", string.Empty) } }; var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create(actionDescriptor, methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource"), - } + ] ); var document = subject.GetSwagger("v1"); @@ -168,30 +167,30 @@ public void GetSwagger_UseProvidedOpenApiOperation_IfExistsInMetadata() var methodInfo = typeof(FakeController).GetMethod(nameof(FakeController.ActionWithParameter)); var actionDescriptor = new ActionDescriptor { - EndpointMetadata = new List() - { + EndpointMetadata = + [ new OpenApiOperation { OperationId = "OperationIdSetInMetadata", - Parameters = new List() - { + Parameters = + [ new OpenApiParameter { Name = "ParameterInMetadata" } - } + ] } - }, + ], RouteValues = new Dictionary { ["controller"] = methodInfo.DeclaringType.Name.Replace("Controller", string.Empty) } }; var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create(actionDescriptor, methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource"), - } + ] ); var document = subject.GetSwagger("v1"); @@ -206,8 +205,8 @@ public void GetSwagger_GenerateProducesSchemas_ForProvidedOpenApiOperation() var methodInfo = typeof(FakeController).GetMethod(nameof(FakeController.ActionWithProducesAttribute)); var actionDescriptor = new ActionDescriptor { - EndpointMetadata = new List() - { + EndpointMetadata = + [ new OpenApiOperation { OperationId = "OperationIdSetInMetadata", @@ -222,30 +221,30 @@ public void GetSwagger_GenerateProducesSchemas_ForProvidedOpenApiOperation() } } } - }, + ], RouteValues = new Dictionary { ["controller"] = methodInfo.DeclaringType.Name.Replace("Controller", string.Empty) } }; var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( actionDescriptor, methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource", - supportedResponseTypes: new[] - { + supportedResponseTypes: + [ new ApiResponseType() { StatusCode = 200, Type = typeof(TestDto) } - }), - } + ]), + ] ); var document = subject.GetSwagger("v1"); @@ -353,44 +352,44 @@ public void GetSwagger_GenerateParametersSchemas_ForProvidedOpenApiOperation() var methodInfo = typeof(FakeController).GetMethod(nameof(FakeController.ActionWithParameter)); var actionDescriptor = new ActionDescriptor { - EndpointMetadata = new List() - { + EndpointMetadata = + [ new OpenApiOperation { OperationId = "OperationIdSetInMetadata", - Parameters = new List() - { + Parameters = + [ new OpenApiParameter { Name = "ParameterInMetadata" } - } + ] } - }, + ], RouteValues = new Dictionary { ["controller"] = methodInfo.DeclaringType.Name.Replace("Controller", string.Empty) } }; var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( actionDescriptor, methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new[] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "ParameterInMetadata", ModelMetadata = ModelMetadataFactory.CreateForType(typeof(string)), Type = typeof(string) } - }), - } + ]), + ] ); var document = subject.GetSwagger("v1"); @@ -414,10 +413,10 @@ public void GetSwagger_SetsOperationIdToNull_IfActionHasNoEndpointMetadata() } }; var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create(actionDescriptor, methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource"), - } + ] ); var document = subject.GetSwagger("v1"); @@ -429,11 +428,11 @@ public void GetSwagger_SetsOperationIdToNull_IfActionHasNoEndpointMetadata() public void GetSwagger_SetsDeprecated_IfActionHasObsoleteAttribute() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithObsoleteAttribute), groupName: "v1", httpMethod: "POST", relativePath: "resource"), - } + ] ); var document = subject.GetSwagger("v1"); @@ -451,22 +450,22 @@ public void GetSwagger_GeneratesParameters_ForApiParametersThatAreNotBoundToBody ParameterLocation expectedParameterLocation) { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = (bindingSourceId != null) ? new BindingSource(bindingSourceId, null, false, true) : null } - }) - } + ]) + ] ); var document = subject.GetSwagger("v1"); @@ -480,16 +479,16 @@ public void GetSwagger_GeneratesParameters_ForApiParametersThatAreNotBoundToBody public void GetSwagger_IgnoresOperations_IfOperationHasSwaggerIgnoreAttribute() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithSwaggerIgnoreAttribute), groupName: "v1", httpMethod: "POST", relativePath: "ignored", - parameterDescriptions: Array.Empty() + parameterDescriptions: [] ) - } + ] ); var document = subject.GetSwagger("v1"); @@ -501,22 +500,22 @@ public void GetSwagger_IgnoresOperations_IfOperationHasSwaggerIgnoreAttribute() public void GetSwagger_IgnoresParameters_IfActionParameterHasBindNeverAttribute() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithParameterWithBindNeverAttribute), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = BindingSource.Query } - }) - } + ]) + ] ); var document = subject.GetSwagger("v1"); @@ -529,23 +528,22 @@ public void GetSwagger_IgnoresParameters_IfActionParameterHasBindNeverAttribute( public void GetSwagger_IgnoresParameters_IfActionParameterHasSwaggerIgnoreAttribute() { var subject = Subject( - new[] - { + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithIntParameterWithSwaggerIgnoreAttribute), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new[] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = BindingSource.Query } - } + ] ) - } + ] ); var document = subject.GetSwagger("v1"); @@ -564,15 +562,14 @@ public void GetSwagger_IgnoresParameters_IfActionParameterIsIllegalHeaderParamet var fromHeaderAttribute = illegalParameter.GetCustomAttribute(); var subject = Subject( - new[] - { + [ ApiDescriptionFactory.Create( c => action, groupName: "v1", httpMethod: "GET", relativePath: "resource", - parameterDescriptions: new[] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = fromHeaderAttribute?.Name ?? illegalParameter.Name, @@ -584,9 +581,9 @@ public void GetSwagger_IgnoresParameters_IfActionParameterIsIllegalHeaderParamet Name = "param", Source = BindingSource.Header } - } + ] ) - } + ] ); var document = subject.GetSwagger("v1"); @@ -608,13 +605,13 @@ public void GetSwagger_GenerateParametersSchemas_IfActionParameterIsIllegalHeade var methodInfo = typeof(FakeController).GetMethod(action); var actionDescriptor = new ActionDescriptor { - EndpointMetadata = new List() - { + EndpointMetadata = + [ new OpenApiOperation { OperationId = "OperationIdSetInMetadata", - Parameters = new List() - { + Parameters = + [ new OpenApiParameter { Name = illegalParameterName, @@ -623,25 +620,25 @@ public void GetSwagger_GenerateParametersSchemas_IfActionParameterIsIllegalHeade { Name = "param", } - } + ] } - }, + ], RouteValues = new Dictionary { ["controller"] = methodInfo.DeclaringType.Name.Replace("Controller", string.Empty) } }; var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( actionDescriptor, methodInfo, groupName: "v1", httpMethod: "GET", relativePath: "resource", - parameterDescriptions: new[] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = illegalParameterName, @@ -655,8 +652,8 @@ public void GetSwagger_GenerateParametersSchemas_IfActionParameterIsIllegalHeade ModelMetadata = ModelMetadataFactory.CreateForType(typeof(string)), Type = typeof(string) } - }), - } + ]), + ] ); var document = subject.GetSwagger("v1"); @@ -670,22 +667,22 @@ public void GetSwagger_GenerateParametersSchemas_IfActionParameterIsIllegalHeade public void GetSwagger_SetsParameterRequired_IfApiParameterIsBoundToPath() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = BindingSource.Path } - }) - } + ]) + ] ); var document = subject.GetSwagger("v1"); @@ -703,22 +700,22 @@ public void GetSwagger_SetsParameterRequired_IfActionParameterHasRequiredOrBindR bool expectedRequired) { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( methodInfo: typeof(FakeController).GetMethod(actionName), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = BindingSource.Query } - }) - } + ]) + ] ); var document = subject.GetSwagger("v1"); @@ -733,23 +730,23 @@ public void GetSwagger_SetsParameterRequired_IfActionParameterHasRequiredOrBindR public void GetSwagger_SetsParameterRequired_IfActionParameterHasRequiredMember() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( methodInfo: typeof(FakeController).GetMethod(nameof(FakeController.ActionWithRequiredMember)), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = BindingSource.Query, ModelMetadata = ModelMetadataFactory.CreateForProperty(typeof(FakeController.TypeWithRequiredProperty), "RequiredProperty") } - }) - } + ]) + ] ); var document = subject.GetSwagger("v1"); @@ -787,10 +784,10 @@ static void Execute(object obj) { } }; var subject = Subject( - apiDescriptions: new[] - { - ApiDescriptionFactory.Create(actionDescriptor, action.Method, groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new[]{ parameter }), - } + apiDescriptions: + [ + ApiDescriptionFactory.Create(actionDescriptor, action.Method, groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: [parameter]), + ] ); var document = subject.GetSwagger("v1"); @@ -802,22 +799,22 @@ static void Execute(object obj) { } public void GetSwagger_SetsParameterTypeToString_IfApiParameterHasNoCorrespondingActionParameter() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = BindingSource.Path } - }) - } + ]) + ] ); var document = subject.GetSwagger("v1"); @@ -831,33 +828,33 @@ public void GetSwagger_SetsParameterTypeToString_IfApiParameterHasNoCorrespondin public void GetSwagger_GeneratesRequestBody_ForFirstApiParameterThatIsBoundToBody() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = BindingSource.Body, } - }, - supportedRequestFormats: new[] - { + ], + supportedRequestFormats: + [ new ApiRequestFormat { MediaType = "application/json" } - }) - } + ]) + ] ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; Assert.NotNull(operation.RequestBody); - Assert.Equal(new[] { "application/json" }, operation.RequestBody.Content.Keys); + Assert.Equal(["application/json"], operation.RequestBody.Content.Keys); var mediaType = operation.RequestBody.Content["application/json"]; Assert.NotNull(mediaType.Schema); } @@ -871,26 +868,26 @@ public void GetSwagger_SetsRequestBodyRequired_IfActionParameterHasRequiredOrBin bool expectedRequired) { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( methodInfo: typeof(FakeController).GetMethod(actionName), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = BindingSource.Body, } - }, - supportedRequestFormats: new[] - { + ], + supportedRequestFormats: + [ new ApiRequestFormat { MediaType = "application/json" } - }) - } + ]) + ] ); var document = subject.GetSwagger("v1"); @@ -903,15 +900,15 @@ public void GetSwagger_SetsRequestBodyRequired_IfActionParameterHasRequiredOrBin public void GetSwagger_GeneratesRequestBody_ForApiParametersThatAreBoundToForm() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithMultipleParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param1", @@ -923,19 +920,19 @@ public void GetSwagger_GeneratesRequestBody_ForApiParametersThatAreBoundToForm() Source = BindingSource.Form, } - } + ] ) - } + ] ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; Assert.NotNull(operation.RequestBody); - Assert.Equal(new[] { "multipart/form-data" }, operation.RequestBody.Content.Keys); + Assert.Equal(["multipart/form-data"], operation.RequestBody.Content.Keys); var mediaType = operation.RequestBody.Content["multipart/form-data"]; Assert.NotNull(mediaType.Schema); - Assert.Equal(new[] { "param1", "param2" }, mediaType.Schema.Properties.Keys); + Assert.Equal(["param1", "param2"], mediaType.Schema.Properties.Keys); Assert.NotNull(mediaType.Encoding); } @@ -946,76 +943,76 @@ public void GetSwagger_SetsRequestBodyContentTypesFromAttribute_IfActionHasConsu string bindingSourceId) { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithConsumesAttribute), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = new BindingSource(bindingSourceId, null, false, true) } - }) - } + ]) + ] ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; - Assert.Equal(new[] { "application/someMediaType" }, operation.RequestBody.Content.Keys); + Assert.Equal(["application/someMediaType"], operation.RequestBody.Content.Keys); } [Fact] public void GetSwagger_GeneratesResponses_ForSupportedResponseTypes() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithReturnValue), groupName: "v1", httpMethod: "POST", relativePath: "resource", - supportedResponseTypes: new [] - { + supportedResponseTypes: + [ new ApiResponseType { - ApiResponseFormats = new [] { new ApiResponseFormat { MediaType = "application/json" } }, + ApiResponseFormats = [new ApiResponseFormat { MediaType = "application/json" }], StatusCode = 200, }, new ApiResponseType { - ApiResponseFormats = new [] { new ApiResponseFormat { MediaType = "application/json" } }, + ApiResponseFormats = [new ApiResponseFormat { MediaType = "application/json" }], StatusCode = 400 }, new ApiResponseType { - ApiResponseFormats = new [] { new ApiResponseFormat { MediaType = "application/json" } }, + ApiResponseFormats = [new ApiResponseFormat { MediaType = "application/json" }], StatusCode = 422 }, new ApiResponseType { - ApiResponseFormats = new [] { new ApiResponseFormat { MediaType = "application/json" } }, + ApiResponseFormats = [new ApiResponseFormat { MediaType = "application/json" }], IsDefaultResponse = true } - } + ] ) - } + ] ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; - Assert.Equal(new[] { "200", "400", "422", "default" }, operation.Responses.Keys); + Assert.Equal(["200", "400", "422", "default"], operation.Responses.Keys); var response200 = operation.Responses["200"]; Assert.Equal("OK", response200.Description); - Assert.Equal(new[] { "application/json" }, response200.Content.Keys); + Assert.Equal(["application/json"], response200.Content.Keys); var response400 = operation.Responses["400"]; Assert.Equal("Bad Request", response400.Description); Assert.Empty(response400.Content.Keys); @@ -1035,21 +1032,21 @@ public void GetSwagger_SetsResponseContentType_WhenActionHasFileResult() groupName: "v1", httpMethod: "POST", relativePath: "resource", - supportedResponseTypes: new[] - { + supportedResponseTypes: + [ new ApiResponseType { - ApiResponseFormats = new [] { new ApiResponseFormat { MediaType = "application/zip" } }, + ApiResponseFormats = [new ApiResponseFormat { MediaType = "application/zip" }], StatusCode = 200, Type = typeof(FileContentResult) } - }); + ]); // ASP.NET Core sets ModelMetadata to null for FileResults apiDescription.SupportedResponseTypes[0].ModelMetadata = null; var subject = Subject( - apiDescriptions: new[] { apiDescription } + apiDescriptions: [apiDescription] ); var document = subject.GetSwagger("v1"); @@ -1065,39 +1062,39 @@ public void GetSwagger_SetsResponseContentType_WhenActionHasFileResult() public void GetSwagger_SetsResponseContentTypesFromAttribute_IfActionHasProducesAttribute() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithProducesAttribute), groupName: "v1", httpMethod: "POST", relativePath: "resource", - supportedResponseTypes: new [] - { + supportedResponseTypes: + [ new ApiResponseType { - ApiResponseFormats = new [] { new ApiResponseFormat { MediaType = "application/json" } }, + ApiResponseFormats = [new ApiResponseFormat { MediaType = "application/json" }], StatusCode = 200, } - }) - } + ]) + ] ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; - Assert.Equal(new[] { "application/someMediaType" }, operation.Responses["200"].Content.Keys); + Assert.Equal(["application/someMediaType"], operation.Responses["200"].Content.Keys); } [Fact] public void GetSwagger_ThrowsUnknownSwaggerDocumentException_IfProvidedDocumentNameNotRegistered() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource"), - } + ] ); var exception = Assert.Throws(() => subject.GetSwagger("v2")); @@ -1110,11 +1107,11 @@ public void GetSwagger_ThrowsUnknownSwaggerDocumentException_IfProvidedDocumentN public void GetSwagger_ThrowsSwaggerGeneratorException_IfActionHasNoHttpBinding() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: null, relativePath: "resource") - } + ] ); var exception = Assert.Throws(() => subject.GetSwagger("v1")); @@ -1128,14 +1125,14 @@ public void GetSwagger_ThrowsSwaggerGeneratorException_IfActionHasNoHttpBinding( public void GetSwagger_ThrowsSwaggerGeneratorException_IfActionsHaveConflictingHttpMethodAndPath() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource"), ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource") - } + ] ); var exception = Assert.Throws(() => subject.GetSwagger("v1")); @@ -1157,14 +1154,14 @@ public void GetSwagger_ThrowsSwaggerGeneratorException_IfActionsHaveConflictingH c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "GET", relativePath: "resource"), ApiDescriptionFactory.Create( - c => nameof(c.ActionWithIntFromQueryParameter), groupName: "v1", httpMethod: "GET", relativePath: "resource", new ApiParameterDescription[] - { + c => nameof(c.ActionWithIntFromQueryParameter), groupName: "v1", httpMethod: "GET", relativePath: "resource", + [ new() { Name = "id", Source = BindingSource.Query, } - }), + ]), ] ); @@ -1181,14 +1178,14 @@ public void GetSwagger_ThrowsSwaggerGeneratorException_IfActionsHaveConflictingH public void GetSwagger_SupportsOption_IgnoreObsoleteActions() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource"), ApiDescriptionFactory.Create( c => nameof(c.ActionWithObsoleteAttribute), groupName: "v1", httpMethod: "GET", relativePath: "resource") - }, + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary @@ -1201,8 +1198,8 @@ public void GetSwagger_SupportsOption_IgnoreObsoleteActions() var document = subject.GetSwagger("v1"); - Assert.Equal(new[] { "/resource" }, document.Paths.Keys.ToArray()); - Assert.Equal(new[] { OperationType.Post }, document.Paths["/resource"].Operations.Keys); + Assert.Equal(["/resource"], [.. document.Paths.Keys]); + Assert.Equal([OperationType.Post], document.Paths["/resource"].Operations.Keys); Assert.Single(document.Paths["/resource"].Operations); } @@ -1210,8 +1207,8 @@ public void GetSwagger_SupportsOption_IgnoreObsoleteActions() public void GetSwagger_SupportsOption_SortKeySelector() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource3"), @@ -1220,7 +1217,7 @@ public void GetSwagger_SupportsOption_SortKeySelector() ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource2"), - }, + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary @@ -1233,7 +1230,7 @@ public void GetSwagger_SupportsOption_SortKeySelector() var document = subject.GetSwagger("v1"); - Assert.Equal(new[] { "/resource1", "/resource2", "/resource3" }, document.Paths.Keys.ToArray()); + Assert.Equal(["/resource1", "/resource2", "/resource3"], [.. document.Paths.Keys]); Assert.Single(document.Paths["/resource1"].Operations); Assert.Single(document.Paths["/resource2"].Operations); Assert.Single(document.Paths["/resource3"].Operations); @@ -1243,24 +1240,24 @@ public void GetSwagger_SupportsOption_SortKeySelector() public void GetSwagger_SupportsOption_TagSelector() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource"), - }, + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } }, - TagsSelector = (apiDesc) => new[] { apiDesc.RelativePath } + TagsSelector = (apiDesc) => [apiDesc.RelativePath] } ); var document = subject.GetSwagger("v1"); - Assert.Equal(new[] { "resource" }, document.Paths["/resource"].Operations[OperationType.Post].Tags.Select(t => t.Name)); + Assert.Equal(["resource"], document.Paths["/resource"].Operations[OperationType.Post].Tags.Select(t => t.Name)); } [Fact] @@ -1269,22 +1266,22 @@ public void GetSwagger_CanReadTagsFromMetadata() var methodInfo = typeof(FakeController).GetMethod(nameof(FakeController.ActionWithParameter)); var actionDescriptor = new ActionDescriptor { - EndpointMetadata = new List() { new TagsAttribute("Some", "Tags", "Here") }, + EndpointMetadata = [new TagsAttribute("Some", "Tags", "Here")], RouteValues = new Dictionary { ["controller"] = methodInfo.DeclaringType.Name.Replace("Controller", string.Empty) } }; var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create(actionDescriptor, methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource"), - } + ] ); var document = subject.GetSwagger("v1"); - Assert.Equal(new[] { "Some", "Tags", "Here" }, document.Paths["/resource"].Operations[OperationType.Post].Tags.Select(t => t.Name)); + Assert.Equal(["Some", "Tags", "Here"], document.Paths["/resource"].Operations[OperationType.Post].Tags.Select(t => t.Name)); } #if NET7_0_OR_GREATER @@ -1294,17 +1291,17 @@ public void GetSwagger_CanReadEndpointSummaryFromMetadata() var methodInfo = typeof(FakeController).GetMethod(nameof(FakeController.ActionWithParameter)); var actionDescriptor = new ActionDescriptor { - EndpointMetadata = new List() { new EndpointSummaryAttribute("A Test Summary") }, + EndpointMetadata = [new EndpointSummaryAttribute("A Test Summary")], RouteValues = new Dictionary { ["controller"] = methodInfo.DeclaringType.Name.Replace("Controller", string.Empty) } }; var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create(actionDescriptor, methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource"), - } + ] ); var document = subject.GetSwagger("v1"); @@ -1318,17 +1315,17 @@ public void GetSwagger_CanReadEndpointDescriptionFromMetadata() var methodInfo = typeof(FakeController).GetMethod(nameof(FakeController.ActionWithParameter)); var actionDescriptor = new ActionDescriptor { - EndpointMetadata = new List() { new EndpointDescriptionAttribute("A Test Description") }, + EndpointMetadata = [new EndpointDescriptionAttribute("A Test Description")], RouteValues = new Dictionary { ["controller"] = methodInfo.DeclaringType.Name.Replace("Controller", string.Empty) } }; var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create(actionDescriptor, methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource"), - } + ] ); var document = subject.GetSwagger("v1"); @@ -1341,14 +1338,14 @@ public void GetSwagger_CanReadEndpointDescriptionFromMetadata() public void GetSwagger_SupportsOption_ConflictingActionsResolver() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource"), ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource") - }, + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary @@ -1361,8 +1358,8 @@ public void GetSwagger_SupportsOption_ConflictingActionsResolver() var document = subject.GetSwagger("v1"); - Assert.Equal(new[] { "/resource" }, document.Paths.Keys.ToArray()); - Assert.Equal(new[] { OperationType.Post }, document.Paths["/resource"].Operations.Keys); + Assert.Equal(["/resource"], [.. document.Paths.Keys]); + Assert.Equal([OperationType.Post], document.Paths["/resource"].Operations.Keys); Assert.Single(document.Paths["/resource"].Operations); } @@ -1377,22 +1374,22 @@ public void GetSwagger_SupportsOption_DescribeAllParametersInCamelCase( string expectedOpenApiParameterName) { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = parameterName, Source = BindingSource.Path } - }) - }, + ]) + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary @@ -1483,17 +1480,17 @@ public void GetSwagger_SupportsOption_DescribeAllParametersInCamelCase_ForParame public void GetSwagger_SupportsOption_Servers() { var subject = Subject( - apiDescriptions: new ApiDescription[] { }, + apiDescriptions: [], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } }, - Servers = new List - { + Servers = + [ new OpenApiServer { Url = "http://tempuri.org/api" } - } + ] } ); @@ -1507,7 +1504,7 @@ public void GetSwagger_SupportsOption_Servers() public void GetSwagger_SupportsOption_SecuritySchemes() { var subject = Subject( - apiDescriptions: new ApiDescription[] { }, + apiDescriptions: [], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary @@ -1523,7 +1520,7 @@ public void GetSwagger_SupportsOption_SecuritySchemes() var document = subject.GetSwagger("v1"); - Assert.Equal(new[] { "basic" }, document.Components.SecuritySchemes.Keys); + Assert.Equal(["basic"], document.Components.SecuritySchemes.Keys); } [Theory] @@ -1535,11 +1532,11 @@ public async Task GetSwagger_SupportsOption_InferSecuritySchemes( { var subject = Subject( - apiDescriptions: new ApiDescription[] { }, - authenticationSchemes: new[] { + apiDescriptions: [], + authenticationSchemes: [ new AuthenticationScheme("Bearer", null, typeof(IAuthenticationHandler)), new AuthenticationScheme("Cookies", null, typeof(IAuthenticationHandler)) - }, + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary @@ -1564,11 +1561,11 @@ public async Task GetSwagger_SupportsOption_SecuritySchemesSelector( { var subject = Subject( - apiDescriptions: new ApiDescription[] { }, - authenticationSchemes: new[] { + apiDescriptions: [], + authenticationSchemes: [ new AuthenticationScheme("Bearer", null, typeof(IAuthenticationHandler)), new AuthenticationScheme("Cookies", null, typeof(IAuthenticationHandler)) - }, + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary @@ -1593,28 +1590,28 @@ public async Task GetSwagger_SupportsOption_SecuritySchemesSelector( public void GetSwagger_SupportsOption_ParameterFilters() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = BindingSource.Query } - }) - }, + ]) + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } }, - ParameterFilters = new List - { + ParameterFilters = + [ new TestParameterFilter() - } + ] } ); @@ -1630,28 +1627,28 @@ public void GetSwagger_SupportsOption_ParameterFilters() public void GetSwagger_SupportsOption_RequestBodyFilters() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = BindingSource.Body } - }) - }, + ]) + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } }, - RequestBodyFilters = new List - { + RequestBodyFilters = + [ new TestRequestBodyFilter() - } + ] } ); @@ -1667,21 +1664,21 @@ public void GetSwagger_SupportsOption_RequestBodyFilters() public void GetSwagger_SupportsOption_OperationFilters() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource") - }, + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } }, - OperationFilters = new List - { + OperationFilters = + [ new TestOperationFilter() - } + ] } ); @@ -1697,17 +1694,17 @@ public void GetSwagger_SupportsOption_OperationFilters() public void GetSwagger_SupportsOption_DocumentFilters() { var subject = Subject( - apiDescriptions: new ApiDescription[] { }, + apiDescriptions: [], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } }, - DocumentFilters = new List - { + DocumentFilters = + [ new TestDocumentFilter() - } + ] } ); @@ -1723,21 +1720,21 @@ public void GetSwagger_SupportsOption_DocumentFilters() public async Task GetSwaggerAsync_SupportsOption_OperationFilters() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource") - }, + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } }, - OperationFilters = new List - { + OperationFilters = + [ new TestOperationFilter() - } + ] } ); @@ -1809,7 +1806,7 @@ public async Task GetSwaggerAsync_SupportsOption_DocumentAsyncFilters() public async Task GetSwaggerAsync_SupportsOption_DocumentFilters() { var subject = Subject( - apiDescriptions: Array.Empty(), + apiDescriptions: [], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary @@ -1835,18 +1832,18 @@ public async Task GetSwaggerAsync_SupportsOption_DocumentFilters() public async Task GetSwaggerAsync_SupportsOption_RequestBodyAsyncFilters() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = BindingSource.Body } - }) - }, + ]) + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary @@ -1872,28 +1869,28 @@ public async Task GetSwaggerAsync_SupportsOption_RequestBodyAsyncFilters() public async Task GetSwaggerAsync_SupportsOption_RequestBodyFilters() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = BindingSource.Body } - }) - }, + ]) + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } }, - RequestBodyFilters = new List - { + RequestBodyFilters = + [ new TestRequestBodyFilter() - } + ] } ); @@ -1909,28 +1906,28 @@ public async Task GetSwaggerAsync_SupportsOption_RequestBodyFilters() public async Task GetSwaggerAsync_SupportsOption_ParameterFilters() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = BindingSource.Query } - }) - }, + ]) + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } }, - ParameterFilters = new List - { + ParameterFilters = + [ new TestParameterFilter() - } + ] } ); @@ -1946,18 +1943,18 @@ public async Task GetSwaggerAsync_SupportsOption_ParameterFilters() public async Task GetSwaggerAsync_SupportsOption_ParameterAsyncFilters() { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new [] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param", Source = BindingSource.Query } - }) - }, + ]) + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary @@ -1986,11 +1983,11 @@ public async Task GetSwaggerAsync_SupportsOption_ParameterAsyncFilters() public void GetSwagger_GeneratesSwaggerDocument_ThrowsIfHttpMethodNotSupported(string httpMethod) { var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: httpMethod, relativePath: "resource"), - }, + ], options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary @@ -2012,23 +2009,23 @@ public void GetSwagger_Throws_Exception_When_FromForm_Attribute_Used_With_IFormF .GetParameters()[0]; var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionHavingIFormFileParamWithFromFormAttribute), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new[] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "fileUpload", // Name of the parameter Type = typeof(IFormFile), // Type of the parameter ParameterDescriptor = new ControllerParameterDescriptor { ParameterInfo = parameterInfo } } - }) - } + ]) + ] ); Assert.Throws(() => subject.GetSwagger("v1")); @@ -2046,15 +2043,15 @@ public void GetSwagger_Works_As_Expected_When_FromForm_Attribute_Not_Used_With_I .GetParameters()[1]; var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionHavingFromFormAttributeButNotWithIFormFile), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new[] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = "param1", // Name of the parameter @@ -2067,14 +2064,14 @@ public void GetSwagger_Works_As_Expected_When_FromForm_Attribute_Not_Used_With_I Type = typeof(IFormFile), // Type of the parameter ParameterDescriptor = new ControllerParameterDescriptor { ParameterInfo = fileUploadParameterInfo } } - }) - } + ]) + ] ); var document = subject.GetSwagger("v1"); Assert.Equal("V1", document.Info.Version); Assert.Equal("Test API", document.Info.Title); - Assert.Equal(new[] { "/resource" }, document.Paths.Keys.ToArray()); + Assert.Equal(["/resource"], [.. document.Paths.Keys]); var operation = document.Paths["/resource"].Operations[OperationType.Post]; Assert.NotNull(operation.Parameters); @@ -2098,15 +2095,15 @@ public void GetSwagger_Works_As_Expected_When_FromForm_Attribute_With_SwaggerIgn new FakeICompositeMetadataDetailsProvider(), new DefaultMetadataDetails(ModelMetadataIdentity.ForProperty(propertyNotIgnored, typeof(string), typeof(SwaggerIngoreAnnotatedType)), ModelAttributes.GetAttributesForProperty(typeof(SwaggerIngoreAnnotatedType), propertyNotIgnored))); var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create( c => nameof(c.ActionHavingFromFormAttributeWithSwaggerIgnore), groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new[] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = nameof(SwaggerIngoreAnnotatedType.IgnoredString), @@ -2121,19 +2118,19 @@ public void GetSwagger_Works_As_Expected_When_FromForm_Attribute_With_SwaggerIgn Type = typeof(string), ModelMetadata = modelMetadataNotIgnored } - }) - } + ]) + ] ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; Assert.NotNull(operation.RequestBody); - Assert.Equal(new[] { "multipart/form-data" }, operation.RequestBody.Content.Keys); + Assert.Equal(["multipart/form-data"], operation.RequestBody.Content.Keys); var mediaType = operation.RequestBody.Content["multipart/form-data"]; Assert.NotNull(mediaType.Schema); - Assert.Equal(new[] { nameof(SwaggerIngoreAnnotatedType.NotIgnoredString) }, mediaType.Schema.Properties.Keys); + Assert.Equal([nameof(SwaggerIngoreAnnotatedType.NotIgnoredString)], mediaType.Schema.Properties.Keys); Assert.NotNull(mediaType.Encoding); - Assert.Equal(new[] { nameof(SwaggerIngoreAnnotatedType.NotIgnoredString) }, mediaType.Encoding.Keys); + Assert.Equal([nameof(SwaggerIngoreAnnotatedType.NotIgnoredString)], mediaType.Encoding.Keys); } [Fact] @@ -2272,8 +2269,8 @@ public void GetSwagger_Copies_Description_From_GeneratedSchema() groupName: "v1", httpMethod: "POST", relativePath: "resource", - parameterDescriptions: new[] - { + parameterDescriptions: + [ new ApiParameterDescription { Name = nameof(TypeWithDefaultAttributeOnEnum.EnumWithDefault), @@ -2288,7 +2285,7 @@ public void GetSwagger_Copies_Description_From_GeneratedSchema() Type = typeof(IntEnum[]), ModelMetadata = modelMetadataForEnumArray } - }) + ]) ], schemaFilters: [new TestEnumSchemaFilter()] ); @@ -2558,8 +2555,8 @@ public void GetSwagger_OpenApiOperationWithRawContent_IsHandled() var methodInfo = typeof(FakeController).GetMethod(nameof(FakeController.ActionWithParameter)); var actionDescriptor = new ActionDescriptor { - EndpointMetadata = new List() - { + EndpointMetadata = + [ new OpenApiOperation() { RequestBody = new OpenApiRequestBody() @@ -2570,25 +2567,25 @@ public void GetSwagger_OpenApiOperationWithRawContent_IsHandled() } } } - }, + ], RouteValues = new Dictionary { ["controller"] = methodInfo.DeclaringType.Name.Replace("Controller", string.Empty) } }; var subject = Subject( - apiDescriptions: new[] - { + apiDescriptions: + [ ApiDescriptionFactory.Create(actionDescriptor, methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource"), - } + ] ); var document = subject.GetSwagger("v1"); Assert.Equal("V1", document.Info.Version); Assert.Equal("Test API", document.Info.Title); - Assert.Equal(new[] { "/resource" }, document.Paths.Keys.ToArray()); - Assert.Equal(new[] { OperationType.Post }, document.Paths["/resource"].Operations.Keys); + Assert.Equal(["/resource"], [.. document.Paths.Keys]); + Assert.Equal([OperationType.Post], document.Paths["/resource"].Operations.Keys); Assert.Single(document.Paths["/resource"].Operations); } @@ -2651,7 +2648,7 @@ private static SwaggerGenerator Subject( ); } - private static readonly SwaggerGeneratorOptions DefaultOptions = new SwaggerGeneratorOptions + private static readonly SwaggerGeneratorOptions DefaultOptions = new() { SwaggerDocs = new Dictionary { diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/XmlComments/XmlCommentsExampleHelperTests.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/XmlComments/XmlCommentsExampleHelperTests.cs index a9b7cfd6b6..a3aef1458c 100644 --- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/XmlComments/XmlCommentsExampleHelperTests.cs +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/XmlComments/XmlCommentsExampleHelperTests.cs @@ -6,14 +6,14 @@ namespace Swashbuckle.AspNetCore.SwaggerGen.Test { public class XmlCommentsExampleHelperTests { - private readonly SchemaRepository schemaRepository = new SchemaRepository(); + private readonly SchemaRepository schemaRepository = new(); [Fact] public void Create_BuildsOpenApiArrayJson__When_NotStringTypeAndDataIsArray() { var schema = new OpenApiSchema(); - IOpenApiAny example = XmlCommentsExampleHelper.Create( + var example = XmlCommentsExampleHelper.Create( schemaRepository, schema, "[\"one\",\"two\",\"three\"]"); @@ -37,7 +37,7 @@ public void Create_BuildsOpenApiString_When_TypeString() OpenApiSchema schema = new OpenApiSchema { Type = "string" }; schemaRepository.AddDefinition("test", schema); - IOpenApiAny example = XmlCommentsExampleHelper.Create( + var example = XmlCommentsExampleHelper.Create( schemaRepository, schema, exampleString); Assert.NotNull(example); @@ -48,10 +48,10 @@ public void Create_BuildsOpenApiString_When_TypeString() [Fact] public void Create_ReturnsNull_When_TypeString_and_ValueNull() { - OpenApiSchema schema = new OpenApiSchema { Type = "string" }; + var schema = new OpenApiSchema { Type = "string" }; schemaRepository.AddDefinition("test", schema); - IOpenApiAny example = XmlCommentsExampleHelper.Create( + var example = XmlCommentsExampleHelper.Create( schemaRepository, schema, "null"); Assert.NotNull(example); @@ -64,7 +64,7 @@ public void Create_AllowsSchemaToBeNull() { OpenApiSchema schema = null; - IOpenApiAny example = XmlCommentsExampleHelper.Create(schemaRepository, schema, "[]"); + var example = XmlCommentsExampleHelper.Create(schemaRepository, schema, "[]"); Assert.NotNull(example); var actual = Assert.IsType(example); diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/XmlComments/XmlCommentsParameterFilterTests.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/XmlComments/XmlCommentsParameterFilterTests.cs index 77502b15ab..392bcdbe3b 100644 --- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/XmlComments/XmlCommentsParameterFilterTests.cs +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/XmlComments/XmlCommentsParameterFilterTests.cs @@ -92,12 +92,10 @@ public void Apply_SetsDescriptionAndExample_FromUriTypePropertySummaryAndExample Assert.Equal("\"https://test.com/a?b=1&c=2\"", parameter.Example.ToJson()); } - private XmlCommentsParameterFilter Subject() + private static XmlCommentsParameterFilter Subject() { - using (var xmlComments = File.OpenText(typeof(FakeControllerWithXmlComments).Assembly.GetName().Name + ".xml")) - { - return new XmlCommentsParameterFilter(new XPathDocument(xmlComments)); - } + using var xmlComments = File.OpenText(typeof(FakeControllerWithXmlComments).Assembly.GetName().Name + ".xml"); + return new XmlCommentsParameterFilter(new XPathDocument(xmlComments)); } } } diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/XmlComments/XmlCommentsSchemaFilterTests.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/XmlComments/XmlCommentsSchemaFilterTests.cs index 36c32db543..cc35e1c7da 100644 --- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/XmlComments/XmlCommentsSchemaFilterTests.cs +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/XmlComments/XmlCommentsSchemaFilterTests.cs @@ -1,10 +1,10 @@ using System; using System.Globalization; -using System.Xml.XPath; using System.IO; +using System.Xml.XPath; using Microsoft.OpenApi.Models; -using Xunit; using Swashbuckle.AspNetCore.TestSupport; +using Xunit; namespace Swashbuckle.AspNetCore.SwaggerGen.Test { @@ -159,12 +159,10 @@ public void Apply_UsesInvariantCulture_WhenSettingExample( Assert.Equal(expectedValue, schema.Example.GetType().GetProperty("Value").GetValue(schema.Example)); } - private XmlCommentsSchemaFilter Subject() + private static XmlCommentsSchemaFilter Subject() { - using (var xmlComments = File.OpenText(typeof(XmlAnnotatedType).Assembly.GetName().Name + ".xml")) - { - return new XmlCommentsSchemaFilter(new XPathDocument(xmlComments)); - } + using var xmlComments = File.OpenText(typeof(XmlAnnotatedType).Assembly.GetName().Name + ".xml"); + return new XmlCommentsSchemaFilter(new XPathDocument(xmlComments)); } } -} \ No newline at end of file +} diff --git a/test/WebSites/Basic/Swagger/ExamplesSchemaFilter.cs b/test/WebSites/Basic/Swagger/ExamplesSchemaFilter.cs index 6ab19b7ec2..95bf8172ca 100644 --- a/test/WebSites/Basic/Swagger/ExamplesSchemaFilter.cs +++ b/test/WebSites/Basic/Swagger/ExamplesSchemaFilter.cs @@ -12,20 +12,18 @@ public void Apply(OpenApiSchema schema, SchemaFilterContext context) schema.Example = GetExampleOrNullFor(context.Type); } - private IOpenApiAny GetExampleOrNullFor(Type type) + private static IOpenApiAny GetExampleOrNullFor(Type type) { - switch (type.Name) + return type.Name switch { - case "Product": - return new OpenApiObject - { - [ "id" ] = new OpenApiInteger(123), - [ "description" ] = new OpenApiString("foobar"), - [ "price" ] = new OpenApiDouble(14.37) - }; - default: - return null; - } + "Product" => new OpenApiObject + { + ["id"] = new OpenApiInteger(123), + ["description"] = new OpenApiString("foobar"), + ["price"] = new OpenApiDouble(14.37) + }, + _ => null, + }; } } } diff --git a/test/WebSites/TestFirst.IntegrationTests/CreateProductTests.cs b/test/WebSites/TestFirst.IntegrationTests/CreateProductTests.cs index c688f2a776..f68bca05cf 100644 --- a/test/WebSites/TestFirst.IntegrationTests/CreateProductTests.cs +++ b/test/WebSites/TestFirst.IntegrationTests/CreateProductTests.cs @@ -1,24 +1,17 @@ using System; -using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Testing; -using Microsoft.OpenApi.Models; using Newtonsoft.Json; using Swashbuckle.AspNetCore.ApiTesting.Xunit; using Xunit; namespace TestFirst.IntegrationTests { - public class CreateProductTests : ApiTestFixture + public class CreateProductTests(ApiTestRunner apiTestRunner, WebApplicationFactory webApplicationFactory) + : ApiTestFixture(apiTestRunner, webApplicationFactory, "v1-imported") { - public CreateProductTests( - ApiTestRunner apiTestRunner, - WebApplicationFactory webApplicationFactory) - : base(apiTestRunner, webApplicationFactory, "v1-imported") - { } - [Fact] public async Task CreateProduct_Returns201_IfContentIsValid() { @@ -55,4 +48,4 @@ await TestAsync( ); } } -} \ No newline at end of file +} diff --git a/test/WebSites/TestFirst.IntegrationTests/GetProductsTests.cs b/test/WebSites/TestFirst.IntegrationTests/GetProductsTests.cs index 02110d2db0..ac2cbc82f3 100644 --- a/test/WebSites/TestFirst.IntegrationTests/GetProductsTests.cs +++ b/test/WebSites/TestFirst.IntegrationTests/GetProductsTests.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; using System.Net.Http; -using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Testing; -using Microsoft.OpenApi.Models; -using Newtonsoft.Json; using Swashbuckle.AspNetCore.ApiTesting.Xunit; using Xunit; @@ -47,4 +43,4 @@ await TestAsync( ); } } -} \ No newline at end of file +} diff --git a/test/WebSites/WebApi/EndPoints/OpenApiEndpoints.cs b/test/WebSites/WebApi/EndPoints/OpenApiEndpoints.cs index a693a02343..88aff58021 100644 --- a/test/WebSites/WebApi/EndPoints/OpenApiEndpoints.cs +++ b/test/WebSites/WebApi/EndPoints/OpenApiEndpoints.cs @@ -48,7 +48,7 @@ public static IEndpointRouteBuilder MapWithOpenApiEndpoints(this IEndpointRouteB return $"{file.FileName}{queryParameter}"; }).WithOpenApi(o => { - var parameter = o.Parameters.FirstOrDefault(p => p.Name.Equals("queryParameter", StringComparison.OrdinalIgnoreCase)); + var parameter = o.Parameters?.FirstOrDefault(p => p.Name.Equals("queryParameter", StringComparison.OrdinalIgnoreCase)); if (parameter is not null) { parameter.Description = $"{parameter.Name} Description";