Skip to content

Commit d1071ea

Browse files
committed
Add client and swagger doc tests
1 parent ba2ec6b commit d1071ea

20 files changed

+2439
-70
lines changed

Diff for: Directory.Build.props

+1
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@
3131
<MoqVersion>4.16.1</MoqVersion>
3232
<XUnitVersion>2.4.*</XUnitVersion>
3333
<TestSdkVersion>17.0.0</TestSdkVersion>
34+
<BlushingPenguinVersion>1.0.*</BlushingPenguinVersion>
3435
</PropertyGroup>
3536
</Project>

Diff for: src/JsonApiDotNetCore.OpenApi.Client/ApiException.cs

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using JetBrains.Annotations;
4+
5+
// ReSharper disable once CheckNamespace
6+
namespace JsonApiDotNetCore.OpenApi.Client.Exceptions
7+
{
8+
// We cannot rely on a generated ApiException as soon as we are generating multiple clients, see https://github.com/RicoSuter/NSwag/issues/2839#issuecomment-776647377.
9+
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
10+
internal class ApiException : Exception
11+
{
12+
public int StatusCode { get; }
13+
14+
public string Response { get; }
15+
16+
public IReadOnlyDictionary<string, IEnumerable<string>> Headers { get; }
17+
18+
public ApiException(string message, int statusCode, string response, IReadOnlyDictionary<string, IEnumerable<string>> headers, Exception innerException)
19+
: base(
20+
message + "\n\nStatus: " + statusCode + "\nResponse: \n" +
21+
(response == null ? "(null)" : response.Substring(0, response.Length >= 512 ? 512 : response.Length)), innerException)
22+
{
23+
StatusCode = statusCode;
24+
Response = response;
25+
Headers = headers;
26+
}
27+
28+
public override string ToString()
29+
{
30+
return $"HTTP Response: \n\n{Response}\n\n{base.ToString()}";
31+
}
32+
}
33+
34+
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
35+
internal sealed class ApiException<TResult> : ApiException
36+
{
37+
public TResult Result { get; }
38+
39+
public ApiException(string message, int statusCode, string response, IReadOnlyDictionary<string, IEnumerable<string>> headers, TResult result,
40+
Exception innerException)
41+
: base(message, statusCode, response, headers, innerException)
42+
{
43+
Result = result;
44+
}
45+
}
46+
}

Diff for: test/OpenApiClientTests/LegacyClient/ApiResponse.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System;
22
using System.Threading.Tasks;
33
using JsonApiDotNetCore.OpenApi.Client;
4-
using OpenApiClientTests.LegacyClient.GeneratedCode;
4+
using JsonApiDotNetCore.OpenApi.Client.Exceptions;
55

66
#pragma warning disable AV1008 // Class should not be static
77

