diff --git a/docs/usage/openapi-client.md b/docs/usage/openapi-client.md index a956e77d1c..8f97ec090c 100644 --- a/docs/usage/openapi-client.md +++ b/docs/usage/openapi-client.md @@ -7,7 +7,7 @@ After [enabling OpenAPI](~/usage/openapi.md), you can generate a typed JSON:API > [client libraries](https://jsonapi.org/implementations/#client-libraries). The following code generators are supported, though you may try others as well: -- [NSwag](https://github.com/RicoSuter/NSwag): Produces clients for C# and TypeScript +- [NSwag](https://github.com/RicoSuter/NSwag) (v14.1 or higher): Produces clients for C# and TypeScript - [Kiota](https://learn.microsoft.com/en-us/openapi/kiota/overview): Produces clients for C#, Go, Java, PHP, Python, Ruby, Swift and TypeScript # [NSwag](#tab/nswag) @@ -39,11 +39,11 @@ To generate your C# client, follow the steps below. ### Visual Studio The easiest way to get started is by using the built-in capabilities of Visual Studio. -The following steps describe how to generate and use a JSON:API client in C#, using our package. +The following steps describe how to generate and use a JSON:API client in C#, combined with our NuGet package. 1. In **Solution Explorer**, right-click your client project, select **Add** > **Service Reference** and choose **OpenAPI**. -2. On the next page, specify the OpenAPI URL to your JSON:API server, for example: `http://localhost:14140/swagger/v1/swagger.json`. +1. On the next page, specify the OpenAPI URL to your JSON:API server, for example: `http://localhost:14140/swagger/v1/swagger.json`. Specify `ExampleApiClient` as the class name, optionally provide a namespace and click **Finish**. Visual Studio now downloads your swagger.json and updates your project file. This adds a pre-build step that generates the client code. @@ -52,25 +52,15 @@ The following steps describe how to generate and use a JSON:API client in C#, us > To later re-download swagger.json and regenerate the client code, > right-click **Dependencies** > **Manage Connected Services** and click the **Refresh** icon. -3. Although not strictly required, we recommend running package update now, which fixes some issues. +1. Run package update now, which fixes incompatibilities and bugs from older versions. - > [!WARNING] - > NSwag v14 is currently *incompatible* with JsonApiDotNetCore (tracked [here](https://github.com/RicoSuter/NSwag/issues/4662)). - > Stick with v13.x for the moment. - -4. Add our client package to your project: +1. Add our client package to your project: ``` dotnet add package JsonApiDotNetCore.OpenApi.Client.NSwag ``` -5. Add the following line inside the **OpenApiReference** section in your project file: - - ```xml - /GenerateExceptionClasses:false /GenerateNullableReferenceTypes:true /GenerateOptionalPropertiesAsNullable:true /GenerateOptionalParameters:true /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag - ``` - -6. Add the following glue code to connect our package with your generated code. +1. Add the following glue code to connect our package with your generated code. > [!NOTE] > The class name must be the same as specified in step 2. @@ -83,14 +73,15 @@ The following steps describe how to generate and use a JSON:API client in C#, us partial class ExampleApiClient : JsonApiClient { - partial void UpdateJsonSerializerSettings(JsonSerializerSettings settings) + partial void Initialize() { - SetSerializerSettingsForJsonApi(settings); + _instanceSettings = new JsonSerializerSettings(_settings.Value); + SetSerializerSettingsForJsonApi(_instanceSettings); } } ``` -7. Add code that calls one of your JSON:API endpoints. +1. Add code that calls one of your JSON:API endpoints. ```c# using var httpClient = new HttpClient(); @@ -101,7 +92,7 @@ The following steps describe how to generate and use a JSON:API client in C#, us ["filter"] = "has(assignedTodoItems)", ["sort"] = "-lastName", ["page[size]"] = "5" - }, null); + }); foreach (var person in getResponse.Data) { @@ -109,7 +100,7 @@ The following steps describe how to generate and use a JSON:API client in C#, us } ``` -8. Extend your demo code to send a partial PATCH request with the help of our package: +1. Extend the demo code to send a partial PATCH request with the help of our package: ```c# var updatePersonRequest = new UpdatePersonRequestDocument @@ -163,16 +154,15 @@ Alternatively, the following section shows what to add to your client project fi - + http://localhost:14140/swagger/v1/swagger.json - NSwagCSharp - ExampleApiClient - ExampleApiClient.cs - /GenerateExceptionClasses:false /GenerateNullableReferenceTypes:true /GenerateOptionalPropertiesAsNullable:true /GenerateOptionalParameters:true /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag + NSwagCSharp + ExampleApiClient + ExampleApiClient.cs ``` @@ -203,23 +193,24 @@ Various switches enable you to tweak the client generation to your needs. See th # [NSwag](#tab/nswag) -The `OpenApiReference` element in the project file accepts an `Options` element to pass additional settings to the client generator, -which are listed [here](https://github.com/RicoSuter/NSwag/blob/master/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToCSharpClientCommand.cs). -A guide with common best practices is available [here](https://stevetalkscode.co.uk/openapireference-commands). +The `OpenApiReference` can be customized using various [NSwag-specific MSBuild properties](https://github.com/RicoSuter/NSwag/blob/7d6df3af95081f3f0ed6dee04be8d27faa86f91a/src/NSwag.ApiDescription.Client/NSwag.ApiDescription.Client.props). +See [the source code](https://github.com/RicoSuter/NSwag/blob/master/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToCSharpClientCommand.cs) for their meaning. -For example, the following section puts the generated code in a namespace and generates an interface (which is handy for dependency injection): +> [!NOTE] +> Earlier versions of NSwag required the use of `` to specify command-line switches directly. +> This is no longer recommended and may conflict with the new MSBuild properties. + +For example, the following section puts the generated code in a namespace and generates an interface (handy when writing tests): ```xml ExampleProject.GeneratedCode SalesApiClient NSwagCSharp - /GenerateClientInterfaces:true + true ``` -Likewise, you can enable nullable reference types by adding `/GenerateNullableReferenceTypes:true /GenerateOptionalPropertiesAsNullable:true /GenerateOptionalParameters:true`. - # [Kiota](#tab/kiota) The available command-line switches for Kiota are described [here](https://learn.microsoft.com/en-us/openapi/kiota/using#client-generation). @@ -257,10 +248,10 @@ The use of HTTP headers varies per client generator. To use [ETags for caching]( # [NSwag](#tab/nswag) -NSwag needs extra settings to make response headers accessible. Specify the following in the `` element of your project file: +To gain access to HTTP response headers, add the following in a `PropertyGroup` or directly in the `OpenApiReference`: ``` -/GenerateExceptionClasses:false /WrapResponses:true /GenerateResponseClasses:false /ResponseClass:ApiResponse /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag +true ``` This enables the following code, which is explained below: @@ -272,7 +263,7 @@ Console.WriteLine($"Retrieved {getResponse.Result?.Data.Count ?? 0} people."); // wait some time... -getResponse = await ApiResponse.TranslateAsync(() => apiClient.GetPersonCollectionAsync(null, eTag)); +getResponse = await ApiResponse.TranslateAsync(() => apiClient.GetPersonCollectionAsync(if_None_Match: eTag)); if (getResponse is { StatusCode: (int)HttpStatusCode.NotModified, Result: null }) { @@ -287,7 +278,7 @@ If you only want to ask whether data has changed without fetching it, use a HEAD # [Kiota](#tab/kiota) -Use `HeadersInspectionHandlerOption` to gain access to response headers. For example: +Use `HeadersInspectionHandlerOption` to gain access to HTTP response headers. For example: ```c# var headerInspector = new HeadersInspectionHandlerOption diff --git a/package-versions.props b/package-versions.props index 5368c47ce0..b5cb4ced38 100644 --- a/package-versions.props +++ b/package-versions.props @@ -20,7 +20,7 @@ 2.0.* 1.* 8.0.* - 13.20.* + 14.1.* 13.0.* 8.0.* 6.*-* diff --git a/src/Examples/OpenApiNSwagClientExample/ExampleApiClient.cs b/src/Examples/OpenApiNSwagClientExample/ExampleApiClient.cs index c60fb8f50f..3937bd915e 100644 --- a/src/Examples/OpenApiNSwagClientExample/ExampleApiClient.cs +++ b/src/Examples/OpenApiNSwagClientExample/ExampleApiClient.cs @@ -7,12 +7,14 @@ namespace OpenApiNSwagClientExample; [UsedImplicitly(ImplicitUseTargetFlags.Itself)] public partial class ExampleApiClient : JsonApiClient { - partial void UpdateJsonSerializerSettings(JsonSerializerSettings settings) + partial void Initialize() { - SetSerializerSettingsForJsonApi(settings); + _instanceSettings = new JsonSerializerSettings(_settings.Value); #if DEBUG - settings.Formatting = Formatting.Indented; + _instanceSettings.Formatting = Formatting.Indented; #endif + + SetSerializerSettingsForJsonApi(_instanceSettings); } } diff --git a/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj b/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj index 942fc78c36..8485aa8c4e 100644 --- a/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj +++ b/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj @@ -5,6 +5,7 @@ + @@ -20,11 +21,11 @@ - OpenApiNSwagClientExample - ExampleApiClient - ExampleApiClient.cs - NSwagCSharp - /GenerateExceptionClasses:false /WrapResponses:true /GenerateResponseClasses:false /ResponseClass:ApiResponse /GenerateNullableReferenceTypes:true /GenerateOptionalPropertiesAsNullable:true /GenerateOptionalParameters:true /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag + ExampleApi + $(MSBuildProjectName) + %(Name)Client + %(ClassName).cs + true diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Build/JsonApiDotNetCore.OpenApi.Client.NSwag.props b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Build/JsonApiDotNetCore.OpenApi.Client.NSwag.props new file mode 100644 index 0000000000..879d38d152 --- /dev/null +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/Build/JsonApiDotNetCore.OpenApi.Client.NSwag.props @@ -0,0 +1,12 @@ + + + NSwagCSharp + false + false + ApiResponse + JsonApiDotNetCore.OpenApi.Client.NSwag + true + true + true + + diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/JsonApiDotNetCore.OpenApi.Client.NSwag.csproj b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/JsonApiDotNetCore.OpenApi.Client.NSwag.csproj index 6dab137594..912bea71d1 100644 --- a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/JsonApiDotNetCore.OpenApi.Client.NSwag.csproj +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/JsonApiDotNetCore.OpenApi.Client.NSwag.csproj @@ -27,6 +27,7 @@ + diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/NullableToOneRelationshipInResponse.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/NullableToOneRelationshipInResponse.cs index f39dee77b3..400edf780a 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/NullableToOneRelationshipInResponse.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/NullableToOneRelationshipInResponse.cs @@ -1,4 +1,3 @@ -using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JetBrains.Annotations; using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; @@ -15,7 +14,7 @@ internal sealed class NullableToOneRelationshipInResponse [JsonPropertyName("links")] public RelationshipLinks Links { get; set; } = null!; - [Required] + // Non-required because related data may not be included in the response. [JsonPropertyName("data")] public ResourceIdentifierInResponse? Data { get; set; } diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToManyRelationshipInResponse.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToManyRelationshipInResponse.cs index aeef460b87..fb7ca5a751 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToManyRelationshipInResponse.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToManyRelationshipInResponse.cs @@ -1,4 +1,3 @@ -using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JetBrains.Annotations; using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; @@ -15,7 +14,7 @@ internal sealed class ToManyRelationshipInResponse [JsonPropertyName("links")] public RelationshipLinks Links { get; set; } = null!; - [Required] + // Non-required because related data may not be included in the response. [JsonPropertyName("data")] public ICollection> Data { get; set; } = null!; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToOneRelationshipInResponse.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToOneRelationshipInResponse.cs index 97be8b3c7a..1232129942 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToOneRelationshipInResponse.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiObjects/Relationships/ToOneRelationshipInResponse.cs @@ -1,4 +1,3 @@ -using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JetBrains.Annotations; using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Links; @@ -15,7 +14,7 @@ internal sealed class ToOneRelationshipInResponse [JsonPropertyName("links")] public RelationshipLinks Links { get; set; } = null!; - [Required] + // Non-required because related data may not be included in the response. [JsonPropertyName("data")] public ResourceIdentifierInResponse Data { get; set; } = null!; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs index fd57d53752..c987c662c5 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs @@ -540,7 +540,7 @@ private static void AddQueryStringParameters(OpenApiOperation operation, bool is // The next best thing is to expose the query string parameters as unstructured and optional. // - This makes SwaggerUI ask for JSON, which is a bit odd, but it works. For example: {"sort":"-id"} produces: ?sort=-id // - This makes NSwag produce a C# client with method signature: GetAsync(IDictionary? query) - // when combined with /GenerateNullableReferenceTypes:true in the project file. + // when combined with true in the project file. operation.Parameters.Add(new OpenApiParameter { diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceFieldSchemaBuilder.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceFieldSchemaBuilder.cs index bf9bd68dd3..921c19ea98 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceFieldSchemaBuilder.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceFieldSchemaBuilder.cs @@ -207,8 +207,6 @@ private OpenApiSchema CreateReferenceSchemaForRelationship(Type relationshipSche if (JsonApiSchemaFacts.IsRelationshipInResponseType(relationshipSchemaType)) { _linksVisibilitySchemaGenerator.UpdateSchemaForRelationship(relationshipSchemaType, fullSchema, schemaRepository); - - fullSchema.Required.Remove(JsonApiPropertyName.Data); } return referenceSchema; diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicCreateResourceTests.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicCreateResourceTests.cs index 10d3e95454..ce60d788c8 100644 --- a/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicCreateResourceTests.cs +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicCreateResourceTests.cs @@ -69,7 +69,8 @@ public async Task Can_create_resource_with_attributes() response.AtomicResults.ShouldHaveCount(1); TeacherDataInResponse teacherDataInResponse = response.AtomicResults.ElementAt(0).Data.Should().BeOfType().Which; - teacherDataInResponse.Attributes!.Name.Should().Be(newTeacher.Name); + teacherDataInResponse.Attributes.ShouldNotBeNull(); + teacherDataInResponse.Attributes.Name.Should().Be(newTeacher.Name); teacherDataInResponse.Attributes.EmailAddress.Should().Be(newTeacher.EmailAddress); long newTeacherId = long.Parse(teacherDataInResponse.Id!); @@ -147,7 +148,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => response.AtomicResults.ShouldHaveCount(1); EnrollmentDataInResponse enrollmentDataInResponse = response.AtomicResults.ElementAt(0).Data.Should().BeOfType().Which; - enrollmentDataInResponse.Attributes!.EnrolledAt.Should().Be((Date)newEnrollment.EnrolledAt); + enrollmentDataInResponse.Attributes.ShouldNotBeNull(); + enrollmentDataInResponse.Attributes.EnrolledAt.Should().Be((Date)newEnrollment.EnrolledAt); enrollmentDataInResponse.Attributes.GraduatedAt.Should().BeNull(); enrollmentDataInResponse.Attributes.HasGraduated.Should().BeFalse(); diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicLocalIdTests.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicLocalIdTests.cs index ce00ca78ee..39b59a519c 100644 --- a/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicLocalIdTests.cs +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicLocalIdTests.cs @@ -180,7 +180,8 @@ public async Task Can_use_local_IDs() response.AtomicResults.ShouldHaveCount(7); TeacherDataInResponse teacherInResponse = response.AtomicResults.ElementAt(0).Data.Should().BeOfType().Which; - teacherInResponse.Attributes!.Name.Should().Be(newTeacher.Name); + teacherInResponse.Attributes.ShouldNotBeNull(); + teacherInResponse.Attributes.Name.Should().Be(newTeacher.Name); teacherInResponse.Attributes.EmailAddress.Should().Be(newTeacher.EmailAddress); long newTeacherId = long.Parse(teacherInResponse.Id!); @@ -188,12 +189,14 @@ public async Task Can_use_local_IDs() response.AtomicResults.ElementAt(2).Data.Should().BeNull(); StudentDataInResponse studentInResponse = response.AtomicResults.ElementAt(3).Data.Should().BeOfType().Which; - studentInResponse.Attributes!.Name.Should().Be(newStudent.Name); + studentInResponse.Attributes.ShouldNotBeNull(); + studentInResponse.Attributes.Name.Should().Be(newStudent.Name); studentInResponse.Attributes.EmailAddress.Should().Be(newStudent.EmailAddress); long newStudentId = long.Parse(studentInResponse.Id!); EnrollmentDataInResponse enrollmentInResponse = response.AtomicResults.ElementAt(4).Data.Should().BeOfType().Which; - enrollmentInResponse.Attributes!.EnrolledAt.Should().Be((Date)newEnrolledAt); + enrollmentInResponse.Attributes.ShouldNotBeNull(); + enrollmentInResponse.Attributes.EnrolledAt.Should().Be((Date)newEnrolledAt); long newEnrollmentId = long.Parse(enrollmentInResponse.Id!); response.AtomicResults.ElementAt(5).Data.Should().BeNull(); diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicUpdateResourceTests.cs b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicUpdateResourceTests.cs index d31eecdcce..98ecc18209 100644 --- a/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicUpdateResourceTests.cs +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/AtomicUpdateResourceTests.cs @@ -85,7 +85,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => StudentDataInResponse studentDataInResponse = response.AtomicResults.ElementAt(0).Data.Should().BeOfType().Which; studentDataInResponse.Id.Should().Be(existingStudent.StringId); - studentDataInResponse.Attributes!.Name.Should().Be(newName); + studentDataInResponse.Attributes.ShouldNotBeNull(); + studentDataInResponse.Attributes.Name.Should().Be(newName); studentDataInResponse.Attributes.EmailAddress.Should().Be(newEmailAddress); await _testContext.RunOnDatabaseAsync(async dbContext => @@ -148,7 +149,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => StudentDataInResponse studentDataInResponse = response.AtomicResults.ElementAt(0).Data.Should().BeOfType().Which; studentDataInResponse.Id.Should().Be(existingStudent.StringId); - studentDataInResponse.Attributes!.Name.Should().Be(existingStudent.Name); + studentDataInResponse.Attributes.ShouldNotBeNull(); + studentDataInResponse.Attributes.Name.Should().Be(existingStudent.Name); studentDataInResponse.Attributes.EmailAddress.Should().Be(newEmailAddress); await _testContext.RunOnDatabaseAsync(async dbContext => @@ -230,7 +232,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => EnrollmentDataInResponse enrollmentDataInResponse = response.AtomicResults.ElementAt(0).Data.Should().BeOfType().Which; enrollmentDataInResponse.Id.Should().Be(existingEnrollment.StringId); - enrollmentDataInResponse.Attributes!.EnrolledAt.Should().Be((Date)newEnrolledAt); + enrollmentDataInResponse.Attributes.ShouldNotBeNull(); + enrollmentDataInResponse.Attributes.EnrolledAt.Should().Be((Date)newEnrolledAt); enrollmentDataInResponse.Attributes.GraduatedAt.Should().Be((Date)existingEnrollment.GraduatedAt!.Value); enrollmentDataInResponse.Attributes.HasGraduated.Should().Be(existingEnrollment.HasGraduated); diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/FilterTests.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/FilterTests.cs index 69aac23c51..f05ef34232 100644 --- a/test/OpenApiKiotaEndToEndTests/QueryStrings/FilterTests.cs +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/FilterTests.cs @@ -57,8 +57,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => response.ShouldNotBeNull(); response.Data.ShouldHaveCount(1); response.Data.ElementAt(0).Id.Should().Be(nodes[1].StringId); - response.Data.ElementAt(0).Attributes!.Name.Should().Be(nodes[1].Name); - response.Data.ElementAt(0).Attributes!.Comment.Should().Be(nodes[1].Comment); + + response.Data.ElementAt(0).Attributes.ShouldNotBeNull().With(attributes => + { + attributes.Name.Should().Be(nodes[1].Name); + attributes.Comment.Should().Be(nodes[1].Comment); + }); + response.Meta.ShouldNotBeNull(); response.Meta.AdditionalData.ShouldContainKey("total").With(total => total.Should().Be(1)); } @@ -97,8 +102,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => response.ShouldNotBeNull(); response.Data.ShouldHaveCount(1); response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(1).StringId); - response.Data.ElementAt(0).Attributes!.Name.Should().Be(node.Children.ElementAt(1).Name); - response.Data.ElementAt(0).Attributes!.Comment.Should().Be(node.Children.ElementAt(1).Comment); + + response.Data.ElementAt(0).Attributes.ShouldNotBeNull().With(attributes => + { + attributes.Name.Should().Be(node.Children.ElementAt(1).Name); + attributes.Comment.Should().Be(node.Children.ElementAt(1).Comment); + }); + response.Meta.ShouldNotBeNull(); response.Meta.AdditionalData.ShouldContainKey("total").With(total => total.Should().Be(1)); } diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/SparseFieldSetTests.cs b/test/OpenApiKiotaEndToEndTests/QueryStrings/SparseFieldSetTests.cs index aa24c1f829..d0ce78ce97 100644 --- a/test/OpenApiKiotaEndToEndTests/QueryStrings/SparseFieldSetTests.cs +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/SparseFieldSetTests.cs @@ -55,9 +55,13 @@ await _testContext.RunOnDatabaseAsync(async dbContext => response.ShouldNotBeNull(); response.Data.ShouldHaveCount(1); response.Data.ElementAt(0).Id.Should().Be(node.StringId); - response.Data.ElementAt(0).Attributes.ShouldNotBeNull(); - response.Data.ElementAt(0).Attributes!.Name.Should().Be(node.Name); - response.Data.ElementAt(0).Attributes!.Comment.Should().BeNull(); + + response.Data.ElementAt(0).Attributes.ShouldNotBeNull().With(attributes => + { + attributes.Name.Should().Be(node.Name); + attributes.Comment.Should().BeNull(); + }); + response.Data.ElementAt(0).Relationships.Should().BeNull(); } } @@ -131,12 +135,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => response.ShouldNotBeNull(); response.Data.ShouldHaveCount(1); response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(0).StringId); - response.Data.ElementAt(0).Attributes.ShouldNotBeNull(); - response.Data.ElementAt(0).Attributes!.Name.Should().BeNull(); - response.Data.ElementAt(0).Attributes!.Comment.Should().Be(node.Children.ElementAt(0).Comment); - response.Data.ElementAt(0).Relationships.ShouldNotBeNull(); - response.Data.ElementAt(0).Relationships!.Parent.Should().BeNull(); - response.Data.ElementAt(0).Relationships!.Children.ShouldNotBeNull(); + + response.Data.ElementAt(0).Attributes.ShouldNotBeNull().With(attributes => + { + attributes.Name.Should().BeNull(); + attributes.Comment.Should().Be(node.Children.ElementAt(0).Comment); + }); + + response.Data.ElementAt(0).Relationships.ShouldNotBeNull().With(relationships => + { + relationships.Parent.Should().BeNull(); + relationships.Children.ShouldNotBeNull(); + }); } } diff --git a/test/OpenApiNSwagClientTests/LegacyOpenApi/GeneratedCode/LegacyClient.cs b/test/OpenApiNSwagClientTests/LegacyOpenApi/GeneratedCode/LegacyClient.cs index 660417de48..5673f76210 100644 --- a/test/OpenApiNSwagClientTests/LegacyOpenApi/GeneratedCode/LegacyClient.cs +++ b/test/OpenApiNSwagClientTests/LegacyOpenApi/GeneratedCode/LegacyClient.cs @@ -5,10 +5,13 @@ namespace OpenApiNSwagClientTests.LegacyOpenApi.GeneratedCode; internal partial class LegacyClient : JsonApiClient { - partial void UpdateJsonSerializerSettings(JsonSerializerSettings settings) + partial void Initialize() { - SetSerializerSettingsForJsonApi(settings); + _instanceSettings = new JsonSerializerSettings(_settings.Value) + { + Formatting = Formatting.Indented + }; - settings.Formatting = Formatting.Indented; + SetSerializerSettingsForJsonApi(_instanceSettings); } } diff --git a/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj b/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj index 4dc9030f70..faca3e46f7 100644 --- a/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj +++ b/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj @@ -5,6 +5,7 @@ + @@ -22,62 +23,73 @@ + + internal + + - OpenApiNSwagClientTests.LegacyOpenApi.GeneratedCode + $(MSBuildProjectName).LegacyOpenApi.GeneratedCode LegacyClient - LegacyClient.cs - NSwagCSharp - /GenerateClientInterfaces:true /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag + %(ClassName).cs + true + false + false + false - OpenApiNSwagClientTests.NamingConventions.KebabCase.GeneratedCode - KebabCaseClient - KebabCaseClient.cs - NSwagCSharp - /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag + KebabCase + $(MSBuildProjectName).NamingConventions.%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs - OpenApiNSwagClientTests.NamingConventions.CamelCase.GeneratedCode - CamelCaseClient - CamelCaseClient.cs - NSwagCSharp - /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag + CamelCase + $(MSBuildProjectName).NamingConventions.%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs - OpenApiNSwagClientTests.NamingConventions.PascalCase.GeneratedCode - PascalCaseClient - PascalCaseClient.cs - NSwagCSharp - /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag + PascalCase + $(MSBuildProjectName).NamingConventions.%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs - NrtOffMsvOffClient - NrtOffMsvOffClient.cs - NSwagCSharp - OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOff.GeneratedCode - /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag /GenerateNullableReferenceTypes:false + NrtOffMsvOff + $(MSBuildProjectName).ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOff.GeneratedCode + %(Name)Client + %(ClassName).cs + false + false + false - NrtOffMsvOnClient - NrtOffMsvOnClient.cs - NSwagCSharp - OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOn.GeneratedCode - /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag /GenerateNullableReferenceTypes:false + NrtOffMsvOn + $(MSBuildProjectName).ResourceFieldValidation.NullableReferenceTypesOff.ModelStateValidationOn.GeneratedCode + %(Name)Client + %(ClassName).cs + false + false + false - NrtOnMsvOffClient - NrtOnMsvOffClient.cs - NSwagCSharp - OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOff.GeneratedCode - /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag /GenerateNullableReferenceTypes:true + NrtOnMsvOff + $(MSBuildProjectName).ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOff.GeneratedCode + %(Name)Client + %(ClassName).cs + true + false + false - NrtOnMsvOnClient - NrtOnMsvOnClient.cs - NSwagCSharp - OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOn.GeneratedCode - /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag /GenerateNullableReferenceTypes:true + NrtOnMsvOn + $(MSBuildProjectName).ResourceFieldValidation.NullableReferenceTypesOn.ModelStateValidationOn.GeneratedCode + %(Name)Client + %(ClassName).cs + true + false + false diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/GeneratedCode/NrtOffMsvOffClient.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/GeneratedCode/NrtOffMsvOffClient.cs index 4a0eed4e39..1d31bdddbb 100644 --- a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/GeneratedCode/NrtOffMsvOffClient.cs +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/GeneratedCode/NrtOffMsvOffClient.cs @@ -5,10 +5,13 @@ namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypes internal partial class NrtOffMsvOffClient : JsonApiClient { - partial void UpdateJsonSerializerSettings(JsonSerializerSettings settings) + partial void Initialize() { - SetSerializerSettingsForJsonApi(settings); + _instanceSettings = new JsonSerializerSettings(_settings.Value) + { + Formatting = Formatting.Indented + }; - settings.Formatting = Formatting.Indented; + SetSerializerSettingsForJsonApi(_instanceSettings); } } diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/GeneratedCode/NrtOffMsvOnClient.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/GeneratedCode/NrtOffMsvOnClient.cs index 1da4da6712..777d976046 100644 --- a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/GeneratedCode/NrtOffMsvOnClient.cs +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/GeneratedCode/NrtOffMsvOnClient.cs @@ -5,10 +5,13 @@ namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypes internal partial class NrtOffMsvOnClient : JsonApiClient { - partial void UpdateJsonSerializerSettings(JsonSerializerSettings settings) + partial void Initialize() { - SetSerializerSettingsForJsonApi(settings); + _instanceSettings = new JsonSerializerSettings(_settings.Value) + { + Formatting = Formatting.Indented + }; - settings.Formatting = Formatting.Indented; + SetSerializerSettingsForJsonApi(_instanceSettings); } } diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/GeneratedCode/NrtOnMsvOffClient.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/GeneratedCode/NrtOnMsvOffClient.cs index f86a5229fc..6c0c012928 100644 --- a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/GeneratedCode/NrtOnMsvOffClient.cs +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/GeneratedCode/NrtOnMsvOffClient.cs @@ -5,10 +5,13 @@ namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypes internal partial class NrtOnMsvOffClient : JsonApiClient { - partial void UpdateJsonSerializerSettings(JsonSerializerSettings settings) + partial void Initialize() { - SetSerializerSettingsForJsonApi(settings); + _instanceSettings = new JsonSerializerSettings(_settings.Value) + { + Formatting = Formatting.Indented + }; - settings.Formatting = Formatting.Indented; + SetSerializerSettingsForJsonApi(_instanceSettings); } } diff --git a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/GeneratedCode/NrtOnMsvOnClient.cs b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/GeneratedCode/NrtOnMsvOnClient.cs index 0a506d41ec..a245b12d17 100644 --- a/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/GeneratedCode/NrtOnMsvOnClient.cs +++ b/test/OpenApiNSwagClientTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/GeneratedCode/NrtOnMsvOnClient.cs @@ -5,10 +5,13 @@ namespace OpenApiNSwagClientTests.ResourceFieldValidation.NullableReferenceTypes internal partial class NrtOnMsvOnClient : JsonApiClient { - partial void UpdateJsonSerializerSettings(JsonSerializerSettings settings) + partial void Initialize() { - SetSerializerSettingsForJsonApi(settings); + _instanceSettings = new JsonSerializerSettings(_settings.Value) + { + Formatting = Formatting.Indented + }; - settings.Formatting = Formatting.Indented; + SetSerializerSettingsForJsonApi(_instanceSettings); } } diff --git a/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicCreateResourceTests.cs b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicCreateResourceTests.cs index ef7aaedf6d..d3d6df406a 100644 --- a/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicCreateResourceTests.cs +++ b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicCreateResourceTests.cs @@ -66,6 +66,7 @@ public async Task Can_create_resource_with_attributes() response.Atomic_results.ShouldHaveCount(1); TeacherDataInResponse teacherDataInResponse = response.Atomic_results.ElementAt(0).Data.Should().BeOfType().Which; + teacherDataInResponse.Attributes.ShouldNotBeNull(); teacherDataInResponse.Attributes.Name.Should().Be(newTeacher.Name); teacherDataInResponse.Attributes.EmailAddress.Should().Be(newTeacher.EmailAddress); @@ -140,6 +141,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => response.Atomic_results.ShouldHaveCount(1); EnrollmentDataInResponse enrollmentDataInResponse = response.Atomic_results.ElementAt(0).Data.Should().BeOfType().Which; + enrollmentDataInResponse.Attributes.ShouldNotBeNull(); enrollmentDataInResponse.Attributes.EnrolledAt.Should().Be(newEnrollment.EnrolledAt.ToDateTime(TimeOnly.MinValue)); enrollmentDataInResponse.Attributes.GraduatedAt.Should().BeNull(); enrollmentDataInResponse.Attributes.HasGraduated.Should().BeFalse(); diff --git a/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicLocalIdTests.cs b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicLocalIdTests.cs index f258a489ca..3a2a93e375 100644 --- a/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicLocalIdTests.cs +++ b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicLocalIdTests.cs @@ -158,6 +158,7 @@ public async Task Can_use_local_IDs() response.Atomic_results.ShouldHaveCount(7); TeacherDataInResponse teacherInResponse = response.Atomic_results.ElementAt(0).Data.Should().BeOfType().Which; + teacherInResponse.Attributes.ShouldNotBeNull(); teacherInResponse.Attributes.Name.Should().Be(newTeacher.Name); teacherInResponse.Attributes.EmailAddress.Should().Be(newTeacher.EmailAddress); long newTeacherId = long.Parse(teacherInResponse.Id); @@ -166,11 +167,13 @@ public async Task Can_use_local_IDs() response.Atomic_results.ElementAt(2).Data.Should().BeNull(); StudentDataInResponse studentInResponse = response.Atomic_results.ElementAt(3).Data.Should().BeOfType().Which; + studentInResponse.Attributes.ShouldNotBeNull(); studentInResponse.Attributes.Name.Should().Be(newStudent.Name); studentInResponse.Attributes.EmailAddress.Should().Be(newStudent.EmailAddress); long newStudentId = long.Parse(studentInResponse.Id); EnrollmentDataInResponse enrollmentInResponse = response.Atomic_results.ElementAt(4).Data.Should().BeOfType().Which; + enrollmentInResponse.Attributes.ShouldNotBeNull(); enrollmentInResponse.Attributes.EnrolledAt.Should().Be(newEnrolledAt.ToDateTime(TimeOnly.MinValue)); long newEnrollmentId = long.Parse(enrollmentInResponse.Id); diff --git a/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicUpdateResourceTests.cs b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicUpdateResourceTests.cs index 8338eb5c06..784f98d5ce 100644 --- a/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicUpdateResourceTests.cs +++ b/test/OpenApiNSwagEndToEndTests/AtomicOperations/AtomicUpdateResourceTests.cs @@ -81,6 +81,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => StudentDataInResponse studentDataInResponse = response.Atomic_results.ElementAt(0).Data.Should().BeOfType().Which; studentDataInResponse.Id.Should().Be(existingStudent.StringId); + studentDataInResponse.Attributes.ShouldNotBeNull(); studentDataInResponse.Attributes.Name.Should().Be(newName); studentDataInResponse.Attributes.EmailAddress.Should().Be(newEmailAddress); @@ -141,6 +142,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => StudentDataInResponse studentDataInResponse = response.Atomic_results.ElementAt(0).Data.Should().BeOfType().Which; studentDataInResponse.Id.Should().Be(existingStudent.StringId); + studentDataInResponse.Attributes.ShouldNotBeNull(); studentDataInResponse.Attributes.Name.Should().Be(existingStudent.Name); studentDataInResponse.Attributes.EmailAddress.Should().Be(newEmailAddress); @@ -219,6 +221,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => EnrollmentDataInResponse enrollmentDataInResponse = response.Atomic_results.ElementAt(0).Data.Should().BeOfType().Which; enrollmentDataInResponse.Id.Should().Be(existingEnrollment.StringId); + enrollmentDataInResponse.Attributes.ShouldNotBeNull(); enrollmentDataInResponse.Attributes.EnrolledAt.Should().Be(newEnrolledAt.ToDateTime(TimeOnly.MinValue)); enrollmentDataInResponse.Attributes.GraduatedAt.Should().Be(existingEnrollment.GraduatedAt!.Value.ToDateTime(TimeOnly.MinValue)); enrollmentDataInResponse.Attributes.HasGraduated.Should().Be(existingEnrollment.HasGraduated); diff --git a/test/OpenApiNSwagEndToEndTests/Headers/ETagTests.cs b/test/OpenApiNSwagEndToEndTests/Headers/ETagTests.cs index 9b624961eb..aa9575fe8e 100644 --- a/test/OpenApiNSwagEndToEndTests/Headers/ETagTests.cs +++ b/test/OpenApiNSwagEndToEndTests/Headers/ETagTests.cs @@ -42,7 +42,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new HeadersClient(httpClient); // Act - ApiResponse response = await ApiResponse.TranslateAsync(async () => await apiClient.HeadCountryCollectionAsync(null, null)); + ApiResponse response = await ApiResponse.TranslateAsync(async () => await apiClient.HeadCountryCollectionAsync()); // Assert response.StatusCode.Should().Be((int)HttpStatusCode.OK); @@ -69,8 +69,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new HeadersClient(httpClient); // Act - ApiResponse response = - await ApiResponse.TranslateAsync(async () => await apiClient.GetCountryCollectionAsync(null, null)); + ApiResponse response = await ApiResponse.TranslateAsync(async () => await apiClient.GetCountryCollectionAsync()); // Assert response.StatusCode.Should().Be((int)HttpStatusCode.OK); @@ -92,7 +91,7 @@ public async Task Returns_no_ETag_for_failed_GET_request() var apiClient = new HeadersClient(httpClient); // Act - Func action = async () => await ApiResponse.TranslateAsync(async () => await apiClient.GetCountryAsync(unknownCountryId, null, null)); + Func action = async () => await ApiResponse.TranslateAsync(async () => await apiClient.GetCountryAsync(unknownCountryId)); // Assert ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; @@ -129,8 +128,7 @@ public async Task Returns_no_ETag_for_POST_request() }; // Act - ApiResponse response = - await ApiResponse.TranslateAsync(async () => await apiClient.PostCountryAsync(null, requestBody)); + ApiResponse response = await ApiResponse.TranslateAsync(async () => await apiClient.PostCountryAsync(requestBody)); // Assert response.StatusCode.Should().Be((int)HttpStatusCode.Created); @@ -156,8 +154,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => using HttpClient httpClient = _testContext.Factory.CreateDefaultClient(_logHttpMessageHandler); var apiClient = new HeadersClient(httpClient); - ApiResponse response1 = - await ApiResponse.TranslateAsync(async () => await apiClient.GetCountryCollectionAsync(null, null)); + ApiResponse response1 = await ApiResponse.TranslateAsync(async () => await apiClient.GetCountryCollectionAsync()); string responseETag = response1.Headers[HeaderNames.ETag].Single(); diff --git a/test/OpenApiNSwagEndToEndTests/Headers/HeaderTests.cs b/test/OpenApiNSwagEndToEndTests/Headers/HeaderTests.cs index 21ad0b942c..26a8d7db2b 100644 --- a/test/OpenApiNSwagEndToEndTests/Headers/HeaderTests.cs +++ b/test/OpenApiNSwagEndToEndTests/Headers/HeaderTests.cs @@ -47,8 +47,7 @@ public async Task Returns_Location_for_post_resource_request() }; // Act - ApiResponse response = - await ApiResponse.TranslateAsync(async () => await apiClient.PostCountryAsync(null, requestBody)); + ApiResponse response = await ApiResponse.TranslateAsync(async () => await apiClient.PostCountryAsync(requestBody)); // Assert response.StatusCode.Should().Be((int)HttpStatusCode.Created); @@ -77,7 +76,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new HeadersClient(httpClient); // Act - ApiResponse response = await ApiResponse.TranslateAsync(async () => await apiClient.HeadCountryCollectionAsync(null, null)); + ApiResponse response = await ApiResponse.TranslateAsync(async () => await apiClient.HeadCountryCollectionAsync()); // Assert response.StatusCode.Should().Be((int)HttpStatusCode.OK); @@ -103,7 +102,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new HeadersClient(httpClient); // Act - ApiResponse response = await ApiResponse.TranslateAsync(async () => await apiClient.HeadCountryAsync(existingCountry.Id, null, null)); + ApiResponse response = await ApiResponse.TranslateAsync(async () => await apiClient.HeadCountryAsync(existingCountry.Id)); // Assert response.StatusCode.Should().Be((int)HttpStatusCode.OK); @@ -130,7 +129,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new HeadersClient(httpClient); // Act - ApiResponse response = await ApiResponse.TranslateAsync(async () => await apiClient.HeadCountryLanguagesAsync(existingCountry.Id, null, null)); + ApiResponse response = await ApiResponse.TranslateAsync(async () => await apiClient.HeadCountryLanguagesAsync(existingCountry.Id)); // Assert response.StatusCode.Should().Be((int)HttpStatusCode.OK); @@ -157,8 +156,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new HeadersClient(httpClient); // Act - ApiResponse response = - await ApiResponse.TranslateAsync(async () => await apiClient.HeadCountryLanguagesRelationshipAsync(existingCountry.Id, null, null)); + ApiResponse response = await ApiResponse.TranslateAsync(async () => await apiClient.HeadCountryLanguagesRelationshipAsync(existingCountry.Id)); // Assert response.StatusCode.Should().Be((int)HttpStatusCode.OK); diff --git a/test/OpenApiNSwagEndToEndTests/Links/AlternateOpenApiRouteTests.cs b/test/OpenApiNSwagEndToEndTests/Links/AlternateOpenApiRouteTests.cs index a99a4889a6..e43e7ba77f 100644 --- a/test/OpenApiNSwagEndToEndTests/Links/AlternateOpenApiRouteTests.cs +++ b/test/OpenApiNSwagEndToEndTests/Links/AlternateOpenApiRouteTests.cs @@ -43,7 +43,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }); // Act - ExcursionPrimaryResponseDocument response = await apiClient.GetExcursionAsync(excursion.StringId!, null, null); + ExcursionPrimaryResponseDocument response = await apiClient.GetExcursionAsync(excursion.StringId!); // Assert response.Links.Describedby.Should().Be("/api-docs/v1/swagger.yaml"); diff --git a/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj b/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj index 00e70aa00b..5c1ffd2c68 100644 --- a/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj +++ b/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj @@ -5,6 +5,7 @@ + @@ -22,55 +23,53 @@ + + internal + + - OpenApiNSwagEndToEndTests.ClientIdGenerationModes.GeneratedCode - ClientIdGenerationModesClient - ClientIdGenerationModesClient.cs - NSwagCSharp - /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag /GenerateNullableReferenceTypes:true /GenerateOptionalPropertiesAsNullable:true /GenerateOptionalParameters:true + ClientIdGenerationModes + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs - OpenApiNSwagEndToEndTests.ModelStateValidation.GeneratedCode - ModelStateValidationClient - ModelStateValidationClient.cs - NSwagCSharp - /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag /GenerateNullableReferenceTypes:true /GenerateOptionalPropertiesAsNullable:true /GenerateOptionalParameters:true + ModelStateValidation + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs - OpenApiNSwagEndToEndTests.Headers.GeneratedCode - HeadersClient - HeadersClient.cs - NSwagCSharp - /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /WrapResponses:true /GenerateResponseClasses:false /ResponseClass:ApiResponse /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag /GenerateNullableReferenceTypes:true + Headers + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs + true - OpenApiNSwagEndToEndTests.QueryStrings.GeneratedCode - QueryStringsClient - QueryStringsClient.cs - NSwagCSharp - /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag /GenerateNullableReferenceTypes:true + QueryStrings + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs - OpenApiNSwagEndToEndTests.RestrictedControllers.GeneratedCode - RestrictedControllersClient - RestrictedControllersClient.cs - NSwagCSharp - /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag /GenerateNullableReferenceTypes:true + RestrictedControllers + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs - OpenApiNSwagEndToEndTests.Links.GeneratedCode - LinksClient - LinksClient.cs - NSwagCSharp - /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag /GenerateNullableReferenceTypes:true + Links + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs - OpenApiNSwagEndToEndTests.AtomicOperations.GeneratedCode - AtomicOperationsClient - AtomicOperationsClient.cs - NSwagCSharp - /ClientClassAccessModifier:internal /GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.NSwag /GenerateNullableReferenceTypes:true + AtomicOperations + $(MSBuildProjectName).%(Name).GeneratedCode + %(Name)Client + %(ClassName).cs diff --git a/test/OpenApiNSwagEndToEndTests/QueryStrings/FilterTests.cs b/test/OpenApiNSwagEndToEndTests/QueryStrings/FilterTests.cs index 44a35c746d..0eda89234f 100644 --- a/test/OpenApiNSwagEndToEndTests/QueryStrings/FilterTests.cs +++ b/test/OpenApiNSwagEndToEndTests/QueryStrings/FilterTests.cs @@ -48,13 +48,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString, null); + NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString); // Assert response.Data.ShouldHaveCount(1); response.Data.ElementAt(0).Id.Should().Be(nodes[1].StringId); - response.Data.ElementAt(0).Attributes.Name.Should().Be(nodes[1].Name); - response.Data.ElementAt(0).Attributes.Comment.Should().Be(nodes[1].Comment); + + response.Data.ElementAt(0).Attributes.ShouldNotBeNull().With(attributes => + { + attributes.Name.Should().Be(nodes[1].Name); + attributes.Comment.Should().Be(nodes[1].Comment); + }); + response.Meta.ShouldNotBeNull(); response.Meta.ShouldContainKey("total").With(total => total.Should().Be(1)); } @@ -84,13 +89,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodeCollectionResponseDocument response = await apiClient.GetNodeChildrenAsync(node.StringId!, queryString, null); + NodeCollectionResponseDocument response = await apiClient.GetNodeChildrenAsync(node.StringId!, queryString); // Assert response.Data.ShouldHaveCount(1); response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(1).StringId); - response.Data.ElementAt(0).Attributes.Name.Should().Be(node.Children.ElementAt(1).Name); - response.Data.ElementAt(0).Attributes.Comment.Should().Be(node.Children.ElementAt(1).Comment); + + response.Data.ElementAt(0).Attributes.ShouldNotBeNull().With(attributes => + { + attributes.Name.Should().Be(node.Children.ElementAt(1).Name); + attributes.Comment.Should().Be(node.Children.ElementAt(1).Comment); + }); + response.Meta.ShouldNotBeNull(); response.Meta.ShouldContainKey("total").With(total => total.Should().Be(1)); } @@ -120,7 +130,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodeIdentifierCollectionResponseDocument response = await apiClient.GetNodeChildrenRelationshipAsync(node.StringId!, queryString, null); + NodeIdentifierCollectionResponseDocument response = await apiClient.GetNodeChildrenRelationshipAsync(node.StringId!, queryString); // Assert response.Data.ShouldHaveCount(1); @@ -144,7 +154,7 @@ public async Task Cannot_use_empty_filter() }; // Act - Func action = async () => _ = await apiClient.GetNodeAsync(Unknown.StringId.Int64, queryString, null); + Func action = async () => _ = await apiClient.GetNodeAsync(Unknown.StringId.Int64, queryString); // Assert ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; diff --git a/test/OpenApiNSwagEndToEndTests/QueryStrings/IncludeTests.cs b/test/OpenApiNSwagEndToEndTests/QueryStrings/IncludeTests.cs index 3cdbcf3b32..1c241c66e8 100644 --- a/test/OpenApiNSwagEndToEndTests/QueryStrings/IncludeTests.cs +++ b/test/OpenApiNSwagEndToEndTests/QueryStrings/IncludeTests.cs @@ -46,7 +46,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString, null); + NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString); // Assert response.Data.ShouldHaveCount(1); @@ -85,7 +85,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodePrimaryResponseDocument response = await apiClient.GetNodeAsync(node.StringId!, queryString, null); + NodePrimaryResponseDocument response = await apiClient.GetNodeAsync(node.StringId!, queryString); // Assert response.Data.Id.Should().Be(node.StringId); @@ -126,7 +126,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NameValuePairCollectionResponseDocument response = await apiClient.GetNodeValuesAsync(node.StringId!, queryString, null); + NameValuePairCollectionResponseDocument response = await apiClient.GetNodeValuesAsync(node.StringId!, queryString); // Assert response.Data.ShouldHaveCount(2); @@ -160,7 +160,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NullableNodeSecondaryResponseDocument response = await apiClient.GetNodeParentAsync(node.StringId!, queryString, null); + NullableNodeSecondaryResponseDocument response = await apiClient.GetNodeParentAsync(node.StringId!, queryString); // Assert response.Data.ShouldNotBeNull(); @@ -170,6 +170,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => NodeDataInResponse? include = response.Included.ElementAt(0).Should().BeOfType().Subject; include.Id.Should().Be(node.Parent.Parent.StringId); + include.Attributes.ShouldNotBeNull(); include.Attributes.Name.Should().Be(node.Parent.Parent.Name); } @@ -194,7 +195,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodePrimaryResponseDocument response = await apiClient.GetNodeAsync(node.StringId!, queryString, null); + NodePrimaryResponseDocument response = await apiClient.GetNodeAsync(node.StringId!, queryString); // Assert response.Data.Id.Should().Be(node.StringId); diff --git a/test/OpenApiNSwagEndToEndTests/QueryStrings/PaginationTests.cs b/test/OpenApiNSwagEndToEndTests/QueryStrings/PaginationTests.cs index 865a173471..42ca05b525 100644 --- a/test/OpenApiNSwagEndToEndTests/QueryStrings/PaginationTests.cs +++ b/test/OpenApiNSwagEndToEndTests/QueryStrings/PaginationTests.cs @@ -47,7 +47,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString, null); + NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString); // Assert response.Data.ShouldHaveCount(1); @@ -80,7 +80,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodeCollectionResponseDocument response = await apiClient.GetNodeChildrenAsync(node.StringId!, queryString, null); + NodeCollectionResponseDocument response = await apiClient.GetNodeChildrenAsync(node.StringId!, queryString); // Assert response.Data.ShouldHaveCount(2); @@ -114,7 +114,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodeIdentifierCollectionResponseDocument response = await apiClient.GetNodeChildrenRelationshipAsync(node.StringId!, queryString, null); + NodeIdentifierCollectionResponseDocument response = await apiClient.GetNodeChildrenRelationshipAsync(node.StringId!, queryString); // Assert response.Data.ShouldHaveCount(1); @@ -136,7 +136,7 @@ public async Task Cannot_use_empty_page_size() }; // Act - Func action = async () => _ = await apiClient.GetNodeAsync(Unknown.StringId.Int64, queryString, null); + Func action = async () => _ = await apiClient.GetNodeAsync(Unknown.StringId.Int64, queryString); // Assert ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; @@ -165,7 +165,7 @@ public async Task Cannot_use_empty_page_number() }; // Act - Func action = async () => _ = await apiClient.GetNodeAsync(Unknown.StringId.Int64, queryString, null); + Func action = async () => _ = await apiClient.GetNodeAsync(Unknown.StringId.Int64, queryString); // Assert ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; diff --git a/test/OpenApiNSwagEndToEndTests/QueryStrings/SortTests.cs b/test/OpenApiNSwagEndToEndTests/QueryStrings/SortTests.cs index 8a06f52ebb..4e231515c6 100644 --- a/test/OpenApiNSwagEndToEndTests/QueryStrings/SortTests.cs +++ b/test/OpenApiNSwagEndToEndTests/QueryStrings/SortTests.cs @@ -48,7 +48,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString, null); + NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString); // Assert response.Data.ShouldHaveCount(2); @@ -81,7 +81,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodeCollectionResponseDocument response = await apiClient.GetNodeChildrenAsync(node.StringId!, queryString, null); + NodeCollectionResponseDocument response = await apiClient.GetNodeChildrenAsync(node.StringId!, queryString); // Assert response.Data.ShouldHaveCount(2); @@ -114,7 +114,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodeIdentifierCollectionResponseDocument response = await apiClient.GetNodeChildrenRelationshipAsync(node.StringId!, queryString, null); + NodeIdentifierCollectionResponseDocument response = await apiClient.GetNodeChildrenRelationshipAsync(node.StringId!, queryString); // Assert response.Data.ShouldHaveCount(2); @@ -135,7 +135,7 @@ public async Task Cannot_use_empty_sort() }; // Act - Func action = async () => _ = await apiClient.GetNodeAsync(Unknown.StringId.Int64, queryString, null); + Func action = async () => _ = await apiClient.GetNodeAsync(Unknown.StringId.Int64, queryString); // Assert ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; diff --git a/test/OpenApiNSwagEndToEndTests/QueryStrings/SparseFieldSetTests.cs b/test/OpenApiNSwagEndToEndTests/QueryStrings/SparseFieldSetTests.cs index 6698effc33..9ce83a06ae 100644 --- a/test/OpenApiNSwagEndToEndTests/QueryStrings/SparseFieldSetTests.cs +++ b/test/OpenApiNSwagEndToEndTests/QueryStrings/SparseFieldSetTests.cs @@ -45,13 +45,18 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString, null); + NodeCollectionResponseDocument response = await apiClient.GetNodeCollectionAsync(queryString); // Assert response.Data.ShouldHaveCount(1); response.Data.ElementAt(0).Id.Should().Be(node.StringId); - response.Data.ElementAt(0).Attributes.Name.Should().Be(node.Name); - response.Data.ElementAt(0).Attributes.Comment.Should().BeNull(); + + response.Data.ElementAt(0).Attributes.ShouldNotBeNull().With(attributes => + { + attributes.Name.Should().Be(node.Name); + attributes.Comment.Should().BeNull(); + }); + response.Data.ElementAt(0).Relationships.Should().BeNull(); } @@ -76,12 +81,14 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodePrimaryResponseDocument response = await apiClient.GetNodeAsync(node.StringId!, queryString, null); + NodePrimaryResponseDocument response = await apiClient.GetNodeAsync(node.StringId!, queryString); // Assert response.Data.Id.Should().Be(node.StringId); + response.Data.Attributes.ShouldNotBeNull(); response.Data.Attributes.Name.Should().BeNull(); response.Data.Attributes.Comment.Should().Be(node.Comment); + response.Data.Relationships.ShouldNotBeNull(); response.Data.Relationships.Parent.ShouldNotBeNull(); response.Data.Relationships.Children.Should().BeNull(); } @@ -109,15 +116,23 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodeCollectionResponseDocument response = await apiClient.GetNodeChildrenAsync(node.StringId!, queryString, null); + NodeCollectionResponseDocument response = await apiClient.GetNodeChildrenAsync(node.StringId!, queryString); // Assert response.Data.ShouldHaveCount(1); response.Data.ElementAt(0).Id.Should().Be(node.Children.ElementAt(0).StringId); - response.Data.ElementAt(0).Attributes.Name.Should().BeNull(); - response.Data.ElementAt(0).Attributes.Comment.Should().Be(node.Children.ElementAt(0).Comment); - response.Data.ElementAt(0).Relationships.Parent.Should().BeNull(); - response.Data.ElementAt(0).Relationships.Children.ShouldNotBeNull(); + + response.Data.ElementAt(0).Attributes.ShouldNotBeNull().With(attributes => + { + attributes.Name.Should().BeNull(); + attributes.Comment.Should().Be(node.Children.ElementAt(0).Comment); + }); + + response.Data.ElementAt(0).Relationships.ShouldNotBeNull().With(relationships => + { + relationships.Parent.Should().BeNull(); + relationships.Children.ShouldNotBeNull(); + }); } [Fact] @@ -142,13 +157,15 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NullableNodeSecondaryResponseDocument response = await apiClient.GetNodeParentAsync(node.StringId!, queryString, null); + NullableNodeSecondaryResponseDocument response = await apiClient.GetNodeParentAsync(node.StringId!, queryString); // Assert response.Data.ShouldNotBeNull(); response.Data.Id.Should().Be(node.Parent.StringId); + response.Data.Attributes.ShouldNotBeNull(); response.Data.Attributes.Name.Should().BeNull(); response.Data.Attributes.Comment.Should().Be(node.Parent.Comment); + response.Data.Relationships.ShouldNotBeNull(); response.Data.Relationships.Parent.Should().BeNull(); response.Data.Relationships.Children.ShouldNotBeNull(); } @@ -174,7 +191,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - NodePrimaryResponseDocument response = await apiClient.GetNodeAsync(node.StringId!, queryString, null); + NodePrimaryResponseDocument response = await apiClient.GetNodeAsync(node.StringId!, queryString); // Assert response.Data.Id.Should().Be(node.StringId); diff --git a/test/OpenApiNSwagEndToEndTests/RestrictedControllers/CreateResourceTests.cs b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/CreateResourceTests.cs index 6168fe2d82..866a87357e 100644 --- a/test/OpenApiNSwagEndToEndTests/RestrictedControllers/CreateResourceTests.cs +++ b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/CreateResourceTests.cs @@ -84,15 +84,20 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Act WriteOnlyChannelPrimaryResponseDocument? response = - await ApiResponse.TranslateAsync(async () => await apiClient.PostWriteOnlyChannelAsync(queryString, requestBody)); + await ApiResponse.TranslateAsync(async () => await apiClient.PostWriteOnlyChannelAsync(requestBody, queryString)); response.ShouldNotBeNull(); + response.Data.Attributes.ShouldNotBeNull(); response.Data.Attributes.Name.Should().Be(newChannel.Name); response.Data.Attributes.IsCommercial.Should().BeNull(); response.Data.Attributes.IsAdultOnly.Should().BeNull(); + response.Data.Relationships.ShouldNotBeNull(); + response.Data.Relationships.VideoStream.ShouldNotBeNull(); + response.Data.Relationships.VideoStream.Data.ShouldNotBeNull(); response.Data.Relationships.VideoStream.Data.Id.Should().Be(existingVideoStream.StringId); response.Data.Relationships.UltraHighDefinitionVideoStream.Should().BeNull(); + response.Data.Relationships.AudioStreams.ShouldNotBeNull(); response.Data.Relationships.AudioStreams.Data.ShouldHaveCount(1); response.Data.Relationships.AudioStreams.Data.ElementAt(0).Id.Should().Be(existingAudioStream.StringId); @@ -100,9 +105,11 @@ await _testContext.RunOnDatabaseAsync(async dbContext => DataStreamDataInResponse[] dataStreamIncludes = response.Included.OfType().ToArray(); DataStreamDataInResponse videoStream = dataStreamIncludes.Single(include => include.Id == existingVideoStream.StringId); + videoStream.Attributes.ShouldNotBeNull(); videoStream.Attributes.BytesTransmitted.Should().Be((long?)existingVideoStream.BytesTransmitted); DataStreamDataInResponse audioStream = dataStreamIncludes.Single(include => include.Id == existingAudioStream.StringId); + audioStream.Attributes.ShouldNotBeNull(); audioStream.Attributes.BytesTransmitted.Should().Be((long?)existingAudioStream.BytesTransmitted); long newChannelId = int.Parse(response.Data.Id.ShouldNotBeNull()); @@ -142,7 +149,7 @@ public async Task Cannot_create_resource_for_missing_request_body() CreateWriteOnlyChannelRequestDocument requestBody = null!; // Act - Func action = async () => _ = await apiClient.PostWriteOnlyChannelAsync(null, requestBody); + Func action = async () => _ = await apiClient.PostWriteOnlyChannelAsync(requestBody); // Assert await action.Should().ThrowExactlyAsync().WithParameterName("body"); @@ -181,7 +188,7 @@ public async Task Cannot_create_resource_with_unknown_relationship_ID() }; // Act - Func action = async () => _ = await apiClient.PostWriteOnlyChannelAsync(null, requestBody); + Func action = async () => _ = await apiClient.PostWriteOnlyChannelAsync(requestBody); // Assert ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; diff --git a/test/OpenApiNSwagEndToEndTests/RestrictedControllers/FetchRelationshipTests.cs b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/FetchRelationshipTests.cs index 18297f3c39..f23e4e054f 100644 --- a/test/OpenApiNSwagEndToEndTests/RestrictedControllers/FetchRelationshipTests.cs +++ b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/FetchRelationshipTests.cs @@ -42,7 +42,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new RestrictedControllersClient(httpClient); // Act - DataStreamIdentifierResponseDocument response = await apiClient.GetReadOnlyChannelVideoStreamRelationshipAsync(channel.StringId!, null, null); + DataStreamIdentifierResponseDocument response = await apiClient.GetReadOnlyChannelVideoStreamRelationshipAsync(channel.StringId!); // Assert response.Data.ShouldNotBeNull(); @@ -67,7 +67,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Act NullableDataStreamIdentifierResponseDocument response = - await apiClient.GetReadOnlyChannelUltraHighDefinitionVideoStreamRelationshipAsync(channel.StringId!, null, null); + await apiClient.GetReadOnlyChannelUltraHighDefinitionVideoStreamRelationshipAsync(channel.StringId!); // Assert response.Data.Should().BeNull(); @@ -91,8 +91,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new RestrictedControllersClient(httpClient); // Act - DataStreamIdentifierCollectionResponseDocument - response = await apiClient.GetReadOnlyChannelAudioStreamsRelationshipAsync(channel.StringId!, null, null); + DataStreamIdentifierCollectionResponseDocument response = await apiClient.GetReadOnlyChannelAudioStreamsRelationshipAsync(channel.StringId!); // Assert response.Data.ShouldHaveCount(2); @@ -117,8 +116,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new RestrictedControllersClient(httpClient); // Act - DataStreamIdentifierCollectionResponseDocument - response = await apiClient.GetReadOnlyChannelAudioStreamsRelationshipAsync(channel.StringId!, null, null); + DataStreamIdentifierCollectionResponseDocument response = await apiClient.GetReadOnlyChannelAudioStreamsRelationshipAsync(channel.StringId!); // Assert response.Data.ShouldHaveCount(0); @@ -134,7 +132,7 @@ public async Task Cannot_get_relationship_for_unknown_primary_ID() var apiClient = new RestrictedControllersClient(httpClient); // Act - Func action = async () => _ = await apiClient.GetReadOnlyChannelVideoStreamRelationshipAsync(unknownChannelId, null, null); + Func action = async () => _ = await apiClient.GetReadOnlyChannelVideoStreamRelationshipAsync(unknownChannelId); // Assert ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; diff --git a/test/OpenApiNSwagEndToEndTests/RestrictedControllers/FetchResourceTests.cs b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/FetchResourceTests.cs index d4279048e8..c4bc78d73c 100644 --- a/test/OpenApiNSwagEndToEndTests/RestrictedControllers/FetchResourceTests.cs +++ b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/FetchResourceTests.cs @@ -43,25 +43,35 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new RestrictedControllersClient(httpClient); // Act - ReadOnlyChannelCollectionResponseDocument response = await apiClient.GetReadOnlyChannelCollectionAsync(null, null); + ReadOnlyChannelCollectionResponseDocument response = await apiClient.GetReadOnlyChannelCollectionAsync(); // Assert response.Data.ShouldHaveCount(2); ReadOnlyChannelDataInResponse channel1 = response.Data.Single(channel => channel.Id == channels.ElementAt(0).StringId); + channel1.Attributes.ShouldNotBeNull(); channel1.Attributes.Name.Should().Be(channels[0].Name); channel1.Attributes.IsCommercial.Should().Be(channels[0].IsCommercial); channel1.Attributes.IsAdultOnly.Should().Be(channels[0].IsAdultOnly); + channel1.Relationships.ShouldNotBeNull(); + channel1.Relationships.VideoStream.ShouldNotBeNull(); channel1.Relationships.VideoStream.Data.Should().BeNull(); + channel1.Relationships.UltraHighDefinitionVideoStream.ShouldNotBeNull(); channel1.Relationships.UltraHighDefinitionVideoStream.Data.Should().BeNull(); + channel1.Relationships.AudioStreams.ShouldNotBeNull(); channel1.Relationships.AudioStreams.Data.Should().BeNull(); ReadOnlyChannelDataInResponse channel2 = response.Data.Single(channel => channel.Id == channels.ElementAt(1).StringId); + channel2.Attributes.ShouldNotBeNull(); channel2.Attributes.Name.Should().Be(channels[1].Name); channel2.Attributes.IsCommercial.Should().Be(channels[1].IsCommercial); channel2.Attributes.IsAdultOnly.Should().Be(channels[1].IsAdultOnly); + channel2.Relationships.ShouldNotBeNull(); + channel2.Relationships.VideoStream.ShouldNotBeNull(); channel2.Relationships.VideoStream.Data.Should().BeNull(); + channel2.Relationships.UltraHighDefinitionVideoStream.ShouldNotBeNull(); channel2.Relationships.UltraHighDefinitionVideoStream.Data.Should().BeNull(); + channel2.Relationships.AudioStreams.ShouldNotBeNull(); channel2.Relationships.AudioStreams.Data.Should().BeNull(); } @@ -82,16 +92,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new RestrictedControllersClient(httpClient); // Act - ReadOnlyChannelPrimaryResponseDocument response = await apiClient.GetReadOnlyChannelAsync(channel.StringId!, null, null); + ReadOnlyChannelPrimaryResponseDocument response = await apiClient.GetReadOnlyChannelAsync(channel.StringId!); // Assert response.Data.ShouldNotBeNull(); response.Data.Id.Should().Be(channel.StringId); + response.Data.Attributes.ShouldNotBeNull(); response.Data.Attributes.Name.Should().Be(channel.Name); response.Data.Attributes.IsCommercial.Should().Be(channel.IsCommercial); response.Data.Attributes.IsAdultOnly.Should().Be(channel.IsAdultOnly); + response.Data.Relationships.ShouldNotBeNull(); + response.Data.Relationships.VideoStream.ShouldNotBeNull(); response.Data.Relationships.VideoStream.Data.Should().BeNull(); + response.Data.Relationships.UltraHighDefinitionVideoStream.ShouldNotBeNull(); response.Data.Relationships.UltraHighDefinitionVideoStream.Data.Should().BeNull(); + response.Data.Relationships.AudioStreams.ShouldNotBeNull(); response.Data.Relationships.AudioStreams.Data.Should().BeNull(); } @@ -105,7 +120,7 @@ public async Task Cannot_get_primary_resource_for_unknown_ID() var apiClient = new RestrictedControllersClient(httpClient); // Act - Func action = async () => _ = await apiClient.GetReadOnlyChannelAsync(unknownChannelId, null, null); + Func action = async () => _ = await apiClient.GetReadOnlyChannelAsync(unknownChannelId); // Assert ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; @@ -136,11 +151,12 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new RestrictedControllersClient(httpClient); // Act - DataStreamSecondaryResponseDocument response = await apiClient.GetReadOnlyChannelVideoStreamAsync(channel.StringId!, null, null); + DataStreamSecondaryResponseDocument response = await apiClient.GetReadOnlyChannelVideoStreamAsync(channel.StringId!); // Assert response.Data.ShouldNotBeNull(); response.Data.Id.Should().Be(channel.VideoStream.StringId); + response.Data.Attributes.ShouldNotBeNull(); response.Data.Attributes.BytesTransmitted.Should().Be((long?)channel.VideoStream.BytesTransmitted); } @@ -161,8 +177,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new RestrictedControllersClient(httpClient); // Act - NullableDataStreamSecondaryResponseDocument response = - await apiClient.GetReadOnlyChannelUltraHighDefinitionVideoStreamAsync(channel.StringId!, null, null); + NullableDataStreamSecondaryResponseDocument response = await apiClient.GetReadOnlyChannelUltraHighDefinitionVideoStreamAsync(channel.StringId!); // Assert response.Data.Should().BeNull(); @@ -186,15 +201,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new RestrictedControllersClient(httpClient); // Act - DataStreamCollectionResponseDocument response = await apiClient.GetReadOnlyChannelAudioStreamsAsync(channel.StringId!, null, null); + DataStreamCollectionResponseDocument response = await apiClient.GetReadOnlyChannelAudioStreamsAsync(channel.StringId!); // Assert response.Data.ShouldHaveCount(2); DataStreamDataInResponse audioStream1 = response.Data.Single(autoStream => autoStream.Id == channel.AudioStreams.ElementAt(0).StringId); + audioStream1.Attributes.ShouldNotBeNull(); audioStream1.Attributes.BytesTransmitted.Should().Be((long?)channel.AudioStreams.ElementAt(0).BytesTransmitted); DataStreamDataInResponse audioStream2 = response.Data.Single(autoStream => autoStream.Id == channel.AudioStreams.ElementAt(1).StringId); + audioStream2.Attributes.ShouldNotBeNull(); audioStream2.Attributes.BytesTransmitted.Should().Be((long?)channel.AudioStreams.ElementAt(1).BytesTransmitted); } @@ -215,7 +232,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => var apiClient = new RestrictedControllersClient(httpClient); // Act - DataStreamCollectionResponseDocument response = await apiClient.GetReadOnlyChannelAudioStreamsAsync(channel.StringId!, null, null); + DataStreamCollectionResponseDocument response = await apiClient.GetReadOnlyChannelAudioStreamsAsync(channel.StringId!); // Assert response.Data.ShouldHaveCount(0); @@ -231,7 +248,7 @@ public async Task Cannot_get_secondary_resource_for_unknown_primary_ID() var apiClient = new RestrictedControllersClient(httpClient); // Act - Func action = async () => _ = await apiClient.GetReadOnlyChannelVideoStreamAsync(unknownChannelId, null, null); + Func action = async () => _ = await apiClient.GetReadOnlyChannelVideoStreamAsync(unknownChannelId); // Assert ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which; diff --git a/test/OpenApiNSwagEndToEndTests/RestrictedControllers/UpdateResourceTests.cs b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/UpdateResourceTests.cs index 910b635b32..688b317a77 100644 --- a/test/OpenApiNSwagEndToEndTests/RestrictedControllers/UpdateResourceTests.cs +++ b/test/OpenApiNSwagEndToEndTests/RestrictedControllers/UpdateResourceTests.cs @@ -91,16 +91,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Act WriteOnlyChannelPrimaryResponseDocument? response = await ApiResponse.TranslateAsync(async () => - await apiClient.PatchWriteOnlyChannelAsync(existingChannel.StringId!, queryString, requestBody)); + await apiClient.PatchWriteOnlyChannelAsync(existingChannel.StringId!, requestBody, queryString)); response.ShouldNotBeNull(); response.Data.Id.Should().Be(existingChannel.StringId); + response.Data.Attributes.ShouldNotBeNull(); response.Data.Attributes.Name.Should().Be(newChannelName); response.Data.Attributes.IsCommercial.Should().Be(existingChannel.IsCommercial); response.Data.Attributes.IsAdultOnly.Should().BeNull(); + response.Data.Relationships.ShouldNotBeNull(); + response.Data.Relationships.VideoStream.ShouldNotBeNull(); + response.Data.Relationships.VideoStream.Data.ShouldNotBeNull(); response.Data.Relationships.VideoStream.Data.Id.Should().Be(existingVideoStream.StringId); response.Data.Relationships.UltraHighDefinitionVideoStream.Should().BeNull(); + response.Data.Relationships.AudioStreams.ShouldNotBeNull(); response.Data.Relationships.AudioStreams.Data.Should().BeEmpty(); response.Included.ShouldHaveCount(1); @@ -165,16 +170,21 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Act WriteOnlyChannelPrimaryResponseDocument? response = - await ApiResponse.TranslateAsync(async () => await apiClient.PatchWriteOnlyChannelAsync(existingChannel.StringId!, null, requestBody)); + await ApiResponse.TranslateAsync(async () => await apiClient.PatchWriteOnlyChannelAsync(existingChannel.StringId!, requestBody)); response.ShouldNotBeNull(); response.Data.Id.Should().Be(existingChannel.StringId); + response.Data.Attributes.ShouldNotBeNull(); response.Data.Attributes.Name.Should().Be(existingChannel.Name); response.Data.Attributes.IsCommercial.Should().Be(existingChannel.IsCommercial); response.Data.Attributes.IsAdultOnly.Should().Be(existingChannel.IsAdultOnly); + response.Data.Relationships.ShouldNotBeNull(); + response.Data.Relationships.VideoStream.ShouldNotBeNull(); response.Data.Relationships.VideoStream.Data.Should().BeNull(); + response.Data.Relationships.UltraHighDefinitionVideoStream.ShouldNotBeNull(); response.Data.Relationships.UltraHighDefinitionVideoStream.Data.Should().BeNull(); + response.Data.Relationships.AudioStreams.ShouldNotBeNull(); response.Data.Relationships.AudioStreams.Data.Should().BeNull(); await _testContext.RunOnDatabaseAsync(async dbContext => @@ -224,7 +234,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => UpdateWriteOnlyChannelRequestDocument requestBody = null!; // Act - Func action = async () => _ = await apiClient.PatchWriteOnlyChannelAsync(existingChannel.StringId!, null, requestBody); + Func action = async () => _ = await apiClient.PatchWriteOnlyChannelAsync(existingChannel.StringId!, requestBody); // Assert await action.Should().ThrowExactlyAsync().WithParameterName("body"); @@ -277,7 +287,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => }; // Act - Func action = async () => _ = await apiClient.PatchWriteOnlyChannelAsync(existingChannel.StringId!, null, requestBody); + Func action = async () => _ = await apiClient.PatchWriteOnlyChannelAsync(existingChannel.StringId!, requestBody); // Assert ApiException exception = (await action.Should().ThrowExactlyAsync>()).Which;