Skip to content

Commit

Permalink
Merge pull request #157 from bit-foundation/feature/#150
Browse files Browse the repository at this point in the history
Several enhancements to Swashbuckle.OData
  • Loading branch information
rbeauchamp authored Sep 15, 2017
2 parents af55e1d + b263453 commit 6bb17b2
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 18 deletions.
115 changes: 115 additions & 0 deletions Swashbuckle.OData.Tests/Fixtures/GlobalEnableQueryTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.OData;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
using System.Web.OData.Query;
using FluentAssertions;
using Microsoft.OData.Edm;
using Microsoft.Owin.Hosting;
using NUnit.Framework;
using Owin;
using Swashbuckle.Swagger;
using System.Web.Http.Description;

namespace Swashbuckle.OData.Tests
{
/// <summary>
/// Tests the scenario where developer adds EnableQuery globally.
/// </summary>
[TestFixture]
public class GlobalEnableQueryTests
{
[Test]
public async Task It_Finds_Global_Enable_Query_AndReturn_Swagger_Doc_With_OData_Standard_Parameters()
{
using (WebApp.Start(HttpClientUtils.BaseAddress, appBuilder => Configuration(appBuilder, typeof(Customer1Controller))))
{
// Arrange
var httpClient = HttpClientUtils.GetHttpClient(HttpClientUtils.BaseAddress);

// Verify that the OData route in the test controller is valid
var customers = await httpClient.GetJsonAsync<ODataResponse<List<Customer1>>>("/odata/Customer1/Default.GetSomeCustomers()");
customers.Should().NotBeNull();

var number = await httpClient.GetJsonAsync<ODataResponse<int>>("/odata/Customer1/Default.GetSomeNumber()");
customers.Should().NotBeNull();

// Act
var swaggerDocument = await httpClient.GetJsonAsync<SwaggerDocument>("swagger/docs/v1");

// Assert
PathItem getCustomersPathItem;
swaggerDocument.paths.TryGetValue("/odata/Customer1/Default.GetSomeCustomers()", out getCustomersPathItem);
getCustomersPathItem.Should().NotBeNull();
getCustomersPathItem.get.Should().NotBeNull();
Assert.IsTrue(getCustomersPathItem.get.parameters.Any(p => p.name == "$filter"));

PathItem getSomeNumber;
swaggerDocument.paths.TryGetValue("/odata/Customer1/Default.GetSomeNumber()", out getSomeNumber);
getSomeNumber.Should().NotBeNull();
getSomeNumber.get.Should().NotBeNull();
Assert.IsTrue(getSomeNumber.get.parameters == null);

await ValidationUtils.ValidateSwaggerJson();
}
}

private void Configuration(IAppBuilder appBuilder, Type targetController)
{
var config = appBuilder.GetStandardHttpConfig(targetController);

config.MapODataServiceRoute("ODataRoute", "odata", GetEdmModel());

config.AddODataQueryFilter();
config.Filters.Add(new EnableQueryAttribute { });

config.EnsureInitialized();
}

private IEdmModel GetEdmModel()
{
ODataModelBuilder builder = new ODataConventionModelBuilder();

var customers = builder.EntitySet<Customer1>("Customer1");

var getSomeCustomers = customers.EntityType.Collection.Function("GetSomeCustomers");
getSomeCustomers.ReturnsCollectionFromEntitySet<Customer1>("Customer1");

var getSomeNumber = customers.EntityType.Collection.Function("GetSomeNumber");
getSomeNumber.Returns<int>();

return builder.GetEdmModel();
}
}

public class Customer1
{
[Key]
public int Id { get; set; }

public string Name { get; set; }
}

public class Customer1Controller : ODataController
{
[HttpGet]
[ResponseType(typeof(List<Customer1>))]
public IHttpActionResult GetSomeCustomers()
{
return Ok(Enumerable.Empty<Customer1>());
}

[HttpGet]
[ResponseType(typeof(int))]
public IHttpActionResult GetSomeNumber()
{
return Ok(0);
}
}
}
15 changes: 11 additions & 4 deletions Swashbuckle.OData.Tests/Swashbuckle.OData.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\NUnit3TestAdapter.3.8.0\build\net35\NUnit3TestAdapter.props" Condition="Exists('..\packages\NUnit3TestAdapter.3.8.0\build\net35\NUnit3TestAdapter.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
Expand Down Expand Up @@ -103,9 +104,8 @@
<HintPath>..\packages\Newtonsoft.Json.Schema.2.0.12\lib\net45\Newtonsoft.Json.Schema.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="nunit.framework, Version=3.6.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.6.1\lib\net45\nunit.framework.dll</HintPath>
<Private>True</Private>
<Reference Include="nunit.framework, Version=3.7.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
Expand Down Expand Up @@ -159,6 +159,7 @@
<Compile Include="Containment\ODataModels.cs" />
<Compile Include="Containment\Program.cs" />
<Compile Include="ContentType.cs" />
<Compile Include="Fixtures\GlobalEnableQueryTests.cs" />
<Compile Include="Fixtures\SummaryTests.cs" />
<Compile Include="Fixtures\ParameterTests\DecimalParameterAndResponseTests.cs" />
<Compile Include="Fixtures\ModelSharedBetweenODataAndWebApiTests.cs" />
Expand Down Expand Up @@ -237,11 +238,17 @@
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\NUnit3TestAdapter.3.8.0\build\net35\NUnit3TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NUnit3TestAdapter.3.8.0\build\net35\NUnit3TestAdapter.props'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
15 changes: 8 additions & 7 deletions Swashbuckle.OData.Tests/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@
<package id="NETStandard.Library" version="1.6.1" targetFramework="net452" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net452" />
<package id="Newtonsoft.Json.Schema" version="2.0.12" targetFramework="net452" />
<package id="NUnit" version="3.6.1" targetFramework="net452" />
<package id="NUnit.ConsoleRunner" version="3.6.1" targetFramework="net452" />
<package id="NUnit.Extension.NUnitProjectLoader" version="3.5.0" targetFramework="net452" />
<package id="NUnit.Extension.NUnitV2Driver" version="3.6.0" targetFramework="net452" />
<package id="NUnit.Extension.NUnitV2ResultWriter" version="3.5.0" targetFramework="net452" />
<package id="NUnit" version="3.7.1" targetFramework="net452" />
<package id="NUnit.ConsoleRunner" version="3.7.0" targetFramework="net452" />
<package id="NUnit.Extension.NUnitProjectLoader" version="3.6.0" targetFramework="net452" />
<package id="NUnit.Extension.NUnitV2Driver" version="3.7.0" targetFramework="net452" />
<package id="NUnit.Extension.NUnitV2ResultWriter" version="3.6.0" targetFramework="net452" />
<package id="NUnit.Extension.TeamCityEventListener" version="1.0.2" targetFramework="net452" />
<package id="NUnit.Extension.VSProjectLoader" version="3.5.0" targetFramework="net452" />
<package id="NUnit.Runners" version="3.6.1" targetFramework="net452" />
<package id="NUnit.Extension.VSProjectLoader" version="3.6.0" targetFramework="net452" />
<package id="NUnit.Runners" version="3.7.0" targetFramework="net452" />
<package id="NUnit3TestAdapter" version="3.8.0" targetFramework="net452" />
<package id="OpenCover" version="4.6.519" targetFramework="net452" />
<package id="Owin" version="1.0" targetFramework="net452" />
<package id="ReportGenerator" version="2.5.8" targetFramework="net452" />
Expand Down
3 changes: 2 additions & 1 deletion Swashbuckle.OData/Descriptions/MapToODataActionParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public HttpParameterDescriptor Map(Parameter swaggerParameter, int parameterInde
if (swaggerParameter.@in == "body" && swaggerParameter.schema != null && swaggerParameter.schema.type == "object")
{
var odataActionParametersDescriptor = actionDescriptor.GetParameters().SingleOrDefault(descriptor => descriptor.ParameterType == typeof (ODataActionParameters));
Contract.Assume(odataActionParametersDescriptor != null);
if (odataActionParametersDescriptor == null)
return null;
return new ODataActionParameterDescriptor(odataActionParametersDescriptor.ParameterName, typeof(ODataActionParameters), !required.Value, swaggerParameter.schema, odataActionParametersDescriptor)
{
Configuration = actionDescriptor.ControllerDescriptor.Configuration,
Expand Down
4 changes: 2 additions & 2 deletions Swashbuckle.OData/Descriptions/TypeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ internal static Type GetInnerElementType(this Type type)

internal static bool IsCollection(this Type type)
{
Contract.Requires(type != null);

if (type == null)
return false;
Type elementType;
return type.IsCollection(out elementType);
}
Expand Down
9 changes: 8 additions & 1 deletion Swashbuckle.OData/EnableQueryFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
using Swashbuckle.OData.Descriptions;
using Swashbuckle.Swagger;
using System;
using System.Web.Http.Filters;
using System.Collections;
using System.Web.Http;

namespace Swashbuckle.OData
{
Expand Down Expand Up @@ -37,7 +40,11 @@ private static bool HasEnableQueryAttribute(ApiDescription apiDescription)
{
var httpActionDescriptor = apiDescription.ActionDescriptor;
Contract.Assume(httpActionDescriptor != null);
return httpActionDescriptor.GetCustomAttributes<EnableQueryAttribute>().Any();
return httpActionDescriptor.GetCustomAttributes<EnableQueryAttribute>().Any() ||
(ReturnsCollection(apiDescription) && httpActionDescriptor.GetFilterPipeline()
.Select(f => f.Instance)
.OfType<ActionFilterAttribute>()
.Any(f => f.TypeId is Type && typeof(EnableQueryAttribute).IsAssignableFrom((Type)f.TypeId)));
}

private static bool ReturnsCollection(ApiDescription apiDescription)
Expand Down
4 changes: 2 additions & 2 deletions Swashbuckle.OData/Swashbuckle.OData.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;CONTRACTS_FULL</DefineConstants>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
<CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
<CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
<CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
<CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ environment:
secure: EFTW/YldlkfUPVuAZTbv09gYi8MtEbZ6WZ6AU23f5Bg9BuCPN8wMAZxvOzycWGvK

after_test:
- packages\OpenCover.4.6.519\tools\OpenCover.Console.exe -register:user -filter:"+[Swashbuckle.OData]* -[Swashbuckle.OData]System.*" -target:"packages\NUnit.ConsoleRunner.3.6.1\tools\nunit3-console.exe" -targetargs:"/noshadow /domain:single Swashbuckle.OData.Tests\bin\Debug\Swashbuckle.OData.Tests.dll" -output:coverage.xml
- packages\OpenCover.4.6.519\tools\OpenCover.Console.exe -register:user -filter:"+[Swashbuckle.OData]* -[Swashbuckle.OData]System.*" -target:"packages\NUnit.ConsoleRunner.3.7.0\tools\nunit3-console.exe" -targetargs:"/noshadow /domain:single Swashbuckle.OData.Tests\bin\Debug\Swashbuckle.OData.Tests.dll" -output:coverage.xml
- packages\coveralls.io.1.3.4\tools\coveralls.net.exe --opencover coverage.xml

deploy:
Expand Down

0 comments on commit 6bb17b2

Please sign in to comment.