Diff for: test/OpenApiClientTests/LegacyClient/ResponseTests.cs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Threading.Tasks;
77
using FluentAssertions;
88
using FluentAssertions.Specialized;
9+
using JsonApiDotNetCore.OpenApi.Client.Exceptions;
910
using OpenApiClientTests.LegacyClient.GeneratedCode;
1011
using Xunit;
1112

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using FluentAssertions;
2+
using OpenApiClientTests.NamingConvention.KebabCase.GeneratedCode;
3+
using Xunit;
4+
5+
namespace OpenApiClientTests.NamingConvention.KebabCase
6+
{
7+
public sealed class GeneratedTypesTests
8+
{
9+
[Fact]
10+
public void Generated_code_is_named_as_expected()
11+
{
12+
nameof(KebabCaseClient.GetSupermarketCollectionAsync).Should().NotBeNull();
13+
nameof(KebabCaseClient.GetSupermarketCollectionAsync).Should().NotBeNull();
14+
nameof(KebabCaseClient.PostSupermarketAsync).Should().NotBeNull();
15+
nameof(KebabCaseClient.GetSupermarketAsync).Should().NotBeNull();
16+
nameof(KebabCaseClient.GetSupermarketAsync).Should().NotBeNull();
17+
nameof(KebabCaseClient.PatchSupermarketAsync).Should().NotBeNull();
18+
nameof(KebabCaseClient.DeleteSupermarketAsync).Should().NotBeNull();
19+
nameof(KebabCaseClient.GetSupermarketBackupStoreManagerAsync).Should().NotBeNull();
20+
nameof(KebabCaseClient.GetSupermarketBackupStoreManagerAsync).Should().NotBeNull();
21+
nameof(KebabCaseClient.GetSupermarketBackupStoreManagerRelationshipAsync).Should().NotBeNull();
22+
nameof(KebabCaseClient.GetSupermarketBackupStoreManagerRelationshipAsync).Should().NotBeNull();
23+
nameof(KebabCaseClient.PatchSupermarketBackupStoreManagerRelationshipAsync).Should().NotBeNull();
24+
nameof(KebabCaseClient.GetSupermarketCashiersAsync).Should().NotBeNull();
25+
nameof(KebabCaseClient.GetSupermarketCashiersAsync).Should().NotBeNull();
26+
nameof(KebabCaseClient.GetSupermarketCashiersRelationshipAsync).Should().NotBeNull();
27+
nameof(KebabCaseClient.GetSupermarketCashiersRelationshipAsync).Should().NotBeNull();
28+
nameof(KebabCaseClient.PostSupermarketCashiersRelationshipAsync).Should().NotBeNull();
29+
nameof(KebabCaseClient.PatchSupermarketCashiersRelationshipAsync).Should().NotBeNull();
30+
nameof(KebabCaseClient.DeleteSupermarketCashiersRelationshipAsync).Should().NotBeNull();
31+
nameof(KebabCaseClient.GetSupermarketStoreManagerAsync).Should().NotBeNull();
32+
nameof(KebabCaseClient.GetSupermarketStoreManagerAsync).Should().NotBeNull();
33+
nameof(KebabCaseClient.GetSupermarketStoreManagerRelationshipAsync).Should().NotBeNull();
34+
nameof(KebabCaseClient.GetSupermarketStoreManagerRelationshipAsync).Should().NotBeNull();
35+
nameof(KebabCaseClient.PatchSupermarketStoreManagerRelationshipAsync).Should().NotBeNull();
36+
37+
nameof(SupermarketCollectionResponseDocument).Should().NotBeNull();
38+
nameof(LinksInResourceCollectionDocument).Should().NotBeNull();
39+
nameof(JsonapiObject).Should().NotBeNull();
40+
nameof(SupermarketDataInResponse).Should().NotBeNull();
41+
nameof(SupermarketsResourceType).Should().NotBeNull();
42+
nameof(SupermarketAttributesInResponse.NameOfCity).Should().NotBeNull();
43+
nameof(SupermarketRelationshipsInResponse.StoreManager).Should().NotBeNull();
44+
nameof(SupermarketRelationshipsInResponse.BackupStoreManager).Should().NotBeNull();
45+
nameof(LinksInResourceObject).Should().NotBeNull();
46+
nameof(SupermarketType).Should().NotBeNull();
47+
nameof(KebabCaseClient.GetSupermarketAsync).Should().NotBeNull();
48+
nameof(ToOneStaffMemberInResponse).Should().NotBeNull();
49+
nameof(NullableToOneStaffMemberInResponse).Should().NotBeNull();
50+
nameof(ToManyStaffMemberInResponse).Should().NotBeNull();
51+
nameof(LinksInRelationshipObject).Should().NotBeNull();
52+
nameof(StaffMemberIdentifier).Should().NotBeNull();
53+
nameof(StaffMembersResourceType).Should().NotBeNull();
54+
nameof(StaffMembersResourceType.StaffMembers).Should().NotBeNull();
55+
nameof(SupermarketPrimaryResponseDocument).Should().NotBeNull();
56+
nameof(LinksInResourceDocument).Should().NotBeNull();
57+
nameof(StaffMemberSecondaryResponseDocument).Should().NotBeNull();
58+
nameof(StaffMemberDataInResponse).Should().NotBeNull();
59+
nameof(StaffMemberAttributesInResponse).Should().NotBeNull();
60+
nameof(NullableStaffMemberSecondaryResponseDocument).Should().NotBeNull();
61+
nameof(StaffMemberCollectionResponseDocument).Should().NotBeNull();
62+
nameof(StaffMemberIdentifierResponseDocument).Should().NotBeNull();
63+
nameof(LinksInResourceIdentifierDocument).Should().NotBeNull();
64+
nameof(NullableStaffMemberIdentifierResponseDocument).Should().NotBeNull();
65+
nameof(StaffMemberIdentifierCollectionResponseDocument).Should().NotBeNull();
66+
nameof(LinksInResourceIdentifierCollectionDocument).Should().NotBeNull();
67+
nameof(SupermarketPostRequestDocument).Should().NotBeNull();
68+
nameof(SupermarketDataInPostRequest).Should().NotBeNull();
69+
nameof(SupermarketAttributesInPostRequest).Should().NotBeNull();
70+
nameof(SupermarketRelationshipsInPostRequest).Should().NotBeNull();
71+
nameof(ToOneStaffMemberInRequest).Should().NotBeNull();
72+
nameof(NullableToOneStaffMemberInRequest).Should().NotBeNull();
73+
nameof(ToManyStaffMemberInRequest).Should().NotBeNull();
74+
nameof(SupermarketPatchRequestDocument).Should().NotBeNull();
75+
nameof(SupermarketDataInPatchRequest).Should().NotBeNull();
76+
nameof(SupermarketAttributesInPatchRequest).Should().NotBeNull();
77+
nameof(SupermarketRelationshipsInPatchRequest).Should().NotBeNull();
78+
}
79+
}
80+
}

