diff --git a/RESTFulSense.WebAssembly/Clients/IRESTFulApiClient.cs b/RESTFulSense.WebAssembly/Clients/IRESTFulApiClient.cs index 840f2c4..5ad7eb0 100644 --- a/RESTFulSense.WebAssembly/Clients/IRESTFulApiClient.cs +++ b/RESTFulSense.WebAssembly/Clients/IRESTFulApiClient.cs @@ -13,13 +13,17 @@ namespace RESTFulSense.WebAssembly.Clients { public interface IRESTFulApiClient { - ValueTask GetContentAsync(string relativeUrl, Func> deserializationFunction = null); + ValueTask GetContentAsync( + string relativeUrl, + Func> deserializationFunction = null); + ValueTask GetContentAsync( string relativeUrl, CancellationToken cancellationToken, Func> deserializationFunction = null); ValueTask GetContentStringAsync(string relativeUrl); + ValueTask GetContentStreamAsync(string relativeUrl); ValueTask PostContentWithNoResponseAsync( @@ -87,6 +91,15 @@ ValueTask PutContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null); + ValueTask PutContentAsync( + string relativeUrl, + T content, + CancellationToken cancellationToken, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null); + ValueTask PutContentAsync( string relativeUrl, TContent content, @@ -104,7 +117,9 @@ ValueTask PutContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null); - ValueTask PutContentAsync(string relativeUrl, Func> deserializationFunction = null); + ValueTask PutContentAsync( + string relativeUrl, + Func> deserializationFunction = null); ValueTask PutContentAsync( string relativeUrl, @@ -112,8 +127,14 @@ ValueTask PutContentAsync( ValueTask> deserializationFunction = null); ValueTask DeleteContentAsync(string relativeUrl); - ValueTask DeleteContentAsync(string relativeUrl, CancellationToken cancellationToken); - ValueTask DeleteContentAsync(string relativeUrl, Func> deserializationFunction = null); + + ValueTask DeleteContentAsync( + string relativeUrl, + CancellationToken cancellationToken); + + ValueTask DeleteContentAsync( + string relativeUrl, + Func> deserializationFunction = null); ValueTask DeleteContentAsync( string relativeUrl, diff --git a/RESTFulSense.WebAssembly/Clients/IRESTFulApiFactoryClient.cs b/RESTFulSense.WebAssembly/Clients/IRESTFulApiFactoryClient.cs index 17b90f9..1effccd 100644 --- a/RESTFulSense.WebAssembly/Clients/IRESTFulApiFactoryClient.cs +++ b/RESTFulSense.WebAssembly/Clients/IRESTFulApiFactoryClient.cs @@ -13,7 +13,10 @@ namespace RESTFulSense.WebAssembly.Clients { public interface IRESTFulApiFactoryClient { - ValueTask GetContentAsync(string relativeUrl, Func> deserializationFunction = null); + ValueTask GetContentAsync( + string relativeUrl, + Func> deserializationFunction = null); + ValueTask GetContentAsync( string relativeUrl, CancellationToken cancellationToken, @@ -104,19 +107,28 @@ ValueTask PutContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null); - ValueTask PutContentAsync(string relativeUrl, Func> deserializationFunction = null); + ValueTask PutContentAsync( + string relativeUrl, + Func> deserializationFunction = null); + ValueTask PutContentAsync( string relativeUrl, CancellationToken cancellationToken, Func> deserializationFunction = null); ValueTask DeleteContentAsync(string relativeUrl); - ValueTask DeleteContentAsync(string relativeUrl, CancellationToken cancellationToken); - ValueTask DeleteContentAsync(string relativeUrl, Func> deserializationFunction = null); + + ValueTask DeleteContentAsync( + string relativeUrl, + CancellationToken cancellationToken); + + ValueTask DeleteContentAsync( + string relativeUrl, + Func> deserializationFunction = null); ValueTask DeleteContentAsync( string relativeUrl, CancellationToken cancellationToken, Func> deserializationFunction = null); } -} +} \ No newline at end of file diff --git a/RESTFulSense.WebAssembly/Clients/RESTFulApiClient.cs b/RESTFulSense.WebAssembly/Clients/RESTFulApiClient.cs index 80dba77..91fb139 100644 --- a/RESTFulSense.WebAssembly/Clients/RESTFulApiClient.cs +++ b/RESTFulSense.WebAssembly/Clients/RESTFulApiClient.cs @@ -16,7 +16,9 @@ namespace RESTFulSense.WebAssembly.Clients { public partial class RESTFulApiClient : HttpClient, IRESTFulApiClient { - public async ValueTask GetContentAsync(string relativeUrl, Func> deserializationFunction = null) + public async ValueTask GetContentAsync( + string relativeUrl, + Func> deserializationFunction = null) { HttpResponseMessage responseMessage = await GetAsync(relativeUrl); await ValidationService.ValidateHttpResponseAsync(responseMessage); @@ -29,7 +31,9 @@ public async ValueTask GetContentAsync( CancellationToken cancellationToken, Func> deserializationFunction = null) { - HttpResponseMessage responseMessage = await GetAsync(relativeUrl, cancellationToken); + HttpResponseMessage responseMessage = + await GetAsync(relativeUrl, cancellationToken); + await ValidationService.ValidateHttpResponseAsync(responseMessage); return await DeserializeResponseContent(responseMessage); @@ -49,7 +53,11 @@ public async ValueTask PostContentWithNoResponseAsync( Func> serializationFunction = null) { HttpContent contentString = - await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = await PostAsync(relativeUrl, contentString); @@ -66,7 +74,11 @@ public async ValueTask PostContentWithNoResponseAsync( Func> serializationFunction = null) { HttpContent contentString = - await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = await PostAsync(relativeUrl, contentString, cancellationToken); @@ -82,7 +94,13 @@ public ValueTask PostContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null) { - return PostContentAsync(relativeUrl, content, mediaType, ignoreDefaultValues, serializationFunction, deserializationFunction); + return PostContentAsync( + relativeUrl, + content, + mediaType, + ignoreDefaultValues, + serializationFunction, + deserializationFunction); } public ValueTask PostContentAsync( @@ -94,7 +112,14 @@ public ValueTask PostContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null) { - return PostContentAsync(relativeUrl, content, cancellationToken, mediaType, ignoreDefaultValues, serializationFunction, deserializationFunction); + return PostContentAsync( + relativeUrl, + content, + cancellationToken, + mediaType, + ignoreDefaultValues, + serializationFunction, + deserializationFunction); } public async ValueTask PostContentWithStreamResponseAsync( @@ -105,9 +130,15 @@ public async ValueTask PostContentWithStreamResponseAsync( bool ignoreDefaultValues = false, Func> serializationFunction = null) { - HttpContent contentString = await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); - HttpResponseMessage responseMessage = await PostAsync(relativeUrl, contentString); + HttpResponseMessage responseMessage = + await PostAsync(relativeUrl, contentString); await ValidationService.ValidateHttpResponseAsync(responseMessage); @@ -123,14 +154,20 @@ public async ValueTask PostContentAsync( Func> deserializationFunction = null) { HttpContent contentString = - await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = await PostAsync(relativeUrl, contentString); await ValidationService.ValidateHttpResponseAsync(responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask PostContentAsync( @@ -142,14 +179,21 @@ public async ValueTask PostContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null) { - HttpContent contentString = await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = await PostAsync(relativeUrl, contentString, cancellationToken); await ValidationService.ValidateHttpResponseAsync(responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask PutContentAsync( @@ -160,14 +204,21 @@ public async ValueTask PutContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null) { - HttpContent contentString = await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = await PutAsync(relativeUrl, contentString); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); - return await DeserializeResponseContent(responseMessage); + return await DeserializeResponseContent( + responseMessage); } public async ValueTask PutContentAsync( @@ -179,14 +230,25 @@ public async ValueTask PutContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null) { - HttpContent contentString = await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = - await PutAsync(relativeUrl, contentString, cancellationToken); + await PutAsync( + relativeUrl, + contentString, + cancellationToken); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask PutContentAsync( @@ -197,14 +259,20 @@ public async ValueTask PutContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null) { - HttpContent contentString = await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + HttpContent contentString = + await ConvertToHttpContent(content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = await PutAsync(relativeUrl, contentString); await ValidationService.ValidateHttpResponseAsync(responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask PutContentAsync( @@ -216,24 +284,36 @@ public async ValueTask PutContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null) { - HttpContent contentString = await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = await PutAsync(relativeUrl, contentString, cancellationToken); await ValidationService.ValidateHttpResponseAsync(responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } - public async ValueTask PutContentAsync(string relativeUrl, Func> deserializationFunction = null) + public async ValueTask PutContentAsync( + string relativeUrl, + Func> deserializationFunction = null) { HttpResponseMessage responseMessage = await PutAsync(relativeUrl, content: default); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask PutContentAsync( @@ -242,50 +322,80 @@ public async ValueTask PutContentAsync( Func> deserializationFunction = null) { HttpResponseMessage responseMessage = - await PutAsync(relativeUrl, content: default, cancellationToken); + await PutAsync( + relativeUrl, + content: default, + cancellationToken); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask DeleteContentAsync(string relativeUrl) { - HttpResponseMessage responseMessage = await DeleteAsync(relativeUrl); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + HttpResponseMessage responseMessage = + await DeleteAsync(relativeUrl); + + await ValidationService.ValidateHttpResponseAsync( + responseMessage); } - public async ValueTask DeleteContentAsync(string relativeUrl, CancellationToken cancellationToken) + public async ValueTask DeleteContentAsync( + string relativeUrl, + CancellationToken cancellationToken) { HttpResponseMessage responseMessage = - await DeleteAsync(relativeUrl, cancellationToken); + await DeleteAsync( + relativeUrl, + cancellationToken); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); } - public async ValueTask DeleteContentAsync(string relativeUrl, Func> deserializationFunction = null) + public async ValueTask DeleteContentAsync( + string relativeUrl, + Func> deserializationFunction = null) { - HttpResponseMessage responseMessage = await DeleteAsync(relativeUrl); - await ValidationService.ValidateHttpResponseAsync(responseMessage); - - return await DeserializeResponseContent(responseMessage, deserializationFunction); + HttpResponseMessage responseMessage = + await DeleteAsync(relativeUrl); + + await ValidationService.ValidateHttpResponseAsync( + responseMessage); + + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } - public async ValueTask DeleteContentAsync(string relativeUrl, CancellationToken cancellationToken, Func> deserializationFunction = null) + public async ValueTask DeleteContentAsync( + string relativeUrl, + CancellationToken cancellationToken, + Func> deserializationFunction = null) { HttpResponseMessage responseMessage = - await DeleteAsync(relativeUrl, cancellationToken); + await DeleteAsync( + relativeUrl, + cancellationToken); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } private static async ValueTask DeserializeResponseContent( HttpResponseMessage responseMessage, Func> deserializationFunction = null) { - string responseString = await responseMessage.Content.ReadAsStringAsync(); + string responseString = + await responseMessage.Content.ReadAsStringAsync(); return deserializationFunction == null ? JsonConvert.DeserializeObject(responseString) diff --git a/RESTFulSense.WebAssembly/Clients/RESTFulApiFactoryClient.cs b/RESTFulSense.WebAssembly/Clients/RESTFulApiFactoryClient.cs index de4c288..cfa6ad4 100644 --- a/RESTFulSense.WebAssembly/Clients/RESTFulApiFactoryClient.cs +++ b/RESTFulSense.WebAssembly/Clients/RESTFulApiFactoryClient.cs @@ -21,14 +21,19 @@ public partial class RESTFulApiFactoryClient : IRESTFulApiFactoryClient public RESTFulApiFactoryClient(HttpClient httpClient) => this.httpClient = httpClient; - public async ValueTask GetContentAsync(string relativeUrl, Func> deserializationFunction = null) + public async ValueTask GetContentAsync( + string relativeUrl, + Func> deserializationFunction = null) { HttpResponseMessage responseMessage = await this.httpClient.GetAsync(relativeUrl); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask GetContentAsync( @@ -37,11 +42,16 @@ public async ValueTask GetContentAsync( Func> deserializationFunction = null) { HttpResponseMessage responseMessage = - await this.httpClient.GetAsync(relativeUrl, cancellationToken); + await this.httpClient.GetAsync( + relativeUrl, + cancellationToken); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask GetContentStringAsync(string relativeUrl) => @@ -55,7 +65,11 @@ public async ValueTask PostContentWithNoResponseAsync( Func> serializationFunction = null) { HttpContent contentString = - await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = await this.httpClient.PostAsync(relativeUrl, contentString); @@ -74,12 +88,21 @@ public async ValueTask PostContentWithNoResponseAsync( bool ignoreDefaultValues = false, Func> serializationFunction = null) { - HttpContent contentString = await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = - await this.httpClient.PostAsync(relativeUrl, contentString, cancellationToken); + await this.httpClient.PostAsync( + relativeUrl, + contentString, + cancellationToken); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); } public ValueTask PostContentAsync( @@ -88,8 +111,16 @@ public ValueTask PostContentAsync( string mediaType = "text/json", bool ignoreDefaultValues = false, Func> serializationFunction = null, - Func> deserializationFunction = null) => - PostContentAsync(relativeUrl, content, mediaType, ignoreDefaultValues, serializationFunction, deserializationFunction); + Func> deserializationFunction = null) + { + return PostContentAsync( + relativeUrl, + content, + mediaType, + ignoreDefaultValues, + serializationFunction, + deserializationFunction); + } public ValueTask PostContentAsync( string relativeUrl, @@ -98,8 +129,17 @@ public ValueTask PostContentAsync( string mediaType = "text/json", bool ignoreDefaultValues = false, Func> serializationFunction = null, - Func> deserializationFunction = null) => - PostContentAsync(relativeUrl, content, cancellationToken, mediaType, ignoreDefaultValues, serializationFunction, deserializationFunction); + Func> deserializationFunction = null) + { + return PostContentAsync( + relativeUrl, + content, + cancellationToken, + mediaType, + ignoreDefaultValues, + serializationFunction, + deserializationFunction); + } public async ValueTask PostContentWithStreamResponseAsync( string relativeUrl, @@ -109,9 +149,18 @@ public async ValueTask PostContentWithStreamResponseAsync( bool ignoreDefaultValues = false, Func> serializationFunction = null) { - HttpContent contentString = await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); - HttpResponseMessage responseMessage = await this.httpClient.PostAsync(relativeUrl, contentString, cancellationToken); + HttpResponseMessage responseMessage = + await this.httpClient.PostAsync( + relativeUrl, + contentString, + cancellationToken); await ValidationService.ValidateHttpResponseAsync(responseMessage); @@ -126,14 +175,21 @@ public async ValueTask PostContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null) { - HttpContent contentString = await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = await this.httpClient.PostAsync(relativeUrl, contentString); await ValidationService.ValidateHttpResponseAsync(responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask PostContentAsync( @@ -145,14 +201,24 @@ public async ValueTask PostContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null) { - HttpContent contentString = await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = - await this.httpClient.PostAsync(relativeUrl, contentString, cancellationToken); + await this.httpClient.PostAsync( + relativeUrl, + contentString, + cancellationToken); await ValidationService.ValidateHttpResponseAsync(responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask PutContentAsync( @@ -163,14 +229,21 @@ public async ValueTask PutContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null) { - HttpContent contentString = await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = await this.httpClient.PutAsync(relativeUrl, contentString); await ValidationService.ValidateHttpResponseAsync(responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask PutContentAsync( @@ -182,14 +255,25 @@ public async ValueTask PutContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null) { - HttpContent contentString = await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = - await this.httpClient.PutAsync(relativeUrl, contentString, cancellationToken); + await this.httpClient.PutAsync( + relativeUrl, + contentString, + cancellationToken); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask PutContentAsync( @@ -200,14 +284,21 @@ public async ValueTask PutContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null) { - HttpContent contentString = await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = await this.httpClient.PutAsync(relativeUrl, contentString); await ValidationService.ValidateHttpResponseAsync(responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask PutContentAsync( @@ -219,24 +310,41 @@ public async ValueTask PutContentAsync( Func> serializationFunction = null, Func> deserializationFunction = null) { - HttpContent contentString = await ConvertToHttpContent(content, mediaType, ignoreDefaultValues, serializationFunction); + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); HttpResponseMessage responseMessage = - await this.httpClient.PutAsync(relativeUrl, contentString, cancellationToken); + await this.httpClient.PutAsync( + relativeUrl, + contentString, + cancellationToken); await ValidationService.ValidateHttpResponseAsync(responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } - public async ValueTask PutContentAsync(string relativeUrl, Func> deserializationFunction = null) + public async ValueTask PutContentAsync( + string relativeUrl, + Func> deserializationFunction = null) { HttpResponseMessage responseMessage = - await this.httpClient.PutAsync(relativeUrl, content: default); + await this.httpClient.PutAsync( + relativeUrl, + content: default); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask PutContentAsync( @@ -245,11 +353,17 @@ public async ValueTask PutContentAsync( Func> deserializationFunction = null) { HttpResponseMessage responseMessage = - await this.httpClient.PutAsync(relativeUrl, content: default, cancellationToken); + await this.httpClient.PutAsync( + relativeUrl, + content: default, + cancellationToken); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask DeleteContentAsync(string relativeUrl) @@ -257,25 +371,36 @@ public async ValueTask DeleteContentAsync(string relativeUrl) HttpResponseMessage responseMessage = await this.httpClient.DeleteAsync(relativeUrl); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); } - public async ValueTask DeleteContentAsync(string relativeUrl, CancellationToken cancellationToken) + public async ValueTask DeleteContentAsync( + string relativeUrl, + CancellationToken cancellationToken) { HttpResponseMessage responseMessage = - await this.httpClient.DeleteAsync(relativeUrl, cancellationToken); + await this.httpClient.DeleteAsync( + relativeUrl, + cancellationToken); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); } - public async ValueTask DeleteContentAsync(string relativeUrl, Func> deserializationFunction = null) + public async ValueTask DeleteContentAsync( + string relativeUrl, + Func> deserializationFunction = null) { - HttpResponseMessage responseMessage = await - this.httpClient.DeleteAsync(relativeUrl); + HttpResponseMessage responseMessage = + await this.httpClient.DeleteAsync(relativeUrl); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } public async ValueTask DeleteContentAsync( @@ -284,18 +409,24 @@ public async ValueTask DeleteContentAsync( Func> deserializationFunction = null) { HttpResponseMessage responseMessage = await - this.httpClient.DeleteAsync(relativeUrl, cancellationToken); + this.httpClient.DeleteAsync( + relativeUrl, + cancellationToken); - await ValidationService.ValidateHttpResponseAsync(responseMessage); + await ValidationService.ValidateHttpResponseAsync( + responseMessage); - return await DeserializeResponseContent(responseMessage, deserializationFunction); + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); } private static async ValueTask DeserializeResponseContent( HttpResponseMessage responseMessage, Func> deserializationFunction = null) { - string responseString = await responseMessage.Content.ReadAsStringAsync(); + string responseString = + await responseMessage.Content.ReadAsStringAsync(); return deserializationFunction == null ? JsonConvert.DeserializeObject(responseString) diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Models/TEntity.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Models/TEntity.cs new file mode 100644 index 0000000..6504423 --- /dev/null +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Models/TEntity.cs @@ -0,0 +1,15 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; + +namespace RESTFulSense.WebAssenbly.Tests.Acceptance.Models +{ + public class TEntity + { + public Guid Id { get; set; } + public string Name { get; set; } + public DateTimeOffset CreateDate { get; set; } + } +} \ No newline at end of file diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/RESTFulSense.WebAssenbly.Tests.Acceptance.csproj b/RESTFulSense.WebAssenbly.Tests.Acceptance/RESTFulSense.WebAssenbly.Tests.Acceptance.csproj new file mode 100644 index 0000000..587781a --- /dev/null +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/RESTFulSense.WebAssenbly.Tests.Acceptance.csproj @@ -0,0 +1,34 @@ + + + + net7.0 + disable + disable + + false + true + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.DeleteContent.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.DeleteContent.cs new file mode 100644 index 0000000..cdc6879 --- /dev/null +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.DeleteContent.cs @@ -0,0 +1,103 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions; +using RESTFulSense.WebAssenbly.Tests.Acceptance.Models; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using Xunit; + +namespace RESTFulSense.WebAssenbly.Tests.Acceptance.Tests +{ + public partial class RestfulSenseWebAssemblyApiClientTests + { + [Fact] + private async Task ShouldDeleteContentAsync() + { + // given + this.wiremockServer + .Given(Request.Create() + .WithPath(relativeUrl) + .UsingDelete()) + .RespondWith(Response.Create() + .WithStatusCode(200)); + + // when . then + await this.restfulWebAssemblyApiClient.DeleteContentAsync( + relativeUrl: relativeUrl); + } + + [Fact] + private async Task ShouldDeleteContentCancellationTokenAsync() + { + // given + var cancellationToken = new CancellationToken(canceled: false); + + this.wiremockServer + .Given(Request.Create() + .WithPath(relativeUrl) + .UsingDelete()) + .RespondWith(Response.Create() + .WithStatusCode(200)); + + // when . then + await this.restfulWebAssemblyApiClient.DeleteContentAsync( + relativeUrl: relativeUrl, + cancellationToken: cancellationToken); + } + + [Fact] + private async Task ShouldDeleteContentReturnsExpectedContentDeserializeAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedDeletedTEntity = randomTEntity; + + this.wiremockServer + .Given(Request.Create() + .WithPath(relativeUrl) + .UsingDelete()) + .RespondWith(Response.Create() + .WithStatusCode(200) + .WithBodyAsJson(randomTEntity)); + + // when + TEntity actualDeletedTEntity = + await this.restfulWebAssemblyApiClient.DeleteContentAsync( + relativeUrl: relativeUrl, + deserializationFunction: DeserializationContentFunction); + + // then + actualDeletedTEntity.Should().BeEquivalentTo(expectedDeletedTEntity); + } + + [Fact] + private async Task ShouldDeleteContentReturnsExpectedContentCancellationTokenAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedDeletedTEntity = randomTEntity; + var cancellationToken = new CancellationToken(canceled: false); + + this.wiremockServer + .Given(Request.Create() + .WithPath(relativeUrl) + .UsingDelete()) + .RespondWith(Response.Create() + .WithStatusCode(200) + .WithBodyAsJson(randomTEntity)); + + // when + TEntity actualDeletedTEntity = + await this.restfulWebAssemblyApiClient.DeleteContentAsync( + relativeUrl: relativeUrl, + cancellationToken: cancellationToken); + + // then + actualDeletedTEntity.Should().BeEquivalentTo(expectedDeletedTEntity); + } + } +} \ No newline at end of file diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.GetContent.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.GetContent.cs new file mode 100644 index 0000000..ed9d776 --- /dev/null +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.GetContent.cs @@ -0,0 +1,112 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions; +using RESTFulSense.WebAssenbly.Tests.Acceptance.Models; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using Xunit; + +namespace RESTFulSense.WebAssenbly.Tests.Acceptance.Tests +{ + public partial class RestfulSenseWebAssemblyApiClientTests + { + [Fact] + private async Task ShouldGetContentWithDeserializationFunctionAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingGet()) + .RespondWith(Response.Create() + .WithStatusCode(200) + .WithBodyAsJson(expectedTEntity)); + + // when + TEntity actualTEntityEntity = + await this.restfulWebAssemblyApiClient.GetContentAsync( + relativeUrl: relativeUrl, + deserializationFunction: DeserializationContentFunction); + + // then + actualTEntityEntity.Should().BeEquivalentTo(expectedTEntity); + } + + [Fact] + private async Task ShouldCancelGetContentDeserializationIfCancellationInvokedAsync() + { + // given + TEntity someContent = GetRandomTEntity(); + var expectedCanceledTaskException = new TaskCanceledException(); + var taskCancelInvoked = new CancellationToken(canceled: true); + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingGet()) + .RespondWith(Response.Create() + .WithBodyAsJson(someContent)); + + // when + TaskCanceledException actualCanceledTask = + await Assert.ThrowsAsync(async () => + await this.restfulWebAssemblyApiClient.GetContentAsync( + relativeUrl: relativeUrl, + cancellationToken: taskCancelInvoked, + deserializationFunction: DeserializationContentFunction)); + + // then + actualCanceledTask.Should().BeEquivalentTo(expectedCanceledTaskException); + } + + [Fact] + private async Task ShouldReturnStringOnGetContentStringAsync() + { + // given + string someContent = CreateRandomContent(); + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingGet()) + .RespondWith(Response.Create() + .WithBody(someContent)); + + // when + string actualContent = + await this.restfulWebAssemblyApiClient.GetContentStringAsync(relativeUrl); + + // then + actualContent.Should().BeEquivalentTo(someContent); + } + + [Fact] + private async Task ShouldReturnStreamOnGetContentStreamAsync() + { + // given + string expectedContent = CreateRandomContent(); + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingGet()) + .RespondWith(Response.Create() + .WithBody(expectedContent)); + + // when + Stream expectedContentStream = + await this.restfulWebAssemblyApiClient.GetContentStreamAsync( + relativeUrl: relativeUrl); + + string actualReadStream = + await ReadStreamToEndAsync(expectedContentStream); + + // then + actualReadStream.Should().BeEquivalentTo(expectedContent); + } + } +} diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.PostContent.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.PostContent.cs new file mode 100644 index 0000000..45fcc48 --- /dev/null +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.PostContent.cs @@ -0,0 +1,255 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions; +using Newtonsoft.Json; +using RESTFulSense.WebAssenbly.Tests.Acceptance.Models; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using Xunit; + +namespace RESTFulSense.WebAssenbly.Tests.Acceptance.Tests +{ + public partial class RestfulSenseWebAssemblyApiClientTests + { + [Fact] + private async Task ShouldPostContentWithNoResponseAndDeserializeContentAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity inputTEntity = randomTEntity; + string mediaType = "application/json"; + bool ignoreDefaultValues = false; + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingPost()) + .RespondWith(Response.Create() + .WithStatusCode(200)); + + // when + Action actualResponseResult = async () => + await this.restfulWebAssemblyApiClient.PostContentWithNoResponseAsync( + relativeUrl: relativeUrl, + content: inputTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction); + + // then + actualResponseResult.Should().NotBeNull(); + } + + [Fact] + private async Task ShouldCancelPostContentWithNoResponseAndDeserializationWhenCancellationInvokedAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity returnedTEntity = randomTEntity; + var expectedPostContentCanceledException = new TaskCanceledException(); + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingPost()) + .RespondWith(Response.Create() + .WithHeader("Content-Type", "application/json") + .WithBodyAsJson(returnedTEntity)); + + // when + var taskCanceledToken = new CancellationToken(canceled: true); + + TaskCanceledException actualPostContentCanceledTask = + await Assert.ThrowsAsync(async () => + await this.restfulWebAssemblyApiClient.PostContentWithNoResponseAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + cancellationToken: taskCanceledToken, + mediaType: "application/json", + ignoreDefaultValues: true, + serializationFunction: SerializationContentFunction)); + + // then + actualPostContentCanceledTask.Should().NotBeNull(); + + actualPostContentCanceledTask.Should().BeEquivalentTo( + expectedPostContentCanceledException); + } + + [Fact] + private async Task ShouldPostContentReturnsContentWithCustomSerializationAndDeserializationAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity returnedTEntity = randomTEntity; + string mediaType = "application/json"; + bool ignoreDefaultValues = false; + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingPost()) + .RespondWith(Response.Create() + .WithStatusCode(200) + .WithBodyAsJson(returnedTEntity)); + + // when + TEntity actualTEntity = + await this.restfulWebAssemblyApiClient.PostContentAsync( + relativeUrl: relativeUrl, + content: returnedTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: DeserializationContentFunction); + + // then + actualTEntity.Should().BeEquivalentTo(returnedTEntity); + } + + [Fact] + private async Task ShouldCancelPostContentWhenCancellationIsInvokedAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity returnedTEntity = randomTEntity; + string mediaType = "application/json"; + bool ignoreDefaultValues = false; + + var expectedPostContentCanceledException = + new TaskCanceledException(); + + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingPost()) + .RespondWith(Response.Create() + .WithHeader("Content-Type", mediaType) + .WithBodyAsJson(returnedTEntity)); + + // when + var taskCanceledToken = new CancellationToken(canceled: true); + + TaskCanceledException actualCanceledTaskResult = + await Assert.ThrowsAsync(async () => + await this.restfulWebAssemblyApiClient.PostContentAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + cancellationToken: taskCanceledToken, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues)); + + // then + actualCanceledTaskResult.Should().BeEquivalentTo( + expectedPostContentCanceledException); + } + + [Fact] + private async Task ShouldPostContentWithStreamResponseAsync() + { + // given + string randomContent = CreateRandomContent(); + var cancellationToken = new CancellationToken(); + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingPost()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithHeader("Content-Type", mediaType) + .WithBody(randomContent)); + + // when + Stream actualContent = + await this.restfulWebAssemblyApiClient.PostContentWithStreamResponseAsync( + relativeUrl: relativeUrl, + content: randomContent, + cancellationToken: cancellationToken, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction); + + string actualReadContent = await ReadStreamToEndAsync(actualContent); + + // then + randomContent.Should().BeEquivalentTo(actualReadContent); + } + + [Fact] + private async Task ShouldPostContentWithTContentReturnsTResultAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + string expectedBody = JsonConvert.SerializeObject(randomTEntity); + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingPost()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithHeader("Content-Type", mediaType) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.restfulWebAssemblyApiClient.PostContentAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: DeserializationContentFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + + [Fact] + private async Task ShouldPostContentWithTContentReturnsTResultCancellationTokenAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + string expectedBody = JsonConvert.SerializeObject(randomTEntity); + var cancellationToken = new CancellationToken(); + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingPost()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithHeader("Content-Type", mediaType) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.restfulWebAssemblyApiClient.PostContentAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + cancellationToken: cancellationToken, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: DeserializationContentFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + } +} \ No newline at end of file diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.PutContent.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.PutContent.cs new file mode 100644 index 0000000..19bfe43 --- /dev/null +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.PutContent.cs @@ -0,0 +1,209 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions; +using Newtonsoft.Json; +using RESTFulSense.WebAssenbly.Tests.Acceptance.Models; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using Xunit; + +namespace RESTFulSense.WebAssenbly.Tests.Acceptance.Tests +{ + public partial class RestfulSenseWebAssemblyApiClientTests + { + [Fact] + private async Task ShouldPutContentReturnsExpectedWithSerializedAndDeserializedContentAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + + this.wiremockServer + .Given(Request.Create() + .WithPath(relativeUrl) + .UsingPut()) + .RespondWith(Response.Create() + .WithStatusCode(200) + .WithBodyAsJson(randomTEntity)); + + // when + TEntity actualTEntity = + await this.restfulWebAssemblyApiClient.PutContentAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: DeserializationContentFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + + [Fact] + private async Task ShouldCancelTaskOnPutContentReturnsContentIfCancellationInvokedAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + var expectedCanceledTaskException = new TaskCanceledException(); + var taskCancelInvoked = new CancellationToken(canceled: true); + + wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingPut()) + .RespondWith(Response.Create() + .WithBodyAsJson(randomTEntity)); + + // when + TaskCanceledException actualCanceledTask = + await Assert.ThrowsAsync(async () => + await this.restfulWebAssemblyApiClient.PutContentAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + cancellationToken: taskCancelInvoked, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: DeserializationContentFunction)); + + // then + actualCanceledTask.Should().BeEquivalentTo(expectedCanceledTaskException); + } + + [Fact] + private async Task ShouldPutContentWithTContentReturnsTResultAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + string expectedBody = JsonConvert.SerializeObject(randomTEntity); + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingPut()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithHeader("Content-Type", mediaType) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.restfulWebAssemblyApiClient.PutContentAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: DeserializationContentFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + + [Fact] + private async Task ShouldPutContentWithTContentReturnsTResultWithCancellationTokenAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + string expectedBody = JsonConvert.SerializeObject(randomTEntity); + CancellationToken cancellationToken = + new CancellationToken(canceled: false); + + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingPut()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithHeader("Content-Type", mediaType) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.restfulWebAssemblyApiClient.PutContentAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + cancellationToken: cancellationToken, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: DeserializationContentFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + + [Fact] + private async Task ShouldPutContentReturnsContentWithDeserializationAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + string expectedBody = JsonConvert.SerializeObject(randomTEntity); + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingPut()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.restfulWebAssemblyApiClient.PutContentAsync( + relativeUrl: relativeUrl, + deserializationFunction: DeserializationContentFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + + [Fact] + private async Task ShouldPutContentReturnsContentWithCancellationTokenDeserializationAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + string expectedBody = JsonConvert.SerializeObject(randomTEntity); + var cancellationToken = new CancellationToken(canceled: false); + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingPut()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.restfulWebAssemblyApiClient.PutContentAsync( + relativeUrl: relativeUrl, + cancellationToken: cancellationToken, + deserializationFunction: DeserializationContentFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + } +} \ No newline at end of file diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.cs new file mode 100644 index 0000000..c69d86b --- /dev/null +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.cs @@ -0,0 +1,83 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using System.IO; +using System.Text.Json; +using System.Threading.Tasks; +using RESTFulSense.WebAssembly.Clients; +using RESTFulSense.WebAssenbly.Tests.Acceptance.Models; +using Tynamix.ObjectFiller; +using WireMock.Server; + +namespace RESTFulSense.WebAssenbly.Tests.Acceptance.Tests +{ + public partial class RestfulSenseWebAssemblyApiClientTests : IDisposable + { + private readonly WireMockServer wiremockServer; + private const string relativeUrl = "/tests"; + private readonly RESTFulApiClient restfulWebAssemblyApiClient; + + public RestfulSenseWebAssemblyApiClientTests() + { + this.wiremockServer = WireMockServer.Start(); + this.restfulWebAssemblyApiClient = new RESTFulApiClient(); + + this.restfulWebAssemblyApiClient.BaseAddress = new Uri( + this.wiremockServer.Urls[0]); + } + + private async Task ReadStreamToEndAsync(Stream result) + { + var reader = new StreamReader(result, leaveOpen: false); + + return await reader.ReadToEndAsync(); + } + + private static ValueTask SerializationContentFunction(TEntity entityContent) + { + string jsonContent = JsonSerializer.Serialize(entityContent); + + return new ValueTask(jsonContent); + } + + private static string CreateRandomContent() + { + var randomContent = new Lipsum( + LipsumFlavor.LoremIpsum, + minWords: 3, + maxWords: 10); + + return randomContent.ToString(); + } + + private static Func> DeserializationContentFunction + { + get + { + return async (entityContent) => + await Task.FromResult(JsonSerializer.Deserialize( + entityContent)); + } + } + + private static TEntity GetRandomTEntity() => + CreateTEntityFiller(GetTestDateTimeOffset()).Create(); + + private static DateTimeOffset GetTestDateTimeOffset() => + new DateTimeOffset(DateTime.Now); + + private static Filler CreateTEntityFiller(DateTimeOffset dates) + { + var filler = new Filler(); + + filler.Setup() + .OnType().Use(dates); + + return filler; + } + + public void Dispose() => this.wiremockServer.Stop(); + } +} \ No newline at end of file diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.DeleteContent.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.DeleteContent.cs new file mode 100644 index 0000000..62e6a0d --- /dev/null +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.DeleteContent.cs @@ -0,0 +1,103 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions; +using RESTFulSense.WebAssenbly.Tests.Acceptance.Models; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using Xunit; + +namespace RESTFulSense.WebAssenbly.Tests.Acceptance.Tests +{ + public partial class RestfulSenseWebAssemblyFactoryApiClientTests + { + [Fact] + private async Task ShouldDeleteContentAsync() + { + // given + this.wiremockServer + .Given(Request.Create() + .WithPath(relativeUrl) + .UsingDelete()) + .RespondWith(Response.Create() + .WithStatusCode(200)); + + // when . then + await this.webAssemblyApiFactoryClient.DeleteContentAsync( + relativeUrl: relativeUrl); + } + + [Fact] + private async Task ShouldDeleteContentCancellationTokenAsync() + { + // given + var cancellationToken = new CancellationToken(canceled: false); + + this.wiremockServer + .Given(Request.Create() + .WithPath(relativeUrl) + .UsingDelete()) + .RespondWith(Response.Create() + .WithStatusCode(200)); + + // when . then + await this.webAssemblyApiFactoryClient.DeleteContentAsync( + relativeUrl: relativeUrl, + cancellationToken: cancellationToken); + } + + [Fact] + private async Task ShouldDeleteContentReturnsExpectedContentDeserializeAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedDeletedTEntity = randomTEntity; + + this.wiremockServer + .Given(Request.Create() + .WithPath(relativeUrl) + .UsingDelete()) + .RespondWith(Response.Create() + .WithStatusCode(200) + .WithBodyAsJson(randomTEntity)); + + // when + TEntity actualDeletedTEntity = + await this.webAssemblyApiFactoryClient.DeleteContentAsync( + relativeUrl: relativeUrl, + deserializationFunction: ContentDeserializationFunction); + + // then + actualDeletedTEntity.Should().BeEquivalentTo(expectedDeletedTEntity); + } + + [Fact] + private async Task ShouldDeleteContentReturnsExpectedContentCancellationTokenAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedDeletedTEntity = randomTEntity; + var cancellationToken = new CancellationToken(canceled: false); + + this.wiremockServer + .Given(Request.Create() + .WithPath(relativeUrl) + .UsingDelete()) + .RespondWith(Response.Create() + .WithStatusCode(200) + .WithBodyAsJson(randomTEntity)); + + // when + TEntity actualDeletedTEntity = + await this.webAssemblyApiFactoryClient.DeleteContentAsync( + relativeUrl: relativeUrl, + cancellationToken: cancellationToken); + + // then + actualDeletedTEntity.Should().BeEquivalentTo(expectedDeletedTEntity); + } + } +} \ No newline at end of file diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.GetContent.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.GetContent.cs new file mode 100644 index 0000000..800f85a --- /dev/null +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.GetContent.cs @@ -0,0 +1,113 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions; +using RESTFulSense.WebAssenbly.Tests.Acceptance.Models; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using Xunit; + +namespace RESTFulSense.WebAssenbly.Tests.Acceptance.Tests +{ + public partial class RestfulSenseWebAssemblyFactoryApiClientTests + { + [Fact] + private async Task ShouldGetContentWithDeserializationFunctionAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedReponseEntity = randomTEntity; + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingGet()) + .RespondWith(Response.Create() + .WithStatusCode(200) + .WithBodyAsJson(expectedReponseEntity)); + + // when + TEntity actualTEntity = + await this.webAssemblyApiFactoryClient.GetContentAsync( + relativeUrl: relativeUrl, + deserializationFunction: ContentDeserializationFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedReponseEntity); + } + + [Fact] + private async Task ShouldCancelGetContentDeserializationIfCancellationInvokedAsync() + { + // given + TEntity someContent = GetRandomTEntity(); + var expectedCanceledTaskException = new TaskCanceledException(); + var taskCancelInvoked = new CancellationToken(canceled: true); + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingGet()) + .RespondWith(Response.Create() + .WithBodyAsJson(someContent)); + + // when + TaskCanceledException actualCanceledTask = + await Assert.ThrowsAsync(async () => + await this.webAssemblyApiFactoryClient.GetContentAsync( + relativeUrl: relativeUrl, + cancellationToken: taskCancelInvoked, + deserializationFunction: ContentDeserializationFunction)); + + // then + actualCanceledTask.Should().BeEquivalentTo(expectedCanceledTaskException); + } + + [Fact] + private async Task ShouldReturnStringOnGetContentStringAsync() + { + // given + string someContent = CreateRandomContent(); + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingGet()) + .RespondWith(Response.Create() + .WithBody(someContent)); + + // when + string actualContent = + await this.webAssemblyApiFactoryClient.GetContentStringAsync( + relativeUrl: relativeUrl); + + // then + actualContent.Should().BeEquivalentTo(someContent); + } + + [Fact] + private async Task ShouldReturnStreamOnGetContentStreamAsync() + { + // given + string expectedContent = CreateRandomContent(); + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingGet()) + .RespondWith(Response.Create() + .WithBody(expectedContent)); + + // when + Stream expectedContentStream = + await this.webAssemblyApiFactoryClient.GetContentStreamAsync( + relativeUrl: relativeUrl); + + var actualReadStream = await ReadStreamToEndAsync( + expectedContentStream); + + // then + actualReadStream.Should().BeEquivalentTo(expectedContent); + } + } +} \ No newline at end of file diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.PostContent.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.PostContent.cs new file mode 100644 index 0000000..3d979e6 --- /dev/null +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.PostContent.cs @@ -0,0 +1,220 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions; +using Newtonsoft.Json; +using RESTFulSense.WebAssenbly.Tests.Acceptance.Models; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using Xunit; + +namespace RESTFulSense.WebAssenbly.Tests.Acceptance.Tests +{ + public partial class RestfulSenseWebAssemblyFactoryApiClientTests + { + [Fact] + private async Task ShouldPostContentWithNoResponseAndDeserializeContentAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + string mediaType = "application/json"; + bool ignoreDefaultValues = false; + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingPost()) + .RespondWith(Response.Create() + .WithStatusCode(200)); + + // when + Action actualResponseResult = async () => + await this.webAssemblyApiFactoryClient.PostContentWithNoResponseAsync( + relativeUrl: relativeUrl, + content: expectedTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction); + + // then + actualResponseResult.Should().NotBeNull(); + } + + [Fact] + private async Task ShouldCancelPostContentWithNoResponseAndDeserializationWhenCancellationInvokedAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity returnedTEntity = randomTEntity; + var expectedPostContentCanceledException = new TaskCanceledException(); + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingPost()) + .RespondWith(Response.Create() + .WithHeader("Content-Type", "application/json") + .WithBodyAsJson(returnedTEntity)); + + // when + var taskCanceledToken = new CancellationToken(canceled: true); + + TaskCanceledException actualPostContentCanceledTask = + await Assert.ThrowsAsync(async () => + await this.webAssemblyApiFactoryClient.PostContentWithNoResponseAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + cancellationToken: taskCanceledToken, + mediaType: "application/json", + ignoreDefaultValues: true, + serializationFunction: SerializationContentFunction)); + + // then + actualPostContentCanceledTask.Should().NotBeNull(); + + actualPostContentCanceledTask.Should().BeEquivalentTo( + expectedPostContentCanceledException); + } + + [Fact] + private async Task ShouldPostContentReturnsContentWithCustomSerializationAndDeserializationAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + var returnedTEntity = randomTEntity; + string mediaType = "application/json"; + bool ignoreDefaultValues = false; + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingPost()) + .RespondWith(Response.Create() + .WithStatusCode(200) + .WithBodyAsJson(returnedTEntity)); + + // when + TEntity actualTEntity = + await this.webAssemblyApiFactoryClient.PostContentAsync( + relativeUrl: relativeUrl, + content: returnedTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: ContentDeserializationFunction); + + // then + actualTEntity.Should().BeEquivalentTo(returnedTEntity); + } + + [Fact] + private async Task ShouldCancelPostContentWhenCancellationIsInvokedAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity returnedTEntity = randomTEntity; + string mediaType = "application/json"; + bool ignoreDefaultValues = false; + + var expectedPostContentCanceledException = new TaskCanceledException(); + + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingPost()) + .RespondWith(Response.Create() + .WithHeader("Content-Type", mediaType) + .WithBodyAsJson(returnedTEntity)); + + // when + var taskCanceledToken = new CancellationToken(canceled: true); + + TaskCanceledException actualCanceledTaskResult = + await Assert.ThrowsAsync(async () => + await this.webAssemblyApiFactoryClient.PostContentAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + cancellationToken: taskCanceledToken, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues)); + + // then + actualCanceledTaskResult.Should().BeEquivalentTo( + expectedPostContentCanceledException); + } + + [Fact] + private async Task ShouldPostContentWithStreamResponseAsync() + { + // given + string randomContent = CreateRandomContent(); + var cancellationToken = new CancellationToken(); + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingPost()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithHeader("Content-Type", mediaType) + .WithBody(randomContent)); + + // when + Stream actualStream = + await this.webAssemblyApiFactoryClient.PostContentWithStreamResponseAsync( + relativeUrl: relativeUrl, + content: randomContent, + cancellationToken: cancellationToken, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction); + + string actualReadContent = await ReadStreamToEndAsync(actualStream); + + // then + actualReadContent.Should().BeEquivalentTo(randomContent); + } + + [Fact] + private async Task ShouldPostContentWithTContentReturnsTResultAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + + string expectedBody = + JsonConvert.SerializeObject(randomTEntity); + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingPost()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithHeader("Content-Type", mediaType) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.webAssemblyApiFactoryClient.PostContentAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: ContentDeserializationFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + } +} \ No newline at end of file diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.PutContent.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.PutContent.cs new file mode 100644 index 0000000..091a142 --- /dev/null +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.PutContent.cs @@ -0,0 +1,210 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions; +using RESTFulSense.WebAssenbly.Tests.Acceptance.Models; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using Xunit; + +namespace RESTFulSense.WebAssenbly.Tests.Acceptance.Tests +{ + public partial class RestfulSenseWebAssemblyFactoryApiClientTests + { + [Fact] + private async Task ShouldPutContentReturnsExpectedWithSerializedAndDeserializedContentAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + + this.wiremockServer + .Given(Request.Create() + .WithPath(relativeUrl) + .UsingPut()) + .RespondWith(Response.Create() + .WithStatusCode(200) + .WithBodyAsJson(randomTEntity)); + + // when + TEntity actualTEntity = + await this.webAssemblyApiFactoryClient.PutContentAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: ContentDeserializationFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + + [Fact] + private async Task ShouldCancelTaskOnPutContentReturnsContentIfCancellationInvokedAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + var expectedCanceledTaskException = new TaskCanceledException(); + var taskCancelInvoked = new CancellationToken(canceled: true); + + wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingPut()) + .RespondWith(Response.Create() + .WithBodyAsJson(randomTEntity)); + + // when + TaskCanceledException actualCanceledTask = + await Assert.ThrowsAsync(async () => + await this.webAssemblyApiFactoryClient.PutContentAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + cancellationToken: taskCancelInvoked, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: ContentDeserializationFunction)); + + // then + actualCanceledTask.Should().BeEquivalentTo(expectedCanceledTaskException); + } + + [Fact] + private async Task ShouldPutContentWithTContentReturnsTResultAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + string expectedBody = JsonSerializer.Serialize(randomTEntity); + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingPut()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithHeader("Content-Type", mediaType) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.webAssemblyApiFactoryClient.PutContentAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: ContentDeserializationFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + + [Fact] + private async Task ShouldPutContentWithTContentReturnsTResultWithCancellationTokenAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + string expectedBody = JsonSerializer.Serialize(randomTEntity); + + CancellationToken cancellationToken = + new CancellationToken(canceled: false); + + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingPut()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithHeader("Content-Type", mediaType) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.webAssemblyApiFactoryClient.PutContentAsync( + relativeUrl: relativeUrl, + content: randomTEntity, + cancellationToken: cancellationToken, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: ContentDeserializationFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + + [Fact] + private async Task ShouldPutContentReturnsContentWithDeserializationAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + string expectedBody = JsonSerializer.Serialize(randomTEntity); + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingPut()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.webAssemblyApiFactoryClient.PutContentAsync( + relativeUrl: relativeUrl, + deserializationFunction: ContentDeserializationFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + + [Fact] + private async Task ShouldPutContentReturnsContentWithCancellationTokenDeserializationAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity expectedTEntity = randomTEntity; + string expectedBody = JsonSerializer.Serialize(randomTEntity); + var cancellationToken = new CancellationToken(canceled: false); + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingPut()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.webAssemblyApiFactoryClient.PutContentAsync( + relativeUrl: relativeUrl, + cancellationToken: cancellationToken, + deserializationFunction: ContentDeserializationFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + } +} \ No newline at end of file diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.cs new file mode 100644 index 0000000..108f5b1 --- /dev/null +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.cs @@ -0,0 +1,86 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using System.IO; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using RESTFulSense.WebAssembly.Clients; +using RESTFulSense.WebAssenbly.Tests.Acceptance.Models; +using Tynamix.ObjectFiller; +using WireMock.Server; + +namespace RESTFulSense.WebAssenbly.Tests.Acceptance.Tests +{ + public partial class RestfulSenseWebAssemblyFactoryApiClientTests : IDisposable + { + private readonly IRESTFulApiFactoryClient webAssemblyApiFactoryClient; + private readonly HttpClient httpClient; + private readonly WireMockServer wiremockServer; + private const string relativeUrl = "/tests"; + + public RestfulSenseWebAssemblyFactoryApiClientTests() + { + this.wiremockServer = WireMockServer.Start(); + + this.httpClient = + new HttpClient { BaseAddress = new Uri(wiremockServer.Urls[0]) }; + + this.webAssemblyApiFactoryClient = new RESTFulApiFactoryClient(httpClient); + } + + private async Task ReadStreamToEndAsync(Stream result) + { + var reader = new StreamReader(result, leaveOpen: false); + + return await reader.ReadToEndAsync(); + } + + private static ValueTask SerializationContentFunction(TEntity entityContent) + { + string jsonContent = JsonSerializer.Serialize(entityContent); + + return new ValueTask(jsonContent); + } + + private static string CreateRandomContent() + { + var randomContent = new Lipsum( + LipsumFlavor.LoremIpsum, + minWords: 3, + maxWords: 10); + + return randomContent.ToString(); + } + + private static Func> ContentDeserializationFunction + { + get + { + return async (entityContent) => + await Task.FromResult(JsonSerializer.Deserialize( + entityContent)); + } + } + + private static TEntity GetRandomTEntity() => + CreateTEntityFiller(GetTestDateTimeOffset()).Create(); + + private static DateTimeOffset GetTestDateTimeOffset() => + new DateTimeOffset(DateTime.Now); + + private static Filler CreateTEntityFiller(DateTimeOffset dates) + { + var filler = new Filler(); + + filler.Setup() + .OnType().Use(dates); + + return filler; + } + + public void Dispose() => this.wiremockServer.Stop(); + } +} \ No newline at end of file diff --git a/RESTFulSense.sln b/RESTFulSense.sln index 19c1e62..3a3dc4f 100644 --- a/RESTFulSense.sln +++ b/RESTFulSense.sln @@ -21,6 +21,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RESTFulSense.WebAssembly.Te EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RESTFulSense.Tests.Acceptance", "RESTFulSense.Tests.Acceptance\RESTFulSense.Tests.Acceptance.csproj", "{90C7D1B5-7018-4FC4-A587-F546370D4411}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RESTFulSense.WebAssenbly.Tests.Acceptance", "RESTFulSense.WebAssenbly.Tests.Acceptance\RESTFulSense.WebAssenbly.Tests.Acceptance.csproj", "{4426B394-62EE-4937-B6A8-0208893A8969}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -51,6 +53,10 @@ Global {90C7D1B5-7018-4FC4-A587-F546370D4411}.Debug|Any CPU.Build.0 = Debug|Any CPU {90C7D1B5-7018-4FC4-A587-F546370D4411}.Release|Any CPU.ActiveCfg = Release|Any CPU {90C7D1B5-7018-4FC4-A587-F546370D4411}.Release|Any CPU.Build.0 = Release|Any CPU + {4426B394-62EE-4937-B6A8-0208893A8969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4426B394-62EE-4937-B6A8-0208893A8969}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4426B394-62EE-4937-B6A8-0208893A8969}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4426B394-62EE-4937-B6A8-0208893A8969}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE