From ae4330726295922d64d3ddfa0547b9c9d702b11f Mon Sep 17 00:00:00 2001 From: Robert Bjarum Date: Tue, 27 Jun 2023 15:19:12 +0200 Subject: [PATCH 1/2] Added methods to assert Method Not Allowed response code 405 --- .../HttpClientDeleteExtensionMethods.cs | 17 +++++++++++++++++ .../HttpClientGetExtensionMethods.cs | 17 +++++++++++++++++ .../HttpClientPostExtensionMethods.cs | 19 +++++++++++++++++++ .../HttpClientPutExtensionMethods.cs | 19 ++++++++++++++++++- .../HttpResponseMessageExtensionMethods.cs | 10 ++++++++++ .../docs/README.md | 15 +++++++++++++++ .../MethodNotAllowedEndpoints/NoDelete.cs | 17 +++++++++++++++++ .../MethodNotAllowedEndpoints/NoGet.cs | 17 +++++++++++++++++ .../MethodNotAllowedEndpoints/NoPost.cs | 17 +++++++++++++++++ .../MethodNotAllowedEndpoints/NoPut.cs | 18 ++++++++++++++++++ .../wwwroot/index.html | 10 ++++++++++ .../HttpClientDeleteExtensionMethodsTests.cs | 8 ++++++++ .../HttpClientGetExtensionMethodsTests.cs | 6 ++++++ .../HttpClientPostExtensionMethodsTests.cs | 8 ++++++++ .../HttpClientPutExtensionMethodsTests.cs | 8 ++++++++ 15 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoDelete.cs create mode 100644 tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoGet.cs create mode 100644 tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoPost.cs create mode 100644 tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoPut.cs create mode 100644 tests/Ardalis.HttpClientTestExtensions.Api/wwwroot/index.html diff --git a/src/Ardalis.HttpClientTestExtensions/HttpClientDeleteExtensionMethods.cs b/src/Ardalis.HttpClientTestExtensions/HttpClientDeleteExtensionMethods.cs index 1c381f9..82431c2 100644 --- a/src/Ardalis.HttpClientTestExtensions/HttpClientDeleteExtensionMethods.cs +++ b/src/Ardalis.HttpClientTestExtensions/HttpClientDeleteExtensionMethods.cs @@ -46,6 +46,23 @@ public static async Task DeleteAndEnsureNotFoundAsync( return response; } + /// + /// Ensures a DELETE to a requestUri returns a 405 Method Not Allowed response status code + /// + /// + /// + /// Optional; used to provide details to standard output. + /// + public static async Task DeleteAndEnsureMethodNotAllowedAsync( + this HttpClient client, + string requestUri, + ITestOutputHelper output = null) + { + var response = await client.DeleteAsync(requestUri, output); + response.EnsureMethodNotAllowed(); + return response; + } + /// /// Ensures a DELETE to a requestUri returns a 204 No Content response status code /// diff --git a/src/Ardalis.HttpClientTestExtensions/HttpClientGetExtensionMethods.cs b/src/Ardalis.HttpClientTestExtensions/HttpClientGetExtensionMethods.cs index 4ec391d..0255863 100644 --- a/src/Ardalis.HttpClientTestExtensions/HttpClientGetExtensionMethods.cs +++ b/src/Ardalis.HttpClientTestExtensions/HttpClientGetExtensionMethods.cs @@ -48,6 +48,23 @@ public static async Task GetAndEnsureNotFoundAsync( return response; } + /// + /// Ensures a GET to a requestUri returns a 405 Method Not Allowed response status code + /// + /// + /// + /// Optional; used to provide details to standard output. + /// + public static async Task GetAndEnsureMethodNotAllowedAsync( + this HttpClient client, + string requestUri, + ITestOutputHelper output = null) + { + var response = await client.GetAsync(requestUri, output); + response.EnsureMethodNotAllowed(); + return response; + } + /// /// Makes a GET request to a requestUri and returns the response string /// diff --git a/src/Ardalis.HttpClientTestExtensions/HttpClientPostExtensionMethods.cs b/src/Ardalis.HttpClientTestExtensions/HttpClientPostExtensionMethods.cs index ac4f1b8..08a5ac9 100644 --- a/src/Ardalis.HttpClientTestExtensions/HttpClientPostExtensionMethods.cs +++ b/src/Ardalis.HttpClientTestExtensions/HttpClientPostExtensionMethods.cs @@ -88,6 +88,25 @@ public static async Task PostAndEnsureForbiddenAsync( return response; } + /// + /// Ensures a POST to a requestUri returns a 405 Method Not Allowed response status code + /// + /// + /// + /// + /// Optional; used to provide details to standard output. + /// + public static async Task PostAndEnsureMethodNotAllowedAsync( + this HttpClient client, + string requestUri, + HttpContent content, + ITestOutputHelper output = null) + { + var response = await client.PostAsync(requestUri, content, output); + response.EnsureMethodNotAllowed(); + return response; + } + /// /// Makes a POST request to a requestUri and ensures the response contains a substring /// diff --git a/src/Ardalis.HttpClientTestExtensions/HttpClientPutExtensionMethods.cs b/src/Ardalis.HttpClientTestExtensions/HttpClientPutExtensionMethods.cs index 2940a8d..a7f1168 100644 --- a/src/Ardalis.HttpClientTestExtensions/HttpClientPutExtensionMethods.cs +++ b/src/Ardalis.HttpClientTestExtensions/HttpClientPutExtensionMethods.cs @@ -31,7 +31,6 @@ public static async Task PutAndDeserializeAsync( return result; } - /// /// Ensures a PUT to a requestUri returns a 404 Not Found response status code /// @@ -50,6 +49,24 @@ public static async Task PutAndEnsureNotFoundAsync(this Htt return response; } + /// + /// Ensures a PUT to a requestUri returns a 405 Method Not Allowed response status code + /// + /// + /// + /// + /// Optional; used to provide details to standard output. + /// + public static async Task PutAndEnsureMethodNotAllowedAsync(this HttpClient client, + string requestUri, + HttpContent content, + ITestOutputHelper output = null) + { + var response = await client.PutAsync(requestUri, content, output); + response.EnsureMethodNotAllowed(); + return response; + } + /// /// Ensures a PUT to a requestUri returns a 401 Unauthorized response status code /// diff --git a/src/Ardalis.HttpClientTestExtensions/HttpResponseMessageExtensionMethods.cs b/src/Ardalis.HttpClientTestExtensions/HttpResponseMessageExtensionMethods.cs index 0b1f425..9735d7f 100644 --- a/src/Ardalis.HttpClientTestExtensions/HttpResponseMessageExtensionMethods.cs +++ b/src/Ardalis.HttpClientTestExtensions/HttpResponseMessageExtensionMethods.cs @@ -17,6 +17,16 @@ public static void EnsureNotFound(this HttpResponseMessage response) response.Ensure(HttpStatusCode.NotFound); } + /// + /// Ensures a response has a status code 405 Method Not Allowed + /// + /// + /// + public static void EnsureMethodNotAllowed(this HttpResponseMessage response) + { + response.Ensure(HttpStatusCode.MethodNotAllowed); + } + /// /// Ensures a response has a status code 204 No Content /// diff --git a/src/Ardalis.HttpClientTestExtensions/docs/README.md b/src/Ardalis.HttpClientTestExtensions/docs/README.md index 16f0597..e156116 100644 --- a/src/Ardalis.HttpClientTestExtensions/docs/README.md +++ b/src/Ardalis.HttpClientTestExtensions/docs/README.md @@ -109,6 +109,9 @@ await client.GetAndEnsureForbiddenAsync("/authors/1"); // GET and assert a 404 is returned await client.GetAndEnsureNotFoundAsync("/authors/-1"); + +// GET and assert a 405 is returned +await client.GetAndEnsureMethodNotAllowedAsync("/wrongendpoint", content) ``` #### [POST](src\Ardalis.HttpClientTestExtensions\HttpClientPostExtensionMethods.cs) @@ -138,6 +141,9 @@ await client.PostAndEnsureForbiddenAsync("/authors", content); // POST and assert a 404 is returned await client.PostAndEnsureNotFoundAsync("/wrongendpoint", content) + +// POST and assert a 405 is returned +await client.PostAndEnsureMethodNotAllowedAsync("/wrongendpoint", content) ``` #### [PUT](src\Ardalis.HttpClientTestExtensions\HttpClientPutExtensionMethods.cs) @@ -166,6 +172,9 @@ await client.PutAndEnsureForbiddenAsync("/authors/1", content); // PUT and assert a 404 is returned await client.PutAndEnsureNotFoundAsync("/wrongendpoint", content) + +// PUT and assert a 405 is returned +await client.PutAndEnsureMethodNotAllowedAsync("/wrongendpoint", content) ``` #### [DELETE](src\Ardalis.HttpClientTestExtensions\HttpClientDeleteExtensionMethods.cs) @@ -195,6 +204,9 @@ await client.DeleteAndEnsureForbiddenAsync("/authors/1"); // DELETE and assert a 404 is returned await client.DeleteAndEnsureNotFoundAsync("/wrongendpoint"); + +// DELETE and assert a 405 is returned +await client.DeleteAndEnsureMethodNotAllowedAsync("/wrongendpoint", content) ``` ### [HttpResponseMessage](src\Ardalis.HttpClientTestExtensions\HttpResponseMessageExtensionMethods.cs) @@ -220,6 +232,9 @@ response.EnsureForbidden(); // Assert a response has a status code of 404 response.EnsureNotFound(); +// Assert a response has a status code of 405 +response.EnsureMethodNotAllowed(); + // Assert a response has a given status code response.Ensure(HttpStatusCode.Created); diff --git a/tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoDelete.cs b/tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoDelete.cs new file mode 100644 index 0000000..05d52aa --- /dev/null +++ b/tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoDelete.cs @@ -0,0 +1,17 @@ +using Ardalis.ApiEndpoints; +using Microsoft.AspNetCore.Mvc; + +namespace Ardalis.HttpClientTestExtensions.Api.Endpoints.MethodNotAllowedEndpoints; + +public class NoDelete : EndpointBaseSync + .WithoutRequest + .WithResult + +{ + [Route("/nodelete")] + [AcceptVerbs("GET", "PUT", "POST")] + public override NoContentResult Handle() + { + return NoContent(); + } +} diff --git a/tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoGet.cs b/tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoGet.cs new file mode 100644 index 0000000..0621b25 --- /dev/null +++ b/tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoGet.cs @@ -0,0 +1,17 @@ +using Ardalis.ApiEndpoints; +using Microsoft.AspNetCore.Mvc; + +namespace Ardalis.HttpClientTestExtensions.Api.Endpoints.MethodNotAllowedEndpoints; + +public class NoGet : EndpointBaseSync + .WithoutRequest + .WithResult + +{ + [Route("/noget")] + [AcceptVerbs("DELETE", "PUT", "POST")] + public override NoContentResult Handle() + { + return NoContent(); + } +} diff --git a/tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoPost.cs b/tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoPost.cs new file mode 100644 index 0000000..5c8b886 --- /dev/null +++ b/tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoPost.cs @@ -0,0 +1,17 @@ +using Ardalis.ApiEndpoints; +using Microsoft.AspNetCore.Mvc; + +namespace Ardalis.HttpClientTestExtensions.Api.Endpoints.ErrorEndpoints; + +public class NoPost : EndpointBaseSync + .WithoutRequest + .WithResult + +{ + [Route("/nopost")] + [AcceptVerbs("DELETE", "PUT", "GET")] + public override NoContentResult Handle() + { + return NoContent(); + } +} diff --git a/tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoPut.cs b/tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoPut.cs new file mode 100644 index 0000000..e52635f --- /dev/null +++ b/tests/Ardalis.HttpClientTestExtensions.Api/Endpoints/MethodNotAllowedEndpoints/NoPut.cs @@ -0,0 +1,18 @@ +using Ardalis.ApiEndpoints; +using Microsoft.AspNetCore.Mvc; + +namespace Ardalis.HttpClientTestExtensions.Api.Endpoints.ErrorEndpoints; + +public class NoPut : EndpointBaseSync + .WithoutRequest + .WithResult + +{ + [Route("/noput")] + [AcceptVerbs("DELETE", "GET", "POST")] + public override NoContentResult Handle() + { + return NoContent(); + } + +} diff --git a/tests/Ardalis.HttpClientTestExtensions.Api/wwwroot/index.html b/tests/Ardalis.HttpClientTestExtensions.Api/wwwroot/index.html new file mode 100644 index 0000000..d51c184 --- /dev/null +++ b/tests/Ardalis.HttpClientTestExtensions.Api/wwwroot/index.html @@ -0,0 +1,10 @@ + + + + + Static Page + + +