Diff for: test/OpenApiClientTests/OpenApiClientTests.csproj

+39-31
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,57 @@
11
<Project Sdk="Microsoft.NET.Sdk">
2-
<PropertyGroup>
3-
<TargetFramework>$(NetCoreAppVersion)</TargetFramework>
4-
</PropertyGroup>
2+
<PropertyGroup>
3+
<TargetFramework>$(NetCoreAppVersion)</TargetFramework>
4+
</PropertyGroup>
55

66
<ItemGroup>
77
<ProjectReference Include="..\..\src\JsonApiDotNetCore.OpenApi.Client\JsonApiDotNetCore.OpenApi.Client.csproj" />
8+
<ProjectReference Include="..\OpenApiTests\OpenApiTests.csproj" />
89
<ProjectReference Include="..\TestBuildingBlocks\TestBuildingBlocks.csproj" />
910
</ItemGroup>
1011

11-
<ItemGroup>
12-
<PackageReference Include="coverlet.collector" Version="$(CoverletVersion)" PrivateAssets="All" />
13-
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="$(AspNetCoreVersion)" />
14-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
15-
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
16-
<PackageReference Include="NSwag.ApiDescription.Client" Version="13.10.9">
17-
<PrivateAssets>all</PrivateAssets>
18-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
19-
</PackageReference>
20-
<PackageReference Include="Microsoft.Extensions.ApiDescription.Client" Version="5.0.9">
21-
<PrivateAssets>all</PrivateAssets>
22-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
23-
</PackageReference>
24-
<PackageReference Include="NSwag.ApiDescription.Client" Version="13.13.2">
25-
<PrivateAssets>all</PrivateAssets>
26-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
27-
</PackageReference>
28-
</ItemGroup>
12+
<ItemGroup>
13+
<PackageReference Include="coverlet.collector" Version="$(CoverletVersion)" PrivateAssets="All" />
14+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="$(AspNetCoreVersion)" />
15+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
16+
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
17+
<PackageReference Include="NSwag.ApiDescription.Client" Version="13.10.9">
18+
<PrivateAssets>all</PrivateAssets>
19+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
20+
</PackageReference>
21+
<PackageReference Include="Microsoft.Extensions.ApiDescription.Client" Version="5.0.9">
22+
<PrivateAssets>all</PrivateAssets>
23+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
24+
</PackageReference>
25+
<PackageReference Include="NSwag.ApiDescription.Client" Version="13.13.2">
26+
<PrivateAssets>all</PrivateAssets>
27+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
28+
</PackageReference>
29+
</ItemGroup>
2930

