public void Apply_SetsParameterDescriptions_FromCorrespondingPropertySummaryTags() { var operation = new OpenApiOperation { Parameters = new List <OpenApiParameter> { new OpenApiParameter { Name = "BoolProperty" } }, Responses = new OpenApiResponses() }; var filterContext = FilterContextFor ( ApiDescriptionFactory.Create <FakeControllerWithXmlComments>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new[] { new ApiParameterDescription { Name = "BoolProperty", Source = BindingSource.Query, ModelMetadata = ModelMetadataFactory.CreateForProperty(typeof(XmlAnnotatedType), "BoolProperty") } }) ); Subject().Apply(operation, filterContext); Assert.Equal("Summary for BoolProperty", operation.Parameters[0].Description); }
public void GetSwagger_SetsParameterDefault_IfActionParameterIsOptionalOrHasDefaultValueAttribute( string actionName) { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create( methodInfo: typeof(FakeController).GetMethod(actionName), groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new [] { new ApiParameterDescription { Name = "param", Source = BindingSource.Query } }) } ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; Assert.Equal(1, operation.Parameters.Count); Assert.Equal("someDefaultValue", ((OpenApiString)operation.Parameters.First().Schema.Default).Value); }
public void GetSwagger_SupportsOption_OperationFilters() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource") }, options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary <string, OpenApiInfo> { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } }, OperationFilters = new List <IOperationFilter> { new VendorExtensionsOperationFilter() } } ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; Assert.NotEmpty(operation.Extensions); }
public void GetSwagger_GeneratesSwaggerDocument_ForApiDescriptionsWithConstrainedRelativePaths(string path, string expectedPath) { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: path), }, options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary <string, OpenApiInfo> { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } } } ); var document = subject.GetSwagger("v1"); Assert.Equal("V1", document.Info.Version); Assert.Equal("Test API", document.Info.Title); Assert.Equal(new[] { expectedPath }, document.Paths.Keys.ToArray()); }
public void GetSwagger_SetsRequestBodyRequired_IfActionParameterHasRequiredOrBindRequiredMetadata( string actionName, bool expectedRequired) { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create( methodInfo: typeof(FakeController).GetMethod(actionName), groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new [] { new ApiParameterDescription { Name = "param", Source = BindingSource.Body, } }, supportedRequestFormats: new[] { new ApiRequestFormat { MediaType = "application/json" } }) } ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; Assert.Equal(expectedRequired, operation.RequestBody.Required); }
public void Apply_SetsRequestBodyDescription_FromCorrespondingActionParamTags() { var operation = new OpenApiOperation { RequestBody = new OpenApiRequestBody(), Responses = new OpenApiResponses() }; var filterContext = FilterContextFor ( ApiDescriptionFactory.Create <FakeControllerWithXmlComments>( c => nameof(c.ActionWithParamTag), groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new [] { new ApiParameterDescription { Name = "param", Source = BindingSource.Body } }) ); Subject().Apply(operation, filterContext); Assert.Equal("Description for param", operation.RequestBody.Description); }
public void GetSwagger_SetsResponseContentTypesFromAttribute_IfActionHasProducesAttribute() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithProducesAttribute), groupName: "v1", httpMethod: "POST", relativePath: "resource", supportedResponseTypes: new [] { new ApiResponseType { ApiResponseFormats = new [] { 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); }
public void GetSwagger_SupportsOption_SortKeySelector() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource3"), ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource1"), ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource2"), }, options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary <string, OpenApiInfo> { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } }, SortKeySelector = (apiDesc) => apiDesc.RelativePath } ); var document = subject.GetSwagger("v1"); Assert.Equal(new[] { "/resource1", "/resource2", "/resource3" }, document.Paths.Keys.ToArray()); }
public void GetSwagger_SetsOperationIdToEndpointName_IfActionHasEndpointNameMetadata() { var methodInfo = typeof(FakeController).GetMethod(nameof(FakeController.ActionWithParameter)); var actionDescriptor = new ActionDescriptor { EndpointMetadata = new List <object>() { new EndpointNameMetadata("SomeEndpointName") }, RouteValues = new Dictionary <string, string> { ["controller"] = methodInfo.DeclaringType.Name.Replace("Controller", string.Empty) } }; var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create(actionDescriptor, methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource"), } ); var document = subject.GetSwagger("v1"); Assert.Equal("SomeEndpointName", document.Paths["/resource"].Operations[OperationType.Post].OperationId); }
public void GetSwagger_SetsParameterRequired_IfActionParameterHasRequiredOrBindRequiredAttribute( string actionName, bool expectedRequired) { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create( methodInfo: typeof(FakeController).GetMethod(actionName), groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new [] { new ApiParameterDescription { Name = "param", Source = BindingSource.Query } }) } ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; Assert.Equal(1, operation.Parameters.Count); Assert.Equal(expectedRequired, operation.Parameters.First().Required); }
public void GetSwagger_SetsParameterTypeToString_IfApiParameterHasNoCorrespondingActionParameter() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new [] { new ApiParameterDescription { Name = "param", Source = BindingSource.Path } }) } ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; Assert.Equal(1, operation.Parameters.Count); Assert.Equal("string", operation.Parameters.First().Schema.Type); }
public void GetSwagger_GeneratesSwaggerDocument_ForApiDescriptionsWithMatchingGroupName() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource"), ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "GET", relativePath: "resource"), ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v2", httpMethod: "POST", relativePath: "resource"), }, options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary <string, OpenApiInfo> { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } } } ); 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, OperationType.Get }, document.Paths["/resource"].Operations.Keys); }
public void GetSwagger_SetsParameterRequired_IfApiParameterIsBoundToPath() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new [] { new ApiParameterDescription { Name = "param", Source = BindingSource.Path } }) } ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; Assert.True(operation.Parameters.First().Required); }
public void GetSwagger_IgnoresParameters_IfActionParameterHasBindNeverAttribute() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithParameterWithBindNeverAttribute), groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new [] { new ApiParameterDescription { Name = "param", Source = BindingSource.Query } }) } ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; Assert.Equal(0, operation.Parameters.Count); }
public void GetSwagger_GeneratesParameters_ForApiParametersThatAreNotBoundToBodyOrForm( string bindingSourceId, ParameterLocation expectedParameterLocation) { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new [] { new ApiParameterDescription { Name = "param", Source = (bindingSourceId != null) ? new BindingSource(bindingSourceId, null, false, true) : null } }) } ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; Assert.Equal(1, operation.Parameters.Count); Assert.Equal(expectedParameterLocation, operation.Parameters.First().In); }
public void GetSwagger_SupportsOption_ConflictingActionsResolver() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource"), ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource") }, options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary <string, OpenApiInfo> { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } }, ConflictingActionsResolver = (apiDescriptions) => apiDescriptions.First() } ); var document = subject.GetSwagger("v1"); Assert.Equal(new[] { "/resource" }, document.Paths.Keys.ToArray()); Assert.Equal(new[] { OperationType.Post }, document.Paths["/resource"].Operations.Keys); }
public void GetSwagger_SetsRequestBodyContentTypesFromAttribute_IfActionHasConsumesAttribute( string bindingSourceId) { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithConsumesAttribute), groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new [] { 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); }
public void GetSwagger_GeneratesResponses_ForSupportedResponseTypes() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithReturnValue), groupName: "v1", httpMethod: "POST", relativePath: "resource", supportedResponseTypes: new [] { new ApiResponseType { ApiResponseFormats = new [] { new ApiResponseFormat { MediaType = "application/json" } }, StatusCode = 200, }, new ApiResponseType { ApiResponseFormats = new [] { new ApiResponseFormat { MediaType = "application/json" } }, StatusCode = 400 }, new ApiResponseType { ApiResponseFormats = new [] { 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", "default" }, operation.Responses.Keys); var response200 = operation.Responses["200"]; Assert.Equal("Success", response200.Description); Assert.Equal(new[] { "application/json" }, response200.Content.Keys); var response400 = operation.Responses["400"]; Assert.Equal("Bad Request", response400.Description); Assert.Empty(response400.Content.Keys); var responseDefault = operation.Responses["default"]; Assert.Equal("Error", responseDefault.Description); Assert.Empty(responseDefault.Content.Keys); }
public void Apply_SetsSummaryAndDescription_FromUnderlyingGenericTypeActionSummaryAndRemarksTags() { var operation = new OpenApiOperation(); var methodInfo = typeof(FakeConstructedControllerWithXmlComments) .GetMethod(nameof(FakeConstructedControllerWithXmlComments.ActionWithSummaryAndResponseTags)); var apiDescription = ApiDescriptionFactory.Create(methodInfo: methodInfo, groupName: "v1", httpMethod: "POST", relativePath: "resource"); var filterContext = new OperationFilterContext(apiDescription, null, null, methodInfo); Subject().Apply(operation, filterContext); Assert.Equal("Summary for ActionWithSummaryAndRemarksTags", operation.Summary); Assert.Equal("Remarks for ActionWithSummaryAndRemarksTags", operation.Description); }
public void GetSwagger_SetsDeprecated_IfActionHasObsoleteAttribute() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithObsoleteAttribute), groupName: "v1", httpMethod: "POST", relativePath: "resource"), } ); var document = subject.GetSwagger("v1"); Assert.True(document.Paths["/resource"].Operations[OperationType.Post].Deprecated); }
public void GetSwagger_SetsOperationIdToRouteName_IfActionHasRouteNameMetadata() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithRouteNameMetadata), groupName: "v1", httpMethod: "POST", relativePath: "resource"), } ); var document = subject.GetSwagger("v1"); Assert.Equal("SomeRouteName", document.Paths["/resource"].Operations[OperationType.Post].OperationId); }
public void GetSwagger_SetsOperationIdToNull_ByDefault() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource"), } ); var document = subject.GetSwagger("v1"); Assert.Null(document.Paths["/resource"].Operations[OperationType.Post].OperationId); }
public void GetSwagger_ThrowsUnknownSwaggerDocumentException_IfProvidedDocumentNameNotRegistered() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource"), } ); var exception = Assert.Throws <UnknownSwaggerDocument>(() => subject.GetSwagger("v2")); Assert.Equal( "Unknown Swagger document - \"v2\". Known Swagger documents: \"v1\"", exception.Message); }
public void Apply_SetsSummaryAndDescription_FromActionSummaryAndRemarksTags() { var operation = new OpenApiOperation { Responses = new OpenApiResponses() }; var filterContext = FilterContextFor ( ApiDescriptionFactory.Create <FakeControllerWithXmlComments>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource") ); Subject().Apply(operation, filterContext); Assert.Equal("Summary for ActionWithNoParameters", operation.Summary); Assert.Equal("Remarks for ActionWithNoParameters", operation.Description); }
public void GetSwagger_ThrowsNotSupportedException_IfActionHasNoHttpBinding() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: null, relativePath: "resource") } ); var exception = Assert.Throws <NotSupportedException>(() => subject.GetSwagger("v1")); Assert.Equal( "Ambiguous HTTP method for action - Swashbuckle.AspNetCore.SwaggerGen.Test.FakeController.ActionWithNoParameters (Swashbuckle.AspNetCore.SwaggerGen.Test). " + "Actions require an explicit HttpMethod binding for Swagger/OpenAPI 3.0", exception.Message); }
public void GetSwagger_SupportsOption_SchemaFilters() { var subject = new SwaggerGenerator( new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary <string, OpenApiInfo> { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } } }, new FakeApiDescriptionGroupCollectionProvider(new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithObjectParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new [] { new ApiParameterDescription { Name = "param", Source = BindingSource.Body } }) }), new SchemaGenerator(new SchemaGeneratorOptions { SchemaFilters = new List <ISchemaFilter> { new VendorExtensionsSchemaFilter() } }, new SystemTextJsonBehavior(new JsonSerializerOptions())) ); var document = subject.GetSwagger("v1"); Assert.Equal(2, document.Components.Schemas["XmlAnnotatedType"].Extensions.Count); Assert.Equal("bar", ((OpenApiString)document.Components.Schemas["XmlAnnotatedType"].Extensions["X-foo"]).Value); Assert.Equal("v1", ((OpenApiString)document.Components.Schemas["XmlAnnotatedType"].Extensions["X-docName"]).Value); }
public void GetSwagger_SupportsOption_DescribeAllParametersInCamelCase( string parameterName, string expectedOpenApiParameterName) { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new [] { new ApiParameterDescription { Name = parameterName, Source = BindingSource.Path } }) }, options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary <string, OpenApiInfo> { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } }, DescribeAllParametersInCamelCase = true } ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; Assert.Equal(1, operation.Parameters.Count); Assert.Equal(expectedOpenApiParameterName, operation.Parameters.First().Name); }
public void GetSwagger_SupportsOption_RequestBodyFilters() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithParameter), groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new [] { new ApiParameterDescription { Name = "param", Source = BindingSource.Body } }) }, options: new SwaggerGeneratorOptions { SwaggerDocs = new Dictionary <string, OpenApiInfo> { ["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" } }, RequestBodyFilters = new List <IRequestBodyFilter> { new VendorExtensionsRequestBodyFilter() } } ); var document = subject.GetSwagger("v1"); var operation = document.Paths["/resource"].Operations[OperationType.Post]; Assert.Equal(2, operation.RequestBody.Extensions.Count); Assert.Equal("bar", ((OpenApiString)operation.RequestBody.Extensions["X-foo"]).Value); Assert.Equal("v1", ((OpenApiString)operation.RequestBody.Extensions["X-docName"]).Value); }
public void GetSwagger_ThrowsNotSupportedException_IfActionsHaveConflictingHttpMethodAndPath() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource"), ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithNoParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource") } ); var exception = Assert.Throws <NotSupportedException>(() => subject.GetSwagger("v1")); Assert.Equal( "Conflicting method/path combination \"POST resource\" for actions - " + "Swashbuckle.AspNetCore.SwaggerGen.Test.FakeController.ActionWithNoParameters (Swashbuckle.AspNetCore.SwaggerGen.Test)," + "Swashbuckle.AspNetCore.SwaggerGen.Test.FakeController.ActionWithNoParameters (Swashbuckle.AspNetCore.SwaggerGen.Test). " + "Actions require a unique method/path combination for Swagger/OpenAPI 3.0. Use ConflictingActionsResolver as a workaround", exception.Message); }
public void GetSwagger_GeneratesRequestBody_ForApiParametersThatAreBoundToForm() { var subject = Subject( apiDescriptions: new[] { ApiDescriptionFactory.Create <FakeController>( c => nameof(c.ActionWithMultipleParameters), groupName: "v1", httpMethod: "POST", relativePath: "resource", parameterDescriptions: new [] { new ApiParameterDescription { Name = "param1", Source = BindingSource.Form, }, new ApiParameterDescription { Name = "param2", 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); var mediaType = operation.RequestBody.Content["multipart/form-data"]; Assert.NotNull(mediaType.Schema); Assert.Equal(new[] { "param1", "param2" }, mediaType.Schema.Properties.Keys); Assert.NotNull(mediaType.Encoding); }