Static Page

+ + \ No newline at end of file diff --git a/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientDeleteExtensionMethodsTests.cs b/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientDeleteExtensionMethodsTests.cs index dd9cbdf..a5c4293 100644 --- a/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientDeleteExtensionMethodsTests.cs +++ b/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientDeleteExtensionMethodsTests.cs @@ -89,4 +89,12 @@ public async Task DeleteAndRedirectAsync() var client = _factory.CreateClient(new WebApplicationFactoryClientOptions() { AllowAutoRedirect = false }); _ = await client.DeleteAndRedirectAsync("/redirect", "/redirected", _outputHelper); } + + [Fact] + public async Task DeleteAndEnsureMethodNotAllowedAsync() + { + var client = _factory.CreateClient(new WebApplicationFactoryClientOptions() { AllowAutoRedirect = false }); + _ = await client.DeleteAndEnsureMethodNotAllowedAsync("/nodelete", _outputHelper); + } + } diff --git a/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientGetExtensionMethodsTests.cs b/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientGetExtensionMethodsTests.cs index 9081be0..a8ca622 100644 --- a/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientGetExtensionMethodsTests.cs +++ b/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientGetExtensionMethodsTests.cs @@ -82,6 +82,12 @@ public async Task GetAndEnsureBadRequestAsync() _ = await _client.GetAndEnsureBadRequestAsync("/badrequest", _outputHelper); } + [Fact] + public async Task GetAndEnsureMethodNotAllowedAsync() + { + _ = await _client.GetAndEnsureMethodNotAllowedAsync("/noget", _outputHelper); + } + [Fact] public async Task GetAndRedirectAsync() { diff --git a/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientPostExtensionMethodsTests.cs b/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientPostExtensionMethodsTests.cs index 8c71e03..a5ebf0f 100644 --- a/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientPostExtensionMethodsTests.cs +++ b/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientPostExtensionMethodsTests.cs @@ -86,4 +86,12 @@ public async Task PostAndRedirectAsync() var client = _factory.CreateClient(new WebApplicationFactoryClientOptions() { AllowAutoRedirect = false }); _ = await client.PostAndRedirectAsync("/redirect", content, "/redirected", _outputHelper); } + + [Fact] + public async Task PostAndEnsureMethodNotAllowedAsync() + { + var dto = new CountryDto { Id = "ESP", Name = "Spain" }; + var content = new StringContent(JsonSerializer.Serialize(dto), Encoding.UTF8, "application/json"); + _ = await _client.PostAndEnsureMethodNotAllowedAsync("/nopost", content, _outputHelper); + } } diff --git a/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientPutExtensionMethodsTests.cs b/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientPutExtensionMethodsTests.cs index 6386da0..061a615 100644 --- a/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientPutExtensionMethodsTests.cs +++ b/tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientPutExtensionMethodsTests.cs @@ -76,6 +76,14 @@ public async Task PutAndEnsureBadRequestAsync() _ = await _client.PutAndEnsureBadRequestAsync("/badrequest", content, _outputHelper); } + [Fact] + public async Task PutAndEnsureMethodNotAllowedAsync() + { + var dto = new CountryDto { Id = SeedData.TestCountry1.Id, Name = "'Merica" }; + var content = new StringContent(JsonSerializer.Serialize(dto), Encoding.UTF8, "application/json"); + _ = await _client.PutAndEnsureMethodNotAllowedAsync("/noput", content, _outputHelper); + } + [Fact] public async Task PutAndRedirectAsync() { From 7154fe567fb798ac17e791a3d7451c6c318cb9c7 Mon Sep 17 00:00:00 2001 From: Robert Bjarum Date: Tue, 27 Jun 2023 15:29:45 +0200 Subject: [PATCH 2/2] Deleted index.html that was added by a mistake --- .../wwwroot/index.html | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 tests/Ardalis.HttpClientTestExtensions.Api/wwwroot/index.html diff --git a/tests/Ardalis.HttpClientTestExtensions.Api/wwwroot/index.html b/tests/Ardalis.HttpClientTestExtensions.Api/wwwroot/index.html deleted file mode 100644 index d51c184..0000000 --- a/tests/Ardalis.HttpClientTestExtensions.Api/wwwroot/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Static Page - - -

Static Page

- - \ No newline at end of file