3031
<ItemGroup>
3132
<OpenApiReference Include="..\OpenApiTests\LegacyOpenApiIntegration\swagger.json">
3233
<Namespace>OpenApiClientTests.LegacyClient.GeneratedCode</Namespace>
3334
<ClassName>OpenApiClient</ClassName>
35+
<OutputPath>OpenApiClient.cs</OutputPath>
3436
<CodeGenerator>NSwagCSharp</CodeGenerator>
35-
<Options>/UseBaseUrl:false /GenerateClientInterfaces:true /ClientClassAccessModifier:internal</Options>
37+
<Options>/UseBaseUrl:false /GenerateClientInterfaces:true /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.Exceptions</Options>
3638
</OpenApiReference>
3739
</ItemGroup>
3840

39-
<ItemGroup>
40-
<EmbeddedResource Include="..\OpenApiTests\LegacyOpenApiIntegration\swagger.json" />
41-
</ItemGroup>
41+
<ItemGroup>
42+
<OpenApiReference Include="..\OpenApiTests\NamingConvention\KebabCase\swagger.json">
43+
<Namespace>OpenApiClientTests.NamingConvention.KebabCase.GeneratedCode</Namespace>
44+
<ClassName>KebabCaseClient</ClassName>
45+
<OutputPath>KebabCaseClient.cs</OutputPath>
46+
<CodeGenerator>NSwagCSharp</CodeGenerator>
47+
<Options>/UseBaseUrl:false /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.Exceptions</Options>
48+
</OpenApiReference>
49+
</ItemGroup>
4250

43-
<!-- Fixes IntelliSense errors on openapi.json in Visual Studio 2019, which uses the schema for OpenAPI 3.1 by default. -->
44-
<ProjectExtensions>
45-
<VisualStudio>
46-
<UserProperties swagger_1json__JsonSchema="https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.0/schema.json" />
47-
</VisualStudio>
48-
</ProjectExtensions>
51+
<!-- Fixes IntelliSense errors on openapi.json in Visual Studio 2019, which uses the schema for OpenAPI 3.1 by default. -->
52+
<ProjectExtensions>
53+
<VisualStudio>
54+
<UserProperties swagger_1json__JsonSchema="https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.0/schema.json" />
55+
</VisualStudio>
56+
</ProjectExtensions>
4957
</Project>

Diff for: test/OpenApiTests/LegacyOpenApiIntegration/LegacyOpenApiIntegrationTests.cs

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public LegacyOpenApiIntegrationTests()
1919
UseController<FlightAttendantsController>();
2020
}
2121

22+
// TODO: This test fails when all tests are openapi tests run in parallel; something isn't going right with the fixtures.
2223
[Fact]
2324
public async Task Retrieved_document_matches_expected_document()
2425
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System.Text.Json.Serialization;
2+
using JetBrains.Annotations;
3+
using JsonApiDotNetCore.Configuration;
4+
using Microsoft.EntityFrameworkCore;
5+
using OpenApiTests.LegacyOpenApiIntegration;
6+
7+
namespace OpenApiTests.NamingConventions.KebabCase
8+
{
9+
[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)]
10+
public sealed class KebabCaseNamingConventionStartup<TDbContext> : OpenApiStartup<TDbContext>
11+
where TDbContext : DbContext
12+
{
13+
protected override void SetJsonApiOptions(JsonApiOptions options)
14+
{
15+
base.SetJsonApiOptions(options);
16+
17+
options.SerializerOptions.PropertyNamingPolicy = JsonKebabCaseNamingPolicy.Instance;
18+
options.SerializerOptions.DictionaryKeyPolicy = JsonKebabCaseNamingPolicy.Instance;
19+
options.SerializerOptions.Converters.Add(new JsonStringEnumConverter());
20+
}
21+
}
22+
}

0 commit comments

Comments
 (0)