diff --git a/FluentAssertions.Web.sln b/FluentAssertions.Web.sln index 7410898..86a7a02 100644 --- a/FluentAssertions.Web.sln +++ b/FluentAssertions.Web.sln @@ -47,6 +47,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentAssertions.Web.Serial EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentAssertions.Web.FluentAssertionsWebConfig.Tests", "test\FluentAssertions.Web.FluentAssertionsWebConfig.Tests\FluentAssertions.Web.FluentAssertionsWebConfig.Tests.csproj", "{538479CE-5922-4FF9-A09D-80C9E91FFFF1}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Api.Net70", "samples\Sample.Api.Net70\Sample.Api.Net70.csproj", "{DCC4B007-DCE3-443E-BC9D-635EE367882B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -101,6 +103,10 @@ Global {538479CE-5922-4FF9-A09D-80C9E91FFFF1}.Debug|Any CPU.Build.0 = Debug|Any CPU {538479CE-5922-4FF9-A09D-80C9E91FFFF1}.Release|Any CPU.ActiveCfg = Release|Any CPU {538479CE-5922-4FF9-A09D-80C9E91FFFF1}.Release|Any CPU.Build.0 = Release|Any CPU + {DCC4B007-DCE3-443E-BC9D-635EE367882B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DCC4B007-DCE3-443E-BC9D-635EE367882B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DCC4B007-DCE3-443E-BC9D-635EE367882B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DCC4B007-DCE3-443E-BC9D-635EE367882B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -119,6 +125,7 @@ Global {1BDE8312-1789-40EA-86B2-83784E560740} = {14FDD52D-B83A-445B-BD2F-04B3E7B8033C} {F2C0B6F2-4ACE-4688-8F96-9EB1D5718B60} = {BFF7517A-C9EA-458D-829E-28A10F8D61BF} {538479CE-5922-4FF9-A09D-80C9E91FFFF1} = {BFF7517A-C9EA-458D-829E-28A10F8D61BF} + {DCC4B007-DCE3-443E-BC9D-635EE367882B} = {B6E9FBF3-AC48-48B0-9CBB-CA260F59CCD9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {81F41C75-2F8A-4E70-BA17-38146C4BB6E6} @@ -130,6 +137,7 @@ Global Samples\Sample.Api.Shared\Sample.Api.Shared.projitems*{a0b5b518-714a-4731-b371-996d5fbc72a0}*SharedItemsImports = 5 Samples\Sample.Api.Shared\Sample.Api.Shared.projitems*{a62abbae-bfb8-467a-9fbc-974172c718e2}*SharedItemsImports = 5 Samples\Sample.Api.Shared\Sample.Api.Shared.projitems*{bae9e107-74fe-4c37-a528-857ac73d2c55}*SharedItemsImports = 5 + Samples\Sample.Api.Shared\Sample.Api.Shared.projitems*{dcc4b007-dce3-443e-bc9d-635ee367882b}*SharedItemsImports = 5 Samples\Sample.Api.Shared\Sample.Api.Shared.projitems*{facc5aed-9978-441d-a359-dcd83f924bf8}*SharedItemsImports = 5 EndGlobalSection EndGlobal diff --git a/common.tests.props b/common.tests.props index 7637d9c..1da1a75 100644 --- a/common.tests.props +++ b/common.tests.props @@ -2,7 +2,7 @@ - netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0 + netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0 latest enable CS8600;CS8602;CS8603 diff --git a/readme.md b/readme.md index 877bf67..b906718 100644 --- a/readme.md +++ b/readme.md @@ -15,10 +15,13 @@ public async Task Post_ReturnsOk() var client = _factory.CreateClient(); // Act - var response = await client.PostAsync("/api/comments", new StringContent(@"{ - ""author"": ""John"", - ""content"": ""Hey, you..."" - }", Encoding.UTF8, "application/json")); + var response = await client.PostAsync("/api/comments", new StringContent( + """ + { + "author": "John", + "content": "Hey, you..." + } + """, Encoding.UTF8, "application/json")); // Assert response.Should().Be200Ok(); @@ -58,10 +61,13 @@ public async Task Post_ReturnsOkAndWithContent() var client = _factory.CreateClient(); // Act - var response = await client.PostAsync("/api/comments", new StringContent(@"{ - ""author"": ""John"", - ""content"": ""Hey, you..."" - }", Encoding.UTF8, "application/json")); + var response = await client.PostAsync("/api/comments", new StringContent( + """ + { + "author": "John", + "content": "Hey, you..." + } + """, Encoding.UTF8, "application/json")); // Assert response.Should().BeAs(new @@ -102,9 +108,12 @@ public async Task Post_WithNoAuthorButWithContent_ReturnsBadRequestWithAnErrorMe var client = _factory.CreateClient(); // Act - var response = await client.PostAsync("/api/comments", new StringContent(@"{ - ""content"": ""Hey, you..."" - }", Encoding.UTF8, "application/json")); + var response = await client.PostAsync("/api/comments", new StringContent( + """ + { + "content": "Hey, you..." + } + """, Encoding.UTF8, "application/json")); // Assert response.Should().Be400BadRequest() @@ -155,7 +164,7 @@ public async Task Get_WithCommentId_Returns_A_NonSpam_Comment() } ``` -- Asserting the response has a header like `X-Correlation-ID` header of `application/json; charset=utf-8` +- Asserting the response has a header with the name `X-Correlation-ID` and the value matches a certain pattern ```csharp [Fact] @@ -172,6 +181,23 @@ public async Task Get_Should_Contain_a_Header_With_Correlation_Id() } ``` +- Asserting the response has a header with the name `X-Correlation-ID` and the value is not empty + +```csharp +[Fact] +public async Task Get_Should_Contain_a_Header_With_Correlation_Id() +{ + // Arrange + var client = _factory.CreateClient(); + + // Act + var response = await client.GetAsync("/api/values"); + + // Assert + response.Should().HaveHeader("X-Correlation-ID").And.NotBeEmpty(); +} +``` + Many more examples can be found in the [Samples](https://github.com/adrianiftode/FluentAssertions.Web/tree/master/samples) projects and in the Specs files from the [FluentAssertions.Web.Tests](https://github.com/adrianiftode/FluentAssertions.Web/tree/master/test/FluentAssertions.Web.Tests) project ## Optional Global Configuration @@ -210,86 +236,88 @@ NewtonsoftJsonSerializerConfig.Options.Converters.Add(new YesNoBooleanJsonConver ## Full API -| *HttpResponseMessageAssertions* | Contains a number of methods to assert that an HttpResponseMessage is in the expected state related to the HTTP content. | +| *HttpResponseMessageAssertions* | Contains a number of methods to assert that an HttpResponseMessage is in the expected state related to the HTTP content. | +| --- | --- | +| **Should().BeAs<TModel>()** | Asserts that HTTP response content can be an equivalent representation of the expected model. | +| **Should().HaveHeader()** | Asserts that an HTTP response has a named header. | +| **Should().NotHaveHeader()** | Asserts that an HTTP response does not have a named header. | +| **Should().HaveHttpStatus()** | Asserts that a HTTP response has a HTTP status with the specified code. | +| **Should().NotHaveHttpStatus()** | that a HTTP response does not have a HTTP status with the specified code. | +| **Should().MatchInContent()** | Asserts that HTTP response has content that matches a wildcard pattern. | +| **Should().Satisfy<TModel>()** | Asserts that an HTTP response content can be a model that satisfies an assertion. | +| **Should().Satisfy<HttpResponseMessage>()** | Asserts that an HTTP response content can be a model that satisfies an assertion. | + +| *Should().HaveHeader().And.* | Contains a number of methods to assert that an HttpResponseMessage is in the expected state related to HTTP headers. | | --- | --- | -| **Should().BeAs<TModel>()** | Asserts that HTTP response content can be an equivalent representation of the expected model. | -| **Should().HaveHeader()** | Asserts that an HTTP response has a named header. | -| **Should().NotHaveHeader()** | Asserts that an HTTP response does not have a named header. | -| **Should().HaveHttpStatus()** | Asserts that a HTTP response has a HTTP status with the specified code. | -| **Should().NotHaveHttpStatus()** | that a HTTP response does not have a HTTP status with the specified code. | -| **Should().MatchInContent()** | Asserts that HTTP response has content that matches a wildcard pattern. | -| **Should().Satisfy<TModel>()** | Asserts that an HTTP response content can be a model that satisfies an assertion. | -| **Should().Satisfy<HttpResponseMessage>()** | Asserts that an HTTP response content can be a model that satisfies an assertion. | - -| *Should().HaveHeader().And.* | Contains a number of methods to assert that an HttpResponseMessage is in the expected state related to HTTP headers. | -| --- | --- | -| **BeEmpty()** | Asserts that an existing HTTP header in a HTTP response has no values. | -| **BeValues()** | Asserts that an existing HTTP header in a HTTP response has an expected list of header values. | -| **Match()** | Asserts that an existing HTTP header in a HTTP response contains at least a value that matches a wildcard pattern. | - -| *Should().Be400BadRequest().And.* | Contains a number of methods to assert that an HttpResponseMessage is in the expected state related to HTTP Bad Request response | -| --- | --- | -| **HaveError()** | Asserts that a Bad Request HTTP response content contains an error message identifiable by an expected field name and a wildcard error text. | -| **OnlyHaveError()** | Asserts that a Bad Request HTTP response content contains only a single error message identifiable by an expected field name and a wildcard error text. | -| **NotHaveError()** | Asserts that a Bad Request HTTP response content does not contain an error message identifiable by an expected field name and a wildcard error text. | -| **HaveErrorMessage()** | Asserts that a Bad Request HTTP response content contains an error message identifiable by an wildcard error text. | - -| *Fine grained status assertions.* | | +| **BeEmpty()** | Asserts that an existing HTTP header in a HTTP response has no values. | +| **NotBeEmpty()** | Asserts that an existing HTTP header in a HTTP response has any values. | +| **BeValue()** |Asserts that an existing HTTP header in a HTTP response has an expected value. | +| **BeValues()** | Asserts that an existing HTTP header in a HTTP response has an expected list of header values. | +| **Match()** | Asserts that an existing HTTP header in a HTTP response contains at least a value that matches a wildcard pattern. | + +| *Should().Be400BadRequest().And.* | Contains a number of methods to assert that an HttpResponseMessage is in the expected state related to HTTP Bad Request response | +| --- | --- | +| **HaveError()** | Asserts that a Bad Request HTTP response content contains an error message identifiable by an expected field name and a wildcard error text. | +| **OnlyHaveError()** | Asserts that a Bad Request HTTP response content contains only a single error message identifiable by an expected field name and a wildcard error text. | +| **NotHaveError()** | Asserts that a Bad Request HTTP response content does not contain an error message identifiable by an expected field name and a wildcard error text. | +| **HaveErrorMessage()** | Asserts that a Bad Request HTTP response content contains an error message identifiable by an wildcard error text. | + +| *Fine grained status assertions.* | | | --- | --- | -| **Should().Be1XXInformational()** | Asserts that a HTTP response has a HTTP status code representing an informational response. | -| **Should().Be2XXSuccessful()** | Asserts that a HTTP response has a successful HTTP status code. | -| **Should().Be4XXClientError()** | Asserts that a HTTP response has a HTTP status code representing a client error. | -| **Should().Be3XXRedirection()** | Asserts that a HTTP response has a HTTP status code representing a redirection response. | -| **Should().Be5XXServerError()** | Asserts that a HTTP response has a HTTP status code representing a server error. | -| **Should().Be100Continue()** | Asserts that a HTTP response has the HTTP status 100 Continue | -| **Should().Be101SwitchingProtocols()** | Asserts that a HTTP response has the HTTP status 101 Switching Protocols | -| **Should().Be200Ok()** | Asserts that a HTTP response has the HTTP status 200 Ok | -| **Should().Be201Created()** | Asserts that a HTTP response has the HTTP status 201 Created | -| **Should().Be202Accepted()** | Asserts that a HTTP response has the HTTP status 202 Accepted | -| **Should().Be203NonAuthoritativeInformation()** | Asserts that a HTTP response has the HTTP status 203 Non Authoritative Information | -| **Should().Be204NoContent()** | Asserts that a HTTP response has the HTTP status 204 No Content | -| **Should().Be205ResetContent()** | Asserts that a HTTP response has the HTTP status 205 Reset Content | -| **Should().Be206PartialContent()** | Asserts that a HTTP response has the HTTP status 206 Partial Content | -| **Should().Be300Ambiguous()** | Asserts that a HTTP response has the HTTP status 300 Ambiguous | -| **Should().Be300MultipleChoices()** | Asserts that a HTTP response has the HTTP status 300 Multiple Choices | -| **Should().Be301Moved()** | Asserts that a HTTP response has the HTTP status 301 Moved Permanently | -| **Should().Be301MovedPermanently()** | Asserts that a HTTP response has the HTTP status 301 Moved Permanently | -| **Should().Be302Found()** | Asserts that a HTTP response has the HTTP status 302 Found | -| **Should().Be302Redirect()** | Asserts that a HTTP response has the HTTP status 302 Redirect | -| **Should().Be303RedirectMethod()** | Asserts that a HTTP response has the HTTP status 303 Redirect Method | -| **Should().Be303SeeOther()** | Asserts that a HTTP response has the HTTP status 303 See Other | -| **Should().Be304NotModified()** | Asserts that a HTTP response has the HTTP status 304 Not Modified | -| **Should().Be305UseProxy()** | Asserts that a HTTP response has the HTTP status 305 Use Proxy | -| **Should().Be306Unused()** | Asserts that a HTTP response has the HTTP status 306 Unused | -| **Should().Be307RedirectKeepVerb()** | Asserts that a HTTP response has the HTTP status 307 Redirect Keep Verb | -| **Should().Be307TemporaryRedirect()** | Asserts that a HTTP response has the HTTP status 307 Temporary Redirect | -| **Should().Be400BadRequest()** | Asserts that a HTTP response has the HTTP status 400 BadRequest | -| **Should().Be401Unauthorized()** | Asserts that a HTTP response has the HTTP status 401 Unauthorized | -| **Should().Be402PaymentRequired()** | Asserts that a HTTP response has the HTTP status 402 Payment Required | -| **Should().Be403Forbidden()** | Asserts that a HTTP response has the HTTP status 403 Forbidden | -| **Should().Be404NotFound()** | Asserts that a HTTP response has the HTTP status 404 Not Found | -| **Should().Be405MethodNotAllowed()** | Asserts that a HTTP response has the HTTP status 405 Method Not Allowed | -| **Should().Be406NotAcceptable()** | Asserts that a HTTP response has the HTTP status 406 Not Acceptable | -| **Should().Be407ProxyAuthenticationRequired()** | Asserts that a HTTP response has the HTTP status 407 Proxy Authentication Required | -| **Should().Be408RequestTimeout()** | Asserts that a HTTP response has the HTTP status 408 Request Timeout | -| **Should().Be409Conflict()** | Asserts that a HTTP response has the HTTP status 409 Conflict | -| **Should().Be410Gone()** | Asserts that a HTTP response has the HTTP status 410 Gone | -| **Should().Be411LengthRequired()** | Asserts that a HTTP response has the HTTP status 411 Length Required | -| **Should().Be412PreconditionFailed()** | Asserts that a HTTP response has the HTTP status 412 Precondition Failed | -| **Should().Be413RequestEntityTooLarge()** | Asserts that a HTTP response has the HTTP status 413 Request Entity Too Large | -| **Should().Be414RequestUriTooLong()** | Asserts that a HTTP response has the HTTP status 414 Request Uri Too Long | -| **Should().Be415UnsupportedMediaType()** | Asserts that a HTTP response has the HTTP status 415 Unsupported Media Type | -| **Should().Be416RequestedRangeNotSatisfiable()** | Asserts that a HTTP response has the HTTP status 416 Requested Range Not Satisfiable | -| **Should().Be417ExpectationFailed()** | Asserts that a HTTP response has the HTTP status 417 Expectation Failed | -| **Should().Be422UnprocessableEntity()** | Asserts that a HTTP response has the HTTP status 422 Unprocessable Entity | -| **Should().Be426UpgradeRequired()** | Asserts that a HTTP response has the HTTP status 426 UpgradeRequired | -| **Should().Be429TooManyRequests()** | Asserts that a HTTP response has the HTTP status 422 Too Many Requests | -| **Should().Be500InternalServerError()** | Asserts that a HTTP response has the HTTP status 500 Internal Server Error | -| **Should().Be501NotImplemented()** | Asserts that a HTTP response has the HTTP status 501 Not Implemented | -| **Should().Be502BadGateway()** | Asserts that a HTTP response has the HTTP status 502 Bad Gateway | -| **Should().Be503ServiceUnavailable()** | Asserts that a HTTP response has the HTTP status 503 Service Unavailable | -| **Should().Be504GatewayTimeout()** | Asserts that a HTTP response has the HTTP status 504 Gateway Timeout | -| **Should().Be505HttpVersionNotSupported()** | Asserts that a HTTP response has the HTTP status 505 Http Version Not Supported | +| **Should().Be1XXInformational()** | Asserts that a HTTP response has a HTTP status code representing an informational response. | +| **Should().Be2XXSuccessful()** | Asserts that a HTTP response has a successful HTTP status code. | +| **Should().Be4XXClientError()** | Asserts that a HTTP response has a HTTP status code representing a client error. | +| **Should().Be3XXRedirection()** | Asserts that a HTTP response has a HTTP status code representing a redirection response. | +| **Should().Be5XXServerError()** | Asserts that a HTTP response has a HTTP status code representing a server error. | +| **Should().Be100Continue()** | Asserts that a HTTP response has the HTTP status 100 Continue | +| **Should().Be101SwitchingProtocols()** | Asserts that a HTTP response has the HTTP status 101 Switching Protocols | +| **Should().Be200Ok()** | Asserts that a HTTP response has the HTTP status 200 Ok | +| **Should().Be201Created()** | Asserts that a HTTP response has the HTTP status 201 Created | +| **Should().Be202Accepted()** | Asserts that a HTTP response has the HTTP status 202 Accepted | +| **Should().Be203NonAuthoritativeInformation()** | Asserts that a HTTP response has the HTTP status 203 Non Authoritative Information | +| **Should().Be204NoContent()** | Asserts that a HTTP response has the HTTP status 204 No Content | +| **Should().Be205ResetContent()** | Asserts that a HTTP response has the HTTP status 205 Reset Content | +| **Should().Be206PartialContent()** | Asserts that a HTTP response has the HTTP status 206 Partial Content | +| **Should().Be300Ambiguous()** | Asserts that a HTTP response has the HTTP status 300 Ambiguous | +| **Should().Be300MultipleChoices()** | Asserts that a HTTP response has the HTTP status 300 Multiple Choices | +| **Should().Be301Moved()** | Asserts that a HTTP response has the HTTP status 301 Moved Permanently | +| **Should().Be301MovedPermanently()** | Asserts that a HTTP response has the HTTP status 301 Moved Permanently | +| **Should().Be302Found()** | Asserts that a HTTP response has the HTTP status 302 Found | +| **Should().Be302Redirect()** | Asserts that a HTTP response has the HTTP status 302 Redirect | +| **Should().Be303RedirectMethod()** | Asserts that a HTTP response has the HTTP status 303 Redirect Method | +| **Should().Be303SeeOther()** | Asserts that a HTTP response has the HTTP status 303 See Other | +| **Should().Be304NotModified()** | Asserts that a HTTP response has the HTTP status 304 Not Modified | +| **Should().Be305UseProxy()** | Asserts that a HTTP response has the HTTP status 305 Use Proxy | +| **Should().Be306Unused()** | Asserts that a HTTP response has the HTTP status 306 Unused | +| **Should().Be307RedirectKeepVerb()** | Asserts that a HTTP response has the HTTP status 307 Redirect Keep Verb | +| **Should().Be307TemporaryRedirect()** | Asserts that a HTTP response has the HTTP status 307 Temporary Redirect | +| **Should().Be400BadRequest()** | Asserts that a HTTP response has the HTTP status 400 BadRequest | +| **Should().Be401Unauthorized()** | Asserts that a HTTP response has the HTTP status 401 Unauthorized | +| **Should().Be402PaymentRequired()** | Asserts that a HTTP response has the HTTP status 402 Payment Required | +| **Should().Be403Forbidden()** | Asserts that a HTTP response has the HTTP status 403 Forbidden | +| **Should().Be404NotFound()** | Asserts that a HTTP response has the HTTP status 404 Not Found | +| **Should().Be405MethodNotAllowed()** | Asserts that a HTTP response has the HTTP status 405 Method Not Allowed | +| **Should().Be406NotAcceptable()** | Asserts that a HTTP response has the HTTP status 406 Not Acceptable | +| **Should().Be407ProxyAuthenticationRequired()** | Asserts that a HTTP response has the HTTP status 407 Proxy Authentication Required | +| **Should().Be408RequestTimeout()** | Asserts that a HTTP response has the HTTP status 408 Request Timeout | +| **Should().Be409Conflict()** | Asserts that a HTTP response has the HTTP status 409 Conflict | +| **Should().Be410Gone()** | Asserts that a HTTP response has the HTTP status 410 Gone | +| **Should().Be411LengthRequired()** | Asserts that a HTTP response has the HTTP status 411 Length Required | +| **Should().Be412PreconditionFailed()** | Asserts that a HTTP response has the HTTP status 412 Precondition Failed | +| **Should().Be413RequestEntityTooLarge()** | Asserts that a HTTP response has the HTTP status 413 Request Entity Too Large | +| **Should().Be414RequestUriTooLong()** | Asserts that a HTTP response has the HTTP status 414 Request Uri Too Long | +| **Should().Be415UnsupportedMediaType()** | Asserts that a HTTP response has the HTTP status 415 Unsupported Media Type | +| **Should().Be416RequestedRangeNotSatisfiable()** | Asserts that a HTTP response has the HTTP status 416 Requested Range Not Satisfiable | +| **Should().Be417ExpectationFailed()** | Asserts that a HTTP response has the HTTP status 417 Expectation Failed | +| **Should().Be422UnprocessableEntity()** | Asserts that a HTTP response has the HTTP status 422 Unprocessable Entity | +| **Should().Be426UpgradeRequired()** | Asserts that a HTTP response has the HTTP status 426 UpgradeRequired | +| **Should().Be429TooManyRequests()** | Asserts that a HTTP response has the HTTP status 422 Too Many Requests | +| **Should().Be500InternalServerError()** | Asserts that a HTTP response has the HTTP status 500 Internal Server Error | +| **Should().Be501NotImplemented()** | Asserts that a HTTP response has the HTTP status 501 Not Implemented | +| **Should().Be502BadGateway()** | Asserts that a HTTP response has the HTTP status 502 Bad Gateway | +| **Should().Be503ServiceUnavailable()** | Asserts that a HTTP response has the HTTP status 503 Service Unavailable | +| **Should().Be504GatewayTimeout()** | Asserts that a HTTP response has the HTTP status 504 Gateway Timeout | +| **Should().Be505HttpVersionNotSupported()** | Asserts that a HTTP response has the HTTP status 505 Http Version Not Supported | ### The HttpResponsesMessage assertions from FluentAssertions vs. FluentAssertions.Web diff --git a/samples/Sample.Api.Net50/Sample.Api.Net50.csproj b/samples/Sample.Api.Net50/Sample.Api.Net50.csproj index 221c18d..25488b5 100644 --- a/samples/Sample.Api.Net50/Sample.Api.Net50.csproj +++ b/samples/Sample.Api.Net50/Sample.Api.Net50.csproj @@ -3,7 +3,9 @@ net5.0 true + false false + false diff --git a/samples/Sample.Api.Net70/Properties/launchSettings.json b/samples/Sample.Api.Net70/Properties/launchSettings.json new file mode 100644 index 0000000..77e49fd --- /dev/null +++ b/samples/Sample.Api.Net70/Properties/launchSettings.json @@ -0,0 +1,30 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:58229", + "sslPort": 44366 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "FluentAssertions.Web.Api": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "api/values", + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/samples/Sample.Api.Net70/Sample.Api.Net70.csproj b/samples/Sample.Api.Net70/Sample.Api.Net70.csproj new file mode 100644 index 0000000..c9cfb8c --- /dev/null +++ b/samples/Sample.Api.Net70/Sample.Api.Net70.csproj @@ -0,0 +1,11 @@ + + + + net7.0 + true + false + + + + + diff --git a/samples/Sample.Api.Shared/Controllers/CommentsController.cs b/samples/Sample.Api.Shared/Controllers/CommentsController.cs index 9b9e8d4..c554bb0 100644 --- a/samples/Sample.Api.Shared/Controllers/CommentsController.cs +++ b/samples/Sample.Api.Shared/Controllers/CommentsController.cs @@ -16,7 +16,11 @@ public IEnumerable Get() => new[] }; [HttpGet("{id}")] - public Comment Get(int id) => new Comment { Author = "Adrian", Content = "Hey", CommentId = id }; + public Comment Get(int id) + { + Response.Headers.Add("x-vendor", "vendor"); + return new Comment { Author = "Adrian", Content = "Hey", CommentId = id }; + } [HttpPost] public Comment Post([FromBody] Comment value) => value; diff --git a/samples/Sample.Api.Tests/CommentsControllerTests.cs b/samples/Sample.Api.Tests/CommentsControllerTests.cs index 820514f..030aafe 100644 --- a/samples/Sample.Api.Tests/CommentsControllerTests.cs +++ b/samples/Sample.Api.Tests/CommentsControllerTests.cs @@ -106,6 +106,19 @@ public async Task Get_WithCommentId_Returns_Response_That_Satisfies_Several_Asse ); } + [Fact] + public async Task Get_Returns_Response_With_A_Certain_Header() + { + // Arrange + var client = _factory.CreateClient(); + + // Act + var response = await client.GetAsync("/api/comments/1"); + + // Assert + response.Should().HaveHeader("x-vendor").And.BeValue("vendor", "we want to test the header has a specific value"); + } + [Fact] public async Task Post_ReturnsOk() { @@ -113,7 +126,7 @@ public async Task Post_ReturnsOk() var client = _factory.CreateClient(); // Act - var response = await client.PostAsync("/api/comments", new StringContent(@"{ + var response = await client.PostAsync("/api/comments", new StringContent(/*lang=json,strict*/ @"{ ""author"": ""John"", ""content"": ""Hey, you..."" }", Encoding.UTF8, "application/json")); @@ -129,7 +142,7 @@ public async Task Post_ReturnsOkAndWithContent() var client = _factory.CreateClient(); // Act - var response = await client.PostAsync("/api/comments", new StringContent(@"{ + var response = await client.PostAsync("/api/comments", new StringContent(/*lang=json,strict*/ @"{ ""author"": ""John"", ""content"": ""Hey, you..."" }", Encoding.UTF8, "application/json")); @@ -168,7 +181,7 @@ public async Task Post_WithNoAuthorAndNoContent_ReturnsBadRequest() var client = _factory.CreateClient(); // Act - var response = await client.PostAsync("/api/comments", new StringContent(@"{ + var response = await client.PostAsync("/api/comments", new StringContent(/*lang=json,strict*/ @"{ ""author"": """", ""content"": """" }", Encoding.UTF8, "application/json")); @@ -186,7 +199,7 @@ public async Task Post_WithNoAuthor_ReturnsBadRequestWithUsefulMessage() var client = _factory.CreateClient(); // Act - var response = await client.PostAsync("/api/comments", new StringContent(@"{ + var response = await client.PostAsync("/api/comments", new StringContent(/*lang=json,strict*/ @"{ ""content"": ""Hey, you..."" }", Encoding.UTF8, "application/json")); @@ -203,7 +216,7 @@ public async Task Post_WithNoAuthorButWithContent_ReturnsBadRequestWithAnErrorMe var client = _factory.CreateClient(); // Act - var response = await client.PostAsync("/api/comments", new StringContent(@"{ + var response = await client.PostAsync("/api/comments", new StringContent(/*lang=json,strict*/ @"{ ""content"": ""Hey, you..."" }", Encoding.UTF8, "application/json")); diff --git a/samples/Sample.Api.Tests/Sample.Api.Tests.csproj b/samples/Sample.Api.Tests/Sample.Api.Tests.csproj index 258eb76..5e16866 100644 --- a/samples/Sample.Api.Tests/Sample.Api.Tests.csproj +++ b/samples/Sample.Api.Tests/Sample.Api.Tests.csproj @@ -26,6 +26,8 @@ + + @@ -34,6 +36,11 @@ + + + + + diff --git a/samples/Sample.Api.Tests/ValuesControllerTests.cs b/samples/Sample.Api.Tests/ValuesControllerTests.cs index 71874dc..2ba8ec6 100644 --- a/samples/Sample.Api.Tests/ValuesControllerTests.cs +++ b/samples/Sample.Api.Tests/ValuesControllerTests.cs @@ -140,7 +140,7 @@ public async Task Post_WithNoContent_ReturnsBadRequest() } [Fact] - public async Task Get_Should_Contain_a_Header_With_Correlation_Id() + public async Task Get_Should_Contain_a_Header_With_Correlation_Id_That_Matches_A_Guid_Like_Pattern() { // Arrange var client = _factory.CreateClient(); @@ -151,5 +151,18 @@ public async Task Get_Should_Contain_a_Header_With_Correlation_Id() // Assert response.Should().HaveHeader("X-Correlation-ID").And.Match("*-*", "we want to test the correlation id is a Guid like one"); } + + [Fact] + public async Task Get_Should_Contain_a_Header_With_Correlation_Id() + { + // Arrange + var client = _factory.CreateClient(); + + // Act + var response = await client.GetAsync("/api/values"); + + // Assert + response.Should().HaveHeader("X-Correlation-ID").And.NotBeEmpty("we want to test the correlation id header has some value"); + } } } diff --git a/src/FluentAssertions.Web.Serializers.NewtonsoftJson/GlobalUsings.cs b/src/FluentAssertions.Web.Serializers.NewtonsoftJson/GlobalUsings.cs new file mode 100644 index 0000000..bafb58d --- /dev/null +++ b/src/FluentAssertions.Web.Serializers.NewtonsoftJson/GlobalUsings.cs @@ -0,0 +1,5 @@ +global using Newtonsoft.Json; +global using System; +global using System.IO; +global using System.Text; +global using System.Threading.Tasks; diff --git a/src/FluentAssertions.Web.Serializers.NewtonsoftJson/NewtonsoftJsonSerializer.cs b/src/FluentAssertions.Web.Serializers.NewtonsoftJson/NewtonsoftJsonSerializer.cs index 29da43b..a21cbd0 100644 --- a/src/FluentAssertions.Web.Serializers.NewtonsoftJson/NewtonsoftJsonSerializer.cs +++ b/src/FluentAssertions.Web.Serializers.NewtonsoftJson/NewtonsoftJsonSerializer.cs @@ -1,34 +1,27 @@ // ReSharper disable once CheckNamespace -using Newtonsoft.Json; -using System; -using System.IO; -using System.Text; -using System.Threading.Tasks; +namespace FluentAssertions; -namespace FluentAssertions +/// +/// Newtonsoft.Json based serializer +/// +public class NewtonsoftJsonSerializer : ISerializer { - /// - /// Newtonsoft.Json based serializer - /// - public class NewtonsoftJsonSerializer : ISerializer + /// + public Task Deserialize(Stream content, Type modelType) { - /// - public Task Deserialize(Stream content, Type modelType) + try { - try - { - var serializer = JsonSerializer.Create(NewtonsoftJsonSerializerConfig.Options); + var serializer = JsonSerializer.Create(NewtonsoftJsonSerializerConfig.Options); - using var sr = new StreamReader(content, Encoding.UTF8, true, 1024, leaveOpen: true); - using var reader = new JsonTextReader(sr); - var result = serializer.Deserialize(reader, modelType); - return Task.FromResult((object?)result); - } + using var sr = new StreamReader(content, Encoding.UTF8, true, 1024, leaveOpen: true); + using var reader = new JsonTextReader(sr); + var result = serializer.Deserialize(reader, modelType); + return Task.FromResult((object?)result); + } - catch (JsonException ex) - { - throw new DeserializationException($"Exception while deserializing the model with {nameof(NewtonsoftJsonSerializer)}", ex); - } + catch (JsonException ex) + { + throw new DeserializationException($"Exception while deserializing the model with {nameof(NewtonsoftJsonSerializer)}", ex); } } } diff --git a/src/FluentAssertions.Web.Serializers.NewtonsoftJson/NewtonsoftJsonSerializerConfig.cs b/src/FluentAssertions.Web.Serializers.NewtonsoftJson/NewtonsoftJsonSerializerConfig.cs index 5513341..00edda7 100644 --- a/src/FluentAssertions.Web.Serializers.NewtonsoftJson/NewtonsoftJsonSerializerConfig.cs +++ b/src/FluentAssertions.Web.Serializers.NewtonsoftJson/NewtonsoftJsonSerializerConfig.cs @@ -1,17 +1,13 @@ -using System.Text.Json; -using Newtonsoft.Json; +// ReSharper disable once CheckNamespace +namespace FluentAssertions; -// ReSharper disable once CheckNamespace -namespace FluentAssertions +/// +/// Holder of the global +/// +public static class NewtonsoftJsonSerializerConfig { /// - /// Holder of the global + /// The options used to deserialize a JSON into a C# object /// - public static class NewtonsoftJsonSerializerConfig - { - /// - /// The options used to deserialize a JSON into a C# object - /// - public static readonly JsonSerializerSettings Options = new(); - } + public static readonly JsonSerializerSettings Options = new(); } diff --git a/src/FluentAssertions.Web/BadRequestAssertions.cs b/src/FluentAssertions.Web/BadRequestAssertions.cs index 5b93b45..9a1aa9e 100644 --- a/src/FluentAssertions.Web/BadRequestAssertions.cs +++ b/src/FluentAssertions.Web/BadRequestAssertions.cs @@ -1,271 +1,262 @@ -using FluentAssertions.Execution; -using FluentAssertions.Web.Internal; -using System; -using System.Linq; -using System.Net.Http; -using System.Text.Json; -using System.Threading.Tasks; - -namespace FluentAssertions.Web +namespace FluentAssertions.Web; + +/// +/// Contains a number of methods to assert that an is in the expected state related to HTTP Bad Request response +/// +public class BadRequestAssertions : HttpResponseMessageAssertions { + private const string ErrorsPropertyName = "errors"; + /// - /// Contains a number of methods to assert that an is in the expected state related to HTTP Bad Request response + /// Initialized a new instance of the + /// class. /// - public class BadRequestAssertions : HttpResponseMessageAssertions + /// The subject value to be asserted. + public BadRequestAssertions(HttpResponseMessage value) : base(value) { - private const string ErrorsPropertyName = "errors"; - - /// - /// Initialized a new instance of the - /// class. - /// - /// The subject value to be asserted. - public BadRequestAssertions(HttpResponseMessage value) : base(value) - { - } - - /// - /// Returns the type of the subject the assertion applies on. - /// - protected override string Identifier => "BadRequest"; - - /// - /// Asserts that a Bad Request HTTP response content contains an error message identifiable by an expected field name and a wildcard error text. - /// - /// - /// This assertion considers the HTTP response content a JSON generated by the ASP.NET Core 3.0 framework or less - /// - /// - /// The expected field name. - /// - /// - /// The wildcard pattern with which the error field associated error message is matched, where * and ? have special meanings. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint HaveError(string expectedErrorField, string expectedWildcardErrorMessage, - string because = "", params object[] becauseArgs) - { - Guard.ThrowIfArgumentIsNullOrEmpty(expectedErrorField, nameof(expectedErrorField), "Cannot verify having an error against a or empty field name."); - Guard.ThrowIfArgumentIsNullOrEmpty(expectedWildcardErrorMessage, nameof(expectedWildcardErrorMessage), "Cannot verify having an error against a or empty wildcard error message."); - - Func> jsonFunc = () => Subject.GetJsonDocument(); - using var json = jsonFunc.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); - - var errorsProperty = json.GetPropertiesByName(ErrorsPropertyName).ToList(); - var hasErrorsProperty = errorsProperty.Any(); - var fieldsOfErrorsProperty = json.GetChildrenNames(ErrorsPropertyName); - var allFields = json.GetChildrenNames(""); - var fields = hasErrorsProperty ? fieldsOfErrorsProperty : allFields; - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(fields.Any(field => string.Equals(field, expectedErrorField, StringComparison.OrdinalIgnoreCase))) - .FailWith("Expected {context:response} " + - "to contain an error message related to the {0} field, but was not found." + - "{1}", - expectedErrorField, Subject); - - var errorsMessages = hasErrorsProperty ? errorsProperty.First().GetStringValuesOf(expectedErrorField) : json.GetStringValuesOf(expectedErrorField); - var matchFound = errorsMessages.Any(errorMessage => - { - using var scope = new AssertionScope(); - errorMessage.Should().Match(expectedWildcardErrorMessage); - return !scope.Discard().Any(); - }); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(matchFound) - .FailWith("Expected {context:response} to contain " + - "the error message {0} related to the {1} field, " + - "but no such message was found in the actual error messages list: " + - "{2}", - expectedWildcardErrorMessage, - expectedErrorField, - Subject); - - return new AndConstraint(this); - } - - /// - /// Asserts that a Bad Request HTTP response content contains only a single error message identifiable by an expected field name and a wildcard error text. - /// - /// - /// This assertion considers the HTTP response content a JSON generated by the ASP.NET Core 3.0 framework or less - /// - /// - /// The expected field name. - /// - /// - /// The wildcard pattern with which the error field associated error message is matched, where * and ? have special meanings. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - - [CustomAssertion] - public AndConstraint OnlyHaveError(string expectedErrorField, string expectedWildcardErrorMessage, - string because = "", params object[] becauseArgs) + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Identifier => "BadRequest"; + + /// + /// Asserts that a Bad Request HTTP response content contains an error message identifiable by an expected field name and a wildcard error text. + /// + /// + /// This assertion considers the HTTP response content a JSON generated by the ASP.NET Core 3.0 framework or less + /// + /// + /// The expected field name. + /// + /// + /// The wildcard pattern with which the error field associated error message is matched, where * and ? have special meanings. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint HaveError(string expectedErrorField, string expectedWildcardErrorMessage, + string because = "", params object[] becauseArgs) + { + Guard.ThrowIfArgumentIsNullOrEmpty(expectedErrorField, nameof(expectedErrorField), "Cannot verify having an error against a or empty field name."); + Guard.ThrowIfArgumentIsNullOrEmpty(expectedWildcardErrorMessage, nameof(expectedWildcardErrorMessage), "Cannot verify having an error against a or empty wildcard error message."); + + Func> jsonFunc = () => Subject.GetJsonDocument(); + using var json = jsonFunc.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); + + var errorsProperty = json.GetPropertiesByName(ErrorsPropertyName).ToList(); + var hasErrorsProperty = errorsProperty.Any(); + var fieldsOfErrorsProperty = json.GetChildrenNames(ErrorsPropertyName); + var allFields = json.GetChildrenNames(""); + var fields = hasErrorsProperty ? fieldsOfErrorsProperty : allFields; + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(fields.Any(field => string.Equals(field, expectedErrorField, StringComparison.OrdinalIgnoreCase))) + .FailWith("Expected {context:response} " + + "to contain an error message related to the {0} field, but was not found." + + "{1}", + expectedErrorField, Subject); + + var errorsMessages = hasErrorsProperty ? errorsProperty.First().GetStringValuesOf(expectedErrorField) : json.GetStringValuesOf(expectedErrorField); + var matchFound = errorsMessages.Any(errorMessage => { - Guard.ThrowIfArgumentIsNullOrEmpty(expectedErrorField, nameof(expectedErrorField), "Cannot verify having only an error against a or empty field name."); - Guard.ThrowIfArgumentIsNullOrEmpty(expectedWildcardErrorMessage, nameof(expectedWildcardErrorMessage), "Cannot verify having only an error against a or empty wildcard error message."); - - Func> jsonFunc = () => Subject.GetJsonDocument(); - using var json = jsonFunc.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); - - var errorsProperty = json.GetPropertiesByName(ErrorsPropertyName).ToList(); - var hasErrorsProperty = errorsProperty.Any(); - var fieldsOfErrorsProperty = json.GetChildrenNames(ErrorsPropertyName); - var allFields = json.GetChildrenNames(""); - var fields = hasErrorsProperty ? fieldsOfErrorsProperty : allFields; - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(fields.Any(field => string.Equals(field, expectedErrorField, StringComparison.OrdinalIgnoreCase))) - .FailWith("Expected {context:response} " + - "to contain an error message related to the {0} field, but was not found." + - "{1}", - expectedErrorField, Subject); - - var parent = hasErrorsProperty ? ErrorsPropertyName : json.GetParentKey(expectedErrorField); - var children = json.GetChildrenNames(parent); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(children.Count() == 1) - .FailWith("Expected {context:response} " + - "to only contain an error message related to the {0} field, but more than this one was found." + - "{1}", - expectedErrorField, Subject); - - var values = json.GetStringValuesOf(expectedErrorField); - var expectedWildcardErrorMessageMatchFound = values.Any(headerValue => - { - using var scope = new AssertionScope(); - headerValue.Should().Match(expectedWildcardErrorMessage); - return !scope.Discard().Any(); - }); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(expectedWildcardErrorMessageMatchFound) - .FailWith("Expected {context:response} to contain " + - "the error message {0} related to the {1} field, " + - "but no such message was found in the actual error messages list: " + - "{2}", - expectedWildcardErrorMessage, - expectedErrorField, - Subject); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(values.Count() == 1) - .FailWith("Expected {context:response} " + - "to only contain an error message related to the {0} field and message {1}, but more than this one was found." + - "{2}", - expectedErrorField, expectedWildcardErrorMessage, Subject); - - return new AndConstraint(this); - } - - /// - /// Asserts that a Bad Request HTTP response content does not contain an error message identifiable by an expected field name. - /// - /// - /// This assertion considers the HTTP response content a JSON generated by the ASP.NET Core 3.0 framework or less - /// - /// - /// The expected field name. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - - [CustomAssertion] - public AndConstraint NotHaveError(string expectedErrorField, string because = "", params object[] becauseArgs) + using var scope = new AssertionScope(); + errorMessage.Should().Match(expectedWildcardErrorMessage); + return !scope.Discard().Any(); + }); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(matchFound) + .FailWith("Expected {context:response} to contain " + + "the error message {0} related to the {1} field, " + + "but no such message was found in the actual error messages list: " + + "{2}", + expectedWildcardErrorMessage, + expectedErrorField, + Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a Bad Request HTTP response content contains only a single error message identifiable by an expected field name and a wildcard error text. + /// + /// + /// This assertion considers the HTTP response content a JSON generated by the ASP.NET Core 3.0 framework or less + /// + /// + /// The expected field name. + /// + /// + /// The wildcard pattern with which the error field associated error message is matched, where * and ? have special meanings. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + + [CustomAssertion] + public AndConstraint OnlyHaveError(string expectedErrorField, string expectedWildcardErrorMessage, + string because = "", params object[] becauseArgs) + { + Guard.ThrowIfArgumentIsNullOrEmpty(expectedErrorField, nameof(expectedErrorField), "Cannot verify having only an error against a or empty field name."); + Guard.ThrowIfArgumentIsNullOrEmpty(expectedWildcardErrorMessage, nameof(expectedWildcardErrorMessage), "Cannot verify having only an error against a or empty wildcard error message."); + + Func> jsonFunc = () => Subject.GetJsonDocument(); + using var json = jsonFunc.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); + + var errorsProperty = json.GetPropertiesByName(ErrorsPropertyName).ToList(); + var hasErrorsProperty = errorsProperty.Any(); + var fieldsOfErrorsProperty = json.GetChildrenNames(ErrorsPropertyName); + var allFields = json.GetChildrenNames(""); + var fields = hasErrorsProperty ? fieldsOfErrorsProperty : allFields; + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(fields.Any(field => string.Equals(field, expectedErrorField, StringComparison.OrdinalIgnoreCase))) + .FailWith("Expected {context:response} " + + "to contain an error message related to the {0} field, but was not found." + + "{1}", + expectedErrorField, Subject); + + var parent = hasErrorsProperty ? ErrorsPropertyName : json.GetParentKey(expectedErrorField); + var children = json.GetChildrenNames(parent); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(children.Count() == 1) + .FailWith("Expected {context:response} " + + "to only contain an error message related to the {0} field, but more than this one was found." + + "{1}", + expectedErrorField, Subject); + + var values = json.GetStringValuesOf(expectedErrorField); + var expectedWildcardErrorMessageMatchFound = values.Any(headerValue => { - Guard.ThrowIfArgumentIsNullOrEmpty(expectedErrorField, nameof(expectedErrorField), "Cannot verify not having an error against a or empty field name."); - - Func> jsonFunc = () => Subject.GetJsonDocument(); - using var json = jsonFunc.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); - - var errorsProperty = json.GetPropertiesByName(ErrorsPropertyName).ToList(); - var hasErrorsProperty = errorsProperty.Any(); - var fieldsOfErrorsProperty = json.GetChildrenNames(ErrorsPropertyName); - var allFields = json.GetChildrenNames(""); - var fields = hasErrorsProperty ? fieldsOfErrorsProperty : allFields; - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(!fields.Any(c => string.Equals(c, expectedErrorField, StringComparison.OrdinalIgnoreCase))) - .FailWith("Expected {context:response} " + - "to not contain an error message related to the {0} field, but was found.{1}", - expectedErrorField, Subject); - - return new AndConstraint(this); - } - - /// - /// Asserts that a Bad Request HTTP response content contains an error message identifiable by an wildcard error text. - /// - /// - /// The wildcard pattern with which the error field associated error message is matched, where * and ? have special meanings. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - - [CustomAssertion] - public AndConstraint HaveErrorMessage(string expectedWildcardErrorMessage, - string because = "", params object[] becauseArgs) + using var scope = new AssertionScope(); + headerValue.Should().Match(expectedWildcardErrorMessage); + return !scope.Discard().Any(); + }); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(expectedWildcardErrorMessageMatchFound) + .FailWith("Expected {context:response} to contain " + + "the error message {0} related to the {1} field, " + + "but no such message was found in the actual error messages list: " + + "{2}", + expectedWildcardErrorMessage, + expectedErrorField, + Subject); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(values.Count() == 1) + .FailWith("Expected {context:response} " + + "to only contain an error message related to the {0} field and message {1}, but more than this one was found." + + "{2}", + expectedErrorField, expectedWildcardErrorMessage, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a Bad Request HTTP response content does not contain an error message identifiable by an expected field name. + /// + /// + /// This assertion considers the HTTP response content a JSON generated by the ASP.NET Core 3.0 framework or less + /// + /// + /// The expected field name. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + + [CustomAssertion] + public AndConstraint NotHaveError(string expectedErrorField, string because = "", params object[] becauseArgs) + { + Guard.ThrowIfArgumentIsNullOrEmpty(expectedErrorField, nameof(expectedErrorField), "Cannot verify not having an error against a or empty field name."); + + Func> jsonFunc = () => Subject.GetJsonDocument(); + using var json = jsonFunc.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); + + var errorsProperty = json.GetPropertiesByName(ErrorsPropertyName).ToList(); + var hasErrorsProperty = errorsProperty.Any(); + var fieldsOfErrorsProperty = json.GetChildrenNames(ErrorsPropertyName); + var allFields = json.GetChildrenNames(""); + var fields = hasErrorsProperty ? fieldsOfErrorsProperty : allFields; + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(!fields.Any(c => string.Equals(c, expectedErrorField, StringComparison.OrdinalIgnoreCase))) + .FailWith("Expected {context:response} " + + "to not contain an error message related to the {0} field, but was found.{1}", + expectedErrorField, Subject); + + return new AndConstraint(this); + } + + /// + /// Asserts that a Bad Request HTTP response content contains an error message identifiable by an wildcard error text. + /// + /// + /// The wildcard pattern with which the error field associated error message is matched, where * and ? have special meanings. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + + [CustomAssertion] + public AndConstraint HaveErrorMessage(string expectedWildcardErrorMessage, + string because = "", params object[] becauseArgs) + { + Guard.ThrowIfArgumentIsNullOrEmpty(expectedWildcardErrorMessage, nameof(expectedWildcardErrorMessage), "Cannot verify having an error against a or empty wildcard error message."); + + Func> jsonFunc = () => Subject.GetJsonDocument(); + using var json = jsonFunc.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); + + var errorsPropertyList = json.GetPropertiesByName(ErrorsPropertyName).ToList(); + var hasErrorsProperty = errorsPropertyList.Any(); + var errorsProperty = errorsPropertyList.FirstOrDefault(); + var allErrors = hasErrorsProperty ? json.GetChildrenNames(ErrorsPropertyName).SelectMany(field => errorsProperty.GetStringValuesOf(field)) : json.GetChildrenNames("").SelectMany(field => json.GetStringValuesOf(field)); + + var matchFound = allErrors.Any(errorMessage => { - Guard.ThrowIfArgumentIsNullOrEmpty(expectedWildcardErrorMessage, nameof(expectedWildcardErrorMessage), "Cannot verify having an error against a or empty wildcard error message."); - - Func> jsonFunc = () => Subject.GetJsonDocument(); - using var json = jsonFunc.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); - - var errorsPropertyList = json.GetPropertiesByName(ErrorsPropertyName).ToList(); - var hasErrorsProperty = errorsPropertyList.Any(); - var errorsProperty = errorsPropertyList.FirstOrDefault(); - var allErrors = hasErrorsProperty ? json.GetChildrenNames(ErrorsPropertyName).SelectMany(field => errorsProperty.GetStringValuesOf(field)) : json.GetChildrenNames("").SelectMany(field => json.GetStringValuesOf(field)); - - var matchFound = allErrors.Any(errorMessage => - { - using var scope = new AssertionScope(); - errorMessage.Should().Match(expectedWildcardErrorMessage); - return !scope.Discard().Any(); - }); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(matchFound) - .FailWith("Expected {context:response} to contain " + - "the error message {0}, " + - "but no such message was found in the actual error messages list: " + - "{1}", - expectedWildcardErrorMessage, - Subject); - - return new AndConstraint(this); - } + using var scope = new AssertionScope(); + errorMessage.Should().Match(expectedWildcardErrorMessage); + return !scope.Discard().Any(); + }); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(matchFound) + .FailWith("Expected {context:response} to contain " + + "the error message {0}, " + + "but no such message was found in the actual error messages list: " + + "{1}", + expectedWildcardErrorMessage, + Subject); + + return new AndConstraint(this); } } \ No newline at end of file diff --git a/src/FluentAssertions.Web/BadRequestAssertionsExtensions.cs b/src/FluentAssertions.Web/BadRequestAssertionsExtensions.cs index cb7f376..ce11c79 100644 --- a/src/FluentAssertions.Web/BadRequestAssertionsExtensions.cs +++ b/src/FluentAssertions.Web/BadRequestAssertionsExtensions.cs @@ -1,115 +1,111 @@ -using FluentAssertions.Web; -using System.Diagnostics; +// ReSharper disable once CheckNamespace +namespace FluentAssertions; -// ReSharper disable once CheckNamespace -namespace FluentAssertions +/// +/// Contains extension methods for custom assertions in unit tests related to . +/// +[DebuggerNonUserCode] +public static class BadRequestAssertionsExtensions { /// - /// Contains extension methods for custom assertions in unit tests related to . + /// Asserts that a Bad Request HTTP response content contains an error message identifiable by an expected field name and a wildcard error text. /// - [DebuggerNonUserCode] - public static class BadRequestAssertionsExtensions - { - /// - /// Asserts that a Bad Request HTTP response content contains an error message identifiable by an expected field name and a wildcard error text. - /// - /// - /// This assertion considers the HTTP response content a JSON generated by the ASP.NET Core 3.0 framework or less - /// - /// - /// The expected field name. - /// - /// - /// The wildcard pattern with which the error field associated error message is matched, where * and ? have special meanings. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint HaveError( + /// + /// This assertion considers the HTTP response content a JSON generated by the ASP.NET Core 3.0 framework or less + /// + /// + /// The expected field name. + /// + /// + /// The wildcard pattern with which the error field associated error message is matched, where * and ? have special meanings. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint HaveError( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - string expectedErrorField, string expectedWildcardErrorMessage, - string because = "", params object[] becauseArgs) - => new BadRequestAssertions(parent.Subject).HaveError(expectedErrorField, expectedWildcardErrorMessage, because, becauseArgs); + string expectedErrorField, string expectedWildcardErrorMessage, + string because = "", params object[] becauseArgs) + => new BadRequestAssertions(parent.Subject).HaveError(expectedErrorField, expectedWildcardErrorMessage, because, becauseArgs); - /// - /// Asserts that a Bad Request HTTP response content contains only a single error message identifiable by an expected field name and a wildcard error text. - /// - /// - /// This assertion considers the HTTP response content a JSON generated by the ASP.NET Core 3.0 framework or less - /// - /// - /// The expected field name. - /// - /// - /// The wildcard pattern with which the error field associated error message is matched, where * and ? have special meanings. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint OnlyHaveError( + /// + /// Asserts that a Bad Request HTTP response content contains only a single error message identifiable by an expected field name and a wildcard error text. + /// + /// + /// This assertion considers the HTTP response content a JSON generated by the ASP.NET Core 3.0 framework or less + /// + /// + /// The expected field name. + /// + /// + /// The wildcard pattern with which the error field associated error message is matched, where * and ? have special meanings. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint OnlyHaveError( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - string expectedErrorField, string expectedWildcardErrorMessage, - string because = "", params object[] becauseArgs) - => new BadRequestAssertions(parent.Subject).OnlyHaveError(expectedErrorField, expectedWildcardErrorMessage, because, becauseArgs); + string expectedErrorField, string expectedWildcardErrorMessage, + string because = "", params object[] becauseArgs) + => new BadRequestAssertions(parent.Subject).OnlyHaveError(expectedErrorField, expectedWildcardErrorMessage, because, becauseArgs); - /// - /// Asserts that a Bad Request HTTP response content does not contain an error message identifiable by an expected field name. - /// - /// - /// This assertion considers the HTTP response content a JSON generated by the ASP.NET Core 3.0 framework or less - /// - /// - /// The expected field name. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint NotHaveError( + /// + /// Asserts that a Bad Request HTTP response content does not contain an error message identifiable by an expected field name. + /// + /// + /// This assertion considers the HTTP response content a JSON generated by the ASP.NET Core 3.0 framework or less + /// + /// + /// The expected field name. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint NotHaveError( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - string expectedErrorField, string because = "", params object[] becauseArgs) - => new BadRequestAssertions(parent.Subject).NotHaveError(expectedErrorField, because, becauseArgs); + string expectedErrorField, string because = "", params object[] becauseArgs) + => new BadRequestAssertions(parent.Subject).NotHaveError(expectedErrorField, because, becauseArgs); - /// - /// Asserts that a Bad Request HTTP response content contains an error message identifiable by an wildcard error text. - /// - /// - /// The wildcard pattern with which the error field associated error message is matched, where * and ? have special meanings. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint HaveErrorMessage( + /// + /// Asserts that a Bad Request HTTP response content contains an error message identifiable by an wildcard error text. + /// + /// + /// The wildcard pattern with which the error field associated error message is matched, where * and ? have special meanings. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint HaveErrorMessage( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - string expectedWildcardErrorMessage, - string because = "", params object[] becauseArgs) - => new BadRequestAssertions(parent.Subject).HaveErrorMessage(expectedWildcardErrorMessage, because, becauseArgs); - } + string expectedWildcardErrorMessage, + string because = "", params object[] becauseArgs) + => new BadRequestAssertions(parent.Subject).HaveErrorMessage(expectedWildcardErrorMessage, because, becauseArgs); } \ No newline at end of file diff --git a/src/FluentAssertions.Web/DeserializationException.cs b/src/FluentAssertions.Web/DeserializationException.cs index e22ebda..b7b45c3 100644 --- a/src/FluentAssertions.Web/DeserializationException.cs +++ b/src/FluentAssertions.Web/DeserializationException.cs @@ -1,49 +1,47 @@ // ReSharper disable once CheckNamespace -using System; using System.Runtime.Serialization; -namespace FluentAssertions +namespace FluentAssertions; + +/// +/// Captures serialization exceptions. +/// +[Serializable] +public class DeserializationException : Exception { /// - /// Captures serialization exceptions. + /// Argless constructor used to created new instances of this class. + /// + public DeserializationException() + { + } + + /// + /// Constructor used to created new instances of this class given a certain message. /// - [Serializable] - public class DeserializationException : Exception + /// The exception message. + + public DeserializationException(string message) : base(message) + { + } + + /// + /// Constructor used to created new instances of this class given a certain message and an exception. + /// + /// The exception message. + /// Usually the caught inner exception. + + public DeserializationException(string message, Exception innerException) : base(message, innerException) + { + } + + /// + /// Specialized constructor used to deserialize eventually serialized exceptions of this type. + /// + /// Serialization info. + /// Streaming context + + protected DeserializationException(SerializationInfo info, StreamingContext context) : base(info, context) { - /// - /// Argless constructor used to created new instances of this class. - /// - public DeserializationException() - { - } - - /// - /// Constructor used to created new instances of this class given a certain message. - /// - /// The exception message. - - public DeserializationException(string message) : base(message) - { - } - - /// - /// Constructor used to created new instances of this class given a certain message and an exception. - /// - /// The exception message. - /// Usually the caught inner exception. - - public DeserializationException(string message, Exception innerException) : base(message, innerException) - { - } - - /// - /// Specialized constructor used to deserialize eventually serialized exceptions of this type. - /// - /// Serialization info. - /// Streaming context - - protected DeserializationException(SerializationInfo info, StreamingContext context) : base(info, context) - { - } } } diff --git a/src/FluentAssertions.Web/FluentAssertionsWebConfig.cs b/src/FluentAssertions.Web/FluentAssertionsWebConfig.cs index 46b7372..4f0317f 100644 --- a/src/FluentAssertions.Web/FluentAssertionsWebConfig.cs +++ b/src/FluentAssertions.Web/FluentAssertionsWebConfig.cs @@ -1,26 +1,22 @@ -using FluentAssertions.Web.Internal.Serializers; -using System; +// ReSharper disable once CheckNamespace +namespace FluentAssertions; -// ReSharper disable once CheckNamespace -namespace FluentAssertions +/// +/// Holder of the global +/// +public static class FluentAssertionsWebConfig { + private static ISerializer? _serializer; + + static FluentAssertionsWebConfig() => Serializer = new SystemTextJsonSerializer(); + /// - /// Holder of the global + /// The serializer instance used to deserialize the responses into a model of a specified typed /// - public static class FluentAssertionsWebConfig + public static ISerializer Serializer { - private static ISerializer? _serializer; - - static FluentAssertionsWebConfig() => Serializer = new SystemTextJsonSerializer(); - - /// - /// The serializer instance used to deserialize the responses into a model of a specified typed - /// - public static ISerializer Serializer - { - get => _serializer ?? throw new InvalidOperationException("Serializer cannot be null"); + get => _serializer ?? throw new InvalidOperationException("Serializer cannot be null"); - set => _serializer = value ?? throw new ArgumentNullException(nameof(value), "Serializer cannot be null."); - } + set => _serializer = value ?? throw new ArgumentNullException(nameof(value), "Serializer cannot be null."); } } diff --git a/src/FluentAssertions.Web/GlobalUsings.cs b/src/FluentAssertions.Web/GlobalUsings.cs new file mode 100644 index 0000000..d6b1d98 --- /dev/null +++ b/src/FluentAssertions.Web/GlobalUsings.cs @@ -0,0 +1,14 @@ +global using FluentAssertions.Equivalency; +global using FluentAssertions.Execution; +global using FluentAssertions.Web; +global using FluentAssertions.Web.Internal; +global using FluentAssertions.Web.Internal.Serializers; +global using System; +global using System.Collections.Generic; +global using System.Diagnostics; +global using System.IO; +global using System.Linq; +global using System.Net; +global using System.Net.Http; +global using System.Text.Json; +global using System.Threading.Tasks; diff --git a/src/FluentAssertions.Web/HaveHeaderAssertions.cs b/src/FluentAssertions.Web/HaveHeaderAssertions.cs index 1190640..5a2215a 100644 --- a/src/FluentAssertions.Web/HaveHeaderAssertions.cs +++ b/src/FluentAssertions.Web/HaveHeaderAssertions.cs @@ -1,217 +1,285 @@ -using FluentAssertions.Execution; -using FluentAssertions.Web.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; - -namespace FluentAssertions.Web +namespace FluentAssertions.Web; + +/// +/// Contains a number of methods to assert that an is in the expected state related to HTTP headers. +/// +public class HeadersAssertions : HttpResponseMessageAssertions { + private readonly string _header; + + /// + /// Initialized a new instance of the + /// class. + /// + /// The subject value to be asserted. + /// The HTTP header name to be asserted. + public HeadersAssertions(HttpResponseMessage value, string header) : base(value) => _header = header; + /// - /// Contains a number of methods to assert that an is in the expected state related to HTTP headers. + /// Asserts that an existing HTTP header in a HTTP response contains at least a value that matches a wildcard pattern. /// - public class HeadersAssertions : HttpResponseMessageAssertions + /// + /// The wildcard pattern with which the subject is matched, where * and ? have special meanings. + /// + /// * - Matches any number of characters. You can use the asterisk (*) anywhere in a character string. Example: wh* finds what, white, and why, but not awhile or watch. + /// ? - Matches a single alphabet in a specific position. Example: b?ll finds ball, bell, and bill. + /// + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Match(string expectedWildcardValue, string because = "", params object[] becauseArgs) { - private readonly string _header; - - /// - /// Initialized a new instance of the - /// class. - /// - /// The subject value to be asserted. - /// The HTTP header name to be asserted. - public HeadersAssertions(HttpResponseMessage value, string header) : base(value) => _header = header; - - /// - /// Asserts that an existing HTTP header in a HTTP response contains at least a value that matches a wildcard pattern. - /// - /// - /// The wildcard pattern with which the subject is matched, where * and ? have special meanings. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Match(string expectedWildcardValue, string because = "", params object[] becauseArgs) - { - Guard.ThrowIfArgumentIsNull(expectedWildcardValue, nameof(expectedWildcardValue), "Cannot verify a HTTP header to be a value against a value. Use And.BeEmpty to test if the HTTP header has no values."); - - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - IEnumerable headerValues = Subject!.GetHeaderValues(_header); - - var matchFound = headerValues.Any(headerValue => - { - using var scope = new AssertionScope(); - headerValue.Should().Match(expectedWildcardValue); - return !scope.Discard().Any(); - }); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(matchFound) - .FailWith("Expected {context:response} to contain " + - "the HTTP header {0} having a value matching {1}, but there was no match{reason}. {2}", - _header, - expectedWildcardValue, - Subject); - - return new AndConstraint(this); - } + Guard.ThrowIfArgumentIsNull(expectedWildcardValue, nameof(expectedWildcardValue), "Cannot verify a HTTP header to be a value against a value. Use And.BeEmpty to test if the HTTP header has no values."); - /// - /// Asserts that an existing HTTP header in a HTTP response has no values. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint BeEmpty(string because = "", params object[] becauseArgs) - { - var headerValues = Subject.GetHeaderValues(_header); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(!headerValues.Any()) - .FailWith("Expected {context:response} to contain " + - "the HTTP header {0} with no header values, but the found the header and it has values {1} in the actual response{reason}. {2}", - _header, - headerValues, - Subject); - - return new AndConstraint(this); - } + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); - /// - /// Asserts that an existing HTTP header in a HTTP response has an expected list of header values. - /// - /// - /// The expected values with which the HTTP headers values list is compared. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint BeValues(IEnumerable expectedValues, - string because = "", params object[] becauseArgs) - { - Guard.ThrowIfArgumentIsNull(expectedValues, nameof(expectedValues), "Cannot verify a HTTP header to be a collection of expected values against a collection. Use And.BeEmpty to test if the HTTP header has no values."); - if (!expectedValues.Any()) - { - throw new ArgumentException("Cannot verify a HTTP header to be a collection of expected values against an empty collection. Use And.BeEmpty to test if the HTTP header has no values.", nameof(expectedValues)); - } + IEnumerable headerValues = Subject!.GetHeaderValues(_header); - var values = Subject.GetHeaders().FirstOrDefault(c => c.Key == _header).Value; + var matchFound = headerValues.Any(headerValue => + { + using var scope = new AssertionScope(); + headerValue.Should().Match(expectedWildcardValue); + return !scope.Discard().Any(); + }); - string[] failures; + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(matchFound) + .FailWith("Expected {context:response} to contain " + + "the HTTP header {0} having a value matching {1}, but there was no match{reason}. {2}", + _header, + expectedWildcardValue, + Subject); - using (var scope = new AssertionScope()) - { - values.Should().BeEquivalentTo(expectedValues); + return new AndConstraint(this); + } - failures = scope.Discard(); - } + /// + /// Asserts that an existing HTTP header in a HTTP response has no values. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint BeEmpty(string because = "", params object[] becauseArgs) + { + var headerValues = Subject.GetHeaderValues(_header); - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(failures.Length == 0) - .FailWith("Expected {context:response} to contain " + - "the HTTP header {0} having values {1}, but the found values have differences{reason}. {2}", - _header, - expectedValues, - Subject); + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(!headerValues.Any()) + .FailWith("Expected {context:response} to contain " + + "the HTTP header {0} with no header values, but found the header and it has values {1} in the actual response{reason}. {2}", + _header, + headerValues, + Subject); - return new AndConstraint(this); - } + return new AndConstraint(this); + } + /// + /// Asserts that an existing HTTP header in a HTTP response has any values. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint NotBeEmpty(string because = "", params object[] becauseArgs) + { + var headerValues = Subject.GetHeaderValues(_header); + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(headerValues.Any()) + .FailWith("Expected {context:response} to contain " + + "the HTTP header {0} with any header values, but found the header and it has no values in the actual response{reason}. {2}", + _header, + headerValues, + Subject); - /// - /// Returns the type of the subject the assertion applies on. - /// - protected override string Identifier => "Header"; + return new AndConstraint(this); } - public partial class HttpResponseMessageAssertions + /// + /// Asserts that an existing HTTP header in a HTTP response has an expected list of header values. + /// + /// + /// The expected values with which the HTTP headers values list is compared. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint BeValues(IEnumerable expectedValues, + string because = "", params object[] becauseArgs) { - /// - /// Asserts that an HTTP response has a named header. - /// - /// - /// The expected header with which the HTTP headers list is matched. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint HaveHeader(string expectedHeader, - string because = "", params object[] becauseArgs) + Guard.ThrowIfArgumentIsNull(expectedValues, nameof(expectedValues), "Cannot verify a HTTP header to be a collection of expected values against a collection. Use And.BeEmpty to test if the HTTP header has no values."); + if (!expectedValues.Any()) { - Guard.ThrowIfArgumentIsNull(expectedHeader, nameof(expectedHeader), "Cannot verify having a header against a header."); + throw new ArgumentException("Cannot verify a HTTP header to be a collection of expected values against an empty collection. Use And.BeEmpty to test if the HTTP header has no values.", nameof(expectedValues)); + } - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(IsHeaderPresent(expectedHeader)) - .FailWith("Expected {context:response} to contain " + - "the HTTP header {0}, but no such header was found in the actual response{reason}.{1}", - expectedHeader, - Subject); + var values = Subject.GetHeaders().FirstOrDefault(c => c.Key == _header).Value; - return new AndConstraint(new HeadersAssertions(Subject, expectedHeader)); - } + string[] failures; - /// - /// Asserts that an HTTP response does not have a named header. - /// - /// - /// The expected header with which the HTTP headers list is matched. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint NotHaveHeader(string expectedHeader, - string because = "", params object[] becauseArgs) + using (var scope = new AssertionScope()) { - Guard.ThrowIfArgumentIsNull(expectedHeader, nameof(expectedHeader), "Cannot verify not having a header against a header."); + values.Should().BeEquivalentTo(expectedValues); + + failures = scope.Discard(); + } - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(!IsHeaderPresent(expectedHeader)) - .FailWith("Expected {context:response} to not to contain " + - "the HTTP header {0}, but the header was found in the actual response{reason}.{1}", - expectedHeader, - Subject); + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(failures.Length == 0) + .FailWith("Expected {context:response} to contain " + + "the HTTP header {0} having values {1}, but the found values have differences{reason}. {2}", + _header, + expectedValues, + Subject); - return new AndConstraint(this); + return new AndConstraint(this); + } + + /// + /// Asserts that an existing HTTP header in a HTTP response has an expected value. + /// + /// + /// The expected value with which the HTTP header value list is compared. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint BeValue(string expectedValue, + string because = "", params object[] becauseArgs) + { + Guard.ThrowIfArgumentIsNullOrEmpty(expectedValue, nameof(expectedValue), "Cannot verify a HTTP header to be a value against a or empty value. Use And.BeEmpty to test if the HTTP header has no value."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(Subject.GetHeaderValues(_header).Count() == 1) + .FailWith($$""" + Expected {context:response} to contain the {0} HTTP header and the value to be equivalent to "{{expectedValue}}", but found the header and has more or no values{reason}.{1} + """, _header, Subject); + + var value = Subject.GetFirstHeaderValue(_header); + + string[] failures; + + using (var scope = new AssertionScope("header value")) + { + value.Should().BeEquivalentTo(expectedValue); + + failures = scope.Discard(); } - private bool IsHeaderPresent(string expectedHeader) - => Subject - .GetHeaders() - .Any(c => string.Equals(c.Key, expectedHeader, StringComparison.OrdinalIgnoreCase)); + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(failures.Length == 0) + .FailWith($$""" + Expected {context:response} to contain the {0} HTTP header and the {{ failures.FirstOrDefault()?.ReplaceFirstWithLowercase().TrimDot() }}{reason}.{1} + """, _header, Subject); + + return new AndConstraint(this); + } + + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Identifier => "Header"; +} + +public partial class HttpResponseMessageAssertions +{ + /// + /// Asserts that an HTTP response has a named header. + /// + /// + /// The expected header with which the HTTP headers list is matched. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint HaveHeader(string expectedHeader, + string because = "", params object[] becauseArgs) + { + Guard.ThrowIfArgumentIsNull(expectedHeader, nameof(expectedHeader), "Cannot verify having a header against a header."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(IsHeaderPresent(expectedHeader)) + .FailWith("Expected {context:response} to contain " + + "the HTTP header {0}, but no such header was found in the actual response{reason}.{1}", + expectedHeader, + Subject); + + return new AndConstraint(new HeadersAssertions(Subject, expectedHeader)); + } + + /// + /// Asserts that an HTTP response does not have a named header. + /// + /// + /// The expected header with which the HTTP headers list is matched. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint NotHaveHeader(string expectedHeader, + string because = "", params object[] becauseArgs) + { + Guard.ThrowIfArgumentIsNull(expectedHeader, nameof(expectedHeader), "Cannot verify not having a header against a header."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(!IsHeaderPresent(expectedHeader)) + .FailWith("Expected {context:response} to not to contain " + + "the HTTP header {0}, but the header was found in the actual response{reason}.{1}", + expectedHeader, + Subject); + + return new AndConstraint(this); } + + private bool IsHeaderPresent(string expectedHeader) + => Subject + .GetHeaders() + .Any(c => string.Equals(c.Key, expectedHeader, StringComparison.OrdinalIgnoreCase)); } \ No newline at end of file diff --git a/src/FluentAssertions.Web/HaveHeaderAssertionsExtensions.cs b/src/FluentAssertions.Web/HaveHeaderAssertionsExtensions.cs index a32ff53..e565ff9 100644 --- a/src/FluentAssertions.Web/HaveHeaderAssertionsExtensions.cs +++ b/src/FluentAssertions.Web/HaveHeaderAssertionsExtensions.cs @@ -1,56 +1,52 @@ -using FluentAssertions.Web; -using System.Diagnostics; +namespace FluentAssertions; -namespace FluentAssertions +/// +/// Contains extension methods for custom assertions in unit tests related to . +/// +[DebuggerNonUserCode] +public static class HeadersAssertionsExtensions { /// - /// Contains extension methods for custom assertions in unit tests related to . + /// Asserts that an HTTP response has a named header. /// - [DebuggerNonUserCode] - public static class HeadersAssertionsExtensions - { - /// - /// Asserts that an HTTP response has a named header. - /// - /// - /// The expected header with which the HTTP headers list is matched. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint HaveHeader( + /// + /// The expected header with which the HTTP headers list is matched. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint HaveHeader( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - string expectedHeader, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).HaveHeader(expectedHeader, because, becauseArgs); + string expectedHeader, + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).HaveHeader(expectedHeader, because, becauseArgs); - /// - /// Asserts that an HTTP response does not have a named header. - /// - /// - /// The expected header with which the HTTP headers list is matched. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint NotHaveHeader( + /// + /// Asserts that an HTTP response does not have a named header. + /// + /// + /// The expected header with which the HTTP headers list is matched. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint NotHaveHeader( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - string expectedHeader, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).NotHaveHeader(expectedHeader, because, becauseArgs); - } + string expectedHeader, + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).NotHaveHeader(expectedHeader, because, becauseArgs); } \ No newline at end of file diff --git a/src/FluentAssertions.Web/HttpResponseContentAssertions.cs b/src/FluentAssertions.Web/HttpResponseContentAssertions.cs index eb9560a..faf5a86 100644 --- a/src/FluentAssertions.Web/HttpResponseContentAssertions.cs +++ b/src/FluentAssertions.Web/HttpResponseContentAssertions.cs @@ -1,154 +1,144 @@ -using FluentAssertions.Equivalency; -using FluentAssertions.Execution; -using FluentAssertions.Web.Internal; -using System; -using System.Net.Http; +namespace FluentAssertions.Web; -namespace FluentAssertions.Web +/// +/// Contains a number of methods to assert that an is in the expected state related to the HTTP content. +/// +public partial class HttpResponseMessageAssertions { /// - /// Contains a number of methods to assert that an is in the expected state related to the HTTP content. + /// Asserts that HTTP response content can be an equivalent representation of the expected model. /// - public partial class HttpResponseMessageAssertions - { - /// - /// Asserts that HTTP response content can be an equivalent representation of the expected model. - /// - /// - /// The expected model. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint BeAs(TModel expectedModel, string because = "", params object[] becauseArgs) - => BeAs(expectedModel, options => options, because, becauseArgs); - - /// - /// Asserts that HTTP response content can be an equivalent representation of the expected model. - /// - /// - /// The expected model. - /// - /// - /// A reference to the configuration object that can be used - /// to influence the way the object graphs are compared. You can also provide an alternative instance of the - /// class. The global defaults are determined by the - /// class. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint BeAs(TModel expectedModel, Func, EquivalencyAssertionOptions> options, string because = "", params object[] becauseArgs) - { - Guard.ThrowIfArgumentIsNull(options, nameof(options)); + /// + /// The expected model. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint BeAs(TModel expectedModel, string because = "", params object[] becauseArgs) + => BeAs(expectedModel, options => options, because, becauseArgs); - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); + /// + /// Asserts that HTTP response content can be an equivalent representation of the expected model. + /// + /// + /// The expected model. + /// + /// + /// A reference to the configuration object that can be used + /// to influence the way the object graphs are compared. You can also provide an alternative instance of the + /// class. The global defaults are determined by the + /// class. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint BeAs(TModel expectedModel, Func, EquivalencyAssertionOptions> options, string because = "", params object[] becauseArgs) + { + Guard.ThrowIfArgumentIsNull(options, nameof(options)); - if (expectedModel == null) - { - throw new ArgumentNullException(nameof(expectedModel), "Cannot verify having a content equivalent to a model against a model."); - } + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); - var expectedModelType = expectedModel.GetType(); + if (expectedModel == null) + { + throw new ArgumentNullException(nameof(expectedModel), "Cannot verify having a content equivalent to a model against a model."); + } - var (success, errorMessage) = TryGetSubjectModel(out var subjectModel, expectedModelType); + var expectedModelType = expectedModel.GetType(); - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(success) - .FailWith("Expected {context:response} to have a content equivalent to a model of type {0}, but the JSON representation could not be parsed, as the operation failed with the following message: {2}{reason}. {1}", - expectedModelType?.ToString() ?? "unknown type", Subject, errorMessage); - - string[] failures; - - using (var scope = new AssertionScope()) - { - if (options != null) - { - subjectModel.Should().BeEquivalentTo(expectedModel, options); - } - else - { - subjectModel.Should().BeEquivalentTo(expectedModel); - } - - failures = scope.Discard(); - } + var (success, errorMessage) = TryGetSubjectModel(out var subjectModel, expectedModelType); - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(failures.Length == 0) - .FailWith("Expected {context:response} to have a content equivalent to a model, but it has differences:{0}{reason}. {1}", - new AssertionsFailures(failures), - Subject); + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(success) + .FailWith("Expected {context:response} to have a content equivalent to a model of type {0}, but the JSON representation could not be parsed, as the operation failed with the following message: {2}{reason}. {1}", + expectedModelType.ToString() ?? "unknown type", Subject, errorMessage); - return new AndConstraint(this); - } + string[] failures; - /// - /// Asserts that HTTP response has content that matches a wildcard pattern. - /// - /// - /// The wildcard pattern with which the subject is matched, where * and ? have special meanings. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint MatchInContent(string expectedWildcardText, string because = "", params object[] becauseArgs) + using (var scope = new AssertionScope()) { - Guard.ThrowIfArgumentIsNull(expectedWildcardText, nameof(expectedWildcardText), "Cannot verify a HTTP response content match a wildcard pattern."); + subjectModel.Should().BeEquivalentTo(expectedModel, options); - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); + failures = scope.Discard(); + } - var content = GetContent(); + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(failures.Length == 0) + .FailWith("Expected {context:response} to have a content equivalent to a model, but it has differences:{0}{reason}. {1}", + new AssertionsFailures(failures), + Subject); - if (string.IsNullOrEmpty(content)) - { - Execute.Assertion - .BecauseOf(because, becauseArgs) - .FailWith("Expected {context:response} to match the wildcard pattern {0} in its content, but content was {reason}. {1}", - expectedWildcardText, - Subject); - } + return new AndConstraint(this); + } - string[] failures; + /// + /// Asserts that HTTP response has content that matches a wildcard pattern. + /// + /// + /// The wildcard pattern with which the subject is matched, where * and ? have special meanings. + /// + /// * - Matches any number of characters. You can use the asterisk (*) anywhere in a character string. Example: wh* finds what, white, and why, but not awhile or watch. + /// ? - Matches a single alphabet in a specific position. Example: b?ll finds ball, bell, and bill. + /// + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint MatchInContent(string expectedWildcardText, string because = "", params object[] becauseArgs) + { + Guard.ThrowIfArgumentIsNull(expectedWildcardText, nameof(expectedWildcardText), "Cannot verify a HTTP response content match a wildcard pattern."); - using (var scope = new AssertionScope()) - { - content.Should().Match(expectedWildcardText); + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); - failures = scope.Discard(); - } + var content = GetContent(); + if (string.IsNullOrEmpty(content)) + { Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(failures.Length == 0) - .FailWith("Expected {context:response} to match a wildcard pattern in its content, but does not since:{0}{reason}. {1}", - new AssertionsFailures(failures), - Subject); + .BecauseOf(because, becauseArgs) + .FailWith("Expected {context:response} to match the wildcard pattern {0} in its content, but content was {reason}. {1}", + expectedWildcardText, + Subject); + } - return new AndConstraint(this); + string[] failures; + + using (var scope = new AssertionScope()) + { + content.Should().Match(expectedWildcardText); + + failures = scope.Discard(); } + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(failures.Length == 0) + .FailWith("Expected {context:response} to match a wildcard pattern in its content, but does not since:{0}{reason}. {1}", + new AssertionsFailures(failures), + Subject); + + return new AndConstraint(this); } } \ No newline at end of file diff --git a/src/FluentAssertions.Web/HttpResponseContentAssertionsExtensions.cs b/src/FluentAssertions.Web/HttpResponseContentAssertionsExtensions.cs index b08ee52..c2d7ad5 100644 --- a/src/FluentAssertions.Web/HttpResponseContentAssertionsExtensions.cs +++ b/src/FluentAssertions.Web/HttpResponseContentAssertionsExtensions.cs @@ -1,83 +1,81 @@ -using FluentAssertions.Equivalency; -using FluentAssertions.Web; -using System; -using System.Diagnostics; +namespace FluentAssertions; -namespace FluentAssertions +/// +/// Contains extension methods for custom assertions in unit tests related to Http Response Content Assertions +/// +[DebuggerNonUserCode] +public static class HttpResponseContentAssertionsExtensions { /// - /// Contains extension methods for custom assertions in unit tests related to Http Response Content Assertions + /// Asserts that HTTP response content can be an equivalent representation of the expected model. /// - [DebuggerNonUserCode] - public static class HttpResponseContentAssertionsExtensions - { - /// - /// Asserts that HTTP response content can be an equivalent representation of the expected model. - /// - /// - /// The expected model. - /// - /// - /// A reference to the configuration object that can be used - /// to influence the way the object graphs are compared. You can also provide an alternative instance of the - /// class. The global defaults are determined by the - /// class. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint BeAs( + /// + /// The expected model. + /// + /// + /// A reference to the configuration object that can be used + /// to influence the way the object graphs are compared. You can also provide an alternative instance of the + /// class. The global defaults are determined by the + /// class. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint BeAs( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - TModel expectedModel, Func, EquivalencyAssertionOptions> options, string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).BeAs(expectedModel, options, because, becauseArgs); + TModel expectedModel, Func, EquivalencyAssertionOptions> options, string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).BeAs(expectedModel, options, because, becauseArgs); - /// - /// Asserts that HTTP response content can be an equivalent representation of the expected model. - /// - /// - /// The expected model. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint BeAs( + /// + /// Asserts that HTTP response content can be an equivalent representation of the expected model. + /// + /// + /// The expected model. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint BeAs( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - TModel expectedModel, string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).BeAs(expectedModel, because, becauseArgs); + TModel expectedModel, string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).BeAs(expectedModel, because, becauseArgs); - /// - /// Asserts that HTTP response has content that matches a wildcard pattern. - /// - /// - /// The wildcard pattern with which the subject is matched, where * and ? have special meanings. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint MatchInContent( + /// + /// Asserts that HTTP response has content that matches a wildcard pattern. + /// + /// + /// The wildcard pattern with which the subject is matched, where * and ? have special meanings. + /// + /// * - Matches any number of characters. You can use the asterisk (*) anywhere in a character string. Example: wh* finds what, white, and why, but not awhile or watch. + /// ? - Matches a single alphabet in a specific position. Example: b?ll finds ball, bell, and bill. + /// + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint MatchInContent( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string expectedWildcardText, string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).MatchInContent(expectedWildcardText, because, becauseArgs); - } + string expectedWildcardText, string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).MatchInContent(expectedWildcardText, because, becauseArgs); } diff --git a/src/FluentAssertions.Web/HttpResponseMessageAssertions.cs b/src/FluentAssertions.Web/HttpResponseMessageAssertions.cs index 98bf7fa..eedc382 100644 --- a/src/FluentAssertions.Web/HttpResponseMessageAssertions.cs +++ b/src/FluentAssertions.Web/HttpResponseMessageAssertions.cs @@ -1,95 +1,88 @@ -using FluentAssertions.Execution; -using FluentAssertions.Formatting; +using FluentAssertions.Formatting; using FluentAssertions.Primitives; -using FluentAssertions.Web.Internal; -using System; -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -namespace FluentAssertions.Web +namespace FluentAssertions.Web; + +/// +/// Contains a number of methods to assert that an is in the expected state. +/// +public partial class HttpResponseMessageAssertions : ReferenceTypeAssertions { + static HttpResponseMessageAssertions() + { + Formatter.AddFormatter(new HttpResponseMessageFormatter()); + Formatter.AddFormatter(new AssertionsFailuresFormatter()); + } + /// - /// Contains a number of methods to assert that an is in the expected state. + /// Initialized a new instance of the + /// class. /// - public partial class HttpResponseMessageAssertions : ReferenceTypeAssertions - { - static HttpResponseMessageAssertions() - { - Formatter.AddFormatter(new HttpResponseMessageFormatter()); - Formatter.AddFormatter(new AssertionsFailuresFormatter()); - } + /// The subject value to be asserted. + public HttpResponseMessageAssertions(HttpResponseMessage value) : base(value) { } - /// - /// Initialized a new instance of the - /// class. - /// - /// The subject value to be asserted. - public HttpResponseMessageAssertions(HttpResponseMessage value) : base(value) { } + /// + /// Returns the type of the subject the assertion applies on. + /// + protected override string Identifier => $"{nameof(HttpResponseMessage)}"; - /// - /// Returns the type of the subject the assertion applies on. - /// - protected override string Identifier => $"{nameof(HttpResponseMessage)}"; + private protected string? GetContent() + { + Func> content = () => Subject.GetStringContent(); + return content.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); + } - private protected string? GetContent() - { - Func> content = () => Subject.GetStringContent(); - return content.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); - } + private protected (bool success, string? errorMessage) TryGetSubjectModel(out TModel? model) + { + var (success, errorMessage) = TryGetSubjectModel(out var subjectModel, typeof(TModel)); + model = (TModel?)subjectModel; + return (success, errorMessage); + } - private protected (bool success, string? errorMessage) TryGetSubjectModel(out TModel? model) + private protected (bool success, string? errorMessage) TryGetSubjectModel(out object? model, Type modelType) + { + Func> readModel = () => Subject.Content.ReadAsAsync(modelType, FluentAssertionsWebConfig.Serializer); + try { - var (success, errorMessage) = TryGetSubjectModel(out var subjectModel, typeof(TModel)); - model = (TModel?)subjectModel; - return (success, errorMessage); + model = readModel.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); + return (true, null); } - - private protected (bool success, string? errorMessage) TryGetSubjectModel(out object? model, Type modelType) + catch (Exception ex) when (ex is DeserializationException or NotSupportedException) { - Func> readModel = () => Subject.Content.ReadAsAsync(modelType, FluentAssertionsWebConfig.Serializer); - try + model = default; + var message = ex.Message; + if (ex.InnerException != null) { - model = readModel.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); - return (true, null); + message += $": {ex.InnerException.Message}"; } - catch (Exception ex) when (ex is DeserializationException || ex is NotSupportedException) - { - model = default; - var message = ex.Message; - if (ex.InnerException != null) - { - message += $": {ex.InnerException.Message}"; - } - return (false, message); - } + return (false, message); } + } - private string[] CollectFailuresFromAssertion(Action assertion, TAsserted subject) + private string[] CollectFailuresFromAssertion(Action assertion, TAsserted subject) + { + using var collectionScope = new AssertionScope(); + string[] assertionFailures; + using (var itemScope = new AssertionScope()) { - using var collectionScope = new AssertionScope(); - string[] assertionFailures; - using (var itemScope = new AssertionScope()) + try { - try - { - assertion(subject); - assertionFailures = itemScope.Discard(); - } - catch (Exception ex) - { - assertionFailures = new[] { $"Expected to successfully verify an assertion, but the following exception occurred: { ex }" }; - } - + assertion(subject); + assertionFailures = itemScope.Discard(); } - - foreach (var assertionFailure in assertionFailures) + catch (Exception ex) { - collectionScope.AddPreFormattedFailure($"{assertionFailure}"); + assertionFailures = new[] { $"Expected to successfully verify an assertion, but the following exception occurred: { ex }" }; } - return collectionScope.Discard(); } + + foreach (var assertionFailure in assertionFailures) + { + collectionScope.AddPreFormattedFailure($"{assertionFailure}"); + } + + return collectionScope.Discard(); } } \ No newline at end of file diff --git a/src/FluentAssertions.Web/HttpResponseMessageFormatter.cs b/src/FluentAssertions.Web/HttpResponseMessageFormatter.cs index 79bb982..fc14ab3 100644 --- a/src/FluentAssertions.Web/HttpResponseMessageFormatter.cs +++ b/src/FluentAssertions.Web/HttpResponseMessageFormatter.cs @@ -1,119 +1,113 @@ using FluentAssertions.Formatting; -using FluentAssertions.Web.Internal; using FluentAssertions.Web.Internal.ContentProcessors; -using System; -using System.Collections.Generic; -using System.Net.Http; using System.Text; -using System.Threading.Tasks; -namespace FluentAssertions.Web +namespace FluentAssertions.Web; + +internal class HttpResponseMessageFormatter : IValueFormatter { - internal class HttpResponseMessageFormatter : IValueFormatter + public bool CanHandle(object value) => value is HttpResponseMessage; + + /// + public void Format(object value, + FormattedObjectGraph formattedGraph, + FormattingContext context, + FormatChild formatChild) { - public bool CanHandle(object value) => value is HttpResponseMessage; + var response = (HttpResponseMessage)value; - /// - public void Format(object value, - FormattedObjectGraph formattedGraph, - FormattingContext context, - FormatChild formatChild) - { - var response = (HttpResponseMessage)value; + var messageBuilder = new StringBuilder(); + messageBuilder.AppendLine(); + messageBuilder.AppendLine(); + messageBuilder.AppendLine("The HTTP response was:"); - var messageBuilder = new StringBuilder(); - messageBuilder.AppendLine(); - messageBuilder.AppendLine(); - messageBuilder.AppendLine("The HTTP response was:"); + Func contentResolver = async () => await AppendHttpResponseMessage(messageBuilder, response); + contentResolver.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); - Func contentResolver = async () => await AppendHttpResponseMessage(messageBuilder, response); - contentResolver.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); + formattedGraph.AddFragment(messageBuilder.ToString()); + } - formattedGraph.AddFragment(messageBuilder.ToString()); + private static async Task AppendHttpResponseMessage(StringBuilder messageBuilder, HttpResponseMessage response) + { + try + { + await AppendResponse(messageBuilder, response); } - - private static async Task AppendHttpResponseMessage(StringBuilder messageBuilder, HttpResponseMessage response) + catch (Exception e) { - try - { - await AppendResponse(messageBuilder, response); - } - catch (Exception e) - { - messageBuilder.AppendLine(); - messageBuilder.AppendLine($"An exception occurred while trying to output the some of the response details: {e}"); - } - try - { - await AppendRequest(messageBuilder, response); - } - catch (Exception e) - { - messageBuilder.AppendLine(); - messageBuilder.AppendLine($"An exception occurred while trying to output some of the request details: {e}"); - } + messageBuilder.AppendLine(); + messageBuilder.AppendLine($"An exception occurred while trying to output the some of the response details: {e}"); } - - private static async Task AppendResponse(StringBuilder messageBuilder, HttpResponseMessage response) + try { - AppendProtocolAndStatusCode(messageBuilder, response); - Appender.AppendHeaders(messageBuilder, response.GetHeaders()); - AppendContentLength(messageBuilder, response.Content); - await AppendResponseContent(messageBuilder, response); + await AppendRequest(messageBuilder, response); } - - private static async Task AppendRequest(StringBuilder messageBuilder, HttpResponseMessage response) + catch (Exception e) { messageBuilder.AppendLine(); - var request = response.RequestMessage; - if (request == null) - { - messageBuilder.AppendLine("The originated HTTP request was ."); - return; - } - messageBuilder.AppendLine("The originated HTTP request was:"); - messageBuilder.AppendLine(); - - messageBuilder.AppendLine($"{request.Method.ToString().ToUpper()} {request.RequestUri} HTTP {request.Version}"); + messageBuilder.AppendLine($"An exception occurred while trying to output some of the request details: {e}"); + } + } - Appender.AppendHeaders(messageBuilder, request.GetHeaders()); - AppendContentLength(messageBuilder, request.Content); + private static async Task AppendResponse(StringBuilder messageBuilder, HttpResponseMessage response) + { + AppendProtocolAndStatusCode(messageBuilder, response); + Appender.AppendHeaders(messageBuilder, response.GetHeaders()); + AppendContentLength(messageBuilder, response.Content); + await AppendResponseContent(messageBuilder, response); + } - await AppendRequestContent(messageBuilder, request.Content); + private static async Task AppendRequest(StringBuilder messageBuilder, HttpResponseMessage response) + { + messageBuilder.AppendLine(); + var request = response.RequestMessage; + if (request == null) + { + messageBuilder.AppendLine("The originating HTTP request was ."); + return; } + messageBuilder.AppendLine("The originating HTTP request was:"); + messageBuilder.AppendLine(); - private static async Task AppendResponseContent(StringBuilder messageBuilder, HttpResponseMessage response) - { - var content = response.Content; - if (content == null) - { - return; - } + messageBuilder.AppendLine($"{request.Method.ToString().ToUpper()} {request.RequestUri} HTTP {request.Version}"); - var processors = new List(); - processors.Add(new InternalServerErrorProcessor(response, content)); - processors.AddRange(ProcessorsRunner.CommonProcessors(content)); + Appender.AppendHeaders(messageBuilder, request.GetHeaders()); + AppendContentLength(messageBuilder, request.Content); - var contentBuilder = await ProcessorsRunner.RunProcessors(processors); - messageBuilder.AppendLine(); - messageBuilder.Append(contentBuilder); - } + await AppendRequestContent(messageBuilder, request.Content); + } - private static async Task AppendRequestContent(StringBuilder messageBuilder, HttpContent content) + private static async Task AppendResponseContent(StringBuilder messageBuilder, HttpResponseMessage response) + { + var content = response.Content; + if (content == null) { - await Appender.AppendContent(messageBuilder, content, false); + return; } - private static void AppendProtocolAndStatusCode(StringBuilder messageBuilder, HttpResponseMessage response) - { - messageBuilder.AppendLine(); - messageBuilder.AppendLine($@"HTTP/{response.Version} {(int)response.StatusCode} {response.StatusCode}"); - } + var processors = new List(); + processors.Add(new InternalServerErrorProcessor(response, content)); + processors.AddRange(ProcessorsRunner.CommonProcessors(content)); - private static void AppendContentLength(StringBuilder messageBuilder, HttpContent content) - { - content.TryGetContentLength(out var length); - messageBuilder.AppendLine($"Content-Length: {length}"); - } + var contentBuilder = await ProcessorsRunner.RunProcessors(processors); + messageBuilder.AppendLine(); + messageBuilder.Append(contentBuilder); + } + + private static async Task AppendRequestContent(StringBuilder messageBuilder, HttpContent content) + { + await Appender.AppendContent(messageBuilder, content, false); + } + + private static void AppendProtocolAndStatusCode(StringBuilder messageBuilder, HttpResponseMessage response) + { + messageBuilder.AppendLine(); + messageBuilder.AppendLine($@"HTTP/{response.Version} {(int)response.StatusCode} {response.StatusCode}"); + } + + private static void AppendContentLength(StringBuilder messageBuilder, HttpContent content) + { + content.TryGetContentLength(out var length); + messageBuilder.AppendLine($"Content-Length: {length}"); } } \ No newline at end of file diff --git a/src/FluentAssertions.Web/HttpStatusCodeAssertions.cs b/src/FluentAssertions.Web/HttpStatusCodeAssertions.cs index 5c1810d..46c63bc 100644 --- a/src/FluentAssertions.Web/HttpStatusCodeAssertions.cs +++ b/src/FluentAssertions.Web/HttpStatusCodeAssertions.cs @@ -1,1501 +1,1497 @@ -using FluentAssertions.Execution; -using System.Net; +namespace FluentAssertions.Web; -namespace FluentAssertions.Web +public partial class HttpResponseMessageAssertions { - public partial class HttpResponseMessageAssertions + #region Be1XXInformational + /// + /// Asserts that a HTTP response has a HTTP status code representing an informational response. + /// + /// The HTTP response was an informational one if was in the range 100-199. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + // ReSharper disable once InconsistentNaming + public AndConstraint Be1XXInformational(string because = "", params object[] becauseArgs) { - #region Be1XXInformational - /// - /// Asserts that a HTTP response has a HTTP status code representing an informational response. - /// - /// The HTTP response was an informational one if was in the range 100-199. - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - // ReSharper disable once InconsistentNaming - public AndConstraint Be1XXInformational(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(Subject!.StatusCode < HttpStatusCode.OK) - .FailWith("Expected {context:response} to have a HTTP status code representing an informational error, but it was {0}{reason}.{1}", - Subject!.StatusCode, Subject); - - return new AndConstraint(this); - } - #endregion - - #region Be2XXSuccessful - /// - /// Asserts that a HTTP response has a successful HTTP status code. - /// - /// The HTTP response was successful if was in the range 200-299. - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - // ReSharper disable once InconsistentNaming - public AndConstraint Be2XXSuccessful(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(Subject!.IsSuccessStatusCode) - .FailWith("Expected {context:response} to have a successful HTTP status code, but it was {0}{reason}.{1}", - Subject!.StatusCode, Subject); - - return new AndConstraint(this); - } - #endregion - - #region Be3XXRedirection - /// - /// Asserts that a HTTP response has a HTTP status code representing a redirection response. - /// - /// The HTTP response was an informational one if was in the range 300-399. - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - // ReSharper disable once InconsistentNaming - public AndConstraint Be3XXRedirection(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(Subject!.StatusCode >= HttpStatusCode.Moved && Subject!.StatusCode < HttpStatusCode.BadRequest) - .FailWith("Expected {context:response} to have a HTTP status code representing a redirection, but it was {0}{reason}.{1}", - Subject!.StatusCode, Subject); - - return new AndConstraint(this); - } - #endregion - - #region Be4XXClientError - /// - /// Asserts that a HTTP response has a HTTP status code representing a client error. - /// - /// The HTTP response was a client error if was in the range 400-499. - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - // ReSharper disable once InconsistentNaming - public AndConstraint Be4XXClientError(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(Subject!.StatusCode >= HttpStatusCode.BadRequest && Subject!.StatusCode < HttpStatusCode.InternalServerError) - .FailWith("Expected {context:response} to have a HTTP status code representing a client error, but it was {0}{reason}.{1}", - Subject!.StatusCode, Subject); - - return new AndConstraint(this); - } - #endregion - - #region Be5XXServerError - /// - /// Asserts that a HTTP response has a HTTP status code representing a server error. - /// - /// The HTTP response was a server error if was above 500. - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - // ReSharper disable once InconsistentNaming - public AndConstraint Be5XXServerError(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(Subject!.StatusCode >= HttpStatusCode.InternalServerError) - .FailWith("Expected {context:response} to have a HTTP status code representing a server error, but it was {0}{reason}.{1}", - Subject!.StatusCode, Subject); - - return new AndConstraint(this); - } - #endregion - - #region HaveHttpStatus - /// - /// Asserts that a HTTP response has a HTTP status with the specified code. - /// - /// - /// The code of the expected HTTP Status. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint HaveHttpStatusCode(HttpStatusCode expected, string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(expected == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , expected, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - #endregion - - #region NotHaveHttpStatus - /// - /// Asserts that a HTTP response does not have a HTTP status with the specified code. - /// - /// - /// The code of the unexpected HTTP Status. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint NotHaveHttpStatusCode(HttpStatusCode unexpected, string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(unexpected != Subject!.StatusCode) - .FailWith("Did not expect {context:response} to have status {0}{reason}.{1}", - Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - #endregion - - #region BeXXXHttpStatus - /// - /// Asserts that a HTTP response has the HTTP status 100 Continue - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be100Continue(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.Continue == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.Continue, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 101 Switching Protocols - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be101SwitchingProtocols(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.SwitchingProtocols == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.SwitchingProtocols, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 200 Ok - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be200Ok(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.OK == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.OK, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 201 Created - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be201Created(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.Created == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.Created, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 202 Accepted - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be202Accepted(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.Accepted == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.Accepted, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 203 Non Authoritative Information - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be203NonAuthoritativeInformation(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.NonAuthoritativeInformation == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.NonAuthoritativeInformation, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 204 No Content - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be204NoContent(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.NoContent == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.NoContent, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 205 Reset Content - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be205ResetContent(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.ResetContent == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.ResetContent, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 206 Partial Content - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be206PartialContent(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.PartialContent == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.PartialContent, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 300 Multiple Choices - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be300MultipleChoices(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.MultipleChoices == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , "HttpStatusCode.MultipleChoices {value: 300}", Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 300 Ambiguous - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be300Ambiguous(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.Ambiguous == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.Ambiguous, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 301 Moved Permanently - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be301MovedPermanently(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.MovedPermanently == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , "HttpStatusCode.MovedPermanently {value: 301}", Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 301 Moved - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be301Moved(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.Moved == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.Moved, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 302 Found - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be302Found(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.Found == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , "HttpStatusCode.Found {value: 302}", Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 302 Redirect - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be302Redirect(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.Redirect == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.Redirect, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 303 See Other - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be303SeeOther(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.SeeOther == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , "HttpStatusCode.SeeOther {value: 303}", Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 303 Redirect Method - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be303RedirectMethod(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.RedirectMethod == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.RedirectMethod, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 304 Not Modified - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be304NotModified(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.NotModified == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.NotModified, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 305 Use Proxy - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be305UseProxy(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.UseProxy == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.UseProxy, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 306 Unused - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be306Unused(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.Unused == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.Unused, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 307 Temporary Redirect - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be307TemporaryRedirect(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.TemporaryRedirect == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.TemporaryRedirect, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 307 Redirect Keep Verb - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be307RedirectKeepVerb(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.RedirectKeepVerb == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , "HttpStatusCode.RedirectKeepVerb {value: 307}", Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 400 BadRequest - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be400BadRequest(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.BadRequest == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.BadRequest, Subject!.StatusCode, Subject); - return new AndConstraint(new BadRequestAssertions(Subject)); - } - - /// - /// Asserts that a HTTP response has the HTTP status 401 Unauthorized - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be401Unauthorized(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.Unauthorized == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.Unauthorized, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 402 Payment Required - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be402PaymentRequired(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.PaymentRequired == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.PaymentRequired, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 403 Forbidden - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be403Forbidden(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.Forbidden == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.Forbidden, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 404 Not Found - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be404NotFound(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.NotFound == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.NotFound, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 405 Method Not Allowed - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be405MethodNotAllowed(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.MethodNotAllowed == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.MethodNotAllowed, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 406 Not Acceptable - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be406NotAcceptable(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.NotAcceptable == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.NotAcceptable, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 407 Proxy Authentication Required - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be407ProxyAuthenticationRequired(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.ProxyAuthenticationRequired == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.ProxyAuthenticationRequired, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 408 Request Timeout - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be408RequestTimeout(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.RequestTimeout == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.RequestTimeout, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 409 Conflict - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be409Conflict(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.Conflict == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.Conflict, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 410 Gone - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be410Gone(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.Gone == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.Gone, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 411 Length Required - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be411LengthRequired(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.LengthRequired == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.LengthRequired, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 412 Precondition Failed - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be412PreconditionFailed(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.PreconditionFailed == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.PreconditionFailed, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 413 Request Entity Too Large - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be413RequestEntityTooLarge(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.RequestEntityTooLarge == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.RequestEntityTooLarge, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 414 Request Uri Too Long - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be414RequestUriTooLong(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.RequestUriTooLong == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.RequestUriTooLong, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 415 Unsupported Media Type - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be415UnsupportedMediaType(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.UnsupportedMediaType == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.UnsupportedMediaType, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 416 Requested Range Not Satisfiable - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be416RequestedRangeNotSatisfiable(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.RequestedRangeNotSatisfiable == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.RequestedRangeNotSatisfiable, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 417 Expectation Failed - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be417ExpectationFailed(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.ExpectationFailed == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.ExpectationFailed, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 422 UnprocessableEntity - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be422UnprocessableEntity(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(422 == (int)Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , "HttpStatusCode.UnprocessableEntity", Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 429 TooManyRequests - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be429TooManyRequests(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(429 == (int)Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , "HttpStatusCode.TooManyRequests", Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 426 UpgradeRequired - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be426UpgradeRequired(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.UpgradeRequired == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.UpgradeRequired, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 500 Internal Server Error - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be500InternalServerError(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.InternalServerError == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.InternalServerError, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 501 Not Implemented - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be501NotImplemented(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.NotImplemented == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.NotImplemented, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 502 Bad Gateway - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be502BadGateway(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.BadGateway == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.BadGateway, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 503 Service Unavailable - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be503ServiceUnavailable(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.ServiceUnavailable == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.ServiceUnavailable, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 504 Gateway Timeout - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be504GatewayTimeout(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.GatewayTimeout == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.GatewayTimeout, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - - /// - /// Asserts that a HTTP response has the HTTP status 505 Http Version Not Supported - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Be505HttpVersionNotSupported(string because = "", params object[] becauseArgs) - { - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(HttpStatusCode.HttpVersionNotSupported == Subject!.StatusCode) - .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" - , HttpStatusCode.HttpVersionNotSupported, Subject!.StatusCode, Subject); - return new AndConstraint(this); - } - #endregion + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(Subject!.StatusCode < HttpStatusCode.OK) + .FailWith("Expected {context:response} to have a HTTP status code representing an informational error, but it was {0}{reason}.{1}", + Subject!.StatusCode, Subject); + + return new AndConstraint(this); } + #endregion + + #region Be2XXSuccessful + /// + /// Asserts that a HTTP response has a successful HTTP status code. + /// + /// The HTTP response was successful if was in the range 200-299. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + // ReSharper disable once InconsistentNaming + public AndConstraint Be2XXSuccessful(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(Subject!.IsSuccessStatusCode) + .FailWith("Expected {context:response} to have a successful HTTP status code, but it was {0}{reason}.{1}", + Subject!.StatusCode, Subject); + + return new AndConstraint(this); + } + #endregion + + #region Be3XXRedirection + /// + /// Asserts that a HTTP response has a HTTP status code representing a redirection response. + /// + /// The HTTP response was an informational one if was in the range 300-399. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + // ReSharper disable once InconsistentNaming + public AndConstraint Be3XXRedirection(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(Subject!.StatusCode >= HttpStatusCode.Moved && Subject!.StatusCode < HttpStatusCode.BadRequest) + .FailWith("Expected {context:response} to have a HTTP status code representing a redirection, but it was {0}{reason}.{1}", + Subject!.StatusCode, Subject); + + return new AndConstraint(this); + } + #endregion + + #region Be4XXClientError + /// + /// Asserts that a HTTP response has a HTTP status code representing a client error. + /// + /// The HTTP response was a client error if was in the range 400-499. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + // ReSharper disable once InconsistentNaming + public AndConstraint Be4XXClientError(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(Subject!.StatusCode >= HttpStatusCode.BadRequest && Subject!.StatusCode < HttpStatusCode.InternalServerError) + .FailWith("Expected {context:response} to have a HTTP status code representing a client error, but it was {0}{reason}.{1}", + Subject!.StatusCode, Subject); + + return new AndConstraint(this); + } + #endregion + + #region Be5XXServerError + /// + /// Asserts that a HTTP response has a HTTP status code representing a server error. + /// + /// The HTTP response was a server error if was above 500. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + // ReSharper disable once InconsistentNaming + public AndConstraint Be5XXServerError(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(Subject!.StatusCode >= HttpStatusCode.InternalServerError) + .FailWith("Expected {context:response} to have a HTTP status code representing a server error, but it was {0}{reason}.{1}", + Subject!.StatusCode, Subject); + + return new AndConstraint(this); + } + #endregion + + #region HaveHttpStatus + /// + /// Asserts that a HTTP response has a HTTP status with the specified code. + /// + /// + /// The code of the expected HTTP Status. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint HaveHttpStatusCode(HttpStatusCode expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(expected == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , expected, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + #endregion + + #region NotHaveHttpStatus + /// + /// Asserts that a HTTP response does not have a HTTP status with the specified code. + /// + /// + /// The code of the unexpected HTTP Status. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint NotHaveHttpStatusCode(HttpStatusCode unexpected, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(unexpected != Subject!.StatusCode) + .FailWith("Did not expect {context:response} to have status {0}{reason}.{1}", + Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + #endregion + + #region BeXXXHttpStatus + /// + /// Asserts that a HTTP response has the HTTP status 100 Continue + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be100Continue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.Continue == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.Continue, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 101 Switching Protocols + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be101SwitchingProtocols(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.SwitchingProtocols == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.SwitchingProtocols, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 200 Ok + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be200Ok(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.OK == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.OK, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 201 Created + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be201Created(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.Created == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.Created, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 202 Accepted + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be202Accepted(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.Accepted == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.Accepted, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 203 Non Authoritative Information + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be203NonAuthoritativeInformation(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.NonAuthoritativeInformation == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.NonAuthoritativeInformation, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 204 No Content + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be204NoContent(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.NoContent == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.NoContent, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 205 Reset Content + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be205ResetContent(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.ResetContent == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.ResetContent, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 206 Partial Content + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be206PartialContent(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.PartialContent == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.PartialContent, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 300 Multiple Choices + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be300MultipleChoices(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.MultipleChoices == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , "HttpStatusCode.MultipleChoices {value: 300}", Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 300 Ambiguous + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be300Ambiguous(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.Ambiguous == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.Ambiguous, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 301 Moved Permanently + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be301MovedPermanently(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.MovedPermanently == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , "HttpStatusCode.MovedPermanently {value: 301}", Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 301 Moved + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be301Moved(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.Moved == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.Moved, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 302 Found + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be302Found(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.Found == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , "HttpStatusCode.Found {value: 302}", Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 302 Redirect + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be302Redirect(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.Redirect == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.Redirect, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 303 See Other + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be303SeeOther(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.SeeOther == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , "HttpStatusCode.SeeOther {value: 303}", Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 303 Redirect Method + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be303RedirectMethod(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.RedirectMethod == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.RedirectMethod, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 304 Not Modified + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be304NotModified(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.NotModified == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.NotModified, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 305 Use Proxy + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be305UseProxy(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.UseProxy == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.UseProxy, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 306 Unused + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be306Unused(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.Unused == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.Unused, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 307 Temporary Redirect + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be307TemporaryRedirect(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.TemporaryRedirect == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.TemporaryRedirect, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 307 Redirect Keep Verb + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be307RedirectKeepVerb(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.RedirectKeepVerb == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , "HttpStatusCode.RedirectKeepVerb {value: 307}", Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 400 BadRequest + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be400BadRequest(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.BadRequest == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.BadRequest, Subject!.StatusCode, Subject); + return new AndConstraint(new BadRequestAssertions(Subject)); + } + + /// + /// Asserts that a HTTP response has the HTTP status 401 Unauthorized + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be401Unauthorized(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.Unauthorized == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.Unauthorized, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 402 Payment Required + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be402PaymentRequired(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.PaymentRequired == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.PaymentRequired, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 403 Forbidden + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be403Forbidden(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.Forbidden == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.Forbidden, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 404 Not Found + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be404NotFound(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.NotFound == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.NotFound, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 405 Method Not Allowed + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be405MethodNotAllowed(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.MethodNotAllowed == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.MethodNotAllowed, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 406 Not Acceptable + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be406NotAcceptable(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.NotAcceptable == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.NotAcceptable, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 407 Proxy Authentication Required + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be407ProxyAuthenticationRequired(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.ProxyAuthenticationRequired == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.ProxyAuthenticationRequired, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 408 Request Timeout + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be408RequestTimeout(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.RequestTimeout == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.RequestTimeout, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 409 Conflict + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be409Conflict(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.Conflict == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.Conflict, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 410 Gone + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be410Gone(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.Gone == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.Gone, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 411 Length Required + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be411LengthRequired(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.LengthRequired == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.LengthRequired, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 412 Precondition Failed + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be412PreconditionFailed(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.PreconditionFailed == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.PreconditionFailed, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 413 Request Entity Too Large + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be413RequestEntityTooLarge(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.RequestEntityTooLarge == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.RequestEntityTooLarge, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 414 Request Uri Too Long + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be414RequestUriTooLong(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.RequestUriTooLong == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.RequestUriTooLong, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 415 Unsupported Media Type + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be415UnsupportedMediaType(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.UnsupportedMediaType == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.UnsupportedMediaType, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 416 Requested Range Not Satisfiable + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be416RequestedRangeNotSatisfiable(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.RequestedRangeNotSatisfiable == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.RequestedRangeNotSatisfiable, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 417 Expectation Failed + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be417ExpectationFailed(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.ExpectationFailed == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.ExpectationFailed, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 422 UnprocessableEntity + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be422UnprocessableEntity(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(422 == (int)Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , "HttpStatusCode.UnprocessableEntity", Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 429 TooManyRequests + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be429TooManyRequests(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(429 == (int)Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , "HttpStatusCode.TooManyRequests", Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 426 UpgradeRequired + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be426UpgradeRequired(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.UpgradeRequired == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.UpgradeRequired, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 500 Internal Server Error + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be500InternalServerError(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.InternalServerError == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.InternalServerError, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 501 Not Implemented + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be501NotImplemented(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.NotImplemented == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.NotImplemented, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 502 Bad Gateway + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be502BadGateway(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.BadGateway == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.BadGateway, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 503 Service Unavailable + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be503ServiceUnavailable(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.ServiceUnavailable == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.ServiceUnavailable, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 504 Gateway Timeout + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be504GatewayTimeout(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.GatewayTimeout == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.GatewayTimeout, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + + /// + /// Asserts that a HTTP response has the HTTP status 505 Http Version Not Supported + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Be505HttpVersionNotSupported(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(HttpStatusCode.HttpVersionNotSupported == Subject!.StatusCode) + .FailWith("Expected {context:response} to be {0}{reason}, but found {1}.{2}" + , HttpStatusCode.HttpVersionNotSupported, Subject!.StatusCode, Subject); + return new AndConstraint(this); + } + #endregion } \ No newline at end of file diff --git a/src/FluentAssertions.Web/HttpStatusCodeAssertionsExtensions.cs b/src/FluentAssertions.Web/HttpStatusCodeAssertionsExtensions.cs index e3c19ef..e317e7b 100644 --- a/src/FluentAssertions.Web/HttpStatusCodeAssertionsExtensions.cs +++ b/src/FluentAssertions.Web/HttpStatusCodeAssertionsExtensions.cs @@ -1,1052 +1,1048 @@ -using FluentAssertions.Web; -using System.Net; +// ReSharper disable once CheckNamespace +namespace FluentAssertions; -// ReSharper disable once CheckNamespace -namespace FluentAssertions +/// +/// Contains extension methods for custom assertions in unit tests related to . +/// +public static class HttpStatusCodeAssertionsExtensions { + #region Be1XXInformational /// - /// Contains extension methods for custom assertions in unit tests related to . + /// Asserts that a HTTP response has a HTTP status code representing an informational response. /// - public static class HttpStatusCodeAssertionsExtensions - { - #region Be1XXInformational - /// - /// Asserts that a HTTP response has a HTTP status code representing an informational response. - /// - /// The HTTP response was an informational one if was in the range 100-199. - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - // ReSharper disable once InconsistentNaming - public static AndConstraint Be1XXInformational( + /// The HTTP response was an informational one if was in the range 100-199. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + // ReSharper disable once InconsistentNaming + public static AndConstraint Be1XXInformational( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be1XXInformational(because, becauseArgs); - #endregion + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be1XXInformational(because, becauseArgs); + #endregion - #region Be2XXSuccessful - /// - /// Asserts that a HTTP response has a successful HTTP status code. - /// - /// The HTTP response was successful if was in the range 200-299. - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - // ReSharper disable once InconsistentNaming - public static AndConstraint Be2XXSuccessful( + #region Be2XXSuccessful + /// + /// Asserts that a HTTP response has a successful HTTP status code. + /// + /// The HTTP response was successful if was in the range 200-299. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + // ReSharper disable once InconsistentNaming + public static AndConstraint Be2XXSuccessful( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be2XXSuccessful(because, becauseArgs); - #endregion + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be2XXSuccessful(because, becauseArgs); + #endregion - #region Be3XXRedirection - /// - /// Asserts that a HTTP response has a HTTP status code representing a redirection response. - /// - /// The HTTP response was an informational one if was in the range 300-399. - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - // ReSharper disable once InconsistentNaming - public static AndConstraint Be3XXRedirection( + #region Be3XXRedirection + /// + /// Asserts that a HTTP response has a HTTP status code representing a redirection response. + /// + /// The HTTP response was an informational one if was in the range 300-399. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + // ReSharper disable once InconsistentNaming + public static AndConstraint Be3XXRedirection( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be3XXRedirection(because, becauseArgs); - #endregion + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be3XXRedirection(because, becauseArgs); + #endregion - #region Be4XXClientError - /// - /// Asserts that a HTTP response has a HTTP status code representing a client error. - /// - /// The HTTP response was a client error if was in the range 400-499. - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - // ReSharper disable once InconsistentNaming - public static AndConstraint Be4XXClientError( + #region Be4XXClientError + /// + /// Asserts that a HTTP response has a HTTP status code representing a client error. + /// + /// The HTTP response was a client error if was in the range 400-499. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + // ReSharper disable once InconsistentNaming + public static AndConstraint Be4XXClientError( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be4XXClientError(because, becauseArgs); - #endregion + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be4XXClientError(because, becauseArgs); + #endregion - #region Be5XXServerError - /// - /// Asserts that a HTTP response has a HTTP status code representing a server error. - /// - /// The HTTP response was a server error if was above 500. - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - // ReSharper disable once InconsistentNaming - public static AndConstraint Be5XXServerError( + #region Be5XXServerError + /// + /// Asserts that a HTTP response has a HTTP status code representing a server error. + /// + /// The HTTP response was a server error if was above 500. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + // ReSharper disable once InconsistentNaming + public static AndConstraint Be5XXServerError( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be5XXServerError(because, becauseArgs); - #endregion + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be5XXServerError(because, becauseArgs); + #endregion - #region HaveHtppStatus - /// - /// Asserts that a HTTP response has a HTTP status with the specified code. - /// - /// - /// The code of the expected HTTP Status. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint HaveHttpStatusCode( + #region HaveHtppStatus + /// + /// Asserts that a HTTP response has a HTTP status with the specified code. + /// + /// + /// The code of the expected HTTP Status. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint HaveHttpStatusCode( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - HttpStatusCode expected, string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).HaveHttpStatusCode(expected, because, becauseArgs); - #endregion + HttpStatusCode expected, string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).HaveHttpStatusCode(expected, because, becauseArgs); + #endregion - #region NotHaveHtppStatus - /// - /// Asserts that a HTTP response does not have a HTTP status with the specified code. - /// - /// - /// The code of the unexpected HTTP Status. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint NotHaveHttpStatusCode( + #region NotHaveHtppStatus + /// + /// Asserts that a HTTP response does not have a HTTP status with the specified code. + /// + /// + /// The code of the unexpected HTTP Status. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint NotHaveHttpStatusCode( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - HttpStatusCode unexpected, string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).NotHaveHttpStatusCode(unexpected, because, becauseArgs); - #endregion + HttpStatusCode unexpected, string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).NotHaveHttpStatusCode(unexpected, because, becauseArgs); + #endregion - #region BeXXXHttpStatus - /// - /// Asserts that a HTTP response has the HTTP status 100 Continue - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be100Continue( + #region BeXXXHttpStatus + /// + /// Asserts that a HTTP response has the HTTP status 100 Continue + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be100Continue( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be100Continue(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be100Continue(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 101 Switching Protocols - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be101SwitchingProtocols( + /// + /// Asserts that a HTTP response has the HTTP status 101 Switching Protocols + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be101SwitchingProtocols( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be101SwitchingProtocols(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be101SwitchingProtocols(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 200 Ok - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be200Ok( + /// + /// Asserts that a HTTP response has the HTTP status 200 Ok + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be200Ok( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be200Ok(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be200Ok(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 201 Created - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be201Created( + /// + /// Asserts that a HTTP response has the HTTP status 201 Created + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be201Created( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be201Created(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be201Created(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 202 Accepted - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be202Accepted( + /// + /// Asserts that a HTTP response has the HTTP status 202 Accepted + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be202Accepted( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be202Accepted(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be202Accepted(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 203 Non Authoritative Information - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be203NonAuthoritativeInformation( + /// + /// Asserts that a HTTP response has the HTTP status 203 Non Authoritative Information + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be203NonAuthoritativeInformation( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be203NonAuthoritativeInformation(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be203NonAuthoritativeInformation(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 204 No Content - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be204NoContent( + /// + /// Asserts that a HTTP response has the HTTP status 204 No Content + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be204NoContent( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be204NoContent(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be204NoContent(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 205 Reset Content - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be205ResetContent( + /// + /// Asserts that a HTTP response has the HTTP status 205 Reset Content + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be205ResetContent( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be205ResetContent(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be205ResetContent(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 206 Partial Content - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be206PartialContent( + /// + /// Asserts that a HTTP response has the HTTP status 206 Partial Content + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be206PartialContent( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be206PartialContent(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be206PartialContent(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 300 Multiple Choices - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be300MultipleChoices( + /// + /// Asserts that a HTTP response has the HTTP status 300 Multiple Choices + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be300MultipleChoices( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be300MultipleChoices(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be300MultipleChoices(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 300 Ambiguous - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be300Ambiguous( + /// + /// Asserts that a HTTP response has the HTTP status 300 Ambiguous + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be300Ambiguous( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be300Ambiguous(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be300Ambiguous(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 301 Moved Permanently - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be301MovedPermanently( + /// + /// Asserts that a HTTP response has the HTTP status 301 Moved Permanently + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be301MovedPermanently( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be301MovedPermanently(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be301MovedPermanently(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 301 Moved - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be301Moved( + /// + /// Asserts that a HTTP response has the HTTP status 301 Moved + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be301Moved( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be301Moved(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be301Moved(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 302 Found - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be302Found( + /// + /// Asserts that a HTTP response has the HTTP status 302 Found + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be302Found( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be302Found(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be302Found(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 302 Redirect - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be302Redirect( + /// + /// Asserts that a HTTP response has the HTTP status 302 Redirect + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be302Redirect( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be302Redirect(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be302Redirect(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 303 See Other - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be303SeeOther( + /// + /// Asserts that a HTTP response has the HTTP status 303 See Other + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be303SeeOther( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be303SeeOther(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be303SeeOther(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 303 Redirect Method - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be303RedirectMethod( + /// + /// Asserts that a HTTP response has the HTTP status 303 Redirect Method + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be303RedirectMethod( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be303RedirectMethod(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be303RedirectMethod(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 304 Not Modified - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be304NotModified( + /// + /// Asserts that a HTTP response has the HTTP status 304 Not Modified + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be304NotModified( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be304NotModified(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be304NotModified(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 305 Use Proxy - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be305UseProxy( + /// + /// Asserts that a HTTP response has the HTTP status 305 Use Proxy + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be305UseProxy( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be305UseProxy(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be305UseProxy(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 306 Unused - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be306Unused( + /// + /// Asserts that a HTTP response has the HTTP status 306 Unused + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be306Unused( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be306Unused(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be306Unused(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 307 Temporary Redirect - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be307TemporaryRedirect( + /// + /// Asserts that a HTTP response has the HTTP status 307 Temporary Redirect + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be307TemporaryRedirect( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be307TemporaryRedirect(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be307TemporaryRedirect(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 307 Redirect Keep Verb - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be307RedirectKeepVerb( + /// + /// Asserts that a HTTP response has the HTTP status 307 Redirect Keep Verb + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be307RedirectKeepVerb( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be307RedirectKeepVerb(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be307RedirectKeepVerb(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 400 BadRequest - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be400BadRequest( + /// + /// Asserts that a HTTP response has the HTTP status 400 BadRequest + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be400BadRequest( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new BadRequestAssertions(parent.Subject).Be400BadRequest(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new BadRequestAssertions(parent.Subject).Be400BadRequest(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 401 Unauthorized - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be401Unauthorized( + /// + /// Asserts that a HTTP response has the HTTP status 401 Unauthorized + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be401Unauthorized( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be401Unauthorized(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be401Unauthorized(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 402 Payment Required - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be402PaymentRequired( + /// + /// Asserts that a HTTP response has the HTTP status 402 Payment Required + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be402PaymentRequired( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be402PaymentRequired(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be402PaymentRequired(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 403 Forbidden - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be403Forbidden( + /// + /// Asserts that a HTTP response has the HTTP status 403 Forbidden + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be403Forbidden( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be403Forbidden(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be403Forbidden(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 404 Not Found - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be404NotFound( + /// + /// Asserts that a HTTP response has the HTTP status 404 Not Found + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be404NotFound( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be404NotFound(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be404NotFound(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 405 Method Not Allowed - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be405MethodNotAllowed( + /// + /// Asserts that a HTTP response has the HTTP status 405 Method Not Allowed + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be405MethodNotAllowed( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be405MethodNotAllowed(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be405MethodNotAllowed(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 406 Not Acceptable - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be406NotAcceptable( + /// + /// Asserts that a HTTP response has the HTTP status 406 Not Acceptable + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be406NotAcceptable( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be406NotAcceptable(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be406NotAcceptable(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 407 Proxy Authentication Required - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be407ProxyAuthenticationRequired( + /// + /// Asserts that a HTTP response has the HTTP status 407 Proxy Authentication Required + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be407ProxyAuthenticationRequired( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be407ProxyAuthenticationRequired(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be407ProxyAuthenticationRequired(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 408 Request Timeout - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be408RequestTimeout( + /// + /// Asserts that a HTTP response has the HTTP status 408 Request Timeout + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be408RequestTimeout( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be408RequestTimeout(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be408RequestTimeout(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 409 Conflict - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be409Conflict( + /// + /// Asserts that a HTTP response has the HTTP status 409 Conflict + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be409Conflict( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be409Conflict(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be409Conflict(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 410 Gone - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be410Gone( + /// + /// Asserts that a HTTP response has the HTTP status 410 Gone + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be410Gone( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be410Gone(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be410Gone(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 411 Length Required - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be411LengthRequired( + /// + /// Asserts that a HTTP response has the HTTP status 411 Length Required + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be411LengthRequired( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be411LengthRequired(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be411LengthRequired(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 412 Precondition Failed - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be412PreconditionFailed( + /// + /// Asserts that a HTTP response has the HTTP status 412 Precondition Failed + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be412PreconditionFailed( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be412PreconditionFailed(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be412PreconditionFailed(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 413 Request Entity Too Large - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be413RequestEntityTooLarge( + /// + /// Asserts that a HTTP response has the HTTP status 413 Request Entity Too Large + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be413RequestEntityTooLarge( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be413RequestEntityTooLarge(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be413RequestEntityTooLarge(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 414 Request Uri Too Long - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be414RequestUriTooLong( + /// + /// Asserts that a HTTP response has the HTTP status 414 Request Uri Too Long + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be414RequestUriTooLong( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be414RequestUriTooLong(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be414RequestUriTooLong(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 415 Unsupported Media Type - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be415UnsupportedMediaType( + /// + /// Asserts that a HTTP response has the HTTP status 415 Unsupported Media Type + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be415UnsupportedMediaType( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be415UnsupportedMediaType(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be415UnsupportedMediaType(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 416 Requested Range Not Satisfiable - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be416RequestedRangeNotSatisfiable( + /// + /// Asserts that a HTTP response has the HTTP status 416 Requested Range Not Satisfiable + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be416RequestedRangeNotSatisfiable( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be416RequestedRangeNotSatisfiable(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be416RequestedRangeNotSatisfiable(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 417 Expectation Failed - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be417ExpectationFailed( + /// + /// Asserts that a HTTP response has the HTTP status 417 Expectation Failed + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be417ExpectationFailed( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be417ExpectationFailed(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be417ExpectationFailed(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 422 UnprocessableEntity - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be422UnprocessableEntity( + /// + /// Asserts that a HTTP response has the HTTP status 422 UnprocessableEntity + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be422UnprocessableEntity( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be422UnprocessableEntity(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be422UnprocessableEntity(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 429 TooManyRequests - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be429TooManyRequests( + /// + /// Asserts that a HTTP response has the HTTP status 429 TooManyRequests + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be429TooManyRequests( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be429TooManyRequests(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be429TooManyRequests(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 426 UpgradeRequired - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be426UpgradeRequired( + /// + /// Asserts that a HTTP response has the HTTP status 426 UpgradeRequired + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be426UpgradeRequired( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be426UpgradeRequired(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be426UpgradeRequired(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 500 Internal Server Error - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be500InternalServerError( + /// + /// Asserts that a HTTP response has the HTTP status 500 Internal Server Error + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be500InternalServerError( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be500InternalServerError(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be500InternalServerError(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 501 Not Implemented - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be501NotImplemented( + /// + /// Asserts that a HTTP response has the HTTP status 501 Not Implemented + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be501NotImplemented( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be501NotImplemented(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be501NotImplemented(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 502 Bad Gateway - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be502BadGateway( + /// + /// Asserts that a HTTP response has the HTTP status 502 Bad Gateway + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be502BadGateway( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be502BadGateway(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be502BadGateway(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 503 Service Unavailable - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be503ServiceUnavailable( + /// + /// Asserts that a HTTP response has the HTTP status 503 Service Unavailable + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be503ServiceUnavailable( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be503ServiceUnavailable(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be503ServiceUnavailable(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 504 Gateway Timeout - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be504GatewayTimeout( + /// + /// Asserts that a HTTP response has the HTTP status 504 Gateway Timeout + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be504GatewayTimeout( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be504GatewayTimeout(because, becauseArgs); + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be504GatewayTimeout(because, becauseArgs); - /// - /// Asserts that a HTTP response has the HTTP status 505 Http Version Not Supported - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Be505HttpVersionNotSupported( + /// + /// Asserts that a HTTP response has the HTTP status 505 Http Version Not Supported + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Be505HttpVersionNotSupported( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Be505HttpVersionNotSupported(because, becauseArgs); - #endregion - } + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Be505HttpVersionNotSupported(because, becauseArgs); + #endregion } diff --git a/src/FluentAssertions.Web/ISerializer.cs b/src/FluentAssertions.Web/ISerializer.cs index 4981612..23cb6eb 100644 --- a/src/FluentAssertions.Web/ISerializer.cs +++ b/src/FluentAssertions.Web/ISerializer.cs @@ -1,21 +1,16 @@ // ReSharper disable once CheckNamespace -using System; -using System.IO; -using System.Threading.Tasks; +namespace FluentAssertions; -namespace FluentAssertions +/// +/// Provides an abstraction to deserialize a Stream of binary data into a C# object. +/// +public interface ISerializer { /// - /// Provides an abstraction to deserialize a Stream of binary data into a C# object. + /// Deserialize a Stream of binary data into a C# object of a specific model. /// - public interface ISerializer - { - /// - /// Deserialize a Stream of binary data into a C# object of a specific model. - /// - /// The stream to read data from. - /// The deserialized model's structure. - /// An object representing the model. - Task Deserialize(Stream content, Type modelType); - } + /// The stream to read data from. + /// The deserialized model's structure. + /// An object representing the model. + Task Deserialize(Stream content, Type modelType); } diff --git a/src/FluentAssertions.Web/Internal/AssertionsFailures.cs b/src/FluentAssertions.Web/Internal/AssertionsFailures.cs index 93dc54f..0525393 100644 --- a/src/FluentAssertions.Web/Internal/AssertionsFailures.cs +++ b/src/FluentAssertions.Web/Internal/AssertionsFailures.cs @@ -1,13 +1,10 @@ -using System.Collections.Generic; +namespace FluentAssertions.Web.Internal; -namespace FluentAssertions.Web.Internal +internal class AssertionsFailures { - internal class AssertionsFailures + public AssertionsFailures(string[] failuresMessages) { - public AssertionsFailures(string[] failuresMessages) - { - FailuresMessages = failuresMessages; - } - public IReadOnlyCollection FailuresMessages { get; } + FailuresMessages = failuresMessages; } + public IReadOnlyCollection FailuresMessages { get; } } diff --git a/src/FluentAssertions.Web/Internal/AssertionsFailuresFormatter.cs b/src/FluentAssertions.Web/Internal/AssertionsFailuresFormatter.cs index cfb9a0a..e406849 100644 --- a/src/FluentAssertions.Web/Internal/AssertionsFailuresFormatter.cs +++ b/src/FluentAssertions.Web/Internal/AssertionsFailuresFormatter.cs @@ -1,29 +1,28 @@ using FluentAssertions.Formatting; using System.Text; -namespace FluentAssertions.Web.Internal -{ - internal class AssertionsFailuresFormatter : IValueFormatter - { - public bool CanHandle(object value) => value is AssertionsFailures; +namespace FluentAssertions.Web.Internal; - public void Format(object value, - FormattedObjectGraph formattedGraph, - FormattingContext context, - FormatChild formatChild) - { - var assertionsFailures = (AssertionsFailures)value; +internal class AssertionsFailuresFormatter : IValueFormatter +{ + public bool CanHandle(object value) => value is AssertionsFailures; - var messageBuilder = new StringBuilder(); - messageBuilder.AppendLine(); - messageBuilder.AppendLine(); + public void Format(object value, + FormattedObjectGraph formattedGraph, + FormattingContext context, + FormatChild formatChild) + { + var assertionsFailures = (AssertionsFailures)value; - foreach (var failure in assertionsFailures.FailuresMessages) - { - messageBuilder.AppendLine($" - { failure.ReplaceFirstWithLowercase() }"); - } + var messageBuilder = new StringBuilder(); + messageBuilder.AppendLine(); + messageBuilder.AppendLine(); - formattedGraph.AddFragment(messageBuilder.ToString()); + foreach (var failure in assertionsFailures.FailuresMessages) + { + messageBuilder.AppendLine($" - { failure.ReplaceFirstWithLowercase() }"); } + + formattedGraph.AddFragment(messageBuilder.ToString()); } } diff --git a/src/FluentAssertions.Web/Internal/ContentFormatterOptions.cs b/src/FluentAssertions.Web/Internal/ContentFormatterOptions.cs index 1d0c7d0..62acc46 100644 --- a/src/FluentAssertions.Web/Internal/ContentFormatterOptions.cs +++ b/src/FluentAssertions.Web/Internal/ContentFormatterOptions.cs @@ -1,10 +1,9 @@ -namespace FluentAssertions.Web.Internal +namespace FluentAssertions.Web.Internal; + +internal static class ContentFormatterOptions { - internal static class ContentFormatterOptions - { - public const int MaximumReadableBytes = 128 * 1024; // 1KB holds like 500 words - public const string WarningMessageWhenDisposed = "***** Content is disposed so it cannot be read. *****"; - public const string WarningMessageWhenContentIsTooLarge = "***** Content is too large to display and only a part is printed. *****"; - public const string ContentIsOfABinaryEncodedTypeHavingLength = "***** Content is of a binary encoded like type having the length {0}. *****"; - } + public const int MaximumReadableBytes = 128 * 1024; // 1KB holds like 500 words + public const string WarningMessageWhenDisposed = "***** Content is disposed so it cannot be read. *****"; + public const string WarningMessageWhenContentIsTooLarge = "***** Content is too large to display and only a part is printed. *****"; + public const string ContentIsOfABinaryEncodedTypeHavingLength = "***** Content is of a binary encoded like type having the length {0}. *****"; } \ No newline at end of file diff --git a/src/FluentAssertions.Web/Internal/ContentProcessors/Appender.cs b/src/FluentAssertions.Web/Internal/ContentProcessors/Appender.cs index 8e64d99..929ef45 100644 --- a/src/FluentAssertions.Web/Internal/ContentProcessors/Appender.cs +++ b/src/FluentAssertions.Web/Internal/ContentProcessors/Appender.cs @@ -1,39 +1,35 @@ -using System.Collections.Generic; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; +using System.Text; -namespace FluentAssertions.Web.Internal.ContentProcessors +namespace FluentAssertions.Web.Internal.ContentProcessors; + +internal static class Appender { - internal static class Appender + public static void AppendHeaders(StringBuilder messageBuilder, IEnumerable>> headers) { - public static void AppendHeaders(StringBuilder messageBuilder, IEnumerable>> headers) + foreach (var header in headers) { - foreach (var header in headers) + if (header.Key != "Content-Length") { - if (header.Key != "Content-Length") + foreach (var headerValue in header.Value) { - foreach (var headerValue in header.Value) - { - messageBuilder.AppendLine($"{header.Key}: {headerValue}"); - } + messageBuilder.AppendLine($"{header.Key}: {headerValue}"); } } } + } - public static async Task AppendContent(StringBuilder contentBuilder, HttpContent content, bool appendLineBeforeContent) - { - var partContentBuilder = await ProcessorsRunner.RunProcessors(ProcessorsRunner.CommonProcessors(content)); + public static async Task AppendContent(StringBuilder contentBuilder, HttpContent content, bool appendLineBeforeContent) + { + var partContentBuilder = await ProcessorsRunner.RunProcessors(ProcessorsRunner.CommonProcessors(content)); - if (partContentBuilder.Length > 0) + if (partContentBuilder.Length > 0) + { + if (appendLineBeforeContent) { - if (appendLineBeforeContent) - { - contentBuilder.AppendLine(); - } - - contentBuilder.Append(partContentBuilder); + contentBuilder.AppendLine(); } + + contentBuilder.Append(partContentBuilder); } } } \ No newline at end of file diff --git a/src/FluentAssertions.Web/Internal/ContentProcessors/BinaryProcessor.cs b/src/FluentAssertions.Web/Internal/ContentProcessors/BinaryProcessor.cs index 39f5a2c..6c27286 100644 --- a/src/FluentAssertions.Web/Internal/ContentProcessors/BinaryProcessor.cs +++ b/src/FluentAssertions.Web/Internal/ContentProcessors/BinaryProcessor.cs @@ -1,71 +1,68 @@ -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; +using System.Text; -namespace FluentAssertions.Web.Internal.ContentProcessors +namespace FluentAssertions.Web.Internal.ContentProcessors; + +internal class BinaryProcessor : ProcessorBase { - internal class BinaryProcessor : ProcessorBase + private readonly HttpContent? _httpContent; + + public BinaryProcessor(HttpContent? httpContent) { - private readonly HttpContent? _httpContent; + _httpContent = httpContent; + } - public BinaryProcessor(HttpContent? httpContent) - { - _httpContent = httpContent; - } + protected override Task Handle(StringBuilder contentBuilder) + { + _httpContent!.TryGetContentLength(out var contentLength); - protected override Task Handle(StringBuilder contentBuilder) - { - _httpContent!.TryGetContentLength(out var contentLength); + contentBuilder.AppendLine(string.Format(ContentFormatterOptions.ContentIsOfABinaryEncodedTypeHavingLength, contentLength)); - contentBuilder.AppendLine(string.Format(ContentFormatterOptions.ContentIsOfABinaryEncodedTypeHavingLength, contentLength)); + return Task.CompletedTask; + } - return Task.CompletedTask; + protected override bool CanHandle() => _httpContent != null + && !_httpContent.IsDisposed() + && _httpContent is not (StringContent or FormUrlEncodedContent) + && (IsNonPrintableContent(_httpContent) || _httpContent is ByteArrayContent); + private static bool IsNonPrintableContent(HttpContent? content) + { + // a file name is passed + if (!string.IsNullOrEmpty(content?.Headers?.ContentDisposition?.FileName)) + { + return true; } - protected override bool CanHandle() => _httpContent != null - && !_httpContent.IsDisposed() - && _httpContent is not (StringContent or FormUrlEncodedContent) - && (IsNonPrintableContent(_httpContent) || _httpContent is ByteArrayContent); - private static bool IsNonPrintableContent(HttpContent? content) + var contentTypeMediaType = content?.Headers?.ContentType?.MediaType; + if (contentTypeMediaType == null) { - // a file name is passed - if (!string.IsNullOrEmpty(content?.Headers?.ContentDisposition?.FileName)) - { - return true; - } - - var contentTypeMediaType = content?.Headers?.ContentType?.MediaType; - if (contentTypeMediaType == null) - { - return false; - } - - // exclude all know "text" like content - if (contentTypeMediaType.Contains("xml") - || contentTypeMediaType.Contains("json") - || contentTypeMediaType.Contains("html") - || contentTypeMediaType.Contains("text") - ) - { - return false; - } + return false; + } - // all audio + video + image - if (contentTypeMediaType.StartsWith("audio/") - || contentTypeMediaType.StartsWith("image/") - || contentTypeMediaType.StartsWith("video/")) - { - return true; - } + // exclude all know "text" like content + if (contentTypeMediaType.Contains("xml") + || contentTypeMediaType.Contains("json") + || contentTypeMediaType.Contains("html") + || contentTypeMediaType.Contains("text") + ) + { + return false; + } - // pdfs - if (contentTypeMediaType.Contains("pdf")) - { - return true; - } + // all audio + video + image + if (contentTypeMediaType.StartsWith("audio/") + || contentTypeMediaType.StartsWith("image/") + || contentTypeMediaType.StartsWith("video/")) + { + return true; + } - // don't know really if it is a binary type, so better to return that it is not, maybe others will continue asking what it is - return false; + // pdfs + if (contentTypeMediaType.Contains("pdf")) + { + return true; } + + // don't know really if it is a binary type, so better to return that it is not, maybe others will continue asking what it is + return false; } } diff --git a/src/FluentAssertions.Web/Internal/ContentProcessors/FallbackProcessor.cs b/src/FluentAssertions.Web/Internal/ContentProcessors/FallbackProcessor.cs index a8f4bc9..2197bdf 100644 --- a/src/FluentAssertions.Web/Internal/ContentProcessors/FallbackProcessor.cs +++ b/src/FluentAssertions.Web/Internal/ContentProcessors/FallbackProcessor.cs @@ -1,46 +1,35 @@ -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; +using System.Text; -namespace FluentAssertions.Web.Internal.ContentProcessors +namespace FluentAssertions.Web.Internal.ContentProcessors; + +internal class FallbackProcessor : ProcessorBase { - internal class FallbackProcessor : ProcessorBase + private readonly HttpContent? _httpContent; + + public FallbackProcessor(HttpContent? httpContent) { - private readonly HttpContent? _httpContent; + _httpContent = httpContent; + } - public FallbackProcessor(HttpContent? httpContent) + protected override bool CanHandle() => _httpContent != null; + + protected override async Task Handle(StringBuilder contentBuilder) + { + if (contentBuilder.Length > 0) { - _httpContent = httpContent; + return; } - protected override bool CanHandle() => _httpContent != null; - - protected override async Task Handle(StringBuilder contentBuilder) + if (_httpContent!.IsDisposed()) { - if (contentBuilder.Length > 0) - { - return; - } - - if (_httpContent!.IsDisposed()) - { - contentBuilder.AppendLine(); - contentBuilder.AppendLine(ContentFormatterOptions.WarningMessageWhenDisposed); - return; - } - - // we might get here some StreamContent, let's try to print it - // but let's try not to get into this issue again https://github.com/adrianiftode/FluentAssertions.Web/issues/93 - _httpContent!.TryGetContentLength(out var contentLength); - var content = await _httpContent!.SafeReadAsStringAsync(); - if (contentLength >= ContentFormatterOptions.MaximumReadableBytes) - { - contentBuilder.AppendLine(); - contentBuilder.AppendLine(ContentFormatterOptions.WarningMessageWhenContentIsTooLarge); - content = content!.Substring(0,ContentFormatterOptions.MaximumReadableBytes); - } - - contentBuilder.Append(content); + contentBuilder.AppendLine(); + contentBuilder.AppendLine(ContentFormatterOptions.WarningMessageWhenDisposed); + return; } + + // we might get here some StreamContent, let's try to print it + // but let's try not to get into this issue again https://github.com/adrianiftode/FluentAssertions.Web/issues/93 + var content = await _httpContent!.SafeReadAsStringAsync(); + AppendContentWithinLimits(contentBuilder, content); } } diff --git a/src/FluentAssertions.Web/Internal/ContentProcessors/IContentProcessor.cs b/src/FluentAssertions.Web/Internal/ContentProcessors/IContentProcessor.cs index dc0e2fc..53567b4 100644 --- a/src/FluentAssertions.Web/Internal/ContentProcessors/IContentProcessor.cs +++ b/src/FluentAssertions.Web/Internal/ContentProcessors/IContentProcessor.cs @@ -1,10 +1,8 @@ using System.Text; -using System.Threading.Tasks; -namespace FluentAssertions.Web.Internal.ContentProcessors +namespace FluentAssertions.Web.Internal.ContentProcessors; + +internal interface IContentProcessor { - internal interface IContentProcessor - { - Task GetContentInfo(StringBuilder contentBuilder); - } + Task GetContentInfo(StringBuilder contentBuilder); } \ No newline at end of file diff --git a/src/FluentAssertions.Web/Internal/ContentProcessors/InternalServerErrorProcessor.cs b/src/FluentAssertions.Web/Internal/ContentProcessors/InternalServerErrorProcessor.cs index ed8a788..1c6c813 100644 --- a/src/FluentAssertions.Web/Internal/ContentProcessors/InternalServerErrorProcessor.cs +++ b/src/FluentAssertions.Web/Internal/ContentProcessors/InternalServerErrorProcessor.cs @@ -1,76 +1,71 @@ -using System; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; +using System.Text; -namespace FluentAssertions.Web.Internal.ContentProcessors +namespace FluentAssertions.Web.Internal.ContentProcessors; + +internal class InternalServerErrorProcessor : ProcessorBase { - internal class InternalServerErrorProcessor : ProcessorBase + private readonly HttpResponseMessage? _httpResponseMessage; + private readonly HttpContent? _httpContent; + + public InternalServerErrorProcessor(HttpResponseMessage? httpResponseMessage, HttpContent? httpContent) { - private readonly HttpResponseMessage? _httpResponseMessage; - private readonly HttpContent? _httpContent; + _httpResponseMessage = httpResponseMessage; + _httpContent = httpContent; + } - public InternalServerErrorProcessor(HttpResponseMessage? httpResponseMessage, HttpContent? httpContent) - { - _httpResponseMessage = httpResponseMessage; - _httpContent = httpContent; - } + protected override bool CanHandle() => _httpContent != null + && _httpResponseMessage != null + && _httpResponseMessage.StatusCode == HttpStatusCode.InternalServerError + && !_httpContent.IsDisposed(); - protected override bool CanHandle() => _httpContent != null - && _httpResponseMessage != null - && _httpResponseMessage.StatusCode == HttpStatusCode.InternalServerError - && !_httpContent.IsDisposed(); + protected override async Task Handle(StringBuilder contentBuilder) + { + var content = await _httpContent!.ReadAsStringAsync(); - protected override async Task Handle(StringBuilder contentBuilder) - { - var content = await _httpContent!.ReadAsStringAsync(); + AspNetCore30(contentBuilder, content); - AspNetCore30(contentBuilder, content); + AspNetCore22(contentBuilder, content); + } - AspNetCore22(contentBuilder, content); + private static void AspNetCore30(StringBuilder contentBuilder, string? content) + { + if (string.IsNullOrEmpty(content)) + { + return; } - private static void AspNetCore30(StringBuilder contentBuilder, string? content) + const string headersText = "HEADERS"; + var headersIndex = content!.IndexOf(headersText, StringComparison.Ordinal); + if (headersIndex >= 0) { - if (string.IsNullOrEmpty(content)) - { - return; - } + var exceptionDetails = content.Substring(0, headersIndex).Trim(); + contentBuilder.Append(exceptionDetails); + } + } - const string headersText = "HEADERS"; - var headersIndex = content!.IndexOf(headersText, StringComparison.Ordinal); - if (headersIndex >= 0) - { - var exceptionDetails = content.Substring(0, headersIndex).Trim(); - contentBuilder.Append(exceptionDetails); - } + private static void AspNetCore22(StringBuilder contentBuilder, string? content) + { + if (string.IsNullOrEmpty(content)) + { + return; } - private static void AspNetCore22(StringBuilder contentBuilder, string? content) + const string startTag = """
""";
+        if (content!.Contains(startTag))
         {
-            if (string.IsNullOrEmpty(content))
+            var startTagIndex = content.LastIndexOf(startTag, StringComparison.Ordinal);
+            var endTagIndex = content.IndexOf("
", startTagIndex, StringComparison.Ordinal); + if (endTagIndex < 0) { + // there is no end tag return; } - const string startTag = @"
";
-            if (content!.Contains(startTag))
-            {
-                var startTagIndex = content.LastIndexOf(startTag, StringComparison.Ordinal);
-                var endTagIndex = content.IndexOf("
", startTagIndex, StringComparison.Ordinal); - if (endTagIndex < 0) - { - // there is no end tag - return; - } + var exceptionDetails = content.Substring(startTagIndex + startTag.Length, endTagIndex - startTagIndex - startTag.Length); - var exceptionDetails = content.Substring(startTagIndex + startTag.Length, endTagIndex - startTagIndex - startTag.Length); + exceptionDetails = WebUtility.HtmlDecode(exceptionDetails); - exceptionDetails = WebUtility.HtmlDecode(exceptionDetails); - - contentBuilder.Append(exceptionDetails); - } + contentBuilder.Append(exceptionDetails); } } } diff --git a/src/FluentAssertions.Web/Internal/ContentProcessors/JsonProcessor.cs b/src/FluentAssertions.Web/Internal/ContentProcessors/JsonProcessor.cs index 874058e..aa2e83a 100644 --- a/src/FluentAssertions.Web/Internal/ContentProcessors/JsonProcessor.cs +++ b/src/FluentAssertions.Web/Internal/ContentProcessors/JsonProcessor.cs @@ -1,85 +1,84 @@ -using System.IO; -using System.Net.Http; using System.Text; using System.Text.Encodings.Web; -using System.Text.Json; using System.Text.Unicode; -using System.Threading.Tasks; -namespace FluentAssertions.Web.Internal.ContentProcessors +namespace FluentAssertions.Web.Internal.ContentProcessors; + +internal class JsonProcessor : ProcessorBase { - internal class JsonProcessor : ProcessorBase + private static readonly JavaScriptEncoder JavaScriptEncoder = JavaScriptEncoder.Create(UnicodeRanges.All); + private readonly HttpContent? _httpContent; + public JsonProcessor(HttpContent? httpContent) { - private static readonly JavaScriptEncoder JavaScriptEncoder = JavaScriptEncoder.Create(UnicodeRanges.All); - private readonly HttpContent? _httpContent; - public JsonProcessor(HttpContent? httpContent) - { - _httpContent = httpContent; - } + _httpContent = httpContent; + } - protected override async Task Handle(StringBuilder contentBuilder) - { - var content = await _httpContent!.ReadAsStreamAsync(); + protected override async Task Handle(StringBuilder contentBuilder) + { + var content = await _httpContent!.ReadAsStreamAsync(); - JsonDocument? jsonDocument = null; - try + JsonDocument? jsonDocument = null; + try + { + if (content != null) { - if (content != null) + if (content.CanSeek) { - jsonDocument = await JsonDocument.ParseAsync(content, new JsonDocumentOptions - { - AllowTrailingCommas = true - }); + content.Seek(0, SeekOrigin.Begin); } - } - catch - { - // ignored - } - if (jsonDocument != null) - { - // write the JsonDocument into a MemoryStream as indented - using var stream = new MemoryStream(); - var writer = new Utf8JsonWriter(stream, new JsonWriterOptions + jsonDocument = await JsonDocument.ParseAsync(content, new JsonDocumentOptions { - Indented = true, - Encoder = JavaScriptEncoder, + AllowTrailingCommas = true }); - jsonDocument.WriteTo(writer); - await writer.FlushAsync(); - - if (stream.CanSeek) - { - stream.Seek(0, SeekOrigin.Begin); - } - - // get the string Json from the MemoryStream - using var streamReader = new StreamReader(stream, Encoding.UTF8); - - var jsonString = await streamReader.ReadToEndAsync(); - - contentBuilder.Append(jsonString); - } - else - { - // append the content as it is if it cannot be parsed as a json - contentBuilder.Append(await _httpContent.ReadAsStringAsync()); } } + catch + { + // ignored + } - protected override bool CanHandle() + if (jsonDocument != null) { - if (_httpContent == null || _httpContent.IsDisposed()) + // write the JsonDocument into a MemoryStream as indented + using var stream = new MemoryStream(); + var writer = new Utf8JsonWriter(stream, new JsonWriterOptions + { + Indented = true, + Encoder = JavaScriptEncoder, + }); + jsonDocument.WriteTo(writer); + await writer.FlushAsync(); + + if (stream.CanSeek) { - return false; + stream.Seek(0, SeekOrigin.Begin); } - _httpContent.TryGetContentLength(out long length); - _httpContent.TryGetContentTypeMediaType(out var mediaType); + // get the string Json from the MemoryStream + using var streamReader = new StreamReader(stream, Encoding.UTF8); + + var jsonString = await streamReader.ReadToEndAsync(); + AppendContentWithinLimits(contentBuilder, jsonString); + } + else + { + // append the content as it is if it cannot be parsed as a json + var stringContent = await _httpContent.ReadAsStringAsync(); + AppendContentWithinLimits(contentBuilder, stringContent); + } + } - return length <= ContentFormatterOptions.MaximumReadableBytes - && (mediaType.EqualsCaseInsensitive("application/json") || mediaType.EqualsCaseInsensitive("application/problem+json")); + protected override bool CanHandle() + { + if (_httpContent == null || _httpContent.IsDisposed()) + { + return false; } + + _httpContent.TryGetContentLength(out long length); + _httpContent.TryGetContentTypeMediaType(out var mediaType); + + return mediaType.EqualsCaseInsensitive("application/json") || mediaType.EqualsCaseInsensitive("application/problem+json"); } } diff --git a/src/FluentAssertions.Web/Internal/ContentProcessors/MultipartProcessor.cs b/src/FluentAssertions.Web/Internal/ContentProcessors/MultipartProcessor.cs index c0aad27..a721ba1 100644 --- a/src/FluentAssertions.Web/Internal/ContentProcessors/MultipartProcessor.cs +++ b/src/FluentAssertions.Web/Internal/ContentProcessors/MultipartProcessor.cs @@ -1,74 +1,68 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; +using System.Text; -namespace FluentAssertions.Web.Internal.ContentProcessors +namespace FluentAssertions.Web.Internal.ContentProcessors; + +internal class MultipartProcessor : ProcessorBase { - internal class MultipartProcessor : ProcessorBase + private readonly HttpContent? _httpContent; + public MultipartProcessor(HttpContent? httpContent) + { + _httpContent = httpContent; + } + + protected override async Task Handle(StringBuilder contentBuilder) { - private readonly HttpContent? _httpContent; - public MultipartProcessor(HttpContent? httpContent) + IEnumerable? multipartContent = null; + if (_httpContent is MultipartFormDataContent dataContent) { - _httpContent = httpContent; + multipartContent = dataContent; } - - protected override async Task Handle(StringBuilder contentBuilder) + else { - IEnumerable? multipartContent = null; - if (_httpContent is MultipartFormDataContent dataContent) - { - multipartContent = dataContent; - } - else + if (_httpContent is StreamContent streamContent) { - if (_httpContent is StreamContent streamContent) + var stream = await streamContent.ReadAsStreamAsync(); + if (stream.CanSeek) { - var stream = await streamContent.ReadAsStreamAsync(); - if (stream.CanSeek) - { - stream.Seek(0, SeekOrigin.Begin); - } - - multipartContent = (await _httpContent.ReadAsMultipartAsync(new MultipartMemoryStreamProvider())).Contents; + stream.Seek(0, SeekOrigin.Begin); } - } - if (multipartContent == null) - { - return; + multipartContent = (await _httpContent.ReadAsMultipartAsync(new MultipartMemoryStreamProvider())).Contents; } + } - var boundary = GetBoundary(); + if (multipartContent == null) + { + return; + } - foreach (var content in multipartContent) - { - contentBuilder.AppendLine(); - contentBuilder.AppendLine(boundary); + var boundary = GetBoundary(); - Appender.AppendHeaders(contentBuilder, content.Headers); + foreach (var content in multipartContent) + { + contentBuilder.AppendLine(); + contentBuilder.AppendLine(boundary); - await Appender.AppendContent(contentBuilder, content, true); - } + Appender.AppendHeaders(contentBuilder, content.Headers); - contentBuilder.AppendLine(); - contentBuilder.AppendLine($"{boundary}--"); + await Appender.AppendContent(contentBuilder, content, true); } - protected override bool CanHandle() - { - if (_httpContent is MultipartContent) - { - return true; - } - - var boundary = GetBoundary(); + contentBuilder.AppendLine(); + contentBuilder.AppendLine($"{boundary}--"); + } - return !string.IsNullOrEmpty(boundary); + protected override bool CanHandle() + { + if (_httpContent is MultipartContent) + { + return true; } - private string? GetBoundary() => _httpContent?.Headers?.ContentType?.Parameters.FirstOrDefault(c => c.Name == "boundary")?.Value?.Trim('\"'); + var boundary = GetBoundary(); + + return !string.IsNullOrEmpty(boundary); } + + private string? GetBoundary() => _httpContent?.Headers?.ContentType?.Parameters.FirstOrDefault(c => c.Name == "boundary")?.Value?.Trim('\"'); } \ No newline at end of file diff --git a/src/FluentAssertions.Web/Internal/ContentProcessors/ProcessorBase.cs b/src/FluentAssertions.Web/Internal/ContentProcessors/ProcessorBase.cs index 305cb10..f67e4ac 100644 --- a/src/FluentAssertions.Web/Internal/ContentProcessors/ProcessorBase.cs +++ b/src/FluentAssertions.Web/Internal/ContentProcessors/ProcessorBase.cs @@ -1,21 +1,38 @@ using System.Text; -using System.Threading.Tasks; -namespace FluentAssertions.Web.Internal.ContentProcessors +namespace FluentAssertions.Web.Internal.ContentProcessors; + +internal abstract class ProcessorBase : IContentProcessor { - internal abstract class ProcessorBase : IContentProcessor + public async Task GetContentInfo(StringBuilder contentBuilder) + { + if (!CanHandle()) + { + return; + } + + await Handle(contentBuilder); + } + + protected abstract bool CanHandle(); + protected abstract Task Handle(StringBuilder contentBuilder); + protected void AppendContentWithinLimits(StringBuilder contentBuilder, string? content) { - public async Task GetContentInfo(StringBuilder contentBuilder) + if (content == null) { - if (!CanHandle()) - { - return; - } + return; + } - await Handle(contentBuilder); + var toAppend = content; + var contentLength = content.Length; + + if (contentLength >= ContentFormatterOptions.MaximumReadableBytes) + { + contentBuilder.AppendLine(); + contentBuilder.AppendLine(ContentFormatterOptions.WarningMessageWhenContentIsTooLarge); + toAppend = content!.Substring(0, ContentFormatterOptions.MaximumReadableBytes); } - protected abstract bool CanHandle(); - protected abstract Task Handle(StringBuilder contentBuilder); + contentBuilder.Append(toAppend); } } \ No newline at end of file diff --git a/src/FluentAssertions.Web/Internal/ContentProcessors/ProcessorsRunner.cs b/src/FluentAssertions.Web/Internal/ContentProcessors/ProcessorsRunner.cs index 649f8af..125a558 100644 --- a/src/FluentAssertions.Web/Internal/ContentProcessors/ProcessorsRunner.cs +++ b/src/FluentAssertions.Web/Internal/ContentProcessors/ProcessorsRunner.cs @@ -1,29 +1,25 @@ -using System.Collections.Generic; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; +using System.Text; -namespace FluentAssertions.Web.Internal.ContentProcessors +namespace FluentAssertions.Web.Internal.ContentProcessors; + +internal static class ProcessorsRunner { - internal static class ProcessorsRunner + public static async Task RunProcessors(IEnumerable processors) { - public static async Task RunProcessors(IEnumerable processors) + var contentBuilder = new StringBuilder(); + foreach (var processor in processors) { - var contentBuilder = new StringBuilder(); - foreach (var processor in processors) - { - await processor.GetContentInfo(contentBuilder); - } - - return contentBuilder; + await processor.GetContentInfo(contentBuilder); } - public static IReadOnlyCollection CommonProcessors(HttpContent content) => new IContentProcessor[] - { - new JsonProcessor(content), - new BinaryProcessor(content), - new MultipartProcessor(content), - new FallbackProcessor(content) - }; + return contentBuilder; } + + public static IReadOnlyCollection CommonProcessors(HttpContent content) => new IContentProcessor[] + { + new JsonProcessor(content), + new BinaryProcessor(content), + new MultipartProcessor(content), + new FallbackProcessor(content) + }; } \ No newline at end of file diff --git a/src/FluentAssertions.Web/Internal/Guard.cs b/src/FluentAssertions.Web/Internal/Guard.cs index 0da7551..7b19163 100644 --- a/src/FluentAssertions.Web/Internal/Guard.cs +++ b/src/FluentAssertions.Web/Internal/Guard.cs @@ -1,41 +1,38 @@ -using System; +namespace FluentAssertions.Web.Internal; -namespace FluentAssertions.Web.Internal +internal static class Guard { - internal static class Guard + public static void ThrowIfArgumentIsNull(T obj, string paramName) + where T : class { - public static void ThrowIfArgumentIsNull(T obj, string paramName) - where T : class + if (obj is null) { - if (obj is null) - { - throw new ArgumentNullException(paramName); - } + throw new ArgumentNullException(paramName); } + } - public static void ThrowIfArgumentIsNull(T obj, string paramName, string message) - where T : class + public static void ThrowIfArgumentIsNull(T obj, string paramName, string message) + where T : class + { + if (obj is null) { - if (obj is null) - { - throw new ArgumentNullException(paramName, message); - } + throw new ArgumentNullException(paramName, message); } + } - public static void ThrowIfArgumentIsNullOrEmpty(string str, string paramName) + public static void ThrowIfArgumentIsNullOrEmpty(string str, string paramName) + { + if (string.IsNullOrEmpty(str)) { - if (string.IsNullOrEmpty(str)) - { - throw new ArgumentNullException(paramName); - } + throw new ArgumentNullException(paramName); } + } - public static void ThrowIfArgumentIsNullOrEmpty(string str, string paramName, string message) + public static void ThrowIfArgumentIsNullOrEmpty(string str, string paramName, string message) + { + if (string.IsNullOrEmpty(str)) { - if (string.IsNullOrEmpty(str)) - { - throw new ArgumentNullException(paramName, message); - } + throw new ArgumentNullException(paramName, message); } } } \ No newline at end of file diff --git a/src/FluentAssertions.Web/Internal/HttpContentExtensions.cs b/src/FluentAssertions.Web/Internal/HttpContentExtensions.cs index a898470..7f4a144 100644 --- a/src/FluentAssertions.Web/Internal/HttpContentExtensions.cs +++ b/src/FluentAssertions.Web/Internal/HttpContentExtensions.cs @@ -1,104 +1,99 @@ -using System; -using System.IO; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; +using System.Text; -namespace FluentAssertions.Web.Internal +namespace FluentAssertions.Web.Internal; + +internal static class HttpContentExtensions { - internal static class HttpContentExtensions + public static async Task ReadAsAsync(this HttpContent content, ISerializer serializer) + { + var model = await ReadAsAsync(content, typeof(T), serializer); + return (T?)model; + } + + public static async Task ReadAsAsync(this HttpContent content, Type modelType, ISerializer serializer) { - public static async Task ReadAsAsync(this HttpContent content, ISerializer serializer) + var contentStream = await content.ReadAsStreamAsync(); + contentStream.Seek(0, SeekOrigin.Begin); + var result = await serializer.Deserialize(contentStream, modelType); + contentStream.Seek(0, SeekOrigin.Begin); + return result; + } + + public static Task ReadAsAsync(this HttpContent content, T _, ISerializer serializer) + => content.ReadAsAsync(serializer); + + public static bool IsDisposed(this HttpContent? content) + { + if (content == null) { - var model = await ReadAsAsync(content, typeof(T), serializer); - return (T?)model; + return true; } - public static async Task ReadAsAsync(this HttpContent content, Type modelType, ISerializer serializer) + try { - var contentStream = await content.ReadAsStreamAsync(); - contentStream.Seek(0, SeekOrigin.Begin); - var result = await serializer.Deserialize(contentStream, modelType); - contentStream.Seek(0, SeekOrigin.Begin); - return result; + var _ = content?.Headers?.ContentLength; + return false; } - - public static Task ReadAsAsync(this HttpContent content, T _, ISerializer serializer) - => content.ReadAsAsync(serializer); - - public static bool IsDisposed(this HttpContent? content) + catch (ObjectDisposedException) { - if (content == null) - { - return true; - } + return true; + } + } - try - { - var _ = content?.Headers?.ContentLength; - return false; - } - catch (ObjectDisposedException) - { - return true; - } + public static bool TryGetContentLength(this HttpContent? content, out long length) + { + try + { + length = content?.Headers?.ContentLength ?? 0; + return true; + } + catch (Exception) + { + length = 0; + return false; } + } - public static bool TryGetContentLength(this HttpContent? content, out long length) + public static bool TryGetContentTypeMediaType(this HttpContent? content, out string? mediaType) + { + try { - try - { - length = content?.Headers?.ContentLength ?? 0; - return true; - } - catch (Exception) - { - length = 0; - return false; - } + mediaType = content?.Headers?.ContentType?.MediaType; + return true; } + catch (Exception) + { + mediaType = null; + return false; + } + } - public static bool TryGetContentTypeMediaType(this HttpContent? content, out string? mediaType) + public static async Task SafeReadAsStringAsync(this HttpContent? content, string? defaultMessage = null) + { + if (content == null) { - try - { - mediaType = content?.Headers?.ContentType?.MediaType; - return true; - } - catch (Exception) - { - mediaType = null; - return false; - } + return null; } - public static async Task SafeReadAsStringAsync(this HttpContent? content, string? defaultMessage = null) + try { - if (content == null) + var stream = await content.ReadAsStreamAsync(); + if (stream == null) { - return null; + return ""; } - try - { - var stream = await content.ReadAsStreamAsync(); - if (stream == null) - { - return ""; - } - - if (stream.CanSeek) - { - stream.Seek(0, SeekOrigin.Begin); - } - - using var sr = new StreamReader(stream, Encoding.UTF8, true, 1024, true); - return await sr.ReadToEndAsync(); - } - catch (ObjectDisposedException) + if (stream.CanSeek) { - return defaultMessage ?? ContentFormatterOptions.WarningMessageWhenDisposed; + stream.Seek(0, SeekOrigin.Begin); } + + using var sr = new StreamReader(stream, Encoding.UTF8, true, 1024, true); + return await sr.ReadToEndAsync(); + } + catch (ObjectDisposedException) + { + return defaultMessage ?? ContentFormatterOptions.WarningMessageWhenDisposed; } } } \ No newline at end of file diff --git a/src/FluentAssertions.Web/Internal/HttpResponseMessageExtensions.cs b/src/FluentAssertions.Web/Internal/HttpResponseMessageExtensions.cs index 60bb68b..d7f5c33 100644 --- a/src/FluentAssertions.Web/Internal/HttpResponseMessageExtensions.cs +++ b/src/FluentAssertions.Web/Internal/HttpResponseMessageExtensions.cs @@ -1,45 +1,44 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text.Json; -using System.Threading.Tasks; - -namespace FluentAssertions.Web.Internal +namespace FluentAssertions.Web.Internal; + +internal static class HttpResponseMessageExtensions { - internal static class HttpResponseMessageExtensions + public static IEnumerable GetHeaderValues(this HttpResponseMessage response, string header) + { + var headers = response.GetHeaders(); + return headers + .FirstOrDefault(c => string.Equals(c.Key, header, StringComparison.OrdinalIgnoreCase)) + .Value + .Where(c => !string.IsNullOrEmpty(c)); + } + + public static string? GetFirstHeaderValue(this HttpResponseMessage response, string header) + { + var values = response.GetHeaderValues(header); + + return values.FirstOrDefault(); + } + + public static IEnumerable>> GetHeaders(this HttpResponseMessage response) { - public static IEnumerable GetHeaderValues(this HttpResponseMessage response, string header) - { - var headers = response.GetHeaders(); - return headers - .FirstOrDefault(c => string.Equals(c.Key, header, StringComparison.OrdinalIgnoreCase)) - .Value - .Where(c => !string.IsNullOrEmpty(c)); - } - - public static IEnumerable>> GetHeaders(this HttpResponseMessage response) - { - var responseContentHeaders = - response.Content?.Headers ?? Enumerable.Empty>>(); - return response.Headers.Union(responseContentHeaders); - } - - public static IEnumerable>> GetHeaders(this HttpRequestMessage request) - { - var requestContentHeaders = - request.Content?.Headers ?? Enumerable.Empty>>(); - return request.Headers.Union(requestContentHeaders); - } - - public static async Task GetStringContent(this HttpResponseMessage response) - => response.Content != null ? await response.Content.ReadAsStringAsync() : null; - - public static async Task GetJsonDocument(this HttpResponseMessage response) - { - var content = await response.GetStringContent(); - - return JsonDocument.Parse(content!); - } + var responseContentHeaders = + response.Content?.Headers ?? Enumerable.Empty>>(); + return response.Headers.Union(responseContentHeaders); + } + + public static IEnumerable>> GetHeaders(this HttpRequestMessage request) + { + var requestContentHeaders = + request.Content?.Headers ?? Enumerable.Empty>>(); + return request.Headers.Union(requestContentHeaders); + } + + public static async Task GetStringContent(this HttpResponseMessage response) + => response.Content != null ? await response.Content.ReadAsStringAsync() : null; + + public static async Task GetJsonDocument(this HttpResponseMessage response) + { + var content = await response.GetStringContent(); + + return JsonDocument.Parse(content!); } } \ No newline at end of file diff --git a/src/FluentAssertions.Web/Internal/JsonExtensions.cs b/src/FluentAssertions.Web/Internal/JsonExtensions.cs index 3a0a12d..27a6a05 100644 --- a/src/FluentAssertions.Web/Internal/JsonExtensions.cs +++ b/src/FluentAssertions.Web/Internal/JsonExtensions.cs @@ -1,106 +1,100 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.Json; +namespace FluentAssertions.Web.Internal; -namespace FluentAssertions.Web.Internal +internal static class JsonExtensions { - internal static class JsonExtensions + public static IEnumerable GetStringValuesOf(this JsonDocument json, string propertyName) { - public static IEnumerable GetStringValuesOf(this JsonDocument json, string propertyName) - { - var byKey = json.GetPropertiesByName(propertyName); + var byKey = json.GetPropertiesByName(propertyName); - return GetStringValues(byKey); - } + return GetStringValues(byKey); + } - public static IEnumerable GetStringValuesOf(this JsonProperty property, string propertyName) - { - var byKey = property.GetPropertiesByName(propertyName); + public static IEnumerable GetStringValuesOf(this JsonProperty property, string propertyName) + { + var byKey = property.GetPropertiesByName(propertyName); - return GetStringValues(byKey); - } + return GetStringValues(byKey); + } - public static IEnumerable GetChildrenNames(this JsonDocument json, string? parentElement) + public static IEnumerable GetChildrenNames(this JsonDocument json, string? parentElement) + { + if (string.IsNullOrEmpty(parentElement)) { - if (string.IsNullOrEmpty(parentElement)) - { - return json.RootElement.AllProperties().Select(c => c.Name); - } - - return json.GetPropertiesByName(parentElement!) - .SelectMany(c => c.Value.AllProperties().Select(p => p.Name)); + return json.RootElement.AllProperties().Select(c => c.Name); } - public static string? GetParentKey(this JsonDocument json, string childElement) - => GetByKeyWithParent(json, childElement) - .Select(c => c.parent?.Name).FirstOrDefault(); + return json.GetPropertiesByName(parentElement!) + .SelectMany(c => c.Value.AllProperties().Select(p => p.Name)); + } + + public static string? GetParentKey(this JsonDocument json, string childElement) + => GetByKeyWithParent(json, childElement) + .Select(c => c.parent?.Name).FirstOrDefault(); - public static IEnumerable GetPropertiesByName(this JsonDocument json, string propertyName) - => json.RootElement.AllProperties().Where(property => string.Equals(property.Name, propertyName, StringComparison.OrdinalIgnoreCase)); + public static IEnumerable GetPropertiesByName(this JsonDocument json, string propertyName) + => json.RootElement.AllProperties().Where(property => string.Equals(property.Name, propertyName, StringComparison.OrdinalIgnoreCase)); - public static IEnumerable GetPropertiesByName(this JsonProperty property, string propertyName) - => property.Value.AllProperties().Where(p => string.Equals(p.Name, propertyName, StringComparison.OrdinalIgnoreCase)); + public static IEnumerable GetPropertiesByName(this JsonProperty property, string propertyName) + => property.Value.AllProperties().Where(p => string.Equals(p.Name, propertyName, StringComparison.OrdinalIgnoreCase)); - private static IEnumerable<(JsonProperty element, JsonProperty? parent)> GetByKeyWithParent(this JsonDocument json, string key) - => json.RootElement.AllPropertiesWithParent().Where(pair => string.Equals(pair.property.Name, key, StringComparison.OrdinalIgnoreCase)); + private static IEnumerable<(JsonProperty element, JsonProperty? parent)> GetByKeyWithParent(this JsonDocument json, string key) + => json.RootElement.AllPropertiesWithParent().Where(pair => string.Equals(pair.property.Name, key, StringComparison.OrdinalIgnoreCase)); - private static IEnumerable AllProperties(this JsonElement obj) - => obj.AllPropertiesWithParent().Select(pair => pair.property); + private static IEnumerable AllProperties(this JsonElement obj) + => obj.AllPropertiesWithParent().Select(pair => pair.property); - private static IEnumerable GetStringValues(IEnumerable properties) + private static IEnumerable GetStringValues(IEnumerable properties) + { + if (!properties.Any()) { - if (!properties.Any()) - { - return Enumerable.Empty(); - } + return Enumerable.Empty(); + } - var first = properties.First(); - switch (first.Value.ValueKind) - { - case JsonValueKind.String: - return new[] { first.Value.GetString() ?? "" }; - case JsonValueKind.Array: - return first.Value.EnumerateArray().Where(c => c.ValueKind == JsonValueKind.String).Select(c => c.GetString() ?? ""); - default: - return Enumerable.Empty(); - } + var first = properties.First(); + switch (first.Value.ValueKind) + { + case JsonValueKind.String: + return new[] { first.Value.GetString() ?? "" }; + case JsonValueKind.Array: + return first.Value.EnumerateArray().Where(c => c.ValueKind == JsonValueKind.String).Select(c => c.GetString() ?? ""); + default: + return Enumerable.Empty(); } + } + + private static IEnumerable<(JsonProperty property, JsonProperty? parent)> AllPropertiesWithParent(this JsonElement obj) + { + var toSearch = new Stack<(JsonElement element, JsonProperty? parent)>(); + toSearch.Push((obj, default)); - private static IEnumerable<(JsonProperty property, JsonProperty? parent)> AllPropertiesWithParent(this JsonElement obj) + while (toSearch.Count > 0) { - var toSearch = new Stack<(JsonElement element, JsonProperty? parent)>(); - toSearch.Push((obj, default)); + var inspected = toSearch.Pop(); - while (toSearch.Count > 0) + if (inspected.element.ValueKind == JsonValueKind.Array) { - var inspected = toSearch.Pop(); - - if (inspected.element.ValueKind == JsonValueKind.Array) + foreach (var arrayElement in inspected.element.EnumerateArray()) { - foreach (var arrayElement in inspected.element.EnumerateArray()) + if (arrayElement.ValueKind == JsonValueKind.Object) { - if (arrayElement.ValueKind == JsonValueKind.Object) + foreach (var property in arrayElement.EnumerateObject()) { - foreach (var property in arrayElement.EnumerateObject()) - { - toSearch.Push((property.Value, inspected.parent)); - } + toSearch.Push((property.Value, inspected.parent)); } } } - else if (inspected.element.ValueKind == JsonValueKind.Object) + } + else if (inspected.element.ValueKind == JsonValueKind.Object) + { + foreach (var property in inspected.element.EnumerateObject()) { - foreach (var property in inspected.element.EnumerateObject()) + if (property.Value.ValueKind == JsonValueKind.Object) { - if (property.Value.ValueKind == JsonValueKind.Object) - { - toSearch.Push((property.Value, property)); - } - - yield return (property, inspected.parent); + toSearch.Push((property.Value, property)); } + + yield return (property, inspected.parent); } } } diff --git a/src/FluentAssertions.Web/Internal/NoSynchronizationContextScope.cs b/src/FluentAssertions.Web/Internal/NoSynchronizationContextScope.cs index d2dcff6..abcf1ab 100644 --- a/src/FluentAssertions.Web/Internal/NoSynchronizationContextScope.cs +++ b/src/FluentAssertions.Web/Internal/NoSynchronizationContextScope.cs @@ -1,30 +1,28 @@ -using System; -using System.Threading; +using System.Threading; -namespace FluentAssertions.Web.Internal +namespace FluentAssertions.Web.Internal; + +internal static class NoSynchronizationContextScope { - internal static class NoSynchronizationContextScope + public static DisposingAction Enter() + { + var context = SynchronizationContext.Current; + SynchronizationContext.SetSynchronizationContext(null); + return new DisposingAction(() => SynchronizationContext.SetSynchronizationContext(context)); + } + + internal sealed class DisposingAction : IDisposable { - public static DisposingAction Enter() + private readonly Action _action; + + public DisposingAction(Action action) { - var context = SynchronizationContext.Current; - SynchronizationContext.SetSynchronizationContext(null); - return new DisposingAction(() => SynchronizationContext.SetSynchronizationContext(context)); + _action = action; } - internal sealed class DisposingAction : IDisposable + public void Dispose() { - private readonly Action _action; - - public DisposingAction(Action action) - { - _action = action; - } - - public void Dispose() - { - _action(); - } + _action(); } } } \ No newline at end of file diff --git a/src/FluentAssertions.Web/Internal/ObjectExtensions.cs b/src/FluentAssertions.Web/Internal/ObjectExtensions.cs index f7c9af3..e5abd94 100644 --- a/src/FluentAssertions.Web/Internal/ObjectExtensions.cs +++ b/src/FluentAssertions.Web/Internal/ObjectExtensions.cs @@ -1,9 +1,6 @@ -using System.Text.Json; +namespace FluentAssertions.Web.Internal; -namespace FluentAssertions.Web.Internal +internal static class ObjectExtensions { - internal static class ObjectExtensions - { - public static string ToJson(this object source) => JsonSerializer.Serialize(source); - } + public static string ToJson(this object source) => JsonSerializer.Serialize(source); } \ No newline at end of file diff --git a/src/FluentAssertions.Web/Internal/Serializers/SystemTextJsonSerializer.cs b/src/FluentAssertions.Web/Internal/Serializers/SystemTextJsonSerializer.cs index f2a9eda..83e04d6 100644 --- a/src/FluentAssertions.Web/Internal/Serializers/SystemTextJsonSerializer.cs +++ b/src/FluentAssertions.Web/Internal/Serializers/SystemTextJsonSerializer.cs @@ -1,64 +1,59 @@ // ReSharper disable once CheckNamespace -using System; -using System.IO; using System.Reflection; -using System.Text.Json; using System.Text.Json.Serialization; -using System.Threading.Tasks; -namespace FluentAssertions.Web.Internal.Serializers +namespace FluentAssertions.Web.Internal.Serializers; + +internal class SystemTextJsonSerializer : ISerializer { - internal class SystemTextJsonSerializer : ISerializer + public async Task Deserialize(Stream content, Type modelType) { - public async Task Deserialize(Stream content, Type modelType) + try { - try - { - var result = await JsonSerializer.DeserializeAsync(content, modelType, SystemTextJsonSerializerConfig.Options); - return result; - } - catch (JsonException ex) - { - throw new DeserializationException($"Exception while deserializing the model with {nameof(SystemTextJsonSerializer)}", ex); - } + var result = await JsonSerializer.DeserializeAsync(content, modelType, SystemTextJsonSerializerConfig.Options); + return result; + } + catch (JsonException ex) + { + throw new DeserializationException($"Exception while deserializing the model with {nameof(SystemTextJsonSerializer)}", ex); } } +} - //https://stackoverflow.com/a/65025191/782754 - internal class NullableConverterFactory : JsonConverterFactory - { - static readonly byte[] Empty = Array.Empty(); +//https://stackoverflow.com/a/65025191/782754 +internal class NullableConverterFactory : JsonConverterFactory +{ + static readonly byte[] Empty = Array.Empty(); - public override bool CanConvert(Type typeToConvert) => Nullable.GetUnderlyingType(typeToConvert) != null; + public override bool CanConvert(Type typeToConvert) => Nullable.GetUnderlyingType(typeToConvert) != null; - public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options) => - (JsonConverter)Activator.CreateInstance( - typeof(NullableConverter<>).MakeGenericType( - new Type[] { Nullable.GetUnderlyingType(type) }), - BindingFlags.Instance | BindingFlags.Public, - binder: null, - args: new object[] { options }, - culture: null); + public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options) => + (JsonConverter)Activator.CreateInstance( + typeof(NullableConverter<>).MakeGenericType( + new Type[] { Nullable.GetUnderlyingType(type) }), + BindingFlags.Instance | BindingFlags.Public, + binder: null, + args: new object[] { options }, + culture: null); - class NullableConverter : JsonConverter where T : struct - { - // DO NOT CACHE the return of (JsonConverter)options.GetConverter(typeof(T)) as DoubleConverter.Read() and DoubleConverter.Write() - // DO NOT WORK for nondefault values of JsonSerializerOptions.NumberHandling which was introduced in .NET 5 - public NullableConverter(JsonSerializerOptions options) { } + class NullableConverter : JsonConverter where T : struct + { + // DO NOT CACHE the return of (JsonConverter)options.GetConverter(typeof(T)) as DoubleConverter.Read() and DoubleConverter.Write() + // DO NOT WORK for nondefault values of JsonSerializerOptions.NumberHandling which was introduced in .NET 5 + public NullableConverter(JsonSerializerOptions options) { } - public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) { - if (reader.TokenType == JsonTokenType.String) - { - if (reader.ValueTextEquals(Empty)) - return null; - } - - return JsonSerializer.Deserialize(ref reader, options); + if (reader.ValueTextEquals(Empty)) + return null; } - public override void Write(Utf8JsonWriter writer, T? value, JsonSerializerOptions options) => - JsonSerializer.Serialize(writer, value != null ? value.Value : default, options); + return JsonSerializer.Deserialize(ref reader, options); } + + public override void Write(Utf8JsonWriter writer, T? value, JsonSerializerOptions options) => + JsonSerializer.Serialize(writer, value != null ? value.Value : default, options); } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Web/Internal/StringExtensions.cs b/src/FluentAssertions.Web/Internal/StringExtensions.cs index 5eaee65..6eed275 100644 --- a/src/FluentAssertions.Web/Internal/StringExtensions.cs +++ b/src/FluentAssertions.Web/Internal/StringExtensions.cs @@ -1,14 +1,13 @@ -using System; +namespace FluentAssertions.Web.Internal; -namespace FluentAssertions.Web.Internal +internal static class StringExtensions { - internal static class StringExtensions - { - public static string ReplaceFirstWithLowercase(this string source) => !string.IsNullOrEmpty(source) ? - source[0].ToString().ToLower() + source.Substring(1) - : source; + public static string ReplaceFirstWithLowercase(this string source) => !string.IsNullOrEmpty(source) ? + source[0].ToString().ToLower() + source.Substring(1) + : source; - public static bool EqualsCaseInsensitive(this string? source, string? other) - => string.Equals(source, other, StringComparison.OrdinalIgnoreCase); - } + public static string TrimDot(this string source) => source.TrimEnd('.'); + + public static bool EqualsCaseInsensitive(this string? source, string? other) + => string.Equals(source, other, StringComparison.OrdinalIgnoreCase); } \ No newline at end of file diff --git a/src/FluentAssertions.Web/Internal/TaskExtensions.cs b/src/FluentAssertions.Web/Internal/TaskExtensions.cs index ef02bde..63bbf0d 100644 --- a/src/FluentAssertions.Web/Internal/TaskExtensions.cs +++ b/src/FluentAssertions.Web/Internal/TaskExtensions.cs @@ -1,29 +1,26 @@ -using System; +namespace FluentAssertions.Web.Internal; -namespace FluentAssertions.Web.Internal +/// +/// Some unit test frameworks (like xUnit) have their own synchronization context +/// that does not work well with blocking waits and can lead to deadlocks. +/// These methods create the task in the default synchronization context +/// and blocks until the task is completed. +/// +internal static class TaskExtensions { - /// - /// Some unit test frameworks (like xUnit) have their own synchronization context - /// that does not work well with blocking waits and can lead to deadlocks. - /// These methods create the task in the default synchronization context - /// and blocks until the task is completed. - /// - internal static class TaskExtensions + public static void ExecuteInDefaultSynchronizationContext(this Action action) { - public static void ExecuteInDefaultSynchronizationContext(this Action action) + using (NoSynchronizationContextScope.Enter()) { - using (NoSynchronizationContextScope.Enter()) - { - action(); - } + action(); } + } - public static TResult ExecuteInDefaultSynchronizationContext(this Func action) + public static TResult ExecuteInDefaultSynchronizationContext(this Func action) + { + using (NoSynchronizationContextScope.Enter()) { - using (NoSynchronizationContextScope.Enter()) - { - return action(); - } + return action(); } } } \ No newline at end of file diff --git a/src/FluentAssertions.Web/SatisfyHttpResponseMessageAssertions.cs b/src/FluentAssertions.Web/SatisfyHttpResponseMessageAssertions.cs index 3620a3e..6c25f17 100644 --- a/src/FluentAssertions.Web/SatisfyHttpResponseMessageAssertions.cs +++ b/src/FluentAssertions.Web/SatisfyHttpResponseMessageAssertions.cs @@ -1,98 +1,90 @@ -using FluentAssertions.Execution; -using FluentAssertions.Web.Internal; -using System; -using System.Linq; -using System.Net.Http; -using System.Threading.Tasks; +namespace FluentAssertions.Web; -namespace FluentAssertions.Web +public partial class HttpResponseMessageAssertions { - public partial class HttpResponseMessageAssertions + /// + /// Asserts that an HTTP response satisfies an assertion. + /// + /// + /// An assertion about the HTTP response. + /// + /// + /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Satisfy(Action assertion, + string because = "", params object[] becauseArgs) { - /// - /// Asserts that an HTTP response satisfies an assertion. - /// - /// - /// An assertion about the HTTP response. - /// - /// - /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Satisfy(Action assertion, - string because = "", params object[] becauseArgs) - { - Guard.ThrowIfArgumentIsNull(assertion, nameof(assertion), "Cannot verify the subject satisfies a `null` assertion."); + Guard.ThrowIfArgumentIsNull(assertion, nameof(assertion), "Cannot verify the subject satisfies a `null` assertion."); + + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + var failuresFromAssertions = CollectFailuresFromAssertion(assertion!, Subject); + + if (failuresFromAssertions.Any()) + { Execute.Assertion - .ForCondition(Subject is not null) .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); + .FailWith( + "Expected {context:response} to satisfy one or more assertions, but it wasn't{reason}: {0}{1}", + new AssertionsFailures(failuresFromAssertions), Subject); + } - var failuresFromAssertions = CollectFailuresFromAssertion(assertion!, Subject); + return new AndConstraint(this); + } - if (failuresFromAssertions.Any()) - { - Execute.Assertion - .BecauseOf(because, becauseArgs) - .FailWith( - "Expected {context:response} to satisfy one or more assertions, but it wasn't{reason}: {0}{1}", - new AssertionsFailures(failuresFromAssertions), Subject); - } + /// + /// Asserts that an HTTP response satisfies an asynchronous assertion. + /// + /// + /// An assertion about the HTTP response. + /// + /// + /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Satisfy(Func assertion, + string because = "", params object[] becauseArgs) + { + Guard.ThrowIfArgumentIsNull(assertion, nameof(assertion), "Cannot verify the subject satisfies a `null` assertion."); - return new AndConstraint(this); - } + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); - /// - /// Asserts that an HTTP response satisfies an asynchronous assertion. - /// - /// - /// An assertion about the HTTP response. - /// - /// - /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Satisfy(Func assertion, - string because = "", params object[] becauseArgs) + var failuresFromAssertions = CollectFailuresFromAssertion(asserted => { - Guard.ThrowIfArgumentIsNull(assertion, nameof(assertion), "Cannot verify the subject satisfies a `null` assertion."); + Func assertionExecutor = () => assertion(asserted!); + assertionExecutor.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); + }, Subject); + if (failuresFromAssertions.Any()) + { Execute.Assertion - .ForCondition(Subject is not null) .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); - - var failuresFromAssertions = CollectFailuresFromAssertion(asserted => - { - Func assertionExecutor = () => assertion(asserted!); - assertionExecutor.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); - }, Subject); - - if (failuresFromAssertions.Any()) - { - Execute.Assertion - .BecauseOf(because, becauseArgs) - .FailWith( - "Expected {context:response} to satisfy one or more assertions, but it wasn't{reason}: {0}{1}", - new AssertionsFailures(failuresFromAssertions), Subject); - } - - return new AndConstraint(this); + .FailWith( + "Expected {context:response} to satisfy one or more assertions, but it wasn't{reason}: {0}{1}", + new AssertionsFailures(failuresFromAssertions), Subject); } + + return new AndConstraint(this); } } diff --git a/src/FluentAssertions.Web/SatisfyHttpResponseMessageAssertionsExtensions.cs b/src/FluentAssertions.Web/SatisfyHttpResponseMessageAssertionsExtensions.cs index a4f56e0..f5f6c57 100644 --- a/src/FluentAssertions.Web/SatisfyHttpResponseMessageAssertionsExtensions.cs +++ b/src/FluentAssertions.Web/SatisfyHttpResponseMessageAssertionsExtensions.cs @@ -1,66 +1,59 @@ -using System; -using System.Diagnostics; -using System.Net.Http; -using System.Threading.Tasks; -using FluentAssertions.Web; +// ReSharper disable once CheckNamespace +namespace FluentAssertions; -// ReSharper disable once CheckNamespace -namespace FluentAssertions +/// +/// Contains extension methods for custom assertions in unit tests related to Http Response Message. +/// +[DebuggerNonUserCode] +public static class SatisfyHttpResponseMessageAssertionsExtensions { /// - /// Contains extension methods for custom assertions in unit tests related to Http Response Message. + /// Asserts that an HTTP response satisfies an assertion. /// - [DebuggerNonUserCode] - public static class SatisfyHttpResponseMessageAssertionsExtensions - { - /// - /// Asserts that an HTTP response satisfies an assertion. - /// - /// - /// An assertion about the HTTP response. - /// - /// - /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Satisfy( + /// + /// An assertion about the HTTP response. + /// + /// + /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Satisfy( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - Action assertion, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Satisfy(assertion, because, becauseArgs); + Action assertion, + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Satisfy(assertion, because, becauseArgs); - /// - /// Asserts that an HTTP response satisfies an asynchronous assertion. - /// - /// - /// An assertion about the HTTP response. - /// - /// - /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Satisfy( + /// + /// Asserts that an HTTP response satisfies an asynchronous assertion. + /// + /// + /// An assertion about the HTTP response. + /// + /// + /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Satisfy( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573, - Func assertion, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Satisfy(assertion, because, becauseArgs); - } + Func assertion, + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Satisfy(assertion, because, becauseArgs); } diff --git a/src/FluentAssertions.Web/SatisfyModelAssertions.cs b/src/FluentAssertions.Web/SatisfyModelAssertions.cs index e11515d..d3efcb5 100644 --- a/src/FluentAssertions.Web/SatisfyModelAssertions.cs +++ b/src/FluentAssertions.Web/SatisfyModelAssertions.cs @@ -1,247 +1,240 @@ -using FluentAssertions.Execution; -using FluentAssertions.Web.Internal; -using System; -using System.Linq; -using System.Threading.Tasks; +namespace FluentAssertions.Web; -namespace FluentAssertions.Web +public partial class HttpResponseMessageAssertions { - public partial class HttpResponseMessageAssertions + /// + /// Asserts that an HTTP response content can be a model that satisfies an assertion. + /// + /// + /// An assertion regarding the given model. + /// + /// + /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Satisfy( + Action assertion, + string because = "", params object[] becauseArgs) { - /// - /// Asserts that an HTTP response content can be a model that satisfies an assertion. - /// - /// - /// An assertion regarding the given model. - /// - /// - /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Satisfy( - Action assertion, - string because = "", params object[] becauseArgs) - { - Guard.ThrowIfArgumentIsNull(assertion, nameof(assertion), - "Cannot verify the subject satisfies a `null` assertion."); + Guard.ThrowIfArgumentIsNull(assertion, nameof(assertion), + "Cannot verify the subject satisfies a `null` assertion."); - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + var (success, errorMessage) = TryGetSubjectModel(out var model); + + Type? modelType = typeof(TModel); - var (success, errorMessage) = TryGetSubjectModel(out var model); + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(success) + .FailWith("Expected {context:response} to have a content equivalent to a model of type {0}, but the JSON representation could not be parsed, as the operation failed with the following message: {2}{reason}. {1}", + modelType?.ToString() ?? "unknown type", Subject, errorMessage); - Type? modelType = typeof(TModel); + var failuresFromAssertions = CollectFailuresFromAssertion(assertion!, model); + if (failuresFromAssertions.Any()) + { Execute.Assertion .BecauseOf(because, becauseArgs) - .ForCondition(success) - .FailWith("Expected {context:response} to have a content equivalent to a model of type {0}, but the JSON representation could not be parsed, as the operation failed with the following message: {2}{reason}. {1}", - modelType?.ToString() ?? "unknown type", Subject, errorMessage); - - var failuresFromAssertions = CollectFailuresFromAssertion(assertion!, model); - - if (failuresFromAssertions.Any()) - { - Execute.Assertion - .BecauseOf(because, becauseArgs) - .FailWith( - "Expected {context:response} to satisfy one or more model assertions, but it wasn't{reason}: {0}{1}", - new AssertionsFailures(failuresFromAssertions), Subject); - } - - return new AndConstraint(this); + .FailWith( + "Expected {context:response} to satisfy one or more model assertions, but it wasn't{reason}: {0}{1}", + new AssertionsFailures(failuresFromAssertions), Subject); } - /// - /// Asserts that an HTTP response content can be a model that satisfies an assertion starting from an inferred model structure. - /// - /// - /// A proposed model structure that will help to compose the assertions. This is used to defined the type of the asserted model and it doesn't have to contain other values than the default one. - /// - /// - /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. - /// - /// - /// An assertion or a collection of assertions regarding the given model. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] + return new AndConstraint(this); + } + + /// + /// Asserts that an HTTP response content can be a model that satisfies an assertion starting from an inferred model structure. + /// + /// + /// A proposed model structure that will help to compose the assertions. This is used to defined the type of the asserted model and it doesn't have to contain other values than the default one. + /// + /// + /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. + /// + /// + /// An assertion or a collection of assertions regarding the given model. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] #pragma warning disable IDE0060 // Remove unused parameter - public AndConstraint Satisfy(TModel givenModelStructure, + public AndConstraint Satisfy(TModel givenModelStructure, #pragma warning restore IDE0060 // Remove unused parameter - Action assertion, - string because = "", params object[] becauseArgs) - { - Guard.ThrowIfArgumentIsNull(assertion, nameof(assertion), "Cannot verify the subject satisfies a `null` assertion."); + Action assertion, + string because = "", params object[] becauseArgs) + { + Guard.ThrowIfArgumentIsNull(assertion, nameof(assertion), "Cannot verify the subject satisfies a `null` assertion."); - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); + + var (success, errorMessage) = TryGetSubjectModel(out var model); + + Type? modelType = typeof(TModel); - var (success, errorMessage) = TryGetSubjectModel(out var model); + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(success) + .FailWith("Expected {context:response} to have a content equivalent to a model of type {0}, but the JSON representation could not be parsed, as the operation failed with the following message: {2}{reason}. {1}", + modelType?.ToString() ?? "unknown type", Subject, errorMessage); - Type? modelType = typeof(TModel); + var failuresFromAssertions = CollectFailuresFromAssertion(assertion!, model); + if (failuresFromAssertions.Any()) + { Execute.Assertion .BecauseOf(because, becauseArgs) - .ForCondition(success) - .FailWith("Expected {context:response} to have a content equivalent to a model of type {0}, but the JSON representation could not be parsed, as the operation failed with the following message: {2}{reason}. {1}", - modelType?.ToString() ?? "unknown type", Subject, errorMessage); - - var failuresFromAssertions = CollectFailuresFromAssertion(assertion!, model); - - if (failuresFromAssertions.Any()) - { - Execute.Assertion - .BecauseOf(because, becauseArgs) - .FailWith( - "Expected {context:response} to satisfy one or more model assertions, but it wasn't{reason}: {0}{1}", - new AssertionsFailures(failuresFromAssertions), Subject); - } - - return new AndConstraint(this); + .FailWith( + "Expected {context:response} to satisfy one or more model assertions, but it wasn't{reason}: {0}{1}", + new AssertionsFailures(failuresFromAssertions), Subject); } - /// - /// Asserts that an HTTP response content can be a model that satisfies an asynchronous assertion. - /// - /// - /// An assertion regarding the given model. - /// - /// - /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public AndConstraint Satisfy( - Func assertion, - string because = "", params object[] becauseArgs) - { - Guard.ThrowIfArgumentIsNull(assertion, nameof(assertion), - "Cannot verify the subject satisfies a `null` assertion."); + return new AndConstraint(this); + } - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); + /// + /// Asserts that an HTTP response content can be a model that satisfies an asynchronous assertion. + /// + /// + /// An assertion regarding the given model. + /// + /// + /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public AndConstraint Satisfy( + Func assertion, + string because = "", params object[] becauseArgs) + { + Guard.ThrowIfArgumentIsNull(assertion, nameof(assertion), + "Cannot verify the subject satisfies a `null` assertion."); + + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); - // ReSharper disable once ConvertToLocalFunction + // ReSharper disable once ConvertToLocalFunction #pragma warning disable IDE0039 // Use local function - Action assertionCaller = asserted => + Action assertionCaller = asserted => #pragma warning restore IDE0039 // Use local function - { - Func assertionExecutor = () => assertion(asserted); - assertionExecutor.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); - }; - var (success, errorMessage) = TryGetSubjectModel(out var model); + { + Func assertionExecutor = () => assertion(asserted); + assertionExecutor.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); + }; + var (success, errorMessage) = TryGetSubjectModel(out var model); + + Type? modelType = typeof(TModel); - Type? modelType = typeof(TModel); + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(success) + .FailWith("Expected {context:response} to have a content equivalent to a model of type {0}, but the JSON representation could not be parsed, as the operation failed with the following message: {2}{reason}. {1}", + modelType?.ToString() ?? "unknown type", Subject, errorMessage); + var failuresFromAssertions = CollectFailuresFromAssertion(assertionCaller!, model); + + if (failuresFromAssertions.Any()) + { Execute.Assertion .BecauseOf(because, becauseArgs) - .ForCondition(success) - .FailWith("Expected {context:response} to have a content equivalent to a model of type {0}, but the JSON representation could not be parsed, as the operation failed with the following message: {2}{reason}. {1}", - modelType?.ToString() ?? "unknown type", Subject, errorMessage); - - var failuresFromAssertions = CollectFailuresFromAssertion(assertionCaller!, model); - - if (failuresFromAssertions.Any()) - { - Execute.Assertion - .BecauseOf(because, becauseArgs) - .FailWith( - "Expected {context:response} to satisfy one or more model assertions, but it wasn't{reason}: {0}{1}", - new AssertionsFailures(failuresFromAssertions), Subject); - } - - return new AndConstraint(this); + .FailWith( + "Expected {context:response} to satisfy one or more model assertions, but it wasn't{reason}: {0}{1}", + new AssertionsFailures(failuresFromAssertions), Subject); } - /// - /// Asserts that an HTTP response content can be a model that satisfies an asynchronous assertion starting from an inferred model structure. - /// - /// - /// A proposed model structure that will help to compose the assertions. This is used to defined the type of the asserted model and it doesn't have to contain other values than the default one. - /// - /// - /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. - /// - /// - /// An assertion or a collection of assertions regarding the given model. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] + return new AndConstraint(this); + } + + /// + /// Asserts that an HTTP response content can be a model that satisfies an asynchronous assertion starting from an inferred model structure. + /// + /// + /// A proposed model structure that will help to compose the assertions. This is used to defined the type of the asserted model and it doesn't have to contain other values than the default one. + /// + /// + /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. + /// + /// + /// An assertion or a collection of assertions regarding the given model. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] #pragma warning disable IDE0060 // Remove unused parameter - public AndConstraint Satisfy(TModel givenModelStructure, + public AndConstraint Satisfy(TModel givenModelStructure, #pragma warning restore IDE0060 // Remove unused parameter - Func assertion, - string because = "", params object[] becauseArgs) - { - Guard.ThrowIfArgumentIsNull(assertion, nameof(assertion), "Cannot verify the subject satisfies a `null` assertion."); + Func assertion, + string because = "", params object[] becauseArgs) + { + Guard.ThrowIfArgumentIsNull(assertion, nameof(assertion), "Cannot verify the subject satisfies a `null` assertion."); - Execute.Assertion - .ForCondition(Subject is not null) - .BecauseOf(because, becauseArgs) - .FailWith("Expected a {context:response} to assert{reason}, but found ."); + Execute.Assertion + .ForCondition(Subject is not null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected a {context:response} to assert{reason}, but found ."); - // ReSharper disable once ConvertToLocalFunction + // ReSharper disable once ConvertToLocalFunction #pragma warning disable IDE0039 // Use local function - Action assertionCaller = model => + Action assertionCaller = model => #pragma warning restore IDE0039 // Use local function - { - Func assertionExecutor = () => assertion(model); - assertionExecutor.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); - }; - var (success, errorMessage) = TryGetSubjectModel(out var subjectModel); + { + Func assertionExecutor = () => assertion(model); + assertionExecutor.ExecuteInDefaultSynchronizationContext().GetAwaiter().GetResult(); + }; + var (success, errorMessage) = TryGetSubjectModel(out var subjectModel); - Type? modelType = typeof(TModel); + Type? modelType = typeof(TModel); + Execute.Assertion + .BecauseOf(because, becauseArgs) + .ForCondition(success) + .FailWith("Expected {context:response} to have a content equivalent to a model of type {0}, but the JSON representation could not be parsed, as the operation failed with the following message: {2}{reason}. {1}", + modelType?.ToString() ?? "unknown type", Subject, errorMessage); + + var failuresFromAssertions = CollectFailuresFromAssertion(assertionCaller!, subjectModel); + + if (failuresFromAssertions.Any()) + { Execute.Assertion .BecauseOf(because, becauseArgs) - .ForCondition(success) - .FailWith("Expected {context:response} to have a content equivalent to a model of type {0}, but the JSON representation could not be parsed, as the operation failed with the following message: {2}{reason}. {1}", - modelType?.ToString() ?? "unknown type", Subject, errorMessage); - - var failuresFromAssertions = CollectFailuresFromAssertion(assertionCaller!, subjectModel); - - if (failuresFromAssertions.Any()) - { - Execute.Assertion - .BecauseOf(because, becauseArgs) - .FailWith( - "Expected {context:response} to satisfy one or more model assertions, but it wasn't{reason}: {0}{1}", - new AssertionsFailures(failuresFromAssertions), Subject); - } - - return new AndConstraint(this); + .FailWith( + "Expected {context:response} to satisfy one or more model assertions, but it wasn't{reason}: {0}{1}", + new AssertionsFailures(failuresFromAssertions), Subject); } + + return new AndConstraint(this); } } diff --git a/src/FluentAssertions.Web/SatisfyModelAssertionsExtensions.cs b/src/FluentAssertions.Web/SatisfyModelAssertionsExtensions.cs index 78015d6..5fd132c 100644 --- a/src/FluentAssertions.Web/SatisfyModelAssertionsExtensions.cs +++ b/src/FluentAssertions.Web/SatisfyModelAssertionsExtensions.cs @@ -1,123 +1,117 @@ -using FluentAssertions.Web; -using System; -using System.Diagnostics; -using System.Threading.Tasks; +// ReSharper disable once CheckNamespace +namespace FluentAssertions; -// ReSharper disable once CheckNamespace -namespace FluentAssertions +/// +/// Contains extension methods for custom assertions in unit tests related to Http Response Message. +/// +[DebuggerNonUserCode] +public static class SatisfyModelAssertionsExtensions { /// - /// Contains extension methods for custom assertions in unit tests related to Http Response Message. + /// Asserts that an HTTP response content can be a model that satisfies an assertion. /// - [DebuggerNonUserCode] - public static class SatisfyModelAssertionsExtensions - { - /// - /// Asserts that an HTTP response content can be a model that satisfies an assertion. - /// - /// - /// An assertion regarding the given model. - /// - /// - /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Satisfy( + /// + /// An assertion regarding the given model. + /// + /// + /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Satisfy( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - Action assertion, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Satisfy(assertion, because, becauseArgs); + Action assertion, + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Satisfy(assertion, because, becauseArgs); - /// - /// Asserts that an HTTP response content can be a model that satisfies an assertion starting from an inferred model structure. - /// - /// - /// A proposed model structure that will help to compose the assertions. This is used to defined the type of the asserted model and it doesn't have to contain other values than the default one. - /// - /// - /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. - /// - /// - /// An assertion or a collection of assertions regarding the given model. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Satisfy( + /// + /// Asserts that an HTTP response content can be a model that satisfies an assertion starting from an inferred model structure. + /// + /// + /// A proposed model structure that will help to compose the assertions. This is used to defined the type of the asserted model and it doesn't have to contain other values than the default one. + /// + /// + /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. + /// + /// + /// An assertion or a collection of assertions regarding the given model. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Satisfy( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - TModel givenModelStructure, - Action assertion, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Satisfy(givenModelStructure, assertion, because, becauseArgs); + TModel givenModelStructure, + Action assertion, + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Satisfy(givenModelStructure, assertion, because, becauseArgs); - /// - /// Asserts that an HTTP response content can be a model that satisfies an asynchronous assertion. - /// - /// - /// An assertion regarding the given model. - /// - /// - /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Satisfy( + /// + /// Asserts that an HTTP response content can be a model that satisfies an asynchronous assertion. + /// + /// + /// An assertion regarding the given model. + /// + /// + /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Satisfy( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - Func assertion, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Satisfy(assertion, because, becauseArgs); + Func assertion, + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Satisfy(assertion, because, becauseArgs); - /// - /// Asserts that an HTTP response content can be a model that satisfies an asynchronous assertion starting from an inferred model structure. - /// - /// - /// A proposed model structure that will help to compose the assertions. This is used to defined the type of the asserted model and it doesn't have to contain other values than the default one. - /// - /// - /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. - /// - /// - /// An assertion or a collection of assertions regarding the given model. - /// - /// - /// A formatted phrase as is supported by explaining why the assertion - /// is needed. If the phrase does not start with the word because, it is prepended automatically. - /// - /// - /// Zero or more objects to format using the placeholders in . - /// - [CustomAssertion] - public static AndConstraint Satisfy( + /// + /// Asserts that an HTTP response content can be a model that satisfies an asynchronous assertion starting from an inferred model structure. + /// + /// + /// A proposed model structure that will help to compose the assertions. This is used to defined the type of the asserted model and it doesn't have to contain other values than the default one. + /// + /// + /// The assertion can be a single assertion or a collection of assertions if the assertion action is expressed as a statement lambda. + /// + /// + /// An assertion or a collection of assertions regarding the given model. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + [CustomAssertion] + public static AndConstraint Satisfy( #pragma warning disable 1573 - this Primitives.HttpResponseMessageAssertions parent, + this Primitives.HttpResponseMessageAssertions parent, #pragma warning restore 1573 - TModel givenModelStructure, - Func assertion, - string because = "", params object[] becauseArgs) - => new HttpResponseMessageAssertions(parent.Subject).Satisfy(givenModelStructure, assertion, because, becauseArgs); - } + TModel givenModelStructure, + Func assertion, + string because = "", params object[] becauseArgs) + => new HttpResponseMessageAssertions(parent.Subject).Satisfy(givenModelStructure, assertion, because, becauseArgs); } diff --git a/src/FluentAssertions.Web/SystemTextJsonSerializerConfig.cs b/src/FluentAssertions.Web/SystemTextJsonSerializerConfig.cs index 3077843..d06b192 100644 --- a/src/FluentAssertions.Web/SystemTextJsonSerializerConfig.cs +++ b/src/FluentAssertions.Web/SystemTextJsonSerializerConfig.cs @@ -1,24 +1,21 @@ // ReSharper disable once CheckNamespace -using FluentAssertions.Web.Internal.Serializers; -using System.Text.Json; using System.Text.Json.Serialization; -namespace FluentAssertions +namespace FluentAssertions; + +/// +/// Holder of the global +/// +public static class SystemTextJsonSerializerConfig { /// - /// Holder of the global + /// The options used to deserialize a JSON into a C# object /// - public static class SystemTextJsonSerializerConfig + public static readonly JsonSerializerOptions Options = new() { - /// - /// The options used to deserialize a JSON into a C# object - /// - public static readonly JsonSerializerOptions Options = new() - { - AllowTrailingCommas = true, - PropertyNameCaseInsensitive = true, - Converters = { new JsonStringEnumConverter(), new NullableConverterFactory() }, - NumberHandling = JsonNumberHandling.AllowReadingFromString - }; - } + AllowTrailingCommas = true, + PropertyNameCaseInsensitive = true, + Converters = { new JsonStringEnumConverter(), new NullableConverterFactory() }, + NumberHandling = JsonNumberHandling.AllowReadingFromString + }; } diff --git a/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/FluentAssertions.Web.FluentAssertionsWebConfig.Tests.csproj b/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/FluentAssertions.Web.FluentAssertionsWebConfig.Tests.csproj index e24f291..9dd5b2c 100644 --- a/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/FluentAssertions.Web.FluentAssertionsWebConfig.Tests.csproj +++ b/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/FluentAssertions.Web.FluentAssertionsWebConfig.Tests.csproj @@ -12,4 +12,9 @@ + + + + + diff --git a/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/GlobalUsings.cs b/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/GlobalUsings.cs new file mode 100644 index 0000000..94d5252 --- /dev/null +++ b/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/GlobalUsings.cs @@ -0,0 +1,2 @@ +global using System; +global using Xunit; diff --git a/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/Serializers/NewtonsoftJsonSerializerTests.cs b/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/Serializers/NewtonsoftJsonSerializerTests.cs index 320ba6a..c81a761 100644 --- a/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/Serializers/NewtonsoftJsonSerializerTests.cs +++ b/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/Serializers/NewtonsoftJsonSerializerTests.cs @@ -1,33 +1,29 @@ -using System; -using Xunit; +namespace FluentAssertions.Web.FluentAssertionsWebConfig.Tests.Serializers; -namespace FluentAssertions.Web.FluentAssertionsWebConfig.Tests +[Collection("Serializers Tests")] +public sealed class NewtonsoftJsonSerializerTests : IDisposable { - [Collection("Serializers Tests")] - public sealed class NewtonsoftJsonSerializerTests : IDisposable + private readonly ISerializer _initialSerializer; + public NewtonsoftJsonSerializerTests() { - private readonly ISerializer _initialSerializer; - public NewtonsoftJsonSerializerTests() - { - _initialSerializer = FluentAssertions.FluentAssertionsWebConfig.Serializer; - } - [Fact] - public void Serializer_Can_Be_Set_To_NewtonsoftJsonDeserializer() - { - FluentAssertions.FluentAssertionsWebConfig.Serializer = new NewtonsoftJsonSerializer(); + _initialSerializer = FluentAssertions.FluentAssertionsWebConfig.Serializer; + } + [Fact] + public void Serializer_Can_Be_Set_To_NewtonsoftJsonDeserializer() + { + FluentAssertions.FluentAssertionsWebConfig.Serializer = new NewtonsoftJsonSerializer(); - FluentAssertions.FluentAssertionsWebConfig.Serializer.Should().BeOfType(); - } + FluentAssertions.FluentAssertionsWebConfig.Serializer.Should().BeOfType(); + } - [Fact] - public void Options_Is_Not_Null() - { - NewtonsoftJsonSerializerConfig.Options.Should().NotBeNull(); - } + [Fact] + public void Options_Is_Not_Null() + { + NewtonsoftJsonSerializerConfig.Options.Should().NotBeNull(); + } - public void Dispose() - { - FluentAssertions.FluentAssertionsWebConfig.Serializer = _initialSerializer; - } + public void Dispose() + { + FluentAssertions.FluentAssertionsWebConfig.Serializer = _initialSerializer; } } diff --git a/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/Serializers/SystemTextJsonSerializerTests.cs b/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/Serializers/SystemTextJsonSerializerTests.cs index c8c146b..29a3cba 100644 --- a/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/Serializers/SystemTextJsonSerializerTests.cs +++ b/test/FluentAssertions.Web.FluentAssertionsWebConfig.Tests/Serializers/SystemTextJsonSerializerTests.cs @@ -1,21 +1,19 @@ using FluentAssertions.Web.Internal.Serializers; -using Xunit; -namespace FluentAssertions.Web.FluentAssertionsWebConfig.Tests +namespace FluentAssertions.Web.FluentAssertionsWebConfig.Tests.Serializers; + +[Collection("Serializers Tests")] +public class SystemTextJsonSerializerTests { - [Collection("Serializers Tests")] - public class SystemTextJsonSerializerTests + [Fact] + public void DefaultSerializer_IsOfSystemTextJsonSerializer_Type() { - [Fact] - public void DefaultSerializer_IsOfSystemTextJsonSerializer_Type() - { - FluentAssertions.FluentAssertionsWebConfig.Serializer.Should().BeOfType(); - } + FluentAssertions.FluentAssertionsWebConfig.Serializer.Should().BeOfType(); + } - [Fact] - public void Options_Is_Not_Null() - { - SystemTextJsonSerializerConfig.Options.Should().NotBeNull(); - } + [Fact] + public void Options_Is_Not_Null() + { + SystemTextJsonSerializerConfig.Options.Should().NotBeNull(); } } diff --git a/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests.csproj b/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests.csproj index 81d9d11..0144fb4 100644 --- a/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests.csproj +++ b/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests.csproj @@ -6,4 +6,9 @@ + + + + + diff --git a/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/GlobalUsings.cs b/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/GlobalUsings.cs new file mode 100644 index 0000000..0f00cdc --- /dev/null +++ b/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/GlobalUsings.cs @@ -0,0 +1,6 @@ +global using System; +global using System.Net.Http; +global using System.Text; +global using Xunit; +global using Xunit.Abstractions; +global using Xunit.Sdk; \ No newline at end of file diff --git a/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/NewtonsoftSerializerTests.cs b/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/NewtonsoftSerializerTests.cs index 5f59e97..2cd2c1b 100644 --- a/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/NewtonsoftSerializerTests.cs +++ b/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/NewtonsoftSerializerTests.cs @@ -1,100 +1,134 @@ -using System; -using System.Net.Http; -using System.Text; -using Xunit; -using Xunit.Abstractions; -using Xunit.Sdk; +[assembly: Xunit.TestFramework("FluentAssertions.Web.Serializers.NewtonsoftJson.Tests.ConfigureFluentAssertionsWebFixture", "FluentAssertions.Web.Serializers.NewtonsoftJson.Tests")] -[assembly: Xunit.TestFramework("FluentAssertions.Web.Serializers.NewtonsoftJson.Tests.ConfigureFluentAssertionsWebFixture", "FluentAssertions.Web.Serializers.NewtonsoftJson.Tests")] +namespace FluentAssertions.Web.Serializers.NewtonsoftJson.Tests; -namespace FluentAssertions.Web.Serializers.NewtonsoftJson.Tests +public class ConfigureFluentAssertionsWebFixture : XunitTestFramework { - public class ConfigureFluentAssertionsWebFixture : XunitTestFramework + public ConfigureFluentAssertionsWebFixture(IMessageSink messageSink) : base(messageSink) { - public ConfigureFluentAssertionsWebFixture(IMessageSink messageSink) : base(messageSink) - { - NewtonsoftJsonSerializerConfig.Options.Converters.Add(new YesNoBooleanJsonConverter()); + NewtonsoftJsonSerializerConfig.Options.Converters.Add(new YesNoBooleanJsonConverter()); - FluentAssertionsWebConfig.Serializer = new NewtonsoftJsonSerializer(); - } + FluentAssertionsWebConfig.Serializer = new NewtonsoftJsonSerializer(); } +} - public class NewtonsoftSerializerTests +public class NewtonsoftSerializerTests +{ + [Fact] + public void When_asserting_response_with_content_convertible_using_Newtonsoft_Json_Converters_to_be_as_model_it_should_succeed() { - [Fact] - public void When_asserting_response_with_content_convertible_using_Newtonsoft_Json_Converters_to_be_as_model_it_should_succeed() + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent(@"{ - ""accepted"": ""yes"", - ""required"": ""no"", - }", Encoding.UTF8, "application/json") - }; + Content = new StringContent(/*lang=json*/""" + { + "accepted": "yes", + "required": "no" + } + """, Encoding.UTF8, "application/json") + }; + + subject.Should().BeAs(new + { + accepted = true, + required = false + }); + // Act + Action act = () => subject.Should().BeAs(new { accepted = true, required = false }); - // Act - Action act = () => - subject.Should().BeAs(new + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_with_content_with_differences_using_Newtonsoft_Json_Converters_to_be_as_model_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage + { + Content = new StringContent(/*lang=json,strict*/ """ { - accepted = true, - required = false - }); + "accepted": "yes" + } + """, Encoding.UTF8, "application/json") + }; - // Assert - act.Should().NotThrow(); - } + // Act + Action act = () => + subject.Should().BeAs(new + { + accepted = false + }); - [Fact] - public void When_asserting_response_with_content_with_differences_using_Newtonsoft_Json_Converters_to_be_as_model_should_throw_with_descriptive_message() + // Assert + act.Should().Throw() + .WithMessage("*accepted to be False, but found True*"); + } + + [Fact] + public void When_asserting_response_with_content_with_not_convertible_value_using_Newtonsoft_Json_Converters_to_be_as_model_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent(@"{ - ""accepted"": ""yes"" - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().BeAs(new - { - accepted = false - }); - - // Assert - act.Should().Throw() - .WithMessage("*accepted to be False, but found True*"); - } - - [Fact] - public void When_asserting_response_with_content_with_not_convertible_value_using_Newtonsoft_Json_Converters_to_be_as_model_should_throw_with_descriptive_message() + Content = new StringContent(/*lang=json,strict*/ """ + { + "accepted": "da" + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().BeAs(new + { + accepted = false + }); + + // Assert + act.Should().Throw() + .WithMessage("""*but the JSON representation*NewtonsoftJsonSerializer*Error converting value "da" to type 'System.Boolean'*"""); + } + + [Fact] + public void When_asserting_response_content_with_a_certain_assertion_to_satisfy_assertion_and_model_is_of_named_tuple_type_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent(@"{ - ""accepted"": ""da"" - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().BeAs(new - { - accepted = false - }); - - // Assert - act.Should().Throw() - .WithMessage(@"*but the JSON representation*NewtonsoftJsonSerializer*Error converting value ""da"" to type 'System.Boolean'*"); - } + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().Satisfy<(string Property, object _)>( + model => model.Property.Should().NotBeEmpty()); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_content_with_a_certain_assertion_to_satisfy_assertion_and_model_is_of_non_named_tuple_type_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage + { + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().Satisfy>( + model => model.Item1.Should().NotBeEmpty()); + + // Assert + act.Should().NotThrow(); } } diff --git a/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/YesNoBooleanJsonConverter.cs b/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/YesNoBooleanJsonConverter.cs index 584fc49..fcd76d2 100644 --- a/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/YesNoBooleanJsonConverter.cs +++ b/test/FluentAssertions.Web.Serializers.NewtonsoftJson.Tests/YesNoBooleanJsonConverter.cs @@ -1,32 +1,30 @@ using Newtonsoft.Json; -using System; -namespace FluentAssertions.Web.Serializers.NewtonsoftJson.Tests +namespace FluentAssertions.Web.Serializers.NewtonsoftJson.Tests; + +public class YesNoBooleanJsonConverter : JsonConverter { - public class YesNoBooleanJsonConverter : JsonConverter + public override bool CanConvert(Type objectType) => objectType == typeof(bool); + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - public override bool CanConvert(Type objectType) => objectType == typeof(bool); + var value = reader.Value.ToString(); - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + if (value != null && value.Equals("yes", StringComparison.OrdinalIgnoreCase)) { - var value = reader.Value.ToString(); - - if (value != null && value.Equals("yes", StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - if (value != null && value.Equals("no", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - return new JsonSerializer().Deserialize(reader, objectType); + return true; } - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + if (value != null && value.Equals("no", StringComparison.OrdinalIgnoreCase)) { - throw new NotImplementedException(); + return false; } + + return new JsonSerializer().Deserialize(reader, objectType); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); } } diff --git a/test/FluentAssertions.Web.Tests/BadRequestAssertionsSpecs.cs b/test/FluentAssertions.Web.Tests/BadRequestAssertionsSpecs.cs index e0181b6..b334000 100644 --- a/test/FluentAssertions.Web.Tests/BadRequestAssertionsSpecs.cs +++ b/test/FluentAssertions.Web.Tests/BadRequestAssertionsSpecs.cs @@ -1,799 +1,871 @@ -using System; -using System.Net; -using System.Net.Http; -using System.Text; -using Xunit; -using Xunit.Sdk; - -namespace FluentAssertions.Web.Tests +namespace FluentAssertions.Web.Tests; + +public class BadRequestAssertionsSpecs { - public class BadRequestAssertionsSpecs + [Fact] + public void When_asserting_bad_request_response_with_content_to_be_BadRequest_it_should_succeed() { - [Fact] - public void When_asserting_bad_request_response_with_content_to_be_BadRequest_it_should_succeed() + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] - } - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().Be400BadRequest(); - - // Assert - act.Should().NotThrow(); - } + Content = new StringContent(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ + "The Author field is required." + ] + } + } + """, Encoding.UTF8, "application/json") + }; - #region HaveError - [Theory] - [InlineData(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] - } - }")] - - [InlineData(@"{ - ""Author"": [ - ""The Author field is required."" - ] - }")] - public void When_asserting_bad_request_response_with_standard_dot_net_json_content_to_be_BadRequest_and_have_error_field_and_error_message_it_should_succeed(string responseContent) - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(responseContent, Encoding.UTF8, "application/json") - }; + // Act + Action act = () => + subject.Should().Be400BadRequest(); - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.HaveError("Author", "The Author field is required."); + // Assert + act.Should().NotThrow(); + } - // Assert - act.Should().NotThrow(); + #region HaveError + [Theory] + [InlineData(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ + "The Author field is required." + ] + } + } + """)] + [InlineData(/*lang=json,strict*/ """ + { + "Author": [ + "The Author field is required." + ] } + """)] + public void When_asserting_bad_request_response_with_standard_dot_net_json_content_to_be_BadRequest_and_have_error_field_and_error_message_it_should_succeed(string responseContent) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(responseContent, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.HaveError("Author", "The Author field is required."); - [Fact] - public void When_asserting_bad_request_response_with_error_field_having_a_reserved_name_from_standard_dot_net_json_to_be_BadRequest_and_HaveError_should_succeed() + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_bad_request_response_with_error_field_having_a_reserved_name_from_standard_dot_net_json_to_be_BadRequest_and_HaveError_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""type"": ""https://tools.ietf.org/html/rfc7231#section-6.5.1"", - ""title"": ""One or more validation errors occurred."", - ""status"": 400, - ""traceId"": ""00-deb7480af23a884e942f7b85cac6bd35-c1abe72874d40c4a-00"", - ""errors"": { - ""Status"": [ - ""Cannot add at Revoked Status."" + Content = new StringContent(/*lang=json,strict*/ """ + { + "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-deb7480af23a884e942f7b85cac6bd35-c1abe72874d40c4a-00", + "errors": { + "Status": [ + "Cannot add at Revoked Status." ] } - }", Encoding.UTF8, "application/json") - }; + } + """, Encoding.UTF8, "application/json") + }; - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.HaveError("Status", "Cannot add at Revoked Status."); + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.HaveError("Status", "Cannot add at Revoked Status."); - // Assert - act.Should().NotThrow(); - } + // Assert + act.Should().NotThrow(); + } - [Fact] - public void When_asserting_bad_request_response_with_error_field_having_a_reserved_name_from_standard_dot_net_json_and_also_error_message_to_be_BadRequest_and_HaveError_should_succeed() + [Fact] + public void When_asserting_bad_request_response_with_error_field_having_a_reserved_name_from_standard_dot_net_json_and_also_error_message_to_be_BadRequest_and_HaveError_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""type"": ""https://tools.ietf.org/html/rfc7231#section-6.5.1"", - ""title"": ""One or more validation errors occurred."", - ""status"": 400, - ""traceId"": ""00-deb7480af23a884e942f7b85cac6bd35-c1abe72874d40c4a-00"", - ""errors"": { - ""Status"": [ - ""2"" + Content = new StringContent(/*lang=json,strict*/ """ + { + "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-deb7480af23a884e942f7b85cac6bd35-c1abe72874d40c4a-00", + "errors": { + "Status": [ + "2" ] } - }", Encoding.UTF8, "application/json") - }; + } + """, Encoding.UTF8, "application/json") + }; - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.HaveError("status", "2"); + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.HaveError("status", "2"); - // Assert - act.Should().NotThrow(); - } + // Assert + act.Should().NotThrow(); + } - [Fact] - public void When_asserting_bad_request_response_with_error_field_having_a_reserved_name_from_standard_dot_net_json_which_does_not_exist_in_the_errors_property_to_be_BadRequest_and_HaveError_should_fail() + [Fact] + public void When_asserting_bad_request_response_with_error_field_having_a_reserved_name_from_standard_dot_net_json_which_does_not_exist_in_the_errors_property_to_be_BadRequest_and_HaveError_should_fail() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""type"": ""https://tools.ietf.org/html/rfc7231#section-6.5.1"", - ""title"": ""One or more validation errors occurred."", - ""status"": 400, - ""traceId"": ""00-deb7480af23a884e942f7b85cac6bd35-c1abe72874d40c4a-00"", - ""errors"": { - } - }", Encoding.UTF8, "application/json") - }; + Content = new StringContent(/*lang=json,strict*/ """ + { + "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-deb7480af23a884e942f7b85cac6bd35-c1abe72874d40c4a-00", + "errors": {} + } + """, Encoding.UTF8, "application/json") + }; - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.HaveError("status", "400"); + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.HaveError("status", "400"); - // Assert - act.Should().Throw() - .WithMessage("*to contain*status*field, but was not found*"); + // Assert + act.Should().Throw() + .WithMessage("*to contain*status*field, but was not found*"); + } + + [Theory] + [InlineData(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ + "The Author field is required." + ] + } } + """)] + [InlineData(/*lang=json,strict*/ """ + { + "Author": [ + "The Author field is required." + ] + } + """)] + public void When_asserting_bad_request_response_without_a_containing_error_to_be_BadRequest_and_HaveError_it_should_throw_with_descriptive_message(string responseContent) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(responseContent, Encoding.UTF8, "application/json") + }; - [Theory] - [InlineData(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] - } - }")] - [InlineData(@"{ - ""Author"": [ - ""The Author field is required."" - ] - }")] - public void When_asserting_bad_request_response_without_a_containing_error_to_be_BadRequest_and_HaveError_it_should_throw_with_descriptive_message(string responseContent) - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(responseContent, Encoding.UTF8, "application/json") - }; + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.HaveError("Comments", "*required*"); + + // Assert + act.Should().Throw() + .WithMessage("*to contain*Comments*field, but was not found*"); + } - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.HaveError("Comments", "*required*"); + [Theory] + [InlineData(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ + "The Author field is required." + ] + } + } + """)] - // Assert - act.Should().Throw() - .WithMessage("*to contain*Comments*field, but was not found*"); + [InlineData(/*lang=json,strict*/ """ + { + "Author": [ + "The Author field is required." + ] } + """)] + public void When_asserting_bad_request_response_be_BadRequest_and_match_error_message_by_pattern_it_should_succeed(string responseContent) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(responseContent, Encoding.UTF8, "application/json") + }; - [Theory] - [InlineData(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] - } - }")] - - [InlineData(@"{ - ""Author"": [ - ""The Author field is required."" - ] - }")] - public void When_asserting_bad_request_response_be_BadRequest_and_match_error_message_by_pattern_it_should_succeed(string responseContent) - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(responseContent, Encoding.UTF8, "application/json") - }; + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.HaveError("Author", "*required*"); - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.HaveError("Author", "*required*"); + // Assert + act.Should().NotThrow(); + } - // Assert - act.Should().NotThrow(); + [Theory] + [InlineData(/*lang=json*/""" + { + "id": [ "Error message 1.", "Error message 2." ] + } + """)] + [InlineData(/*lang=json*/""" + { + "errors": { + "id": [ "Error message 1.", "Error message 2." ] + } } + """)] + public void When_asserting_bad_request_response_with_multiple_error_messages_to_be_BadRequest_and_have_error_field_and_error_message_and_also_having_another_error_message_it_should_succeed(string responseContent) + { + // Arrange + using var response = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(responseContent, Encoding.UTF8, "application/json") + }; - [Theory] - [InlineData(@"{ - ""id"": [""Error message 1."", ""Error message 2.""] - }")] - [InlineData(@"{ - ""errors"" : - { - ""id"": [""Error message 1."", ""Error message 2.""] - } - }")] - public void When_asserting_bad_request_response_with_multiple_error_messages_to_be_BadRequest_and_have_error_field_and_error_message_and_also_having_another_error_message_it_should_succeed(string responseContent) - { - // Arrange - using var response = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(responseContent, Encoding.UTF8, "application/json") - }; + // Act + Action act = () => + response.Should().Be400BadRequest() + .And.HaveError("id", "Error message 1.") + .And.HaveError("id", "Error message 2."); - // Act - Action act = () => - response.Should().Be400BadRequest() - .And.HaveError("id", "Error message 1.") - .And.HaveError("id", "Error message 2."); + // Assert + act.Should().NotThrow(); + } - // Assert - act.Should().NotThrow(); + [Theory] + [InlineData(/*lang=json,strict*/ """ + { + "Author": "The Author field is required." } + """)] - [Theory] - [InlineData(@"{ - ""Author"": ""The Author field is required."" - }")] + [InlineData(/*lang=json,strict*/ """ + { + "errors": { + "Author": "The Author field is required." + } + } + """)] + public void When_asserting_bad_request_response_with_the_errors_messages_as_a_single_field_to_be_BadRequest_and_have_error_field_and_error_message_it_should_succeed(string responseContent) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(responseContent, Encoding.UTF8, "application/json") + }; - [InlineData(@"{ - ""errors"" : { - ""Author"": ""The Author field is required."" - } - }")] - public void When_asserting_bad_request_response_with_the_errors_messages_as_a_single_field_to_be_BadRequest_and_have_error_field_and_error_message_it_should_succeed(string responseContent) + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.HaveError("Author", "The Author field is required."); + + // Assert + act.Should().NotThrow(); + } + + [Theory] + [InlineData(/*lang=json,strict*/ """ + [ + { + "code": "previous_steps_validation_error", + "description": null + } + ] + """)] + + [InlineData(/*lang=json,strict*/ """ { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) + "errors": [ { - Content = new StringContent(responseContent, Encoding.UTF8, "application/json") - }; + "code": "previous_steps_validation_error", + "description": null + } + ] + } + """)] + public void When_asserting_bad_request_response_with_a_response_content_having_an_array_to_BeBadRequest_and_have_error_field_and_error_message_it_should_throw_with_descriptive_message(string responseContent) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(responseContent, Encoding.UTF8, "application/json") + }; - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.HaveError("Author", "The Author field is required."); + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.HaveError("error", "*required*"); - // Assert - act.Should().NotThrow(); - } + // Assert + act.Should().Throw() + .WithMessage("*error*"); + } - [Theory] - [InlineData(@"[ - { - ""code"": ""previous_steps_validation_error"", - ""description"": null - } - ]")] - - [InlineData(@"{ ""errors"" : [ - { - ""code"": ""previous_steps_validation_error"", - ""description"": null - } - ] }")] - public void When_asserting_bad_request_response_with_a_response_content_having_an_array_to_BeBadRequest_and_have_error_field_and_error_message_it_should_throw_with_descriptive_message(string responseContent) - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(responseContent, Encoding.UTF8, "application/json") - }; + [Theory] + [InlineData(null)] + [InlineData("")] + public void When_asserting_bad_request_response_to_be_BadRequest_And_HaveError_against_null_or_empty_string_value_for_the_error_field_it_should_throw_with_descriptive_message(string expectedField) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ + "The Author field is required." + ] + } + } + """, Encoding.UTF8, "application/json") + }; - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.HaveError("error", "*required*"); + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.HaveError(expectedField, "*required*"); - // Assert - act.Should().Throw() - .WithMessage("*error*"); - } + // Assert + act.Should().Throw() + .WithMessage("* or empty field name*"); + } - [Theory] - [InlineData(null)] - [InlineData("")] - public void When_asserting_bad_request_response_to_be_BadRequest_And_HaveError_against_null_or_empty_string_value_for_the_error_field_it_should_throw_with_descriptive_message(string expectedField) + [Theory] + [InlineData(null)] + [InlineData("")] + public void When_asserting_bad_request_response_to_be_BadRequest_And_HaveError_against_null_or_empty_string_value_for_the_error_message_it_should_throw_with_descriptive_message(string expectedWildcardErrorMessage) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] - } - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.HaveError(expectedField, "*required*"); - - // Assert - act.Should().Throw() - .WithMessage("* or empty field name*"); - } + Content = new StringContent(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ + "The Author field is required." + ] + } + } + """, Encoding.UTF8, "application/json") + }; - [Theory] - [InlineData(null)] - [InlineData("")] - public void When_asserting_bad_request_response_to_be_BadRequest_And_HaveError_against_null_or_empty_string_value_for_the_error_message_it_should_throw_with_descriptive_message(string expectedWildcardErrorMessage) + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.HaveError("Author", expectedWildcardErrorMessage); + + // Assert + act.Should().Throw() + .WithMessage("* or empty wildcard error message*"); + } + #endregion + + #region HaveErrorMessage + [Fact] + public void When_asserting_bad_request_response_with_only_the_error_description_and_no_name_for_the_error_field_to_be_BadRequest_with_specific_message_it_should_succeed() + { + // Arrange + using var response = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] - } - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.HaveError("Author", expectedWildcardErrorMessage); - - // Assert - act.Should().Throw() - .WithMessage("* or empty wildcard error message*"); - } - #endregion + Content = new StringContent(/*lang=json*/""" + { + "errors": { + "": [ + "A non-empty request body is required." + ] + } + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + response.Should().Be400BadRequest() + .And.HaveErrorMessage("A non-empty request body is required."); + + // Assert + act.Should().NotThrow(); + } - #region HaveErrorMessage - [Fact] - public void When_asserting_bad_request_response_with_only_the_error_description_and_no_name_for_the_error_field_to_be_BadRequest_with_specific_message_it_should_succeed() + [Fact] + public void When_asserting_bad_request_response_with_the_errors_messages_as_a_single_field_to_be_BadRequest_and_HaveErrorMessage_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var response = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""errors"":{ - """":[ - ""A non-empty request body is required."" - ] - } - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - response.Should().Be400BadRequest() - .And.HaveErrorMessage("A non-empty request body is required."); - - // Assert - act.Should().NotThrow(); - } + Content = new StringContent(/*lang=json,strict*/ """ + { + "Author": "The Author field is required." + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.HaveErrorMessage("The Author field is required."); - [Fact] - public void When_asserting_bad_request_response_with_the_errors_messages_as_a_single_field_to_be_BadRequest_and_HaveErrorMessage_it_should_succeed() + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_bad_request_response_with_a_list_errors_messages_to_be_BadRequest_and_HaveErrorMessage_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""Author"": ""The Author field is required."" - }", Encoding.UTF8, "application/json") - }; + Content = new StringContent(/*lang=json,strict*/ """ + { + "Author": [ "The Author field is required." ] + } + """, Encoding.UTF8, "application/json") + }; - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.HaveErrorMessage("The Author field is required."); + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.HaveErrorMessage("The Author field is required."); - // Assert - act.Should().NotThrow(); - } + // Assert + act.Should().NotThrow(); + } - [Fact] - public void When_asserting_bad_request_response_with_a_list_errors_messages_to_be_BadRequest_and_HaveErrorMessage_it_should_succeed() + [Fact] + public void When_asserting_bad_request_response_with_content_generated_by_AspNetCore22_to_be_BadRequest_with_specific_message_it_should_succeed() + { + // Arrange + using var response = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""Author"": [ ""The Author field is required."" ] - }", Encoding.UTF8, "application/json") - }; + Content = new StringContent(/*lang=json*/""" + { + "": [ + "A non-empty request body is required." + ] + } + """, Encoding.UTF8, "application/json") + }; - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.HaveErrorMessage("The Author field is required."); + // Act + Action act = () => + response.Should().Be400BadRequest() + .And.HaveErrorMessage("A non-empty request body is required."); - // Assert - act.Should().NotThrow(); - } + // Assert + act.Should().NotThrow(); + } - [Fact] - public void When_asserting_bad_request_response_with_content_generated_by_AspNetCore22_to_be_BadRequest_with_specific_message_it_should_succeed() + [Fact] + public void When_asserting_bad_request_response_with_only_the_error_description_and_a_name_for_the_error_field_to_be_BadRequest_with_specific_message_it_should_succeed() + { + // Arrange + using var response = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var response = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - """":[ - ""A non-empty request body is required."" - ] - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - response.Should().Be400BadRequest() - .And.HaveErrorMessage("A non-empty request body is required."); - - // Assert - act.Should().NotThrow(); - } + Content = new StringContent(/*lang=json,strict*/ """ + { + "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "|2e128730-44b8587a25408f28.", + "errors": { + "$": [ + "The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0." + ] + } + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + response.Should().Be400BadRequest() + .And.HaveErrorMessage("The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0."); + + // Assert + act.Should().NotThrow(); + } - [Fact] - public void When_asserting_bad_request_response_with_only_the_error_description_and_a_name_for_the_error_field_to_be_BadRequest_with_specific_message_it_should_succeed() + [Fact] + public void When_asserting_bad_request_response_with_error_field_having_a_reserved_name_from_standard_dot_net_json_which_does_not_exist_in_the_errors_property_to_be_BadRequest_and_HaveErrorMessage_should_fail() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var response = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""type"": ""https://tools.ietf.org/html/rfc7231#section-6.5.1"", - ""title"": ""One or more validation errors occurred."", - ""status"": 400, - ""traceId"": ""|2e128730-44b8587a25408f28."", - ""errors"": { - ""$"": [ - ""The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0."" - ] - } - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - response.Should().Be400BadRequest() - .And.HaveErrorMessage("The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0."); - - // Assert - act.Should().NotThrow(); - } + Content = new StringContent(/*lang=json,strict*/ """ + { + "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-deb7480af23a884e942f7b85cac6bd35-c1abe72874d40c4a-00", + "errors": { + } + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.HaveErrorMessage("One or more validation errors occurred."); - [Fact] - public void When_asserting_bad_request_response_with_error_field_having_a_reserved_name_from_standard_dot_net_json_which_does_not_exist_in_the_errors_property_to_be_BadRequest_and_HaveErrorMessage_should_fail() + // Assert + act.Should().Throw() + .WithMessage("""Expected * to contain the error message "One or more validation errors occurred.", but no such message was found in the actual error messages list*"""); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void When_asserting_bad_request_response_to_be_BadRequest_And_HaveErrorMessage_against_null_or_empty_string_value_for_the_error_message_it_should_throw_with_descriptive_message(string expectedWildcardErrorMessage) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""type"": ""https://tools.ietf.org/html/rfc7231#section-6.5.1"", - ""title"": ""One or more validation errors occurred."", - ""status"": 400, - ""traceId"": ""00-deb7480af23a884e942f7b85cac6bd35-c1abe72874d40c4a-00"", - ""errors"": { + Content = new StringContent(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ + "The Author field is required." + ] } - }", Encoding.UTF8, "application/json") - }; + } + """, Encoding.UTF8, "application/json") + }; - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.HaveErrorMessage("One or more validation errors occurred."); + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.HaveErrorMessage(expectedWildcardErrorMessage); - // Assert - act.Should().Throw() - .WithMessage("Expected * to contain the error message \"One or more validation errors occurred.\", but no such message was found in the actual error messages list*"); - } + // Assert + act.Should().Throw() + .WithMessage("* or empty wildcard error message*"); + } + #endregion - [Theory] - [InlineData(null)] - [InlineData("")] - public void When_asserting_bad_request_response_to_be_BadRequest_And_HaveErrorMessage_against_null_or_empty_string_value_for_the_error_message_it_should_throw_with_descriptive_message(string expectedWildcardErrorMessage) + #region NotHaveError + [Theory] + [InlineData(/*lang=json,strict*/ """ { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] - } - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.HaveErrorMessage(expectedWildcardErrorMessage); - - // Assert - act.Should().Throw() - .WithMessage("* or empty wildcard error message*"); + "errors": { + "Author": [ + "The Author field is required." + ] + } } - #endregion - - #region NotHaveError - [Theory] - [InlineData(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] - } - }")] - [InlineData(@"{ - ""Author"": [ - ""The Author field is required."" - ] - }")] - public void When_asserting_bad_request_response_with_standard_to_be_BadRequest_and_NotHaveError_it_should_succeed(string responseContent) - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(responseContent, Encoding.UTF8, "application/json") - }; + """)] + [InlineData(/*lang=json,strict*/ """ + { + "Author": [ + "The Author field is required." + ] + } + """)] + public void When_asserting_bad_request_response_with_standard_to_be_BadRequest_and_NotHaveError_it_should_succeed(string responseContent) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(responseContent, Encoding.UTF8, "application/json") + }; - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.NotHaveError("Comments"); + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.NotHaveError("Comments"); - // Assert - act.Should().NotThrow(); - } + // Assert + act.Should().NotThrow(); + } - [Fact] - public void When_asserting_bad_request_response_with_error_field_having_a_reserved_name_from_standard_dot_net_json_which_does_not_exist_in_the_errors_property_to_be_BadRequest_and_NotHaveError_should_succeed() + [Fact] + public void When_asserting_bad_request_response_with_error_field_having_a_reserved_name_from_standard_dot_net_json_which_does_not_exist_in_the_errors_property_to_be_BadRequest_and_NotHaveError_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""type"": ""https://tools.ietf.org/html/rfc7231#section-6.5.1"", - ""title"": ""One or more validation errors occurred."", - ""status"": 400, - ""traceId"": ""00-deb7480af23a884e942f7b85cac6bd35-c1abe72874d40c4a-00"", - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] + Content = new StringContent(/*lang=json,strict*/ """ + { + "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "traceId": "00-deb7480af23a884e942f7b85cac6bd35-c1abe72874d40c4a-00", + "errors": { + "Author": [ + "The Author field is required." + ] } - }", Encoding.UTF8, "application/json") - }; + } + """, Encoding.UTF8, "application/json") + }; - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.NotHaveError("status"); + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.NotHaveError("status"); - // Assert - act.Should().NotThrow(); + // Assert + act.Should().NotThrow(); + } + + [Theory] + [InlineData(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ + "The Author field is required." + ] + } } + """)] - [Theory] - [InlineData(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] - } - }")] - - [InlineData(@"{ - ""Author"": [ - ""The Author field is required."" - ] - }")] - public void When_asserting_bad_request_response_with_a_containing_error_to_be_BadRequest_and_NotHaveError_it_should_throw_with_descriptive_message(string responseContent) - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(responseContent, Encoding.UTF8, "application/json") - }; + [InlineData(/*lang=json,strict*/ """ + { + "Author": [ + "The Author field is required." + ] + } + """)] + public void When_asserting_bad_request_response_with_a_containing_error_to_be_BadRequest_and_NotHaveError_it_should_throw_with_descriptive_message(string responseContent) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(responseContent, Encoding.UTF8, "application/json") + }; - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.NotHaveError("Author"); + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.NotHaveError("Author"); - // Assert - act.Should().Throw() - .WithMessage("*to not contain*Author*field, but was found*"); - } + // Assert + act.Should().Throw() + .WithMessage("*to not contain*Author*field, but was found*"); + } - [Theory] - [InlineData(null)] - [InlineData("")] - public void When_asserting_bad_request_response_to_be_BadRequest_And_NotHaveError_against_null_or_empty_string_value_for_the_expected_error_field_it_should_throw_with_descriptive_message(string expectedErrorField) + [Theory] + [InlineData(null)] + [InlineData("")] + public void When_asserting_bad_request_response_to_be_BadRequest_And_NotHaveError_against_null_or_empty_string_value_for_the_expected_error_field_it_should_throw_with_descriptive_message(string expectedErrorField) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] - } - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.NotHaveError(expectedErrorField); - - // Assert - act.Should().Throw() - .WithMessage("*not having* or empty field name*"); - } - #endregion - - #region OnlyHaveError - [Theory] - [InlineData(@"{ - ""errors"": { - ""Author"": [ ""The Author field is required."" ] - } - }")] - [InlineData(@"{ - ""Author"": [ ""The Author field is required."" ] - }")] - public void When_asserting_bad_request_response_with_a_single_error_field_to_be_BadRequest_and_OnlyHaveError_for_that_field_it_should_succeed(string responseContent) - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(responseContent, Encoding.UTF8, "application/json") - }; + Content = new StringContent(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ + "The Author field is required." + ] + } + } + """, Encoding.UTF8, "application/json") + }; - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.OnlyHaveError("Author", "*required*"); + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.NotHaveError(expectedErrorField); - // Assert - act.Should().NotThrow(); + // Assert + act.Should().Throw() + .WithMessage("*not having* or empty field name*"); + } + #endregion + + #region OnlyHaveError + [Theory] + [InlineData(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ "The Author field is required." ] + } } + """)] + [InlineData(/*lang=json,strict*/ """ + { + "Author": [ "The Author field is required." ] + } + """)] + public void When_asserting_bad_request_response_with_a_single_error_field_to_be_BadRequest_and_OnlyHaveError_for_that_field_it_should_succeed(string responseContent) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(responseContent, Encoding.UTF8, "application/json") + }; - [Theory] - [InlineData(@"{ - ""errors"": { - ""Author"": [ ""The Author field is required."" ], - ""Comments"": [ ""The Comments field is required."" ] - } - }")] - [InlineData(@"{ - ""Author"": [ ""The Author field is required."" ], - ""Comments"": [ ""The Comments field is required."" ] - }")] - public void When_asserting_bad_request_response_with_multiple_error_fields_where_one_of_them_is_the_actual_error_from_standard_dot_net_json_to_be_BadRequest_and_OnlyHaveError_fo_it_should_throw_with_descriptive_message(string responseContent) - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(responseContent, Encoding.UTF8, "application/json") - }; + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.OnlyHaveError("Author", "*required*"); - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.OnlyHaveError("Author", "*required*"); + // Assert + act.Should().NotThrow(); + } - // Assert - act.Should().Throw() - .WithMessage("*author*but more than this one was found.*"); + [Theory] + [InlineData(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ "The Author field is required." ], + "Comments": [ "The Comments field is required." ] + } } + """)] + [InlineData(/*lang=json,strict*/ """ + { + "Author": [ "The Author field is required." ], + "Comments": [ "The Comments field is required." ] + } + """)] + public void When_asserting_bad_request_response_with_multiple_error_fields_where_one_of_them_is_the_actual_error_from_standard_dot_net_json_to_be_BadRequest_and_OnlyHaveError_fo_it_should_throw_with_descriptive_message(string responseContent) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(responseContent, Encoding.UTF8, "application/json") + }; - [Theory] - [InlineData(@"{ - ""errors"": { - ""Author"": [ - ""Message 1."", - ""Message 2."" - ] - } - }")] - [InlineData(@"{ - ""Author"": [ - ""Message 1."", - ""Message 2."" - ] - }")] - public void When_asserting_bad_request_response_with_multiple_error_messages_where_one_of_them_is_the_actual_error_from_standard_dot_net_json_to_be_BadRequest_and_OnlyHaveError_fo_it_should_throw_with_descriptive_message(string responseContent) - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(responseContent, Encoding.UTF8, "application/json") - }; + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.OnlyHaveError("Author", "*required*"); - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.OnlyHaveError("Author", "*Message 1*"); + // Assert + act.Should().Throw() + .WithMessage("*author*but more than this one was found.*"); + } - // Assert - act.Should().Throw() - .WithMessage("*author* field and message *Message 1*but more than this one was found.*"); + [Theory] + [InlineData(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ + "Message 1.", + "Message 2." + ] + } } + """)] + [InlineData(/*lang=json,strict*/ """ + { + "Author": [ + "Message 1.", + "Message 2." + ] + } + """)] + public void When_asserting_bad_request_response_with_multiple_error_messages_where_one_of_them_is_the_actual_error_from_standard_dot_net_json_to_be_BadRequest_and_OnlyHaveError_fo_it_should_throw_with_descriptive_message(string responseContent) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(responseContent, Encoding.UTF8, "application/json") + }; - [Theory] - [InlineData(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ], - ""Comments"": [ - ""The Comments field is required."" - ] - } - }")] - [InlineData(@"{ - ""Author"": [ - ""The Author field is required."" - ], - ""Comments"": [ - ""The Comments field is required."" - ] - }")] - public void When_asserting_bad_request_response_with_multiple_error_fields_where_none_one_of_them_is_the_actual_error_to_be_BadRequest_and_OnlyHaveError_it_should_throw_with_descriptive_message(string responseContent) - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(responseContent, Encoding.UTF8, "application/json") - }; + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.OnlyHaveError("Author", "*Message 1*"); - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.OnlyHaveError("Date", "*required*"); + // Assert + act.Should().Throw() + .WithMessage("*author* field and message *Message 1*but more than this one was found.*"); + } - // Assert - act.Should().Throw() - .WithMessage("*to contain*Date*field, but was not found*"); + [Theory] + [InlineData(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ + "The Author field is required." + ], + "Comments": [ + "The Comments field is required." + ] + } } - - [Theory] - [InlineData(null)] - [InlineData("")] - public void When_asserting_bad_request_response_to_be_BadRequest_And_OnlyHaveError_against_null_or_empty_string_value_for_the_error_field_it_should_throw_with_descriptive_message(string expectedField) + """)] + [InlineData(/*lang=json,strict*/ """ { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] - } - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.OnlyHaveError(expectedField, "*required*"); - - // Assert - act.Should().Throw() - .WithMessage("* or empty field name*"); + "Author": [ + "The Author field is required." + ], + "Comments": [ + "The Comments field is required." + ] } + """)] + public void When_asserting_bad_request_response_with_multiple_error_fields_where_none_one_of_them_is_the_actual_error_to_be_BadRequest_and_OnlyHaveError_it_should_throw_with_descriptive_message(string responseContent) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(responseContent, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.OnlyHaveError("Date", "*required*"); - [Theory] - [InlineData(null)] - [InlineData("")] - public void When_asserting_bad_request_response_to_be_BadRequest_And_OnlyHaveError_against_null_or_empty_string_value_for_the_error_message_it_should_throw_with_descriptive_message(string expectedWildcardErrorMessage) + // Assert + act.Should().Throw() + .WithMessage("*to contain*Date*field, but was not found*"); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void When_asserting_bad_request_response_to_be_BadRequest_And_OnlyHaveError_against_null_or_empty_string_value_for_the_error_field_it_should_throw_with_descriptive_message(string expectedField) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) - { - Content = new StringContent(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] - } - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => subject.Should().Be400BadRequest() - .And.OnlyHaveError("Author", expectedWildcardErrorMessage); - - // Assert - act.Should().Throw() - .WithMessage("* or empty wildcard error message*"); - } - #endregion + Content = new StringContent(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ + "The Author field is required." + ] + } + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.OnlyHaveError(expectedField, "*required*"); + + // Assert + act.Should().Throw() + .WithMessage("* or empty field name*"); } -} + [Theory] + [InlineData(null)] + [InlineData("")] + public void When_asserting_bad_request_response_to_be_BadRequest_And_OnlyHaveError_against_null_or_empty_string_value_for_the_error_message_it_should_throw_with_descriptive_message(string expectedWildcardErrorMessage) + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ + "The Author field is required." + ] + } + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => subject.Should().Be400BadRequest() + .And.OnlyHaveError("Author", expectedWildcardErrorMessage); + + // Assert + act.Should().Throw() + .WithMessage("* or empty wildcard error message*"); + } + #endregion +} diff --git a/test/FluentAssertions.Web.Tests/DeserializationExceptionTests.cs b/test/FluentAssertions.Web.Tests/DeserializationExceptionTests.cs index 3b8415f..5fcdc71 100644 --- a/test/FluentAssertions.Web.Tests/DeserializationExceptionTests.cs +++ b/test/FluentAssertions.Web.Tests/DeserializationExceptionTests.cs @@ -1,48 +1,44 @@ -using System; -using Xunit; +namespace FluentAssertions.Web.Tests; -namespace FluentAssertions.Web.Tests +public class DeserializationExceptionTests { - public class DeserializationExceptionTests + [Fact] + public void Ctor_DoesNotThrow() { - [Fact] - public void Ctor_DoesNotThrow() - { - // Act - Action act = () => new DeserializationException(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void Ctor_WhenMessage_DoesNotThrow() - { - // Act - Action act = () => new DeserializationException("Exception message"); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void Ctor_WhenInnerException_DoesNotThrow() - { - // Act - Action act = () => new DeserializationException("Exception message", new Exception()); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void Exception_ShouldBeBinarySerializable() - { - // Arrange - var sut = new DeserializationException("Exception message", new Exception()); - - // Assert - sut.Should().BeBinarySerializable(); - } + // Act + Action act = () => new DeserializationException(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void Ctor_WhenMessage_DoesNotThrow() + { + // Act + Action act = () => new DeserializationException("Exception message"); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void Ctor_WhenInnerException_DoesNotThrow() + { + // Act + Action act = () => new DeserializationException("Exception message", new Exception()); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void Exception_ShouldBeBinarySerializable() + { + // Arrange + var sut = new DeserializationException("Exception message", new Exception()); + + // Assert + sut.Should().BeBinarySerializable(); } } diff --git a/test/FluentAssertions.Web.Tests/FluentAssertions.Web.Tests.csproj b/test/FluentAssertions.Web.Tests/FluentAssertions.Web.Tests.csproj index b364c66..6a32c83 100644 --- a/test/FluentAssertions.Web.Tests/FluentAssertions.Web.Tests.csproj +++ b/test/FluentAssertions.Web.Tests/FluentAssertions.Web.Tests.csproj @@ -6,4 +6,10 @@ + + + + + + diff --git a/test/FluentAssertions.Web.Tests/GlobalUsings.cs b/test/FluentAssertions.Web.Tests/GlobalUsings.cs new file mode 100644 index 0000000..f38e0f4 --- /dev/null +++ b/test/FluentAssertions.Web.Tests/GlobalUsings.cs @@ -0,0 +1,16 @@ +global using FluentAssertions.Equivalency; +global using FluentAssertions.Execution; +global using FluentAssertions.Web.Internal; +global using FluentAssertions.Web.Internal.Serializers; +global using System; +global using System.Collections.Generic; +global using System.IO; +global using System.Linq; +global using System.Net; +global using System.Net.Http.Headers; +global using System.Net.Http; +global using System.Text; +global using System.Text.Json; +global using System.Threading.Tasks; +global using Xunit; +global using Xunit.Sdk; diff --git a/test/FluentAssertions.Web.Tests/HeadersAssertionsSpecs.cs b/test/FluentAssertions.Web.Tests/HeadersAssertionsSpecs.cs index 9f4b4c1..5327f7c 100644 --- a/test/FluentAssertions.Web.Tests/HeadersAssertionsSpecs.cs +++ b/test/FluentAssertions.Web.Tests/HeadersAssertionsSpecs.cs @@ -1,373 +1,561 @@ -using System; -using System.Linq; -using System.Net.Http; -using Xunit; -using Xunit.Sdk; +namespace FluentAssertions.Web.Tests; -namespace FluentAssertions.Web.Tests +public class HeadersAssertionsSpecs { - public class HeadersAssertionsSpecs + #region HaveHeader + [Fact] + public void When_asserting_response_with_header_to_have_header_it_should_succeed() { - #region HaveHeader - [Fact] - public void When_asserting_response_with_header_to_have_header_it_should_succeed() + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Headers = { - Headers = - { - { "custom-header", "value1" } - } - }; - - // Act - Action act = () => - subject.Should().HaveHeader("custom-header"); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_response_with_header_and_no_header_value_to_have_header_it_should_succeed() + { "custom-header", "value1" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header"); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_with_header_and_no_header_value_to_have_header_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage + { + Headers = + { + { "custom-header", (string?)null } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header"); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_with_no_headers_to_have_header_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header", "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("*the HTTP header*custom-header*but no such header was found*reason*"); + } + + [Fact] + public void When_asserting_response_without_header_to_have_header_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage + { + Headers = + { + { "other-header", "other-header-value" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header", "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("*the HTTP header*custom-header*but no such header was found*reason*"); + } + + [Fact] + public void When_asserting_response_to_have_header_against_null_value_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); + + // Act + Action act = () => + subject.Should().HaveHeader(null!); + + // Assert + act.Should().Throw() + .WithMessage("*header**"); + } + + #endregion + + #region NotHaveHeader + [Fact] + public void When_asserting_response_with_headers_to_to_not_have_a_header_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Headers = { - Headers = - { - { "custom-header", (string?)null } - } - }; - - // Act - Action act = () => - subject.Should().HaveHeader("custom-header"); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_response_with_no_headers_to_have_header_it_should_throw_with_descriptive_message() + { "a-header", "with-a-value" } + } + }; + + // Act + Action act = () => + subject.Should().NotHaveHeader("other-header"); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_with_no_headers_to_not_to_have_header_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(); + + // Act + Action act = () => + subject.Should().NotHaveHeader("custom-header"); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_with_a_header_to_not_have_that_header_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage(); + Headers = + { + { "that-header", "with-a-value" } + } + }; + + // Act + Action act = () => + subject.Should().NotHaveHeader("that-header", "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("*to not to contain the HTTP header*that-header*but the header was found*reason*"); + } - // Act - Action act = () => - subject.Should().HaveHeader("custom-header", "we want to test the {0}", "reason"); + [Fact] + public void When_asserting_response_to_not_have_header_against_null_value_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); + + // Act + Action act = () => + subject.Should().NotHaveHeader(null!); + + // Assert + act.Should().Throw() + .WithMessage("*not having*header**"); + } - // Assert - act.Should().Throw() - .WithMessage("*the HTTP header*custom-header*but no such header was found*reason*"); - } + #endregion - [Fact] - public void When_asserting_response_without_header_to_have_header_it_should_throw_with_descriptive_message() + #region BeEmpty + [Fact] + public void When_asserting_response_with_header_and_no_header_value_to_have_header_and_be_empty_value_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Headers = { - Headers = - { - { "other-header", "other-header-value" } - } - }; - - // Act - Action act = () => - subject.Should().HaveHeader("custom-header", "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage("*the HTTP header*custom-header*but no such header was found*reason*"); - } - - [Fact] - public void When_asserting_response_to_have_header_against_null_value_it_should_throw_with_descriptive_message() + { "custom-header", (string?)null } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.BeEmpty(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_with_header_and_a_header_value_to_have_that_header_and_be_empty_value_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage(); + Headers = + { + { "custom-header", "some-non-empty-value" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.BeEmpty("we want to test the {0}", "reason"); - // Act - Action act = () => - subject.Should().HaveHeader(null!); + // Assert + act.Should().Throw() + .WithMessage("*the HTTP header *custom-header* with no header values*some-non-empty-value*reason*"); + } + #endregion + + #region NotBeEmpty + [Fact] + public void When_asserting_response_with_header_and_header_value_to_have_header_and_not_be_empty_value_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage + { + Headers = + { + { "custom-header", "some-value" } + } + }; - // Assert - act.Should().Throw() - .WithMessage("*header**"); - } + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.NotBeEmpty(); - #endregion + // Assert + act.Should().NotThrow(); + } - #region NotHaveHeader - [Fact] - public void When_asserting_response_with_headers_to_to_not_have_a_header_it_should_succeed() + [Fact] + public void When_asserting_response_with_header_and_header_values_to_have_header_and_not_be_empty_value_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Headers = { - Headers = - { - { "a-header", "with-a-value" } - } - }; - - // Act - Action act = () => - subject.Should().NotHaveHeader("other-header"); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_response_with_no_headers_to_not_to_have_header_it_should_succeed() + { "custom-header", "some-value" }, + { "custom-header", "another-value" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.NotBeEmpty(); + + // Assert + act.Should().NotThrow(); + } + + + [Theory] + [InlineData("")] + [InlineData((string?)null)] + public void When_asserting_response_with_header_and_no_header_value_to_have_that_header_and_not_be_empty_value_it_should_throw_with_descriptive_message(string? headerValue) + { + // Arrange + using var subject = new HttpResponseMessage + { + Headers = + { + { "custom-header", headerValue } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.NotBeEmpty("we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("*the HTTP header *custom-header* with any header values, but found the header and it has no values in the actual response*reason*"); + } + #endregion + + #region Match + [Fact] + public void When_asserting_response_with_header_to_have_header_with_a_value_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage(); + Headers = + { + { "custom-header", "value1" } + } + }; - // Act - Action act = () => - subject.Should().NotHaveHeader("custom-header"); + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.Match("value*"); - // Assert - act.Should().NotThrow(); - } + // Assert + act.Should().NotThrow(); + } - [Fact] - public void When_asserting_response_with_a_header_to_not_have_that_header_it_should_throw_with_descriptive_message() + [Fact] + public void When_asserting_response_with_header_without_a_value_to_have_value_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Headers = { - Headers = - { - { "that-header", "with-a-value" } - } - }; - - // Act - Action act = () => - subject.Should().NotHaveHeader("that-header", "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage("*to not to contain the HTTP header*that-header*but the header was found*reason*"); - } - - [Fact] - public void When_asserting_response_to_not_have_header_against_null_value_it_should_throw_with_descriptive_message() + { "custom-header", "value1" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.Match("other-than-value1", "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("*the HTTP header*custom-header* having a value matching *other-than-value1*, but there was no match*reason*"); + } + + [Fact] + public void When_asserting_response_to_have_header_and_be_value_against_null_expected_value_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage(); + Headers = + { + { "custom-header", "value1" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.Match(null!); + + // Assert + act.Should().Throw() + .WithMessage("**Use And.BeEmpty to test if the HTTP header has no values.*"); + } + #endregion - // Act - Action act = () => - subject.Should().NotHaveHeader(null!); + #region BeValue + [Fact] + public void When_asserting_response_with_header_with_value_to_have_the_value_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage + { + Headers = + { + { "custom-header", "value1" } + } + }; - // Assert - act.Should().Throw() - .WithMessage("*not having*header**"); - } + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.BeValue("value1"); - #endregion + // Assert + act.Should().NotThrow(); + } - #region BeEmpty - [Fact] - public void When_asserting_response_with_header_and_no_header_value_to_have_header_and_be_empty_value_it_should_succeed() + [Fact] + public void When_asserting_response_with_header_with_multiple_values_to_have_the_value_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Headers = { - Headers = - { - { "custom-header", (string?)null } - } - }; - - // Act - Action act = () => - subject.Should().HaveHeader("custom-header").And.BeEmpty(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_response_with_header_and_a_header_value_to_have_that_header_and_be_empty_value_it_should_throw_with_descriptive_message() + { "custom-header", "value1" }, + { "custom-header", "value2" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.BeValue("value1", "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("*the*custom-header*HTTP header*value to be equivalent to*value1*but found the header and has more or no values*reason*"); + } + + [Fact] + public void When_asserting_response_with_header_with_multiple_values_indicated_by_comma_separation_to_have_the_value_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Headers = { - Headers = - { - { "custom-header", "some-non-empty-value" } - } - }; - - // Act - Action act = () => - subject.Should().HaveHeader("custom-header").And.BeEmpty("we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage("*the HTTP header *custom-header* with no header values*some-non-empty-value*reason*"); - } - #endregion - - #region Match - [Fact] - public void When_asserting_response_with_header_to_have_header_with_a_value_it_should_succeed() + { "custom-header", "value1,value2" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.BeValue("value1", "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("*the *custom-header* HTTP header*value to be equivalent to*value1*but*value1,value2*differs*reason*"); + } + + [Fact] + public void When_asserting_response_with_header_without_some_value_to_be_different_value_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Headers = { - Headers = - { - { "custom-header", "value1" } - } - }; - - // Act - Action act = () => - subject.Should().HaveHeader("custom-header").And.Match("value*"); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_response_with_header_without_a_value_to_have_value_it_should_throw_with_descriptive_message() + { "custom-header", "value1" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.BeValue("other-than-value1", "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("*the *custom-header* HTTP header*value to be equivalent to*other-than-value1*but*value1*differs*reason*"); + } + + [Fact] + public void When_asserting_response_to_have_header_and_be_value_against_null_expected_values_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Headers = { - Headers = - { - { "custom-header", "value1" } - } - }; - - // Act - Action act = () => - subject.Should().HaveHeader("custom-header").And.Match("other-than-value1", "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage("*the HTTP header*custom-header* having a value matching *other-than-value1*, but there was no match*reason*"); - } - - [Fact] - public void When_asserting_response_to_have_header_and_be_value_against_null_expected_value_it_should_throw_with_descriptive_message() + { "custom-header", "value1" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.BeValue(null!); + + // Assert + act.Should().Throw() + .WithMessage("**Use And.BeEmpty to test if the HTTP header has no value.*"); + } + + [Fact] + public void When_asserting_response_to_have_header_and_be_values_against_empty_expected_value_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Headers = { - Headers = - { - { "custom-header", "value1" } - } - }; - - // Act - Action act = () => - subject.Should().HaveHeader("custom-header").And.Match(null!); - - // Assert - act.Should().Throw() - .WithMessage("**Use And.BeEmpty to test if the HTTP header has no values.*"); - } - #endregion - - #region BeValues - [Fact] - public void When_asserting_response_with_header_with_values_to_have_those_values_it_should_succeed() + { "custom-header", "value1" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.BeValue(""); + + // Assert + act.Should().Throw() + .WithMessage("*empty*Use And.BeEmpty to test if the HTTP header has no value.*"); + } + #endregion + + #region BeValues + [Fact] + public void When_asserting_response_with_header_with_values_to_have_those_values_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Headers = { - Headers = - { - { "custom-header", "value1" }, - { "custom-header", "value2" } - } - }; - - // Act - Action act = () => - subject.Should().HaveHeader("custom-header").And.BeValues(new[] { "value1", "value2" }); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_response_with_header_without_some_value_to_be_different_values_it_should_throw_with_descriptive_message() + { "custom-header", "value1" }, + { "custom-header", "value2" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.BeValues(new[] { "value1", "value2" }); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_with_header_without_some_value_to_be_different_values_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Headers = { - Headers = - { - { "custom-header", "value1" } - } - }; - - // Act - Action act = () => - subject.Should().HaveHeader("custom-header").And.BeValues(new[] { - "other-than-value1", - "another-other-than-value1" }, "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage("*the HTTP header*custom-header*having values*other-than-value1*another-other-than-value1*reason*"); - } - - [Fact] - public void When_asserting_response_to_have_header_and_be_values_against_null_expected_values_it_should_throw_with_descriptive_message() + { "custom-header", "value1" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.BeValues(new[] { + "other-than-value1", + "another-other-than-value1" }, "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("*the HTTP header*custom-header*having values*other-than-value1*another-other-than-value1*reason*"); + } + + [Fact] + public void When_asserting_response_to_have_header_and_be_values_against_null_expected_values_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Headers = { - Headers = - { - { "custom-header", "value1" } - } - }; - - // Act - Action act = () => - subject.Should().HaveHeader("custom-header").And.BeValues(null!); - - // Assert - act.Should().Throw() - .WithMessage("**Use And.BeEmpty to test if the HTTP header has no values.*"); - } - - [Fact] - public void When_asserting_response_to_have_header_and_be_values_against_empty_expected_values_it_should_throw_with_descriptive_message() + { "custom-header", "value1" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.BeValues(null!); + + // Assert + act.Should().Throw() + .WithMessage("**Use And.BeEmpty to test if the HTTP header has no values.*"); + } + + [Fact] + public void When_asserting_response_to_have_header_and_be_values_against_empty_expected_values_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Headers = { - Headers = - { - { "custom-header", "value1" } - } - }; - - // Act - Action act = () => - subject.Should().HaveHeader("custom-header").And.BeValues(Enumerable.Empty()); - - // Assert - act.Should().Throw() - .WithMessage("*empty*Use And.BeEmpty to test if the HTTP header has no values.*"); - } - #endregion + { "custom-header", "value1" } + } + }; + + // Act + Action act = () => + subject.Should().HaveHeader("custom-header").And.BeValues(Enumerable.Empty()); + + // Assert + act.Should().Throw() + .WithMessage("*empty*Use And.BeEmpty to test if the HTTP header has no values.*"); } + #endregion } \ No newline at end of file diff --git a/test/FluentAssertions.Web.Tests/HttpResponseContentAssertionsSpecs.cs b/test/FluentAssertions.Web.Tests/HttpResponseContentAssertionsSpecs.cs index e90f50b..1daabec 100644 --- a/test/FluentAssertions.Web.Tests/HttpResponseContentAssertionsSpecs.cs +++ b/test/FluentAssertions.Web.Tests/HttpResponseContentAssertionsSpecs.cs @@ -1,380 +1,419 @@ -using FluentAssertions.Equivalency; -using FluentAssertions.Web.Internal; -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Text; -using Xunit; -using Xunit.Sdk; - -namespace FluentAssertions.Web.Tests +namespace FluentAssertions.Web.Tests; + +public class HttpResponseContentAssertionsSpecs { - public class HttpResponseContentAssertionsSpecs + #region BeAs + [Fact] + public void When_asserting_response_with_content_to_be_as_model_it_should_succeed() { - #region BeAs - [Fact] - public void When_asserting_response_with_content_to_be_as_model_it_should_succeed() + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent(/*lang=json*/""" { - Content = new StringContent(@"{ - ""comment"": ""Hey"", - ""author"": ""John"", - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().BeAs(new - { - Comment = "Hey", - Author = "John" - }); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_response_with_content_with_more_JSON_properties_than_a_model_to_be_as_model_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage + "comment": "Hey", + "author": "John" + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().BeAs(new { - Content = new StringContent(@"{ - ""author"": ""John"", - ""comment"": ""Hey"", - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().BeAs(new - { - Comment = "Hey", - }); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_response_with_content_with_differences_to_be_as_model_it_should_throw_with_descriptive_message() + Comment = "Hey", + Author = "John" + }); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_with_content_with_more_JSON_properties_than_a_model_to_be_as_model_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent(/*lang=json*/""" + { + "author": "John", + "comment": "Hey" + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().BeAs(new { - Content = new StringContent(@"{ - ""comment"": ""Hey"", - ""author"": ""John"", - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().BeAs(new - { - Comment = "Not Hey", - Author = "John" - }, "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage("*Not Hey*with a length*reason*"); - } - - public static IEnumerable Data => - new List - { - new object[] { 1 }, - new object[] { "" }, - new object[] { new DateTime(2019, 10, 11) } - }; - [Theory] - [MemberData(nameof(Data))] - public void When_asserting_response_with_content_as_primitives_types_to_be_as_the_primitive_value_it_should_succeed(object expectedModel) + Comment = "Hey", + }); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_with_content_with_differences_to_be_as_model_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent(/*lang=json*/""" + { + "comment": "Hey", + "author": "John" + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().BeAs(new { - Content = new StringContent(expectedModel.ToJson(), Encoding.UTF8, "application/json") - }; + Comment = "Not Hey", + Author = "John" + }, "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("*Not Hey*with a length*reason*"); + } + + public static IEnumerable Data => + new List + { + new object[] { 1 }, + new object[] { "" }, + new object[] { new DateTime(2019, 10, 11) } + }; + [Theory] + [MemberData(nameof(Data))] + public void When_asserting_response_with_content_as_primitives_types_to_be_as_the_primitive_value_it_should_succeed(object expectedModel) + { + // Arrange + using var subject = new HttpResponseMessage + { + Content = new StringContent(expectedModel.ToJson(), Encoding.UTF8, "application/json") + }; - // Act - Action act = () => - subject.Should().BeAs(expectedModel); + // Act + Action act = () => + subject.Should().BeAs(expectedModel); - // Assert - act.Should().NotThrow(); - } + // Assert + act.Should().NotThrow(); + } - [Fact] - public void When_asserting_response_with_content_as_int_to_be_as_the_primitive_value_it_should_succeed() + [Fact] + public void When_asserting_response_with_content_as_int_to_be_as_the_primitive_value_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent(1.ToJson(), Encoding.UTF8, "application/json") - }; + Content = new StringContent(1.ToJson(), Encoding.UTF8, "application/json") + }; - // Act - Action act = () => - subject.Should().BeAs(1); + // Act + Action act = () => + subject.Should().BeAs(1); - // Assert - act.Should().NotThrow(); - } + // Assert + act.Should().NotThrow(); + } - [Fact] - public void When_asserting_response_with_fewer_JSON_properties_than_the_model_to_be_as_model_it_should_throw_with_descriptive_message() + [Fact] + public void When_asserting_response_with_fewer_JSON_properties_than_the_model_to_be_as_model_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent(/*lang=json*/""" + { + "comment": "Hey" + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().BeAs(new { - Content = new StringContent(@"{ - ""comment"": ""Hey"", - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().BeAs(new - { - Comment = "Hey", - Author = "John" - }, "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage(@"*Author to be ""John""*reason*"); - } - - [Fact] - public void When_asserting_response_with_not_a_proper_JSON_to_be_as_model_it_should_throw_with_descriptive_message() + Comment = "Hey", + Author = "John" + }, "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("""*Author to be "John"*reason*"""); + } + + [Fact] + public void When_asserting_response_with_not_a_proper_JSON_to_be_as_model_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent("some text:that doesn't look like a json {", Encoding.UTF8, "text/plain") + }; + + // Act + Action act = () => + subject.Should().BeAs(new { - Content = new StringContent(@"some text:that doesn't look like a json {", Encoding.UTF8, "text/plain") - }; - - // Act - Action act = () => - subject.Should().BeAs(new - { - Comment = "Hey" - }, "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage(@"*to have a content equivalent to a model of type*, but the JSON representation could not be parsed*"); - } - - [Fact] - public void When_asserting_response_with_not_a_proper_JSON_to_be_as_model_it_should_throw_with_descriptive_message_which_includes_the_parsing_error_details() + Comment = "Hey" + }, "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("*to have a content equivalent to a model of type*, but the JSON representation could not be parsed*"); + } + + [Fact] + public void When_asserting_response_with_not_a_proper_JSON_to_be_as_model_it_should_throw_with_descriptive_message_which_includes_the_parsing_error_details() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent(/*lang=json,strict*/ """{ "price" : 0.0}""", Encoding.UTF8, "text/plain") + }; + + // Act + Action act = () => + subject.Should().BeAs(new { - Content = new StringContent(@"{ ""price"" : 0.0}", Encoding.UTF8, "text/plain") - }; - - // Act - Action act = () => - subject.Should().BeAs(new - { - price = 0 - }, "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage(@"*to have a content equivalent to a model of type*, but the JSON representation could not be parsed, as the operation failed with the following message: ""Exception while deserializing the model with SystemTextJsonSerializer: The JSON value could not be converted to * Path: $.price | LineNumber: 0 | BytePositionInLine: 15.*"); - } - - [Fact] - public void When_asserting_with_equivalency_assertion_options_to_be_as_model_it_should_succeed() + price = 0 + }, "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("""*to have a content equivalent to a model of type*, but the JSON representation could not be parsed, as the operation failed with the following message: "Exception while deserializing the model with SystemTextJsonSerializer: The JSON value could not be converted to * Path: $.price | LineNumber: 0 | BytePositionInLine: 15.*"""); + } + + [Fact] + public void When_asserting_response_with_a_syntactically_correct_JSON_array_to_be_as_a_single_object_model_it_should_throw_with_descriptive_message_which_includes_the_serialization_error_details_but_keep_the_original_content() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent(/*lang=json,strict*/ """[{ "price" : 0.0}, { "price" : 1.0}]""", Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().BeAs(new { - Content = new StringContent(@"{ - ""author"": ""John"", - ""comment"": ""Hey"", - ""version"": ""version 1"" - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().BeAs(new - { - author = "John", - comment = "Hey", - version = "version 2" - }, options => options.Excluding(model => model.version)); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_response_with_equivalency_assertion_options_and_with_differences_to_be_as_model_it_should_throw_with_descriptive_message() + price = 0m + }, "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage(""" + *to have a content equivalent to a model of type*, but the JSON representation could not be parsed, as the operation failed with the following message: "Exception while deserializing the model with SystemTextJsonSerializer: The JSON value could not be converted to * Path: $ | LineNumber: 0 | BytePositionInLine: 1.* + [ + { + "price": 0.0 + }, + { + "price": 1.0 + } + ]* + """); + } + + [Fact] + public void When_asserting_with_equivalency_assertion_options_to_be_as_model_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent(/*lang=json,strict*/ """ + { + "author": "John", + "comment": "Hey", + "version": "version 1" + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().BeAs(new { - Content = new StringContent(@"{ - ""comment"": ""Hey"", - ""author"": ""John"", - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().BeAs(new - { - Comment = "Not Hey", - Author = "John" - }, options => options.Excluding(model => model.Author), "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage("*Not Hey*with a length*reason*"); - } - - [Fact] - public void When_asserting_response_to_be_as_model_with_null_equivalency_assertion_options_it_should_throw_with_descriptive_message() + author = "John", + comment = "Hey", + version = "version 2" + }, options => options.Excluding(model => model.version)); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_with_equivalency_assertion_options_and_with_differences_to_be_as_model_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage(); + Content = new StringContent(/*lang=json*/""" + { + "comment": "Hey", + "author": "John" + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().BeAs(new + { + Comment = "Not Hey", + Author = "John" + }, options => options.Excluding(model => model.Author), "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("*Not Hey*with a length*reason*"); + } - // Act - Action act = () => - subject.Should().BeAs(new { }, options: (Func, EquivalencyAssertionOptions>)(null!)); + [Fact] + public void When_asserting_response_to_be_as_model_with_null_equivalency_assertion_options_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); - // Assert - act.Should().Throw() - .WithMessage("Value cannot be null*options*"); - } + // Act + Action act = () => + subject.Should().BeAs(new { }, options: (Func, EquivalencyAssertionOptions>)(null!)); - [Fact] - public void When_asserting_response_to_be_as_against_null_value_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(); + // Assert + act.Should().Throw() + .WithMessage("Value cannot be null*options*"); + } + + [Fact] + public void When_asserting_response_to_be_as_against_null_value_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); - // Act - Action act = () => - subject.Should().BeAs((object?)null); + // Act + Action act = () => + subject.Should().BeAs((object?)null); - // Assert - act.Should().Throw() - .WithMessage("*content**"); - } + // Assert + act.Should().Throw() + .WithMessage("*content**"); + } - [Fact] - public void When_asserting_null_response_to_be_as_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().BeAs((object?)null, "because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region MatchInContent - [Fact] - public void When_asserting_response_with_keywords_in_content_to_match_in_content_it_should_succeed() + [Fact] + public void When_asserting_null_response_to_be_as_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().BeAs((object?)null, "because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region MatchInContent + [Theory] + [InlineData("*comment*author*")] + [InlineData("*co?ment*a?thor*")] + public void When_asserting_response_with_keywords_in_content_to_match_in_content_it_should_succeed(string wildcardText) + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent(/*lang=json*/""" { - Content = new StringContent(@"{ - ""comment"": ""Hey"", - ""author"": ""John"", - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().MatchInContent("*comment*author*"); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_response_without_keywords_in_content_to_match_in_content_it_should_throw_with_descriptive_message() + "comment": "Hey", + "author": "John" + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().MatchInContent(wildcardText); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_without_keywords_in_content_to_match_in_content_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent(/*lang=json*/""" { - Content = new StringContent(@"{ - ""comment"": ""Hey"", - ""author"": ""John"", - }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().MatchInContent("*notes*", "because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage("*notes*message*"); - } - - [Fact] - public void When_asserting_response_with_no_string_content_to_match_in_content_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(); + "comment": "Hey", + "author": "John" + } + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().MatchInContent("*notes*", "because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*notes*message*"); + } - // Act - Action act = () => - subject.Should().MatchInContent("*notes*", "because we want to test the failure {0}", "message"); + [Fact] + public void When_asserting_response_with_no_string_content_to_match_in_content_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); - // Assert - act.Should().Throw() - .WithMessage("*the wildcard pattern*notes*content was *message*"); - } + // Act + Action act = () => + subject.Should().MatchInContent("*notes*", "because we want to test the failure {0}", "message"); - [Fact] - public void When_asserting_response_to_match_in_content_against_null_wildcard_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(); + // Assert + act.Should().Throw() + .WithMessage("*the wildcard pattern*notes*content was *message*"); + } - // Act - Action act = () => - subject.Should().MatchInContent(null!); + [Fact] + public void When_asserting_response_to_match_in_content_against_null_wildcard_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); - // Assert - act.Should().Throw() - .WithMessage("**wildcard*"); - } + // Act + Action act = () => + subject.Should().MatchInContent(null!); - [Fact] - public void When_asserting_null_response_to_match_in_content_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().MatchInContent("wildcard", "because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion + // Assert + act.Should().Throw() + .WithMessage("**wildcard*"); + } + + [Fact] + public void When_asserting_null_response_to_match_in_content_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().MatchInContent("wildcard", "because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); } + #endregion } diff --git a/test/FluentAssertions.Web.Tests/HttpResponseMessageFormatterSpecs.cs b/test/FluentAssertions.Web.Tests/HttpResponseMessageFormatterSpecs.cs index 5eb8924..a43878a 100644 --- a/test/FluentAssertions.Web.Tests/HttpResponseMessageFormatterSpecs.cs +++ b/test/FluentAssertions.Web.Tests/HttpResponseMessageFormatterSpecs.cs @@ -1,1041 +1,1090 @@ using FluentAssertions.Formatting; -using FluentAssertions.Web.Internal; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Text; -using System.Threading.Tasks; -using Xunit; - -namespace FluentAssertions.Web.Tests + +namespace FluentAssertions.Web.Tests; + +public class HttpResponseMessageFormatterSpecs { - public class HttpResponseMessageFormatterSpecs + [Fact] + public void GivenUnspecifiedResponse_ShouldPrintProtocolAndHaveContentLengthZero() { - [Fact] - public void GivenUnspecifiedResponse_ShouldPrintProtocolAndHaveContentLengthZero() - { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(); - var sut = new HttpResponseMessageFormatter(); - - // Act - sut.Format(subject, formattedGraph, null!, null!); - - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match(@"* -The HTTP response was:* -HTTP/1.1 200 OK* -Content-Length: 0* -The originated HTTP request was .*"); - } + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(); + var sut = new HttpResponseMessageFormatter(); + + // Act + sut.Format(subject, formattedGraph, null!, null!); + + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match(""" + * + The HTTP response was:* + HTTP/1.1 200 OK* + Content-Length: 0* + The originating HTTP request was .* + """); + } - [Fact] - public void GivenHeaders_ShouldPrintAllHeaders() + [Fact] + public void GivenHeaders_ShouldPrintAllHeaders() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new StringContent("", Encoding.UTF8, "text/html") - }; - subject.Headers.Add("Cache-Control", "no-store, no-cache, max-age=0"); - subject.Headers.Add("Pragma", "no-cache"); - subject.Headers.Add("Request-Context", "appId=cid-v1:2e15fa14-72b6-44b3-a9b2-560e7b3234e5"); - subject.Headers.Add("Strict-Transport-Security", "max-age=31536000"); - subject.Headers.Add("Date", "Thu, 26 Sep 2019 22:33:34 GMT"); - subject.Headers.Add("Connection", "close"); - var sut = new HttpResponseMessageFormatter(); - - // Act - sut.Format(subject, formattedGraph, null!, null!); - - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*The HTTP response was:* -HTTP/1.1 200 OK* -Cache-Control: no-store, no-cache, max-age=0* -Pragma: no-cache* -Request-Context: appId=cid-v1:2e15fa14-72b6-44b3-a9b2-560e7b3234e5* -Strict-Transport-Security: max-age=31536000* -Date: Thu, 26 Sep 2019 22:33:34 GMT* -Connection: close* -Content-Type: text/html; charset=utf-8* -Content-Length: 0* -The originated HTTP request was .*"); - } + Content = new StringContent("", Encoding.UTF8, "text/html") + }; + subject.Headers.Add("Cache-Control", "no-store, no-cache, max-age=0"); + subject.Headers.Add("Pragma", "no-cache"); + subject.Headers.Add("Request-Context", "appId=cid-v1:2e15fa14-72b6-44b3-a9b2-560e7b3234e5"); + subject.Headers.Add("Strict-Transport-Security", "max-age=31536000"); + subject.Headers.Add("Date", "Thu, 26 Sep 2019 22:33:34 GMT"); + subject.Headers.Add("Connection", "close"); + var sut = new HttpResponseMessageFormatter(); + + // Act + sut.Format(subject, formattedGraph, null!, null!); + + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + """ + *The HTTP response was:* + HTTP/1.1 200 OK* + Cache-Control: no-store, no-cache, max-age=0* + Pragma: no-cache* + Request-Context: appId=cid-v1:2e15fa14-72b6-44b3-a9b2-560e7b3234e5* + Strict-Transport-Security: max-age=31536000* + Date: Thu, 26 Sep 2019 22:33:34 GMT* + Connection: close* + Content-Type: text/html; charset=utf-8* + Content-Length: 0* + The originating HTTP request was .* + """); + } - [Fact] - public void GivenDuplicatedHeaders_ShouldPrintOnNewLines() + [Fact] + public void GivenDuplicatedHeaders_ShouldPrintOnNewLines() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new StringContent("", Encoding.UTF8, "text/html") - }; - subject.Headers.Add("Set-Cookie", "name1=value1"); - subject.Headers.Add("Set-Cookie", "name2=value2"); - var sut = new HttpResponseMessageFormatter(); - - // Act - sut.Format(subject, formattedGraph, null!, null!); - - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*The HTTP response was:* -HTTP/1.1 200 OK* -Set-Cookie: name1=value1* -Set-Cookie: name2=value2*"); - } + Content = new StringContent("", Encoding.UTF8, "text/html") + }; + subject.Headers.Add("Set-Cookie", "name1=value1"); + subject.Headers.Add("Set-Cookie", "name2=value2"); + var sut = new HttpResponseMessageFormatter(); + + // Act + sut.Format(subject, formattedGraph, null!, null!); + + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + """ + *The HTTP response was:* + HTTP/1.1 200 OK* + Set-Cookie: name1=value1* + Set-Cookie: name2=value2* + """); + } - [Fact] - public void GivenResponseWithContent_ShouldPrintContent() + [Fact] + public void GivenResponseWithContent_ShouldPrintContent() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + Content = new StringContent(/*lang=json,strict*/ """ { - Content = new StringContent(@"{ - ""glossary"": { - ""title"": ""example glossary"", - ""GlossDiv"": { - ""title"": ""S"", - ""GlossList"": { - ""GlossEntry"": { - ""ID"": ""SGML"", - ""SortAs"": ""SGML"", - ""GlossTerm"": ""Standard Generalized Markup Language"", - ""Acronym"": ""SGML"", - ""Abbrev"": ""ISO 8879:1986"", - ""GlossDef"": { - ""para"": ""A meta-markup language, used to create markup languages such as DocBook."", - ""GlossSeeAlso"": [ - ""GML"", - ""XML"" + "glossary": { + "title": "example glossary", + "GlossDiv": { + "title": "S", + "GlossList": { + "GlossEntry": { + "ID": "SGML", + "SortAs": "SGML", + "GlossTerm": "Standard Generalized Markup Language", + "Acronym": "SGML", + "Abbrev": "ISO 8879:1986", + "GlossDef": { + "para": "A meta-markup language, used to create markup languages such as DocBook.", + "GlossSeeAlso": [ + "GML", + "XML" ] - }, - ""GlossSee"": ""markup"" + }, + "GlossSee": "markup" + } + } } + } } - } + """, Encoding.UTF8, "application/json") + }; + var sut = new HttpResponseMessageFormatter(); + + // Act + sut.Format(subject, formattedGraph, null!, null!); + + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match(""" + *The HTTP response was:* + HTTP/1.1 200 OK* + Content-Type: application/json; charset=utf-8* + Content-Length:* + {* + "glossary": {* + "title": "example glossary",* + "GlossDiv": {* + "title": "S",* + "GlossList": {* + "GlossEntry": {* + "ID": "SGML",* + "SortAs": "SGML",* + "GlossTerm": "Standard Generalized Markup Language",* + "Acronym": "SGML",* + "Abbrev": "ISO 8879:1986",* + "GlossDef": {* + "para": "A meta-markup language, used to create markup languages such as DocBook.",* + "GlossSeeAlso": [* + "GML",* + "XML"* + ]* + },* + "GlossSee": "markup"* + }* + }* + }* + }* + }* + The originating HTTP request was .* + """); } -}", Encoding.UTF8, "application/json") - }; - var sut = new HttpResponseMessageFormatter(); - - // Act - sut.Format(subject, formattedGraph, null!, null!); - - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match(@"*The HTTP response was:* -HTTP/1.1 200 OK* -Content-Type: application/json; charset=utf-8* -Content-Length:* -{* - ""glossary"": {* - ""title"": ""example glossary"",* - ""GlossDiv"": {* - ""title"": ""S"",* - ""GlossList"": {* - ""GlossEntry"": {* - ""ID"": ""SGML"",* - ""SortAs"": ""SGML"",* - ""GlossTerm"": ""Standard Generalized Markup Language"",* - ""Acronym"": ""SGML"",* - ""Abbrev"": ""ISO 8879:1986"",* - ""GlossDef"": {* - ""para"": ""A meta-markup language, used to create markup languages such as DocBook."",* - ""GlossSeeAlso"": [* - ""GML"",* - ""XML""* - ]* - },* - ""GlossSee"": ""markup""* - }* - }* - }* - }* -}* -The originated HTTP request was .*"); - } - [Fact] - public void GivenResponseWithJsonContainsNonEnglishChars_ShouldNotEscaped() + [Fact] + public void GivenResponseWithJsonContainsNonEnglishChars_ShouldNotEscaped() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + Content = new StringContent(/*lang=json,strict*/ """ { - Content = new StringContent( - @"{""message"":""папка""}", - Encoding.UTF8, "application/json") - }; - var sut = new HttpResponseMessageFormatter(); + "message": "папка" + } + """, Encoding.UTF8, "application/json") + }; + var sut = new HttpResponseMessageFormatter(); - // Act - sut.Format(subject, formattedGraph, null!, null!); + // Act + sut.Format(subject, formattedGraph, null!, null!); - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match(@"*The HTTP response wa*""папка""*The originated HTTP request was .*"); - } - - [Fact] - public void GivenResponseWithMinifiedJson_ShouldPrintFormattedJson() + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match("""*The HTTP response wa*"папка"*The originating HTTP request was .*"""); + } + + [Fact] + public void GivenResponseWithMinifiedJson_ShouldPrintFormattedJson() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new StringContent( - @"{""glossary"":{""title"":""example glossary"",""GlossDiv"":{""title"":""S"",""GlossList"":{""GlossEntry"":{""ID"":""SGML"",""SortAs"":""SGML"",""GlossTerm"":""Standard Generalized Markup Language"",""Acronym"":""SGML"",""Abbrev"":""ISO 8879:1986"",""GlossDef"":{""para"":""A meta-markup language, used to create markup languages such as DocBook."",""GlossSeeAlso"":[""GML"",""XML""]},""GlossSee"":""markup""}}}}}", - Encoding.UTF8, "application/json") - }; - var sut = new HttpResponseMessageFormatter(); - - // Act - sut.Format(subject, formattedGraph, null!, null!); - - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match(@"* -The HTTP response was:* -HTTP/1.1 200 OK* -Content-Type: application/json; charset=utf-8* -Content-Length:* -{* - ""glossary"": {* - ""title"": ""example glossary"",* - ""GlossDiv"": {* - ""title"": ""S"",* - ""GlossList"": {* - ""GlossEntry"": {* - ""ID"": ""SGML"",* - ""SortAs"": ""SGML"",* - ""GlossTerm"": ""Standard Generalized Markup Language"",* - ""Acronym"": ""SGML"",* - ""Abbrev"": ""ISO 8879:1986"",* - ""GlossDef"": {* - ""para"": ""A meta-markup language, used to create markup languages such as DocBook."",* - ""GlossSeeAlso"": [* - ""GML"",* - ""XML""* - ]* - },* - ""GlossSee"": ""markup""* - }* - }* - }* - }* -}* -The originated HTTP request was .*"); - } + Content = new StringContent( + /*lang=json,strict*/ + """{"glossary":{"title":"example glossary","GlossDiv":{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}}}""", + Encoding.UTF8, "application/json") + }; + var sut = new HttpResponseMessageFormatter(); + + // Act + sut.Format(subject, formattedGraph, null!, null!); + + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match(""" + * + The HTTP response was:* + HTTP/1.1 200 OK* + Content-Type: application/json; charset=utf-8* + Content-Length:* + {* + "glossary": {* + "title": "example glossary",* + "GlossDiv": {* + "title": "S",* + "GlossList": {* + "GlossEntry": {* + "ID": "SGML",* + "SortAs": "SGML",* + "GlossTerm": "Standard Generalized Markup Language",* + "Acronym": "SGML",* + "Abbrev": "ISO 8879:1986",* + "GlossDef": {* + "para": "A meta-markup language, used to create markup languages such as DocBook.",* + "GlossSeeAlso": [* + "GML",* + "XML"* + ]* + },* + "GlossSee": "markup"* + }* + }* + }* + }* + }* + The originating HTTP request was .* + """); + } - [Fact] - public void GivenHtmlResponse_ShouldPrintAsItIs() + [Fact] + public void GivenHtmlResponse_ShouldPrintAsItIs() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new StringContent(@" - -Title of the document - - - -The content of the document...... - - -", Encoding.UTF8, "text/html") - }; - var sut = new HttpResponseMessageFormatter(); - - // Act - sut.Format(subject, formattedGraph, null!, null!); - - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match(@"* -The HTTP response was:* -HTTP/1.1 200 OK* -Content-Type: text/html; charset=utf-8* -Content-Length:* -* -* -Title of the document* -* -* -The content of the document......* -* -* -The originated HTTP request was .*"); - } + Content = new StringContent(""" + + + Title of the document + + + + The content of the document...... + + + + """, Encoding.UTF8, "text/html") + }; + var sut = new HttpResponseMessageFormatter(); + + // Act + sut.Format(subject, formattedGraph, null!, null!); + + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match(""" + * + The HTTP response was:* + HTTP/1.1 200 OK* + Content-Type: text/html; charset=utf-8* + Content-Length:* + * + * + Title of the document* + * + * + The content of the document......* + * + * + The originating HTTP request was .* + """); + } - [Fact] - public void GivenContentLengthInHeaders_ShouldNotPrintItTwice() + [Fact] + public void GivenContentLengthInHeaders_ShouldNotPrintItTwice() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new StringContent("") - }; - subject.Content.Headers.Add("Content-Length", "0"); - var sut = new HttpResponseMessageFormatter(); - - // Act - sut.Format(subject, formattedGraph, null!, null!); - - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*The HTTP response was:* -HTTP/1.1 200 OK* -Content-Type: text/plain; charset=utf-8* -Content-Length: 0* -The originated HTTP request was .*"); - } + Content = new StringContent("") + }; + subject.Content.Headers.Add("Content-Length", "0"); + var sut = new HttpResponseMessageFormatter(); + + // Act + sut.Format(subject, formattedGraph, null!, null!); + + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + """ + *The HTTP response was:* + HTTP/1.1 200 OK* + Content-Type: text/plain; charset=utf-8* + Content-Length: 0* + The originating HTTP request was .* + """); + } - [Fact] - public void GivenRequest_ShouldPrintRequestDetails() + [Fact] + public void GivenRequest_ShouldPrintRequestDetails() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + RequestMessage = new HttpRequestMessage(HttpMethod.Post, "http://localhost:5001/") { - RequestMessage = new HttpRequestMessage(HttpMethod.Post, "http://localhost:5001/") - { - Content = new StringContent("Some content."), - Headers = { { "Authorization", "Bearer xyz" } } - } - }; - var sut = new HttpResponseMessageFormatter(); - - // Act - sut.Format(subject, formattedGraph, null!, null!); - - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*The HTTP response was:* -HTTP/1.1 200 OK* -Content-Length: 0* -The originated HTTP request was:* -POST http://localhost:5001/ HTTP* -Authorization: Bearer xyz* -Content-Type: text/plain; charset=utf-8* -Content-Length: * -Some content.*"); - } + Content = new StringContent("Some content."), + Headers = { { "Authorization", "Bearer xyz" } } + } + }; + var sut = new HttpResponseMessageFormatter(); + + // Act + sut.Format(subject, formattedGraph, null!, null!); + + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + """ + *The HTTP response was:* + HTTP/1.1 200 OK* + Content-Length: 0* + The originating HTTP request was:* + POST http://localhost:5001/ HTTP* + Authorization: Bearer xyz* + Content-Type: text/plain; charset=utf-8* + Content-Length: * + Some content.* + """); + } - [Fact] - public void GivenRequest_WhenRequestStreamAtTheEnd_ShouldPrintRequestDetails() + [Fact] + public void GivenRequest_WhenRequestStreamAtTheEnd_ShouldPrintRequestDetails() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + RequestMessage = new HttpRequestMessage(HttpMethod.Post, "http://localhost:5001/") { - RequestMessage = new HttpRequestMessage(HttpMethod.Post, "http://localhost:5001/") - { - Content = new StringContent("Some content."), - Headers = { { "Authorization", "Bearer xyz" } } - } - }; - var readOnce = subject.RequestMessage.Content.ReadAsStreamAsync().GetAwaiter().GetResult(); - readOnce.Seek(readOnce.Length, SeekOrigin.Begin); - var sut = new HttpResponseMessageFormatter(); - - // Act - sut.Format(subject, formattedGraph, null!, null!); - - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*The HTTP response was:* -HTTP/1.1 200 OK* -Content-Length: 0* -The originated HTTP request was:* -POST http://localhost:5001/ HTTP* -Authorization: Bearer xyz* -Content-Type: text/plain; charset=utf-8* -Content-Length: * -Some content.*"); - } + Content = new StringContent("Some content."), + Headers = { { "Authorization", "Bearer xyz" } } + } + }; + var readOnce = subject.RequestMessage.Content.ReadAsStreamAsync().GetAwaiter().GetResult(); + readOnce.Seek(readOnce.Length, SeekOrigin.Begin); + var sut = new HttpResponseMessageFormatter(); + + // Act + sut.Format(subject, formattedGraph, null!, null!); + + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + """ + *The HTTP response was:* + HTTP/1.1 200 OK* + Content-Length: 0* + The originating HTTP request was:* + POST http://localhost:5001/ HTTP* + Authorization: Bearer xyz* + Content-Type: text/plain; charset=utf-8* + Content-Length: * + Some content.* + """); + } - [Fact] - public void GivenResponseWithNoContentType_ShouldPrint() + [Fact] + public void GivenResponseWithNoContentType_ShouldPrint() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new StringContent("", Encoding.UTF8) - }; - subject.Content.Headers.ContentType = null; - var sut = new HttpResponseMessageFormatter(); - - // Act - sut.Format(subject, formattedGraph, null!, null!); - - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*The HTTP response was:* -HTTP/1.1 200 OK* -Content-Length: 0*HTTP request**"); - } + Content = new StringContent("", Encoding.UTF8) + }; + subject.Content.Headers.ContentType = null; + var sut = new HttpResponseMessageFormatter(); + + // Act + sut.Format(subject, formattedGraph, null!, null!); + + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + """ + *The HTTP response was:* + HTTP/1.1 200 OK* + Content-Length: 0*HTTP request** + """); + } - [Theory] - [InlineData(AspNetCore22InternalServerErrorResponse, - "*System.Exception: Wow!*DeveloperExceptionPageMiddleware*", "")] - [InlineData(AspNetCore30InternalServerErrorResponse, - "*System.Exception: Wow!*DeveloperExceptionPageMiddleware*", "HEADERS")] - [InlineData(@"
", "*rawExceptionStackTrace*", "DOCTYPE")]
-        [InlineData(@"
", "**", "DOCTYPE")] - public void GivenInternalServerError_ShouldPrintExceptionDetails(string content, string expected, - string unexpected) + [Theory] + [InlineData(AspNetCore22InternalServerErrorResponse, + "*System.Exception: Wow!*DeveloperExceptionPageMiddleware*", "")] + [InlineData(AspNetCore30InternalServerErrorResponse, + "*System.Exception: Wow!*DeveloperExceptionPageMiddleware*", "HEADERS")] + [InlineData("""
""", "*rawExceptionStackTrace*", "DOCTYPE")]
+    [InlineData("
", "**", "DOCTYPE")] + public void GivenInternalServerError_ShouldPrintExceptionDetails(string content, string expected, + string unexpected) + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.InternalServerError) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.InternalServerError) - { - Content = new StringContent(content) - }; - var sut = new HttpResponseMessageFormatter(); - - // Act - sut.Format(subject, formattedGraph, null!, null!); + Content = new StringContent(content) + }; + var sut = new HttpResponseMessageFormatter(); - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match(expected); - formatted.Should().NotContain(unexpected); - } - - private const string AspNetCore22InternalServerErrorResponse = @" - - - - Internal Server Error - - - -

An unhandled exception occurred while processing the request.

-
Exception: Wow!
-

Sample.Api.Tests.CustomStartupConfigurationsTests+<>c.<GetException_WhenDeveloperPageIsConfigured_ShouldBeInternalServerError>b__0_2(HttpContext context, Func<Task> next) in CustomStartupConfigurationsTests.cs, line 26

-
    -
  • - Stack -
  • -
  • - Query -
  • -
  • - Cookies -
  • -
  • - Headers -
  • -
- -
-
    -
  • -

    Exception: Wow!

    -
      -
    • -

      Sample.Api.Tests.CustomStartupConfigurationsTests+<>c.<GetException_WhenDeveloperPageIsConfigured_ShouldBeInternalServerError>b__0_2(HttpContext context, Func<Task> next) in CustomStartupConfigurationsTests.cs

      - - -
      -
        -
      1. {
      2. -
      3. services.AddMvc();
      4. -
      5. });
      6. -
      7. builder.Configure(app => app
      8. -
      9. .UseDeveloperExceptionPage()
      10. -
      11. .Use((context, next) => {
      12. -
      - -
        -
      1. throw new Exception("Wow!");
      2. -
      - -
        -
      1. }));
      2. -
      3. -
      4. using var testServer = new TestServer(builder);
      5. -
      6. using var client = testServer.CreateClient();
      7. -
      8. -
      9. // Act
      10. -
      -
      -
    • -
    • -

      Microsoft.AspNetCore.Builder.UseExtensions+<>c__DisplayClass0_1.<Use>b__1(HttpContext context)

      + .showRawExceptionContainer { + margin-top: 10px; + margin-bottom: 10px; + } -
    • -
    • -

      Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

      + .expandCollapseButton { + cursor: pointer; + float: left; + height: 16px; + width: 16px; + font-size: 10px; + position: absolute; + left: 10px; + background-color: #eee; + padding: 0; + border: 0; + margin: 0; + } -
    • -
    + + + +

    An unhandled exception occurred while processing the request.

    +
    Exception: Wow!
    +

    Sample.Api.Tests.CustomStartupConfigurationsTests+<>c.<GetException_WhenDeveloperPageIsConfigured_ShouldBeInternalServerError>b__0_2(HttpContext context, Func<Task> next) in CustomStartupConfigurationsTests.cs, line 26

    + -
- -
-

No QueryString data.

-
- -
-

No cookie data.

-
-
- - - - - - - - +
  • + Cookies +
  • +
  • + Headers +
  • + + +
    +
      +
    • +

      Exception: Wow!

      +
        +
      • +

        Sample.Api.Tests.CustomStartupConfigurationsTests+<>c.<GetException_WhenDeveloperPageIsConfigured_ShouldBeInternalServerError>b__0_2(HttpContext context, Func<Task> next) in CustomStartupConfigurationsTests.cs

        + + +
        +
          +
        1. {
        2. +
        3. services.AddMvc();
        4. +
        5. });
        6. +
        7. builder.Configure(app => app
        8. +
        9. .UseDeveloperExceptionPage()
        10. +
        11. .Use((context, next) => {
        12. +
        + +
          +
        1. throw new Exception("Wow!");
        2. +
        + +
          +
        1. }));
        2. +
        3. +
        4. using var testServer = new TestServer(builder);
        5. +
        6. using var client = testServer.CreateClient();
        7. +
        8. +
        9. // Act
        10. +
        +
        +
      • +
      • +

        Microsoft.AspNetCore.Builder.UseExtensions+<>c__DisplayClass0_1.<Use>b__1(HttpContext context)

        + +
      • +
      • +

        Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

        + +
      • +
      +
    • +
    • +
      +
      +
      + +
      +
      +
      System.Exception: Wow!
         at Sample.Api.Tests.CustomStartupConfigurationsTests.<>c.<GetException_WhenDeveloperPageIsConfigured_ShouldBeInternalServerError>b__0_2(HttpContext context, Func`1 next) in E:\projects\mine\FluentAssertions.Web\samples\Sample.Api.Net22.Tests\CustomStartupConfigurationsTests.cs:line 26
         at Microsoft.AspNetCore.Builder.UseExtensions.<>c__DisplayClass0_1.<Use>b__1(HttpContext context)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
      +
      +
      +
    • +
    +
    + +
    +

    No QueryString data.

    +
    + +
    +

    No cookie data.

    +
    +
    +
    VariableValue
    + - - + + - -
    HostlocalhostVariableValue
    -
    - + + + """; + + private const string AspNetCore30InternalServerErrorResponse = """ + System.Exception: Wow! + at Sample.Api.Tests.CustomStartupConfigurationsTests.<>c.b__0_3(HttpContext context) in E:\projects\mine\FluentAssertions.Web\samples\Sample.Api.Net30.Tests\CustomStartupConfigurationsTests.cs:line 30 + at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext) + --- End of stack trace from previous location where exception was thrown --- + at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) + + HEADERS + ======= + Host: localhost + + """; + + [Fact] + public void GivenDisposedRequestContent_ShouldPrintAndShowWarning() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent("", Encoding.UTF8), + RequestMessage = new HttpRequestMessage(HttpMethod.Post, "http://localhost:5001/") + { + Content = new StringContent("Some content.", Encoding.UTF8, "application/json"), + } + }; + subject.RequestMessage.Content.Dispose(); + var sut = new HttpResponseMessageFormatter(); - function tab(el) { - var unselected = ns(""#header .selected"").removeClass(""selected"").attr(""id""); - var selected = ns(""#"" + el.id).addClass(""selected"").attr(""id""); + // Act + sut.Format(subject, formattedGraph, null!, null!); - ns(""#"" + unselected + ""page"").hide(); - ns(""#"" + selected + ""page"").show(); + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + "*Content is disposed so it cannot be read.*"); } - ns("".rawExceptionDetails"").hide(); - ns("".collapsible"").hide(); - ns("".page"").hide(); - ns(""#stackpage"").show(); - - ns("".expandCollapseButton"") - .click(function () { - expandCollapseButton(this); - }) - .keypress(function (e) { - if (e.which === 13) { - expandCollapseButton(this); - } - }); - - ns(""#header li"") - .click(function () { - tab(this); - }) - .keypress(function (e) { - if (e.which === 13) { - tab(this); - } - }); - - ns("".showRawException"") - .click(function () { - var exceptionDetailId = this.getAttribute(""data-exceptionDetailId""); - ns(""#"" + exceptionDetailId).toggle(); - }); -})(window); - //--> - - -"; - - private const string AspNetCore30InternalServerErrorResponse = @"System.Exception: Wow! - at Sample.Api.Tests.CustomStartupConfigurationsTests.<>c.b__0_3(HttpContext context) in E:\projects\mine\FluentAssertions.Web\samples\Sample.Api.Net30.Tests\CustomStartupConfigurationsTests.cs:line 30 - at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext) ---- End of stack trace from previous location where exception was thrown --- - at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) - -HEADERS -======= -Host: localhost -"; - - [Fact] - public void GivenDisposedRequestContent_ShouldPrintAndShowWarning() + [Fact] + public void GivenDisposedRequest_ShouldPrintAndShowWarning() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + Content = new StringContent("", Encoding.UTF8), + RequestMessage = new HttpRequestMessage(HttpMethod.Post, "http://localhost:5001/") { - Content = new StringContent("", Encoding.UTF8), - RequestMessage = new HttpRequestMessage(HttpMethod.Post, "http://localhost:5001/") - { - Content = new StringContent("Some content.", Encoding.UTF8, "application/json"), - } - }; - subject.RequestMessage.Content.Dispose(); - var sut = new HttpResponseMessageFormatter(); + Content = new StringContent("Some content.", Encoding.UTF8, "application/json") + } + }; + subject.RequestMessage.Dispose(); + var sut = new HttpResponseMessageFormatter(); - // Act - sut.Format(subject, formattedGraph, null!, null!); + // Act + sut.Format(subject, formattedGraph, null!, null!); - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*Content is disposed so it cannot be read.*"); - } + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + "*Content is disposed so it cannot be read*"); + } - [Fact] - public void GivenDisposedRequest_ShouldPrintAndShowWarning() + [Fact] + public void GivenByteArrayResponse_ShouldPrintMessageInfo() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new StringContent("", Encoding.UTF8), - RequestMessage = new HttpRequestMessage(HttpMethod.Post, "http://localhost:5001/") - { - Content = new StringContent("Some content.", Encoding.UTF8, "application/json") - } - }; - subject.RequestMessage.Dispose(); - var sut = new HttpResponseMessageFormatter(); + Content = new ByteArrayContent(new byte[1]) + }; + var sut = new HttpResponseMessageFormatter(); - // Act - sut.Format(subject, formattedGraph, null!, null!); + // Act + sut.Format(subject, formattedGraph, null!, null!); - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*Content is disposed so it cannot be read*"); - } + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + "*Content is of a binary encoded like type having the length 1.*"); + } - [Fact] - public void GivenByteArrayResponse_ShouldPrintMessageInfo() + [Fact] + public void GivenByteArrayRequest_ShouldPrintMessageInfo() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + RequestMessage = new HttpRequestMessage { Content = new ByteArrayContent(new byte[1]) - }; - var sut = new HttpResponseMessageFormatter(); + } + }; + var sut = new HttpResponseMessageFormatter(); - // Act - sut.Format(subject, formattedGraph, null!, null!); + // Act + sut.Format(subject, formattedGraph, null!, null!); - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*Content is of a binary encoded like type having the length 1.*"); - } + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + "*Content is of a binary encoded like type having the length 1.*"); + } - [Fact] - public void GivenByteArrayRequest_ShouldPrintMessageInfo() + [Fact] + public void GivenStreamResponse_ShouldPrintMessageInfo() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + Content = new StreamContent(new MemoryStream(new byte[1])) { - RequestMessage = new HttpRequestMessage + Headers = { - Content = new ByteArrayContent(new byte[1]) + ContentType = new MediaTypeHeaderValue("image/jpeg") } - }; - var sut = new HttpResponseMessageFormatter(); + } + }; - // Act - sut.Format(subject, formattedGraph, null!, null!); + var sut = new HttpResponseMessageFormatter(); - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*Content is of a binary encoded like type having the length 1.*"); - } + // Act + sut.Format(subject, formattedGraph, null!, null!); - [Fact] - public void GivenStreamResponse_ShouldPrintMessageInfo() + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + "*Content is of a binary encoded like type having the length 1.*"); + } + + [Fact] + public void GivenStreamRequest_ShouldPrintMessageInfo() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + RequestMessage = new HttpRequestMessage { Content = new StreamContent(new MemoryStream(new byte[1])) { @@ -1044,321 +1093,388 @@ public void GivenStreamResponse_ShouldPrintMessageInfo() ContentType = new MediaTypeHeaderValue("image/jpeg") } } - }; + } + }; - var sut = new HttpResponseMessageFormatter(); + var sut = new HttpResponseMessageFormatter(); - // Act - sut.Format(subject, formattedGraph, null!, null!); + // Act + sut.Format(subject, formattedGraph, null!, null!); - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*Content is of a binary encoded like type having the length 1.*"); - } + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + "*Content is of a binary encoded like type having the length 1.*"); + } - [Fact] - public void GivenStreamRequest_ShouldPrintMessageInfo() + [Fact(Skip = "Don't know how to handle this yet.")] + public void GivenReadOnlyMemoryResponse_ShouldPrintMessageInfo() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) - { - RequestMessage = new HttpRequestMessage - { - Content = new StreamContent(new MemoryStream(new byte[1])) - { - Headers = - { - ContentType = new MediaTypeHeaderValue("image/jpeg") - } - } - } - }; + Content = new ReadOnlyMemoryContent(new ReadOnlyMemory(new byte[1])) + }; - var sut = new HttpResponseMessageFormatter(); + var sut = new HttpResponseMessageFormatter(); - // Act - sut.Format(subject, formattedGraph, null!, null!); + // Act + sut.Format(subject, formattedGraph, null!, null!); - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*Content is of a binary encoded like type having the length 1.*"); - } + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + "*Content is of a binary encoded like type having the length 1.*"); + } - [Fact(Skip = "Don't know how to handle this yet.")] - public void GivenReadOnlyMemoryResponse_ShouldPrintMessageInfo() + [Fact(Skip = "Don't know how to handle this yet.")] + public void GivenReadOnlyMemoryRequest_ShouldPrintMessageInfo() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + RequestMessage = new HttpRequestMessage { Content = new ReadOnlyMemoryContent(new ReadOnlyMemory(new byte[1])) - }; + } + }; - var sut = new HttpResponseMessageFormatter(); + var sut = new HttpResponseMessageFormatter(); - // Act - sut.Format(subject, formattedGraph, null!, null!); + // Act + sut.Format(subject, formattedGraph, null!, null!); - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*Content is of a binary encoded like type having the length 1.*"); - } + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + "*Content is of a binary encoded like type having the length 1.*"); + } - [Fact(Skip = "Don't know how to handle this yet.")] - public void GivenReadOnlyMemoryRequest_ShouldPrintMessageInfo() + [Fact] + public void GivenFormUrlEncodedRequest_ShouldPrintFormUrlEncodedData() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + RequestMessage = new HttpRequestMessage { - RequestMessage = new HttpRequestMessage + Content = new FormUrlEncodedContent(new[] { - Content = new ReadOnlyMemoryContent(new ReadOnlyMemory(new byte[1])) - } - }; + new KeyValuePair("key1", "value1"), + new KeyValuePair("key2", "value2") + }) + } + }; - var sut = new HttpResponseMessageFormatter(); + var sut = new HttpResponseMessageFormatter(); - // Act - sut.Format(subject, formattedGraph, null!, null!); + // Act + sut.Format(subject, formattedGraph, null!, null!); - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*Content is of a binary encoded like type having the length 1.*"); - } + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match( + "*key1=value1&key2=value2*"); + } - [Fact] - public void GivenFormUrlEncodedRequest_ShouldPrintFormUrlEncodedData() + [Fact] + public void GivenMultipartFormDataResponse_ShouldPrintAsSingleParts() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + var content = new MultipartFormDataContent("-----------------------------9051914041544843365972754266") { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + new FormUrlEncodedContent(new[] { - RequestMessage = new HttpRequestMessage - { - Content = new FormUrlEncodedContent(new[] - { - new KeyValuePair("key1", "value1"), - new KeyValuePair("key2", "value2") - }) - } - }; + new KeyValuePair("key1", "value1"), + new KeyValuePair("key2", "value2") + }), + {new ByteArrayContent(new byte[1]), "ByteArray"}, + {new ByteArrayContent(new byte[2]), "ByteArray", "a-file-name.jpg"}, + new StringContent("some string content", Encoding.UTF8, "plain/text") + }; + + using var subject = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = content + }; - var sut = new HttpResponseMessageFormatter(); + var sut = new HttpResponseMessageFormatter(); - // Act - sut.Format(subject, formattedGraph, null!, null!); + // Act + sut.Format(subject, formattedGraph, null!, null!); - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match( - @"*key1=value1&key2=value2*"); - } + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should() + .Match("*key1=value1&key2=value2*") + .And.Match("*Content is of a binary encoded like type having the length 1.*") + .And.Match("*a-file-name.jpg*Content is of a binary encoded like type having the length 2.*") + .And.Match("*plain/text*some string content*"); + } - [Fact] - public void GivenMultipartFormDataResponse_ShouldPrintAsSingleParts() + [Fact] + public async Task GivenMultipartFormDataResponse_AsStreamContent_ShouldPrintAsSingleParts() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + var content = new MultipartFormDataContent("-----------------------------9051914041544843365972754266") { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - var content = new MultipartFormDataContent("-----------------------------9051914041544843365972754266") - { - new FormUrlEncodedContent(new[] - { - new KeyValuePair("key1", "value1"), - new KeyValuePair("key2", "value2") - }), - {new ByteArrayContent(new byte[1]), "ByteArray"}, - {new ByteArrayContent(new byte[2]), "ByteArray", "a-file-name.jpg"}, - new StringContent("some string content", Encoding.UTF8, "plain/text") - }; - - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + new FormUrlEncodedContent(new[] { - Content = content - }; - - var sut = new HttpResponseMessageFormatter(); + new KeyValuePair("key1", "value1"), + new KeyValuePair("key2", "value2") + }), + {new ByteArrayContent(new byte[1]), "ByteArray"}, + {new ByteArrayContent(new byte[2]), "ByteArray", "a-file-name.jpg"}, + new StringContent("some string content", Encoding.UTF8, "plain/text") + }; + + var stream = await content.ReadAsStreamAsync(); + var streamContent = new StreamContent(stream); + + using var subject = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = content + }; - // Act - sut.Format(subject, formattedGraph, null!, null!); + var contentHeaders = subject.Content.Headers.Select(c => new { c.Key, c.Value }).ToArray(); - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should() - .Match(@"*key1=value1&key2=value2*") - .And.Match(@"*Content is of a binary encoded like type having the length 1.*") - .And.Match(@"*a-file-name.jpg*Content is of a binary encoded like type having the length 2.*") - .And.Match(@"*plain/text*some string content*") - ; - } + subject.Content = streamContent; - [Fact] - public async Task GivenMultipartFormDataResponse_AsStreamContent_ShouldPrintAsSingleParts() + foreach (var header in contentHeaders) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - var content = new MultipartFormDataContent("-----------------------------9051914041544843365972754266") - { - new FormUrlEncodedContent(new[] - { - new KeyValuePair("key1", "value1"), - new KeyValuePair("key2", "value2") - }), - {new ByteArrayContent(new byte[1]), "ByteArray"}, - {new ByteArrayContent(new byte[2]), "ByteArray", "a-file-name.jpg"}, - new StringContent("some string content", Encoding.UTF8, "plain/text") - }; - - var stream = await content.ReadAsStreamAsync(); - var streamContent = new StreamContent(stream); + subject.Content.Headers.Add(header.Key, header.Value); + } - using var subject = new HttpResponseMessage(HttpStatusCode.OK) - { - Content = content - }; + var sut = new HttpResponseMessageFormatter(); - var contentHeaders = subject.Content.Headers.Select(c => new { c.Key, c.Value }).ToArray(); + // Act + sut.Format(subject, formattedGraph, null!, null!); - subject.Content = streamContent; + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should() + .Match("*key1=value1&key2=value2*") + .And.Match("*Content-Disposition: form-data; name=ByteArray*") // ByteArrayContent is also presented as a StreamContent so the FallbackProcessor will handle it + .And.Match("*a-file-name.jpg*Content is of a binary encoded like type having the length 2.*") + .And.Match("*plain/text*some string content*"); + } - foreach (var header in contentHeaders) + [Fact] + public void GivenMultipartFormDataRequest_ShouldPrintAsSingleParts() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + var content = new MultipartFormDataContent("-----------------------------9051914041544843365972754266") + { + new FormUrlEncodedContent(new[] + { + new KeyValuePair("key1", "value1"), + new KeyValuePair("key2", "value2") + }), + {new ByteArrayContent(new byte[1]), "ByteArray"}, + {new ByteArrayContent(new byte[2]), "ByteArray", "a-file-name.jpg"}, + new StringContent("some string content", Encoding.UTF8, "plain/text") + }; + + using var subject = new HttpResponseMessage(HttpStatusCode.OK) + { + RequestMessage = new HttpRequestMessage { - subject.Content.Headers.Add(header.Key, header.Value); + Content = content } + }; - var sut = new HttpResponseMessageFormatter(); + var sut = new HttpResponseMessageFormatter(); - // Act - sut.Format(subject, formattedGraph, null!, null!); + // Act + sut.Format(subject, formattedGraph, null!, null!); - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should() - .Match(@"*key1=value1&key2=value2*") - .And.Match(@"*Content-Disposition: form-data; name=ByteArray*") // ByteArrayContent is also presented as a StreamContent so the FallbackProcessor will handle it - .And.Match(@"*a-file-name.jpg*Content is of a binary encoded like type having the length 2.*") - .And.Match(@"*plain/text*some string content*") - ; - } + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should() + .Match("*key1=value1&key2=value2*") + .And.Match("*Content is of a binary encoded like type having the length 1.*") + .And.Match("*a-file-name.jpg*Content is of a binary encoded like type having the length 2.*") + .And.Match("*plain/text*some string content*"); + } - [Fact] - public void GivenMultipartFormDataRequest_ShouldPrintAsSingleParts() + [Fact] + public async Task GivenMultipartFormDataRequest_AsStreamContent_ShouldPrintAsSingleParts() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + var content = new MultipartFormDataContent("-----------------------------9051914041544843365972754266") { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - var content = new MultipartFormDataContent("-----------------------------9051914041544843365972754266") + new FormUrlEncodedContent(new[] { - new FormUrlEncodedContent(new[] - { - new KeyValuePair("key1", "value1"), - new KeyValuePair("key2", "value2") - }), - {new ByteArrayContent(new byte[1]), "ByteArray"}, - {new ByteArrayContent(new byte[2]), "ByteArray", "a-file-name.jpg"}, - new StringContent("some string content", Encoding.UTF8, "plain/text") - }; - - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + new KeyValuePair("key1", "value1"), + new KeyValuePair("key2", "value2") + }), + {new ByteArrayContent(new byte[1]), "ByteArray"}, + {new ByteArrayContent(new byte[2]), "ByteArray", "a-file-name.jpg"}, + new StringContent("some string content", Encoding.UTF8, "plain/text") + }; + + var stream = await content.ReadAsStreamAsync(); + var streamContent = new StreamContent(stream); + + using var subject = new HttpResponseMessage(HttpStatusCode.OK) + { + RequestMessage = new HttpRequestMessage { - RequestMessage = new HttpRequestMessage - { - Content = content - } - }; + Content = content + } + }; - var sut = new HttpResponseMessageFormatter(); + var contentHeaders = subject.RequestMessage.Content.Headers.Select(c => new { c.Key, c.Value }).ToArray(); - // Act - sut.Format(subject, formattedGraph, null!, null!); + subject.RequestMessage.Content = streamContent; - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should() - .Match(@"*key1=value1&key2=value2*") - .And.Match(@"*Content is of a binary encoded like type having the length 1.*") - .And.Match(@"*a-file-name.jpg*Content is of a binary encoded like type having the length 2.*") - .And.Match(@"*plain/text*some string content*") - ; + foreach (var header in contentHeaders) + { + subject.RequestMessage.Content.Headers.Add(header.Key, header.Value); } - [Fact] - public async Task GivenMultipartFormDataRequest_AsStreamContent_ShouldPrintAsSingleParts() - { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - var content = new MultipartFormDataContent("-----------------------------9051914041544843365972754266") - { - new FormUrlEncodedContent(new[] - { - new KeyValuePair("key1", "value1"), - new KeyValuePair("key2", "value2") - }), - {new ByteArrayContent(new byte[1]), "ByteArray"}, - {new ByteArrayContent(new byte[2]), "ByteArray", "a-file-name.jpg"}, - new StringContent("some string content", Encoding.UTF8, "plain/text") - }; + var sut = new HttpResponseMessageFormatter(); - var stream = await content.ReadAsStreamAsync(); - var streamContent = new StreamContent(stream); + // Act + sut.Format(subject, formattedGraph, null!, null!); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) - { - RequestMessage = new HttpRequestMessage - { - Content = content - } - }; + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should() + .Match("*key1=value1&key2=value2*") + .And.Match("*Content-Disposition: form-data; name=ByteArray*") // ByteArrayContent is also presented as a StreamContent so the FallbackProcessor will handle it + .And.Match("*a-file-name.jpg*Content is of a binary encoded like type having the length 2.*") + .And.Match("*plain/text*some string content*"); + } - var contentHeaders = subject.RequestMessage.Content.Headers.Select(c => new { c.Key, c.Value }).ToArray(); + [Fact] + public void GivenLargeStringContent_ShouldNotPrintEverything() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + var whatShouldBePrinted = new string('-', ContentFormatterOptions.MaximumReadableBytes); + var whatNotShouldBePrinted = new string('+', 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent(whatShouldBePrinted + whatNotShouldBePrinted) + }; - subject.RequestMessage.Content = streamContent; + var sut = new HttpResponseMessageFormatter(); - foreach (var header in contentHeaders) - { - subject.RequestMessage.Content.Headers.Add(header.Key, header.Value); + // Act + sut.Format(subject, formattedGraph, null!, null!); + + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match("*Content is too large to display*") + .And.Contain(whatShouldBePrinted) + .And.NotContain(whatNotShouldBePrinted); + } + + [Fact] + public void GivenLargeJsonStringContent_ShouldNotPrintEverything() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + var whatNotShouldBePrinted = new string('+', 100); + var bigPropertyValue = new string('-', ContentFormatterOptions.MaximumReadableBytes); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent($$""" + { + "title": "{{ bigPropertyValue }}", + "description": "{{ whatNotShouldBePrinted }}" } + """, Encoding.UTF8, "application/json") + }; - var sut = new HttpResponseMessageFormatter(); + var sut = new HttpResponseMessageFormatter(); - // Act - sut.Format(subject, formattedGraph, null!, null!); + // Act + sut.Format(subject, formattedGraph, null!, null!); - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should() - .Match(@"*key1=value1&key2=value2*") - .And.Match(@"*Content-Disposition: form-data; name=ByteArray*") // ByteArrayContent is also presented as a StreamContent so the FallbackProcessor will handle it - .And.Match(@"*a-file-name.jpg*Content is of a binary encoded like type having the length 2.*") - .And.Match(@"*plain/text*some string content*"); - } + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match("*Content is too large to display*") + .And.Contain("---") + .And.NotContain(whatNotShouldBePrinted); + } - [Fact] - public void GivenLargeStringContent_ShouldNotPrintEverything() + [Fact] + public void GivenLargeNonPrettifiedJson_ShouldPrintPrettified() + { + // Arrange + var bigPropertyValue = new string('-', ContentFormatterOptions.MaximumReadableBytes); + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - var formattedGraph = new FormattedObjectGraph(maxLines: 100); - var whatShouldBePrinted = new string('-', ContentFormatterOptions.MaximumReadableBytes); - var whatNotShouldBePrinted = new string('+', 100); - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + Content = new StringContent(/*lang=json,strict*/ $$""" { - Content = new StringContent(whatShouldBePrinted + whatNotShouldBePrinted) - }; - - var sut = new HttpResponseMessageFormatter(); - - // Act - sut.Format(subject, formattedGraph, null!, null!); + "glossary":{ + "title":"{{bigPropertyValue}}" + } + } + """, Encoding.UTF8, "application/json") + }; + var sut = new HttpResponseMessageFormatter(); + + // Act + sut.Format(subject, formattedGraph, null!, null!); + + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match(""" + *The HTTP response was:* + HTTP/1.1 200 OK* + Content-Type: application/json; charset=utf-8* + Content-Length:* + *Content is too large to display and only a part is printed* + {* + "glossary": {* + "title": "----* + The originating HTTP request was .* + """); + } - // Assert - var formatted = formattedGraph.ToString(); - formatted.Should().Match("*Content is too large to display*") - .And.Contain(whatShouldBePrinted) - .And.NotContain(whatNotShouldBePrinted); - } + [Fact (Skip = "Nice to have, but not really possible until this one is closed https://github.com/dotnet/runtime/issues/32291")] + public void GivenSyntacticallyMalformedNonPrettifiedJson_ShouldPrintPrettified() + { + // Arrange + var formattedGraph = new FormattedObjectGraph(maxLines: 100); + using var subject = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent(""" + { + "glossary":{ + "title":"" + // syntax error here + } + """, Encoding.UTF8, "application/json") + }; + var sut = new HttpResponseMessageFormatter(); + + // Act + sut.Format(subject, formattedGraph, null!, null!); + + // Assert + var formatted = formattedGraph.ToString(); + formatted.Should().Match(""" + *The HTTP response was:* + HTTP/1.1 200 OK* + Content-Type: application/json; charset=utf-8* + Content-Length:* + {* + "glossary": {* + "title":* + }* + The originating HTTP request was .* + """); } } diff --git a/test/FluentAssertions.Web.Tests/HttpStatusCodeAssertionsSpecs.cs b/test/FluentAssertions.Web.Tests/HttpStatusCodeAssertionsSpecs.cs index 6e20a4b..6b338db 100644 --- a/test/FluentAssertions.Web.Tests/HttpStatusCodeAssertionsSpecs.cs +++ b/test/FluentAssertions.Web.Tests/HttpStatusCodeAssertionsSpecs.cs @@ -1,2613 +1,2606 @@ -using System; -using System.Net; -using System.Net.Http; -using Xunit; -using Xunit.Sdk; +namespace FluentAssertions.Web.Tests; -namespace FluentAssertions.Web.Tests +public class HttpStatusCodeAssertionsSpecs { - public class HttpStatusCodeAssertionsSpecs - { - #region Be1XXInformational - [Theory] - [InlineData(HttpStatusCode.Continue)] - [InlineData(HttpStatusCode.SwitchingProtocols)] - public void When_asserting_response_with_an_informational_status_to_Be1XXInformational_it_should_succeed(HttpStatusCode status) - { - // Arrange - using var subject = new HttpResponseMessage(status); - - // Act - Action act = () => - subject.Should().Be1XXInformational(); - - // Assert - act.Should().NotThrow(); - } - - [Theory] - [InlineData(HttpStatusCode.OK)] - [InlineData(HttpStatusCode.BadRequest)] - [InlineData(HttpStatusCode.InternalServerError)] - public void When_asserting_other_than_an_informational_status_code_response_to_Be1XXInformational_it_should_throw_with_descriptive_message(HttpStatusCode status) - { - // Arrange - using var subject = new HttpResponseMessage(status); - - // Act - Action act = () => - subject.Should().Be1XXInformational("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*to have a HTTP status code representing an informational error*message*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_Be1XXInformational_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be1XXInformational("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region Be2XXSuccessful - [Theory] - [InlineData(HttpStatusCode.OK)] - [InlineData(HttpStatusCode.PartialContent)] - public void When_asserting_response_with_a_successful_status_to_Be2XXSuccessful_it_should_succeed(HttpStatusCode status) - { - // Arrange - using var subject = new HttpResponseMessage(status); - - // Act - Action act = () => - subject.Should().Be2XXSuccessful(); - - // Assert - act.Should().NotThrow(); - } - - [Theory] - [InlineData(HttpStatusCode.SwitchingProtocols)] - [InlineData(HttpStatusCode.PermanentRedirect)] - [InlineData(HttpStatusCode.InternalServerError)] - public void When_asserting_other_than_a_successful_status_code_response_to_Be2XXSuccessful_it_should_throw_with_descriptive_message(HttpStatusCode status) - { - // Arrange - using var subject = new HttpResponseMessage(status); - - // Act - Action act = () => - subject.Should().Be2XXSuccessful("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*have a successful HTTP status code, but it was*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_Be2XXSuccessful_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be2XXSuccessful("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region Be3XXRedirection - [Theory] - [InlineData(HttpStatusCode.Moved)] - [InlineData(HttpStatusCode.TemporaryRedirect)] - public void When_asserting_response_with_a_redirection_status_code_to_Be3XXRedirection_it_should_succeed(HttpStatusCode status) - { - // Arrange - using var subject = new HttpResponseMessage(status); - - // Act - Action act = () => - subject.Should().Be3XXRedirection(); - - // Assert - act.Should().NotThrow(); - } - - [Theory] - [InlineData(HttpStatusCode.Continue)] - [InlineData(HttpStatusCode.OK)] - [InlineData(HttpStatusCode.BadRequest)] - [InlineData(HttpStatusCode.InternalServerError)] - public void When_asserting_other_than_a_client_redirection_status_code_response_to_Be3XXRedirection_it_should_throw_with_descriptive_message(HttpStatusCode status) - { - // Arrange - using var subject = new HttpResponseMessage(status); - - // Act - Action act = () => - subject.Should().Be3XXRedirection("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*to have a HTTP status code representing a redirection*message*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_Be3XXRedirection_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be3XXRedirection("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region Be4XXClientError - [Theory] - [InlineData(HttpStatusCode.BadRequest)] - [InlineData(HttpStatusCode.UpgradeRequired)] - public void When_asserting_response_with_a_client_error_status_code_to_Be4XXClientError_it_should_succeed(HttpStatusCode status) - { - // Arrange - using var subject = new HttpResponseMessage(status); - - // Act - Action act = () => - subject.Should().Be4XXClientError(); - - // Assert - act.Should().NotThrow(); - } - - [Theory] - [InlineData(HttpStatusCode.Continue)] - [InlineData(HttpStatusCode.OK)] - [InlineData(HttpStatusCode.InternalServerError)] - public void When_asserting_other_than_a_client_error_status_code_response_to_Be4XXClientError_it_should_throw_with_descriptive_message(HttpStatusCode status) - { - // Arrange - using var subject = new HttpResponseMessage(status); - - // Act - Action act = () => - subject.Should().Be4XXClientError("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*to have a HTTP status code representing a client error*message*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_Be4XXClientError_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be4XXClientError("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region Be5XXServerError - [Theory] - [InlineData(HttpStatusCode.InternalServerError)] - [InlineData(HttpStatusCode.HttpVersionNotSupported)] - public void When_asserting_response_with_a_server_error_status_code_to_Be5XXServerError_it_should_succeed(HttpStatusCode status) - { - // Arrange - using var subject = new HttpResponseMessage(status); - - // Act - Action act = () => - subject.Should().Be5XXServerError(); - - // Assert - act.Should().NotThrow(); - } - - [Theory] - [InlineData(HttpStatusCode.Continue)] - [InlineData(HttpStatusCode.OK)] - [InlineData(HttpStatusCode.UpgradeRequired)] - public void When_asserting_other_than_a_server_error_status_code_response_to_Be5XXServerError_it_should_throw_with_descriptive_message(HttpStatusCode status) - { - // Arrange - using var subject = new HttpResponseMessage(status); - - // Act - Action act = () => - subject.Should().Be5XXServerError("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*to have a HTTP status code representing a server error*message*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_Be5XXServerError_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be5XXServerError("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region HaveHttpStatusCode - [Fact] - public void When_asserting_response_with_a_status_to_HaveHttpStatusCode_with_that_status_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.Continue); - - // Act - Action act = () => - subject.Should().HaveHttpStatusCode(HttpStatusCode.Continue); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_the_expected_status_response_to_HaveHttpStatusCode_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().HaveHttpStatusCode(HttpStatusCode.BadRequest, "because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.BadRequest*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_HaveHttpStatusCode_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().HaveHttpStatusCode(HttpStatusCode.InternalServerError, "because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region NotHaveHttpStatusCode - [Fact] - public void When_asserting_response_with_a_status_to_NotHaveHttpStatusCode_with_that_other_status_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.Continue); - - // Act - Action act = () => - subject.Should().NotHaveHttpStatusCode(HttpStatusCode.InsufficientStorage); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_response_with_the_unexpected_status_to_NotHaveHttpStatusCode_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().NotHaveHttpStatusCode(HttpStatusCode.OK, "because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*Did not expect*to have status HttpStatusCode.OK {value: 200}*message*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_NotHaveHttpStatusCode_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().NotHaveHttpStatusCode(HttpStatusCode.InternalServerError, "because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 100 Continue - [Fact] - public void When_asserting_100_Continue_response_to_be_100Continue_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.Continue); - - // Act - Action act = () => - subject.Should().Be100Continue(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_100_Continue_response_to_be_100Continue_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be100Continue("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.Continue*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_100Continue_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be100Continue("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 101 Switching Protocols - [Fact] - public void When_asserting_101_Switching_Protocols_response_to_be_101SwitchingProtocols_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.SwitchingProtocols); - - // Act - Action act = () => - subject.Should().Be101SwitchingProtocols(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_101_Switching_Protocols_response_to_be_101SwitchingProtocols_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be101SwitchingProtocols("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.SwitchingProtocols*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_101SwitchingProtocols_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be101SwitchingProtocols("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 200 Ok - [Fact] - public void When_asserting_200_Ok_response_to_be_200_Ok_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be200Ok(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_200_Ok_response_to_be_200_Ok_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest); - - // Act - Action act = () => - subject.Should().Be200Ok("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.OK*because we want to test the failure message, but found HttpStatusCode.BadRequest {value: 400}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_200_Ok_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be200Ok("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 201 Created - [Fact] - public void When_asserting_201_Created_response_to_be_201Created_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.Created); - - // Act - Action act = () => - subject.Should().Be201Created(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_201_Created_response_to_be_201Created_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be201Created("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.Created*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_201Created_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be201Created("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 202 Accepted - [Fact] - public void When_asserting_202_Accepted_response_to_be_202Accepted_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.Accepted); - - // Act - Action act = () => - subject.Should().Be202Accepted(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_202_Accepted_response_to_be_202Accepted_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be202Accepted("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.Accepted*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_202Accepted_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be202Accepted("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 203 Non Authoritative Information - [Fact] - public void When_asserting_203_Non_Authoritative_Information_response_to_be_203NonAuthoritativeInformation_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.NonAuthoritativeInformation); - - // Act - Action act = () => - subject.Should().Be203NonAuthoritativeInformation(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_203_Non_Authoritative_Information_response_to_be_203NonAuthoritativeInformation_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be203NonAuthoritativeInformation("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.NonAuthoritativeInformation*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_203NonAuthoritativeInformation_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be203NonAuthoritativeInformation("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 204 No Content - [Fact] - public void When_asserting_204_No_Content_response_to_be_204NoContent_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.NoContent); - - // Act - Action act = () => - subject.Should().Be204NoContent(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_204_No_Content_response_to_be_204NoContent_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be204NoContent("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.NoContent*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_204NoContent_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be204NoContent("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 205 Reset Content - [Fact] - public void When_asserting_205_Reset_Content_response_to_be_205ResetContent_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.ResetContent); - - // Act - Action act = () => - subject.Should().Be205ResetContent(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_205_Reset_Content_response_to_be_205ResetContent_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be205ResetContent("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.ResetContent*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_205ResetContent_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be205ResetContent("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 206 Partial Content - [Fact] - public void When_asserting_206_Partial_Content_response_to_be_206PartialContent_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.PartialContent); - - // Act - Action act = () => - subject.Should().Be206PartialContent(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_206_Partial_Content_response_to_be_206PartialContent_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be206PartialContent("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.PartialContent*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_206PartialContent_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be206PartialContent("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 300 Multiple Choices - [Fact] - public void When_asserting_300_Multiple_Choices_response_to_be_300MultipleChoices_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.MultipleChoices); - - // Act - Action act = () => - subject.Should().Be300MultipleChoices(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_300_Multiple_Choices_response_to_be_300MultipleChoices_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be300MultipleChoices("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.MultipleChoices*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_300MultipleChoices_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be300MultipleChoices("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 300 Ambiguous - [Fact] - public void When_asserting_300_Ambiguous_response_to_be_300Ambiguous_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.Ambiguous); - - // Act - Action act = () => - subject.Should().Be300Ambiguous(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_300_Ambiguous_response_to_be_300Ambiguous_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be300Ambiguous("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.Ambiguous*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_300Ambiguous_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be300Ambiguous("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 301 Moved Permanently - [Fact] - public void When_asserting_301_Moved_Permanently_response_to_be_301MovedPermanently_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.MovedPermanently); - - // Act - Action act = () => - subject.Should().Be301MovedPermanently(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_301_Moved_Permanently_response_to_be_301MovedPermanently_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be301MovedPermanently("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.MovedPermanently*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_301MovedPermanently_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be301MovedPermanently("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 301 Moved - [Fact] - public void When_asserting_301_Moved_response_to_be_301Moved_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.Moved); - - // Act - Action act = () => - subject.Should().Be301Moved(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_301_Moved_response_to_be_301Moved_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be301Moved("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.Moved*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_301Moved_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be301Moved("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 302 Found - [Fact] - public void When_asserting_302_Found_response_to_be_302Found_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.Found); - - // Act - Action act = () => - subject.Should().Be302Found(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_302_Found_response_to_be_302Found_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be302Found("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.Found*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_302Found_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be302Found("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 302 Redirect - [Fact] - public void When_asserting_302_Redirect_response_to_be_302Redirect_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.Redirect); - - // Act - Action act = () => - subject.Should().Be302Redirect(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_302_Redirect_response_to_be_302Redirect_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be302Redirect("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.Redirect*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_302Redirect_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be302Redirect("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 303 See Other - [Fact] - public void When_asserting_303_See_Other_response_to_be_303SeeOther_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.SeeOther); - - // Act - Action act = () => - subject.Should().Be303SeeOther(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_303_See_Other_response_to_be_303SeeOther_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be303SeeOther("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.SeeOther*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_303SeeOther_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be303SeeOther("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 303 Redirect Method - [Fact] - public void When_asserting_303_Redirect_Method_response_to_be_303RedirectMethod_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.RedirectMethod); - - // Act - Action act = () => - subject.Should().Be303RedirectMethod(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_303_Redirect_Method_response_to_be_303RedirectMethod_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be303RedirectMethod("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.RedirectMethod*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_303RedirectMethod_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be303RedirectMethod("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 304 Not Modified - [Fact] - public void When_asserting_304_Not_Modified_response_to_be_304NotModified_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.NotModified); - - // Act - Action act = () => - subject.Should().Be304NotModified(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_304_Not_Modified_response_to_be_304NotModified_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be304NotModified("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.NotModified*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_304NotModified_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be304NotModified("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 305 Use Proxy - [Fact] - public void When_asserting_305_Use_Proxy_response_to_be_305UseProxy_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.UseProxy); - - // Act - Action act = () => - subject.Should().Be305UseProxy(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_305_Use_Proxy_response_to_be_305UseProxy_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be305UseProxy("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.UseProxy*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_305UseProxy_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be305UseProxy("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 306 Unused - [Fact] - public void When_asserting_306_Unused_response_to_be_306Unused_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.Unused); - - // Act - Action act = () => - subject.Should().Be306Unused(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_306_Unused_response_to_be_306Unused_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be306Unused("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.Unused*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_306Unused_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be306Unused("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 307 Temporary Redirect - [Fact] - public void When_asserting_307_Temporary_Redirect_response_to_be_307TemporaryRedirect_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.TemporaryRedirect); - - // Act - Action act = () => - subject.Should().Be307TemporaryRedirect(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_307_Temporary_Redirect_response_to_be_307TemporaryRedirect_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be307TemporaryRedirect("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.TemporaryRedirect*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_307TemporaryRedirect_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be307TemporaryRedirect("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 307 Redirect Keep Verb - [Fact] - public void When_asserting_307_Redirect_Keep_Verb_response_to_be_307RedirectKeepVerb_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.RedirectKeepVerb); - - // Act - Action act = () => - subject.Should().Be307RedirectKeepVerb(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_307_Redirect_Keep_Verb_response_to_be_307RedirectKeepVerb_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be307RedirectKeepVerb("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.RedirectKeepVerb*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_307RedirectKeepVerb_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be307RedirectKeepVerb("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 400 BadRequest - [Fact] - public void When_asserting_400_BadRequest_response_to_be_400_BadRequest_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest); - - // Act - Action act = () => - subject.Should().Be400BadRequest(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_400_BadRequest_response_to_be_400_BadRequest_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be400BadRequest("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.BadRequest*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_400_BadRequest_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be400BadRequest("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 401 Unauthorized - [Fact] - public void When_asserting_401_Unauthorized_response_to_be_401_Unauthorized_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.Unauthorized); - - // Act - Action act = () => - subject.Should().Be401Unauthorized(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_401_Unauthorized_response_to_be_401_Unauthorized_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be401Unauthorized("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.Unauthorized*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_401_Unauthorized_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be401Unauthorized("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 402 Payment Required - [Fact] - public void When_asserting_402_Payment_Required_response_to_be_402PaymentRequired_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.PaymentRequired); - - // Act - Action act = () => - subject.Should().Be402PaymentRequired(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_402_Payment_Required_response_to_be_402PaymentRequired_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be402PaymentRequired("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.PaymentRequired*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_402PaymentRequired_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be402PaymentRequired("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 403 Forbidden - [Fact] - public void When_asserting_403_Forbidden_response_to_be_403Forbidden_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.Forbidden); - - // Act - Action act = () => - subject.Should().Be403Forbidden(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_403_Forbidden_response_to_be_403Forbidden_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be403Forbidden("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.Forbidden*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_403Forbidden_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be403Forbidden("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 404 Not Found - [Fact] - public void When_asserting_404_Not_Found_response_to_be_404NotFound_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.NotFound); - - // Act - Action act = () => - subject.Should().Be404NotFound(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_404_Not_Found_response_to_be_404NotFound_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be404NotFound("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.NotFound*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_404NotFound_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be404NotFound("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 405 Method Not Allowed - [Fact] - public void When_asserting_405_Method_Not_Allowed_response_to_be_405MethodNotAllowed_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.MethodNotAllowed); - - // Act - Action act = () => - subject.Should().Be405MethodNotAllowed(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_405_Method_Not_Allowed_response_to_be_405MethodNotAllowed_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be405MethodNotAllowed("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.MethodNotAllowed*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_405MethodNotAllowed_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be405MethodNotAllowed("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 406 Not Acceptable - [Fact] - public void When_asserting_406_Not_Acceptable_response_to_be_406NotAcceptable_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.NotAcceptable); - - // Act - Action act = () => - subject.Should().Be406NotAcceptable(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_406_Not_Acceptable_response_to_be_406NotAcceptable_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be406NotAcceptable("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.NotAcceptable*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_406NotAcceptable_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be406NotAcceptable("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 407 Proxy Authentication Required - [Fact] - public void When_asserting_407_Proxy_Authentication_Required_response_to_be_407ProxyAuthenticationRequired_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.ProxyAuthenticationRequired); - - // Act - Action act = () => - subject.Should().Be407ProxyAuthenticationRequired(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_407_Proxy_Authentication_Required_response_to_be_407ProxyAuthenticationRequired_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be407ProxyAuthenticationRequired("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.ProxyAuthenticationRequired*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_407ProxyAuthenticationRequired_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be407ProxyAuthenticationRequired("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 408 Request Timeout - [Fact] - public void When_asserting_408_Request_Timeout_response_to_be_408RequestTimeout_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.RequestTimeout); - - // Act - Action act = () => - subject.Should().Be408RequestTimeout(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_408_Request_Timeout_response_to_be_408RequestTimeout_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be408RequestTimeout("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.RequestTimeout*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_408RequestTimeout_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be408RequestTimeout("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 409 Conflict - [Fact] - public void When_asserting_409_Conflict_response_to_be_409Conflict_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.Conflict); - - // Act - Action act = () => - subject.Should().Be409Conflict(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_409_Conflict_response_to_be_409Conflict_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be409Conflict("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.Conflict*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_409Conflict_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be409Conflict("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 410 Gone - [Fact] - public void When_asserting_410_Gone_response_to_be_410Gone_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.Gone); - - // Act - Action act = () => - subject.Should().Be410Gone(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_410_Gone_response_to_be_410Gone_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be410Gone("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.Gone*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_410Gone_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be410Gone("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 411 Length Required - [Fact] - public void When_asserting_411_Length_Required_response_to_be_411LengthRequired_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.LengthRequired); - - // Act - Action act = () => - subject.Should().Be411LengthRequired(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_411_Length_Required_response_to_be_411LengthRequired_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be411LengthRequired("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.LengthRequired*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_411LengthRequired_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be411LengthRequired("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 412 Precondition Failed - [Fact] - public void When_asserting_412_Precondition_Failed_response_to_be_412PreconditionFailed_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.PreconditionFailed); - - // Act - Action act = () => - subject.Should().Be412PreconditionFailed(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_412_Precondition_Failed_response_to_be_412PreconditionFailed_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be412PreconditionFailed("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.PreconditionFailed*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_412PreconditionFailed_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be412PreconditionFailed("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 413 Request Entity Too Large - [Fact] - public void When_asserting_413_Request_Entity_Too_Large_response_to_be_413RequestEntityTooLarge_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.RequestEntityTooLarge); - - // Act - Action act = () => - subject.Should().Be413RequestEntityTooLarge(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_413_Request_Entity_Too_Large_response_to_be_413RequestEntityTooLarge_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be413RequestEntityTooLarge("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.RequestEntityTooLarge*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_413RequestEntityTooLarge_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be413RequestEntityTooLarge("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 414 Request Uri Too Long - [Fact] - public void When_asserting_414_Request_Uri_Too_Long_response_to_be_414RequestUriTooLong_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.RequestUriTooLong); - - // Act - Action act = () => - subject.Should().Be414RequestUriTooLong(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_414_Request_Uri_Too_Long_response_to_be_414RequestUriTooLong_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be414RequestUriTooLong("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.RequestUriTooLong*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_414RequestUriTooLong_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be414RequestUriTooLong("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 415 Unsupported Media Type - [Fact] - public void When_asserting_415_Unsupported_Media_Type_response_to_be_415UnsupportedMediaType_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType); - - // Act - Action act = () => - subject.Should().Be415UnsupportedMediaType(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_415_Unsupported_Media_Type_response_to_be_415UnsupportedMediaType_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be415UnsupportedMediaType("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.UnsupportedMediaType*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_415UnsupportedMediaType_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be415UnsupportedMediaType("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 416 Requested Range Not Satisfiable - [Fact] - public void When_asserting_416_Requested_Range_Not_Satisfiable_response_to_be_416RequestedRangeNotSatisfiable_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.RequestedRangeNotSatisfiable); - - // Act - Action act = () => - subject.Should().Be416RequestedRangeNotSatisfiable(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_416_Requested_Range_Not_Satisfiable_response_to_be_416RequestedRangeNotSatisfiable_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be416RequestedRangeNotSatisfiable("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.RequestedRangeNotSatisfiable*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_416RequestedRangeNotSatisfiable_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be416RequestedRangeNotSatisfiable("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 417 Expectation Failed - [Fact] - public void When_asserting_417_Expectation_Failed_response_to_be_417ExpectationFailed_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.ExpectationFailed); - - // Act - Action act = () => - subject.Should().Be417ExpectationFailed(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_417_Expectation_Failed_response_to_be_417ExpectationFailed_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be417ExpectationFailed("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.ExpectationFailed*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_417ExpectationFailed_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be417ExpectationFailed("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 422 Unprocessable Entity - [Fact] - public void When_asserting_422_Unprocessable_Entity_response_to_be_417ExpectationFailed_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage((HttpStatusCode)422); - - // Act - Action act = () => - subject.Should().Be422UnprocessableEntity(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_422_Unprocessable_Entity_response_to_be_417ExpectationFailed_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be422UnprocessableEntity("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.UnprocessableEntity*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_422_Unprocessable_Entity_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be422UnprocessableEntity("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 429 Too Many Requests - [Fact] - public void When_asserting_429_Too_Many_Requests_response_to_be_417ExpectationFailed_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage((HttpStatusCode)429); - - // Act - Action act = () => - subject.Should().Be429TooManyRequests(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_429_Too_Many_Requests_response_to_be_417ExpectationFailed_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be429TooManyRequests("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.TooManyRequests*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_429_Too_Many_Requests_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be429TooManyRequests("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 426 Upgrade Required - [Fact] - public void When_asserting_426_Upgrade_Required_response_to_be_426UpgradeRequired_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.UpgradeRequired); - - // Act - Action act = () => - subject.Should().Be426UpgradeRequired(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_426_Upgrade_Required_response_to_be_426UpgradeRequired_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be426UpgradeRequired("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.UpgradeRequired*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_426UpgradeRequired_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be426UpgradeRequired("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 500 Internal Server Error - [Fact] - public void When_asserting_500_Internal_Server_Error_response_to_be_500InternalServerError_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.InternalServerError); - - // Act - Action act = () => - subject.Should().Be500InternalServerError(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_500_Internal_Server_Error_response_to_be_500InternalServerError_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be500InternalServerError("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.InternalServerError*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_500InternalServerError_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be500InternalServerError("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 501 Not Implemented - [Fact] - public void When_asserting_501_Not_Implemented_response_to_be_501NotImplemented_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.NotImplemented); - - // Act - Action act = () => - subject.Should().Be501NotImplemented(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_501_Not_Implemented_response_to_be_501NotImplemented_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be501NotImplemented("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.NotImplemented*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_501NotImplemented_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be501NotImplemented("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 502 Bad Gateway - [Fact] - public void When_asserting_502_Bad_Gateway_response_to_be_502BadGateway_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.BadGateway); - - // Act - Action act = () => - subject.Should().Be502BadGateway(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_502_Bad_Gateway_response_to_be_502BadGateway_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be502BadGateway("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.BadGateway*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_502BadGateway_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be502BadGateway("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 503 Service Unavailable - [Fact] - public void When_asserting_503_Service_Unavailable_response_to_be_503ServiceUnavailable_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.ServiceUnavailable); - - // Act - Action act = () => - subject.Should().Be503ServiceUnavailable(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_503_Service_Unavailable_response_to_be_503ServiceUnavailable_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be503ServiceUnavailable("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.ServiceUnavailable*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_503ServiceUnavailable_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be503ServiceUnavailable("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 504 Gateway Timeout - [Fact] - public void When_asserting_504_Gateway_Timeout_response_to_be_504GatewayTimeout_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.GatewayTimeout); - - // Act - Action act = () => - subject.Should().Be504GatewayTimeout(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_504_Gateway_Timeout_response_to_be_504GatewayTimeout_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be504GatewayTimeout("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.GatewayTimeout*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_504GatewayTimeout_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be504GatewayTimeout("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region 505 Http Version Not Supported - [Fact] - public void When_asserting_505_Http_Version_Not_Supported_response_to_be_505HttpVersionNotSupported_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.HttpVersionNotSupported); - - // Act - Action act = () => - subject.Should().Be505HttpVersionNotSupported(); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_other_than_505_Http_Version_Not_Supported_response_to_be_505HttpVersionNotSupported_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK); - - // Act - Action act = () => - subject.Should().Be505HttpVersionNotSupported("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"*HttpStatusCode.HttpVersionNotSupported*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); - } - - [Fact] - public void When_asserting_null_HttpResponse_to_be_505HttpVersionNotSupported_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Be505HttpVersionNotSupported("because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion + #region Be1XXInformational + [Theory] + [InlineData(HttpStatusCode.Continue)] + [InlineData(HttpStatusCode.SwitchingProtocols)] + public void When_asserting_response_with_an_informational_status_to_Be1XXInformational_it_should_succeed(HttpStatusCode status) + { + // Arrange + using var subject = new HttpResponseMessage(status); + + // Act + Action act = () => + subject.Should().Be1XXInformational(); + + // Assert + act.Should().NotThrow(); + } + + [Theory] + [InlineData(HttpStatusCode.OK)] + [InlineData(HttpStatusCode.BadRequest)] + [InlineData(HttpStatusCode.InternalServerError)] + public void When_asserting_other_than_an_informational_status_code_response_to_Be1XXInformational_it_should_throw_with_descriptive_message(HttpStatusCode status) + { + // Arrange + using var subject = new HttpResponseMessage(status); + + // Act + Action act = () => + subject.Should().Be1XXInformational("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*to have a HTTP status code representing an informational error*message*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_Be1XXInformational_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be1XXInformational("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region Be2XXSuccessful + [Theory] + [InlineData(HttpStatusCode.OK)] + [InlineData(HttpStatusCode.PartialContent)] + public void When_asserting_response_with_a_successful_status_to_Be2XXSuccessful_it_should_succeed(HttpStatusCode status) + { + // Arrange + using var subject = new HttpResponseMessage(status); + + // Act + Action act = () => + subject.Should().Be2XXSuccessful(); + + // Assert + act.Should().NotThrow(); + } + + [Theory] + [InlineData(HttpStatusCode.SwitchingProtocols)] + [InlineData(HttpStatusCode.PermanentRedirect)] + [InlineData(HttpStatusCode.InternalServerError)] + public void When_asserting_other_than_a_successful_status_code_response_to_Be2XXSuccessful_it_should_throw_with_descriptive_message(HttpStatusCode status) + { + // Arrange + using var subject = new HttpResponseMessage(status); + + // Act + Action act = () => + subject.Should().Be2XXSuccessful("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*have a successful HTTP status code, but it was*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_Be2XXSuccessful_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be2XXSuccessful("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region Be3XXRedirection + [Theory] + [InlineData(HttpStatusCode.Moved)] + [InlineData(HttpStatusCode.TemporaryRedirect)] + public void When_asserting_response_with_a_redirection_status_code_to_Be3XXRedirection_it_should_succeed(HttpStatusCode status) + { + // Arrange + using var subject = new HttpResponseMessage(status); + + // Act + Action act = () => + subject.Should().Be3XXRedirection(); + + // Assert + act.Should().NotThrow(); + } + + [Theory] + [InlineData(HttpStatusCode.Continue)] + [InlineData(HttpStatusCode.OK)] + [InlineData(HttpStatusCode.BadRequest)] + [InlineData(HttpStatusCode.InternalServerError)] + public void When_asserting_other_than_a_client_redirection_status_code_response_to_Be3XXRedirection_it_should_throw_with_descriptive_message(HttpStatusCode status) + { + // Arrange + using var subject = new HttpResponseMessage(status); + + // Act + Action act = () => + subject.Should().Be3XXRedirection("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*to have a HTTP status code representing a redirection*message*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_Be3XXRedirection_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be3XXRedirection("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region Be4XXClientError + [Theory] + [InlineData(HttpStatusCode.BadRequest)] + [InlineData(HttpStatusCode.UpgradeRequired)] + public void When_asserting_response_with_a_client_error_status_code_to_Be4XXClientError_it_should_succeed(HttpStatusCode status) + { + // Arrange + using var subject = new HttpResponseMessage(status); + + // Act + Action act = () => + subject.Should().Be4XXClientError(); + + // Assert + act.Should().NotThrow(); + } + + [Theory] + [InlineData(HttpStatusCode.Continue)] + [InlineData(HttpStatusCode.OK)] + [InlineData(HttpStatusCode.InternalServerError)] + public void When_asserting_other_than_a_client_error_status_code_response_to_Be4XXClientError_it_should_throw_with_descriptive_message(HttpStatusCode status) + { + // Arrange + using var subject = new HttpResponseMessage(status); + + // Act + Action act = () => + subject.Should().Be4XXClientError("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*to have a HTTP status code representing a client error*message*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_Be4XXClientError_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be4XXClientError("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region Be5XXServerError + [Theory] + [InlineData(HttpStatusCode.InternalServerError)] + [InlineData(HttpStatusCode.HttpVersionNotSupported)] + public void When_asserting_response_with_a_server_error_status_code_to_Be5XXServerError_it_should_succeed(HttpStatusCode status) + { + // Arrange + using var subject = new HttpResponseMessage(status); + + // Act + Action act = () => + subject.Should().Be5XXServerError(); + + // Assert + act.Should().NotThrow(); + } + + [Theory] + [InlineData(HttpStatusCode.Continue)] + [InlineData(HttpStatusCode.OK)] + [InlineData(HttpStatusCode.UpgradeRequired)] + public void When_asserting_other_than_a_server_error_status_code_response_to_Be5XXServerError_it_should_throw_with_descriptive_message(HttpStatusCode status) + { + // Arrange + using var subject = new HttpResponseMessage(status); + + // Act + Action act = () => + subject.Should().Be5XXServerError("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*to have a HTTP status code representing a server error*message*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_Be5XXServerError_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be5XXServerError("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region HaveHttpStatusCode + [Fact] + public void When_asserting_response_with_a_status_to_HaveHttpStatusCode_with_that_status_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.Continue); + + // Act + Action act = () => + subject.Should().HaveHttpStatusCode(HttpStatusCode.Continue); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_the_expected_status_response_to_HaveHttpStatusCode_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().HaveHttpStatusCode(HttpStatusCode.BadRequest, "because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.BadRequest*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_HaveHttpStatusCode_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().HaveHttpStatusCode(HttpStatusCode.InternalServerError, "because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region NotHaveHttpStatusCode + [Fact] + public void When_asserting_response_with_a_status_to_NotHaveHttpStatusCode_with_that_other_status_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.Continue); + + // Act + Action act = () => + subject.Should().NotHaveHttpStatusCode(HttpStatusCode.InsufficientStorage); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_with_the_unexpected_status_to_NotHaveHttpStatusCode_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().NotHaveHttpStatusCode(HttpStatusCode.OK, "because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*Did not expect*to have status HttpStatusCode.OK {value: 200}*message*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_NotHaveHttpStatusCode_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().NotHaveHttpStatusCode(HttpStatusCode.InternalServerError, "because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 100 Continue + [Fact] + public void When_asserting_100_Continue_response_to_be_100Continue_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.Continue); + + // Act + Action act = () => + subject.Should().Be100Continue(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_100_Continue_response_to_be_100Continue_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be100Continue("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.Continue*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_100Continue_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be100Continue("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 101 Switching Protocols + [Fact] + public void When_asserting_101_Switching_Protocols_response_to_be_101SwitchingProtocols_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.SwitchingProtocols); + + // Act + Action act = () => + subject.Should().Be101SwitchingProtocols(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_101_Switching_Protocols_response_to_be_101SwitchingProtocols_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be101SwitchingProtocols("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.SwitchingProtocols*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_101SwitchingProtocols_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be101SwitchingProtocols("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 200 Ok + [Fact] + public void When_asserting_200_Ok_response_to_be_200_Ok_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be200Ok(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_200_Ok_response_to_be_200_Ok_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest); + + // Act + Action act = () => + subject.Should().Be200Ok("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.OK*because we want to test the failure message, but found HttpStatusCode.BadRequest {value: 400}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_200_Ok_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be200Ok("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 201 Created + [Fact] + public void When_asserting_201_Created_response_to_be_201Created_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.Created); + + // Act + Action act = () => + subject.Should().Be201Created(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_201_Created_response_to_be_201Created_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be201Created("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.Created*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_201Created_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be201Created("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 202 Accepted + [Fact] + public void When_asserting_202_Accepted_response_to_be_202Accepted_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.Accepted); + + // Act + Action act = () => + subject.Should().Be202Accepted(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_202_Accepted_response_to_be_202Accepted_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be202Accepted("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.Accepted*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_202Accepted_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be202Accepted("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 203 Non Authoritative Information + [Fact] + public void When_asserting_203_Non_Authoritative_Information_response_to_be_203NonAuthoritativeInformation_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.NonAuthoritativeInformation); + + // Act + Action act = () => + subject.Should().Be203NonAuthoritativeInformation(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_203_Non_Authoritative_Information_response_to_be_203NonAuthoritativeInformation_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be203NonAuthoritativeInformation("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.NonAuthoritativeInformation*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_203NonAuthoritativeInformation_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be203NonAuthoritativeInformation("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 204 No Content + [Fact] + public void When_asserting_204_No_Content_response_to_be_204NoContent_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.NoContent); + + // Act + Action act = () => + subject.Should().Be204NoContent(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_204_No_Content_response_to_be_204NoContent_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be204NoContent("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.NoContent*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_204NoContent_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be204NoContent("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 205 Reset Content + [Fact] + public void When_asserting_205_Reset_Content_response_to_be_205ResetContent_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.ResetContent); + + // Act + Action act = () => + subject.Should().Be205ResetContent(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_205_Reset_Content_response_to_be_205ResetContent_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be205ResetContent("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.ResetContent*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_205ResetContent_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be205ResetContent("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 206 Partial Content + [Fact] + public void When_asserting_206_Partial_Content_response_to_be_206PartialContent_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.PartialContent); + + // Act + Action act = () => + subject.Should().Be206PartialContent(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_206_Partial_Content_response_to_be_206PartialContent_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be206PartialContent("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.PartialContent*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_206PartialContent_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be206PartialContent("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 300 Multiple Choices + [Fact] + public void When_asserting_300_Multiple_Choices_response_to_be_300MultipleChoices_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.MultipleChoices); + + // Act + Action act = () => + subject.Should().Be300MultipleChoices(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_300_Multiple_Choices_response_to_be_300MultipleChoices_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be300MultipleChoices("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.MultipleChoices*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_300MultipleChoices_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be300MultipleChoices("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 300 Ambiguous + [Fact] + public void When_asserting_300_Ambiguous_response_to_be_300Ambiguous_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.Ambiguous); + + // Act + Action act = () => + subject.Should().Be300Ambiguous(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_300_Ambiguous_response_to_be_300Ambiguous_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be300Ambiguous("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.Ambiguous*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_300Ambiguous_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be300Ambiguous("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 301 Moved Permanently + [Fact] + public void When_asserting_301_Moved_Permanently_response_to_be_301MovedPermanently_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.MovedPermanently); + + // Act + Action act = () => + subject.Should().Be301MovedPermanently(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_301_Moved_Permanently_response_to_be_301MovedPermanently_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be301MovedPermanently("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.MovedPermanently*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_301MovedPermanently_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be301MovedPermanently("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 301 Moved + [Fact] + public void When_asserting_301_Moved_response_to_be_301Moved_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.Moved); + + // Act + Action act = () => + subject.Should().Be301Moved(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_301_Moved_response_to_be_301Moved_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be301Moved("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.Moved*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_301Moved_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be301Moved("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 302 Found + [Fact] + public void When_asserting_302_Found_response_to_be_302Found_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.Found); + + // Act + Action act = () => + subject.Should().Be302Found(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_302_Found_response_to_be_302Found_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be302Found("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.Found*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_302Found_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be302Found("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 302 Redirect + [Fact] + public void When_asserting_302_Redirect_response_to_be_302Redirect_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.Redirect); + + // Act + Action act = () => + subject.Should().Be302Redirect(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_302_Redirect_response_to_be_302Redirect_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be302Redirect("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.Redirect*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_302Redirect_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be302Redirect("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 303 See Other + [Fact] + public void When_asserting_303_See_Other_response_to_be_303SeeOther_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.SeeOther); + + // Act + Action act = () => + subject.Should().Be303SeeOther(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_303_See_Other_response_to_be_303SeeOther_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be303SeeOther("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.SeeOther*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_303SeeOther_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be303SeeOther("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 303 Redirect Method + [Fact] + public void When_asserting_303_Redirect_Method_response_to_be_303RedirectMethod_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.RedirectMethod); + + // Act + Action act = () => + subject.Should().Be303RedirectMethod(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_303_Redirect_Method_response_to_be_303RedirectMethod_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be303RedirectMethod("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.RedirectMethod*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_303RedirectMethod_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be303RedirectMethod("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 304 Not Modified + [Fact] + public void When_asserting_304_Not_Modified_response_to_be_304NotModified_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.NotModified); + + // Act + Action act = () => + subject.Should().Be304NotModified(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_304_Not_Modified_response_to_be_304NotModified_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be304NotModified("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.NotModified*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_304NotModified_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be304NotModified("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 305 Use Proxy + [Fact] + public void When_asserting_305_Use_Proxy_response_to_be_305UseProxy_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.UseProxy); + + // Act + Action act = () => + subject.Should().Be305UseProxy(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_305_Use_Proxy_response_to_be_305UseProxy_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be305UseProxy("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.UseProxy*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_305UseProxy_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be305UseProxy("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 306 Unused + [Fact] + public void When_asserting_306_Unused_response_to_be_306Unused_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.Unused); + + // Act + Action act = () => + subject.Should().Be306Unused(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_306_Unused_response_to_be_306Unused_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be306Unused("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.Unused*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_306Unused_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be306Unused("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 307 Temporary Redirect + [Fact] + public void When_asserting_307_Temporary_Redirect_response_to_be_307TemporaryRedirect_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.TemporaryRedirect); + + // Act + Action act = () => + subject.Should().Be307TemporaryRedirect(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_307_Temporary_Redirect_response_to_be_307TemporaryRedirect_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be307TemporaryRedirect("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.TemporaryRedirect*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_307TemporaryRedirect_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be307TemporaryRedirect("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 307 Redirect Keep Verb + [Fact] + public void When_asserting_307_Redirect_Keep_Verb_response_to_be_307RedirectKeepVerb_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.RedirectKeepVerb); + + // Act + Action act = () => + subject.Should().Be307RedirectKeepVerb(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_307_Redirect_Keep_Verb_response_to_be_307RedirectKeepVerb_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be307RedirectKeepVerb("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.RedirectKeepVerb*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_307RedirectKeepVerb_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be307RedirectKeepVerb("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 400 BadRequest + [Fact] + public void When_asserting_400_BadRequest_response_to_be_400_BadRequest_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadRequest); + + // Act + Action act = () => + subject.Should().Be400BadRequest(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_400_BadRequest_response_to_be_400_BadRequest_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be400BadRequest("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.BadRequest*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_400_BadRequest_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be400BadRequest("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 401 Unauthorized + [Fact] + public void When_asserting_401_Unauthorized_response_to_be_401_Unauthorized_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.Unauthorized); + + // Act + Action act = () => + subject.Should().Be401Unauthorized(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_401_Unauthorized_response_to_be_401_Unauthorized_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be401Unauthorized("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.Unauthorized*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_401_Unauthorized_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be401Unauthorized("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 402 Payment Required + [Fact] + public void When_asserting_402_Payment_Required_response_to_be_402PaymentRequired_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.PaymentRequired); + + // Act + Action act = () => + subject.Should().Be402PaymentRequired(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_402_Payment_Required_response_to_be_402PaymentRequired_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be402PaymentRequired("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.PaymentRequired*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_402PaymentRequired_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be402PaymentRequired("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 403 Forbidden + [Fact] + public void When_asserting_403_Forbidden_response_to_be_403Forbidden_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.Forbidden); + + // Act + Action act = () => + subject.Should().Be403Forbidden(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_403_Forbidden_response_to_be_403Forbidden_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be403Forbidden("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.Forbidden*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_403Forbidden_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be403Forbidden("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 404 Not Found + [Fact] + public void When_asserting_404_Not_Found_response_to_be_404NotFound_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.NotFound); + + // Act + Action act = () => + subject.Should().Be404NotFound(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_404_Not_Found_response_to_be_404NotFound_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be404NotFound("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.NotFound*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_404NotFound_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be404NotFound("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 405 Method Not Allowed + [Fact] + public void When_asserting_405_Method_Not_Allowed_response_to_be_405MethodNotAllowed_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.MethodNotAllowed); + + // Act + Action act = () => + subject.Should().Be405MethodNotAllowed(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_405_Method_Not_Allowed_response_to_be_405MethodNotAllowed_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be405MethodNotAllowed("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.MethodNotAllowed*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_405MethodNotAllowed_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be405MethodNotAllowed("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 406 Not Acceptable + [Fact] + public void When_asserting_406_Not_Acceptable_response_to_be_406NotAcceptable_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.NotAcceptable); + + // Act + Action act = () => + subject.Should().Be406NotAcceptable(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_406_Not_Acceptable_response_to_be_406NotAcceptable_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be406NotAcceptable("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.NotAcceptable*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_406NotAcceptable_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be406NotAcceptable("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 407 Proxy Authentication Required + [Fact] + public void When_asserting_407_Proxy_Authentication_Required_response_to_be_407ProxyAuthenticationRequired_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.ProxyAuthenticationRequired); + + // Act + Action act = () => + subject.Should().Be407ProxyAuthenticationRequired(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_407_Proxy_Authentication_Required_response_to_be_407ProxyAuthenticationRequired_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be407ProxyAuthenticationRequired("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.ProxyAuthenticationRequired*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_407ProxyAuthenticationRequired_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be407ProxyAuthenticationRequired("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 408 Request Timeout + [Fact] + public void When_asserting_408_Request_Timeout_response_to_be_408RequestTimeout_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.RequestTimeout); + + // Act + Action act = () => + subject.Should().Be408RequestTimeout(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_408_Request_Timeout_response_to_be_408RequestTimeout_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be408RequestTimeout("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.RequestTimeout*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_408RequestTimeout_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be408RequestTimeout("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 409 Conflict + [Fact] + public void When_asserting_409_Conflict_response_to_be_409Conflict_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.Conflict); + + // Act + Action act = () => + subject.Should().Be409Conflict(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_409_Conflict_response_to_be_409Conflict_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be409Conflict("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.Conflict*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_409Conflict_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be409Conflict("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 410 Gone + [Fact] + public void When_asserting_410_Gone_response_to_be_410Gone_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.Gone); + + // Act + Action act = () => + subject.Should().Be410Gone(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_410_Gone_response_to_be_410Gone_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be410Gone("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.Gone*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_410Gone_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be410Gone("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 411 Length Required + [Fact] + public void When_asserting_411_Length_Required_response_to_be_411LengthRequired_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.LengthRequired); + + // Act + Action act = () => + subject.Should().Be411LengthRequired(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_411_Length_Required_response_to_be_411LengthRequired_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be411LengthRequired("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.LengthRequired*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_411LengthRequired_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be411LengthRequired("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 412 Precondition Failed + [Fact] + public void When_asserting_412_Precondition_Failed_response_to_be_412PreconditionFailed_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.PreconditionFailed); + + // Act + Action act = () => + subject.Should().Be412PreconditionFailed(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_412_Precondition_Failed_response_to_be_412PreconditionFailed_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be412PreconditionFailed("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.PreconditionFailed*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_412PreconditionFailed_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be412PreconditionFailed("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 413 Request Entity Too Large + [Fact] + public void When_asserting_413_Request_Entity_Too_Large_response_to_be_413RequestEntityTooLarge_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.RequestEntityTooLarge); + + // Act + Action act = () => + subject.Should().Be413RequestEntityTooLarge(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_413_Request_Entity_Too_Large_response_to_be_413RequestEntityTooLarge_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be413RequestEntityTooLarge("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.RequestEntityTooLarge*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_413RequestEntityTooLarge_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be413RequestEntityTooLarge("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 414 Request Uri Too Long + [Fact] + public void When_asserting_414_Request_Uri_Too_Long_response_to_be_414RequestUriTooLong_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.RequestUriTooLong); + + // Act + Action act = () => + subject.Should().Be414RequestUriTooLong(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_414_Request_Uri_Too_Long_response_to_be_414RequestUriTooLong_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be414RequestUriTooLong("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.RequestUriTooLong*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_414RequestUriTooLong_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be414RequestUriTooLong("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 415 Unsupported Media Type + [Fact] + public void When_asserting_415_Unsupported_Media_Type_response_to_be_415UnsupportedMediaType_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType); + + // Act + Action act = () => + subject.Should().Be415UnsupportedMediaType(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_415_Unsupported_Media_Type_response_to_be_415UnsupportedMediaType_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be415UnsupportedMediaType("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.UnsupportedMediaType*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_415UnsupportedMediaType_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be415UnsupportedMediaType("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 416 Requested Range Not Satisfiable + [Fact] + public void When_asserting_416_Requested_Range_Not_Satisfiable_response_to_be_416RequestedRangeNotSatisfiable_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.RequestedRangeNotSatisfiable); + + // Act + Action act = () => + subject.Should().Be416RequestedRangeNotSatisfiable(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_416_Requested_Range_Not_Satisfiable_response_to_be_416RequestedRangeNotSatisfiable_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be416RequestedRangeNotSatisfiable("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.RequestedRangeNotSatisfiable*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_416RequestedRangeNotSatisfiable_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be416RequestedRangeNotSatisfiable("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 417 Expectation Failed + [Fact] + public void When_asserting_417_Expectation_Failed_response_to_be_417ExpectationFailed_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.ExpectationFailed); + + // Act + Action act = () => + subject.Should().Be417ExpectationFailed(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_417_Expectation_Failed_response_to_be_417ExpectationFailed_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be417ExpectationFailed("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.ExpectationFailed*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_417ExpectationFailed_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be417ExpectationFailed("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 422 Unprocessable Entity + [Fact] + public void When_asserting_422_Unprocessable_Entity_response_to_be_417ExpectationFailed_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage((HttpStatusCode)422); + + // Act + Action act = () => + subject.Should().Be422UnprocessableEntity(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_422_Unprocessable_Entity_response_to_be_417ExpectationFailed_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be422UnprocessableEntity("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.UnprocessableEntity*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_422_Unprocessable_Entity_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be422UnprocessableEntity("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 429 Too Many Requests + [Fact] + public void When_asserting_429_Too_Many_Requests_response_to_be_417ExpectationFailed_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage((HttpStatusCode)429); + + // Act + Action act = () => + subject.Should().Be429TooManyRequests(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_429_Too_Many_Requests_response_to_be_417ExpectationFailed_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be429TooManyRequests("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.TooManyRequests*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_429_Too_Many_Requests_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be429TooManyRequests("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 426 Upgrade Required + [Fact] + public void When_asserting_426_Upgrade_Required_response_to_be_426UpgradeRequired_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.UpgradeRequired); + + // Act + Action act = () => + subject.Should().Be426UpgradeRequired(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_426_Upgrade_Required_response_to_be_426UpgradeRequired_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be426UpgradeRequired("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.UpgradeRequired*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_426UpgradeRequired_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be426UpgradeRequired("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 500 Internal Server Error + [Fact] + public void When_asserting_500_Internal_Server_Error_response_to_be_500InternalServerError_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.InternalServerError); + + // Act + Action act = () => + subject.Should().Be500InternalServerError(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_500_Internal_Server_Error_response_to_be_500InternalServerError_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be500InternalServerError("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.InternalServerError*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_500InternalServerError_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be500InternalServerError("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 501 Not Implemented + [Fact] + public void When_asserting_501_Not_Implemented_response_to_be_501NotImplemented_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.NotImplemented); + + // Act + Action act = () => + subject.Should().Be501NotImplemented(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_501_Not_Implemented_response_to_be_501NotImplemented_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be501NotImplemented("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.NotImplemented*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_501NotImplemented_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be501NotImplemented("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 502 Bad Gateway + [Fact] + public void When_asserting_502_Bad_Gateway_response_to_be_502BadGateway_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.BadGateway); + + // Act + Action act = () => + subject.Should().Be502BadGateway(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_502_Bad_Gateway_response_to_be_502BadGateway_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be502BadGateway("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.BadGateway*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_502BadGateway_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be502BadGateway("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 503 Service Unavailable + [Fact] + public void When_asserting_503_Service_Unavailable_response_to_be_503ServiceUnavailable_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.ServiceUnavailable); + + // Act + Action act = () => + subject.Should().Be503ServiceUnavailable(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_503_Service_Unavailable_response_to_be_503ServiceUnavailable_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be503ServiceUnavailable("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.ServiceUnavailable*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_503ServiceUnavailable_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be503ServiceUnavailable("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 504 Gateway Timeout + [Fact] + public void When_asserting_504_Gateway_Timeout_response_to_be_504GatewayTimeout_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.GatewayTimeout); + + // Act + Action act = () => + subject.Should().Be504GatewayTimeout(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_504_Gateway_Timeout_response_to_be_504GatewayTimeout_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be504GatewayTimeout("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.GatewayTimeout*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_504GatewayTimeout_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be504GatewayTimeout("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region 505 Http Version Not Supported + [Fact] + public void When_asserting_505_Http_Version_Not_Supported_response_to_be_505HttpVersionNotSupported_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.HttpVersionNotSupported); + + // Act + Action act = () => + subject.Should().Be505HttpVersionNotSupported(); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_other_than_505_Http_Version_Not_Supported_response_to_be_505HttpVersionNotSupported_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK); + + // Act + Action act = () => + subject.Should().Be505HttpVersionNotSupported("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("*HttpStatusCode.HttpVersionNotSupported*because we want to test the failure message, but found HttpStatusCode.OK {value: 200}*"); + } + + [Fact] + public void When_asserting_null_HttpResponse_to_be_505HttpVersionNotSupported_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Be505HttpVersionNotSupported("because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); } + #endregion } \ No newline at end of file diff --git a/test/FluentAssertions.Web.Tests/Internal/ApiAccessibilityTests.cs b/test/FluentAssertions.Web.Tests/Internal/ApiAccessibilityTests.cs index 4958d48..176706f 100644 --- a/test/FluentAssertions.Web.Tests/Internal/ApiAccessibilityTests.cs +++ b/test/FluentAssertions.Web.Tests/Internal/ApiAccessibilityTests.cs @@ -1,166 +1,161 @@ -using FluentAssertions.Execution; -using FluentAssertions.Primitives; -using System.Linq; -using System.Net.Http; +using FluentAssertions.Primitives; using System.Reflection; -using Xunit; -namespace FluentAssertions.Web.Tests.Internal +namespace FluentAssertions.Web.Tests.Internal; + +public class ApiAccessibilityTests { - public class ApiAccessibilityTests + [Fact] + public void GivenTypesFromTheInternalNamespace_ThenShouldBeInternalOrLessThanInternal() { - [Fact] - public void GivenTypesFromTheInternalNamespace_ThenShouldBeInternalOrLessThanInternal() - { - // Arrange - var typesFromInternal = typeof(HttpResponseMessageAssertions).Assembly - .GetTypes() - .Where(c => c.Namespace?.Contains("Internal") == true); - - // Assert - using (new AssertionScope()) - foreach (var type in typesFromInternal) - { - type.Should().NotHaveAccessModifier(Common.CSharpAccessModifier.Public); - } - } + // Arrange + var typesFromInternal = typeof(HttpResponseMessageAssertions).Assembly + .GetTypes() + .Where(c => c.Namespace?.Contains("Internal") == true); + + // Assert + using (new AssertionScope()) + foreach (var type in typesFromInternal) + { + type.Should().NotHaveAccessModifier(Common.CSharpAccessModifier.Public); + } + } - [Fact] - public void GivenAssertionsExtensions_ThenShouldHaveFluentAssertionsNamespaceOnly() - { - // Arrange - var assertionsExtensionsTypes = typeof(HttpResponseMessageAssertions).Assembly - .GetTypes() - .Where(c => c.Name.EndsWith("AssertionsExtensions")); - - // Assert - using (new AssertionScope()) - foreach (var type in assertionsExtensionsTypes) - { - type.Namespace.Should().Be("FluentAssertions", "because we want to make sure {0} has the FluentAssertions namespace", type.Name); - } - } + [Fact] + public void GivenAssertionsExtensions_ThenShouldHaveFluentAssertionsNamespaceOnly() + { + // Arrange + var assertionsExtensionsTypes = typeof(HttpResponseMessageAssertions).Assembly + .GetTypes() + .Where(c => c.Name.EndsWith("AssertionsExtensions")); + + // Assert + using (new AssertionScope()) + foreach (var type in assertionsExtensionsTypes) + { + type.Namespace.Should().Be("FluentAssertions", "because we want to make sure {0} has the FluentAssertions namespace", type.Name); + } + } - [Fact] - public void ThereShouldAlways_Be_Assertions_Extensions_Ending_With_The_AssertionsExtensions_Suffix() - { - // Arrange - var assertionsExtensionsTypes = typeof(HttpResponseMessageAssertions).Assembly - .GetTypes() - .Where(c => c.Name.EndsWith("AssertionsExtensions")); + [Fact] + public void ThereShouldAlways_Be_Assertions_Extensions_Ending_With_The_AssertionsExtensions_Suffix() + { + // Arrange + var assertionsExtensionsTypes = typeof(HttpResponseMessageAssertions).Assembly + .GetTypes() + .Where(c => c.Name.EndsWith("AssertionsExtensions")); - // Assert - assertionsExtensionsTypes.Should().NotBeEmpty(); - } + // Assert + assertionsExtensionsTypes.Should().NotBeEmpty(); + } - [Fact] - public void Each_HttpResponseMessage_Assertion_ShouldHaveAnExtensionOverPrimitivesHttpResponseMessageAssertions() + [Fact] + public void Each_HttpResponseMessage_Assertion_ShouldHaveAnExtensionOverPrimitivesHttpResponseMessageAssertions() + { + // Arrange + var baseAssertionsType = typeof(ReferenceTypeAssertions); + var httpResponseMessageAssertions = typeof(HttpResponseMessageAssertions).Assembly + .GetTypes() + .Where(c => c.BaseType == baseAssertionsType) + .ToList(); + httpResponseMessageAssertions.Should().NotBeEmpty(); + + var allExtensions = typeof(HttpResponseMessageAssertions).Assembly + .GetTypes() + .Where(c => c.Name.EndsWith("AssertionsExtensions")) + .SelectMany(c => c.GetMethods(BindingFlags.Static | BindingFlags.Public)) + .ToList(); + + // Assert + foreach (var assertionType in httpResponseMessageAssertions) { - // Arrange - var baseAssertionsType = typeof(ReferenceTypeAssertions); - var httpResponseMessageAssertions = typeof(HttpResponseMessageAssertions).Assembly - .GetTypes() - .Where(c => c.BaseType == baseAssertionsType) - .ToList(); - httpResponseMessageAssertions.Should().NotBeEmpty(); - - var allExtensions = typeof(HttpResponseMessageAssertions).Assembly - .GetTypes() - .Where(c => c.Name.EndsWith("AssertionsExtensions")) - .SelectMany(c => c.GetMethods(BindingFlags.Static | BindingFlags.Public)) - .ToList(); - - // Assert - foreach (var assertionType in httpResponseMessageAssertions) + foreach (var assertionMethod in assertionType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { - foreach (var assertionMethod in assertionType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) - { - allExtensions.Should().Contain(extensionMethod => - extensionMethod.Name == assertionMethod.Name - && extensionMethod.ReturnType.GetType() == assertionMethod.ReturnType.GetType() - && SameParameters(extensionMethod, assertionMethod), - "\n we wanted to check \n" + - "the assertion method {0} \n" + - "from assertion type {1} \n" + - "and return type {2} \n" + - "and arguments {3} \n" + - "has a corresponding extension method", - assertionMethod.Name, - assertionType.FullName, - assertionMethod.ReturnType.FullName, - string.Join(", ", assertionMethod.GetParameters().Select(c => $"{c.Name} of type {c.ParameterType.FullName}"))); - } + allExtensions.Should().Contain(extensionMethod => + extensionMethod.Name == assertionMethod.Name + && extensionMethod.ReturnType.GetType() == assertionMethod.ReturnType.GetType() + && SameParameters(extensionMethod, assertionMethod), + "\n we wanted to check \n" + + "the assertion method {0} \n" + + "from assertion type {1} \n" + + "and return type {2} \n" + + "and arguments {3} \n" + + "has a corresponding extension method", + assertionMethod.Name, + assertionType.FullName, + assertionMethod.ReturnType.FullName, + string.Join(", ", assertionMethod.GetParameters().Select(c => $"{c.Name} of type {c.ParameterType.FullName}"))); } } + } - [Fact] - public void Each_HttpResponseMessage_Assertion_Should_Have_The_CustomAssertion_Attribute() - { - // Arrange - var baseAssertionsType = typeof(ReferenceTypeAssertions); - var httpResponseMessageAssertions = typeof(HttpResponseMessageAssertions).Assembly - .GetTypes() - .Where(c => c.BaseType == baseAssertionsType) - .SelectMany(assertionType => - assertionType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) - .ToList(); - - // Assert - httpResponseMessageAssertions - .Should().AllSatisfy(method => method.Should().BeDecoratedWith()); - } + [Fact] + public void Each_HttpResponseMessage_Assertion_Should_Have_The_CustomAssertion_Attribute() + { + // Arrange + var baseAssertionsType = typeof(ReferenceTypeAssertions); + var httpResponseMessageAssertions = typeof(HttpResponseMessageAssertions).Assembly + .GetTypes() + .Where(c => c.BaseType == baseAssertionsType) + .SelectMany(assertionType => + assertionType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) + .ToList(); + + // Assert + httpResponseMessageAssertions + .Should().AllSatisfy(method => method.Should().BeDecoratedWith()); + } - [Fact] - public void Each_HttpResponseMessage_Assertion_Extension_Should_Have_The_CustomAssertion_Attribute() - { - // Arrange - var allExtensions = typeof(HttpResponseMessageAssertions).Assembly - .GetTypes() - .Where(c => c.Name.EndsWith("AssertionsExtensions")) - .SelectMany(c => c.GetMethods(BindingFlags.Static | BindingFlags.Public)) - .ToList(); - - // Assert - allExtensions.Should().AllSatisfy(method => method.Should().BeDecoratedWith()); - } + [Fact] + public void Each_HttpResponseMessage_Assertion_Extension_Should_Have_The_CustomAssertion_Attribute() + { + // Arrange + var allExtensions = typeof(HttpResponseMessageAssertions).Assembly + .GetTypes() + .Where(c => c.Name.EndsWith("AssertionsExtensions")) + .SelectMany(c => c.GetMethods(BindingFlags.Static | BindingFlags.Public)) + .ToList(); + + // Assert + allExtensions.Should().AllSatisfy(method => method.Should().BeDecoratedWith()); + } + + [Fact] + public void Each_HttpResponseMessage_Assertion_Extension_Should_Be_In_The_Fluent_Assertions_Namespace_Only() + { + // Arrange + var httpResponseMessageAssertionsExtensionsTypes = typeof(HttpResponseMessageAssertions).Assembly + .GetTypes() + .Where(c => c.Name.EndsWith("AssertionsExtensions")) + .ToList(); + + // Assert + httpResponseMessageAssertionsExtensionsTypes + .Should().OnlyContain(type => type.Namespace == "FluentAssertions"); + } + + private static bool SameParameters(MethodInfo extensionMethod, MethodInfo assertionMethod) + { + var extensionMethodParameters = extensionMethod.GetParameters(); + var assertionMethodParameters = assertionMethod.GetParameters(); - [Fact] - public void Each_HttpResponseMessage_Assertion_Extension_Should_Be_In_The_Fluent_Assertions_Namespace_Only() + if (assertionMethodParameters.Length == 0) { - // Arrange - var httpResponseMessageAssertionsExtensionsTypes = typeof(HttpResponseMessageAssertions).Assembly - .GetTypes() - .Where(c => c.Name.EndsWith("AssertionsExtensions")) - .ToList(); - - // Assert - httpResponseMessageAssertionsExtensionsTypes - .Should().OnlyContain(type => type.Namespace == "FluentAssertions"); + return true; } - private static bool SameParameters(MethodInfo extensionMethod, MethodInfo assertionMethod) + if (assertionMethodParameters.Length == extensionMethodParameters.Length - 1) // skip this from ext { - var extensionMethodParameters = extensionMethod.GetParameters(); - var assertionMethodParameters = assertionMethod.GetParameters(); - - if (assertionMethodParameters.Length == 0) + for (var i = 0; i < assertionMethodParameters.Length; i++) { - return true; - } - - if (assertionMethodParameters.Length == extensionMethodParameters.Length - 1) // skip this from ext - { - for (var i = 0; i < assertionMethodParameters.Length; i++) + if (extensionMethodParameters[i + 1].Name != assertionMethodParameters[i].Name + && extensionMethodParameters[i + 1].ParameterType != assertionMethodParameters[i].ParameterType) { - if (extensionMethodParameters[i + 1].Name != assertionMethodParameters[i].Name - && extensionMethodParameters[i + 1].ParameterType != assertionMethodParameters[i].ParameterType) - { - return false; - } + return false; } } - - return true; } + + return true; } } diff --git a/test/FluentAssertions.Web.Tests/Internal/ContentProcessors/FallbackProcessorTests.cs b/test/FluentAssertions.Web.Tests/Internal/ContentProcessors/FallbackProcessorTests.cs index 46b78c1..3fa2b45 100644 --- a/test/FluentAssertions.Web.Tests/Internal/ContentProcessors/FallbackProcessorTests.cs +++ b/test/FluentAssertions.Web.Tests/Internal/ContentProcessors/FallbackProcessorTests.cs @@ -1,133 +1,124 @@ -using System.IO; -using FluentAssertions.Web.Internal; -using FluentAssertions.Web.Internal.ContentProcessors; -using System.Linq; -using System.Net; -using System.Net.Http; +using FluentAssertions.Web.Internal.ContentProcessors; using System.Net.Http.Headers; -using System.Text; -using System.Threading.Tasks; -using Xunit; -namespace FluentAssertions.Web.Tests.Internal.ContentProcessors +namespace FluentAssertions.Web.Tests.Internal.ContentProcessors; + +public class FallbackProcessorTests { - public class FallbackProcessorTests + [Fact] + public async Task GivenHttpResponseWithNoContent_WhenGetContentInfo_ThenIsEmpty() { - [Fact] - public async Task GivenHttpResponseWithNoContent_WhenGetContentInfo_ThenIsEmpty() - { - // Arrange - using var response = new HttpResponseMessage(); - var sut = new FallbackProcessor(response.Content); - var contentBuilder = new StringBuilder(); + // Arrange + using var response = new HttpResponseMessage(); + var sut = new FallbackProcessor(response.Content); + var contentBuilder = new StringBuilder(); - // Act - await sut.GetContentInfo(contentBuilder); + // Act + await sut.GetContentInfo(contentBuilder); - // Assert - contentBuilder.ToString().Should().BeEmpty(); - } + // Assert + contentBuilder.ToString().Should().BeEmpty(); + } - [Fact] - public async Task GivenHttpResponseWithContent_WhenGetContentInfo_ThenItContainsTheContent() + [Fact] + public async Task GivenHttpResponseWithContent_WhenGetContentInfo_ThenItContainsTheContent() + { + // Arrange + using var response = new HttpResponseMessage { - // Arrange - using var response = new HttpResponseMessage - { - Content = new StringContent("the content") - }; - var sut = new FallbackProcessor(response.Content); - var contentBuilder = new StringBuilder(); + Content = new StringContent("the content") + }; + var sut = new FallbackProcessor(response.Content); + var contentBuilder = new StringBuilder(); - // Act - await sut.GetContentInfo(contentBuilder); + // Act + await sut.GetContentInfo(contentBuilder); - // Assert - contentBuilder.ToString().Should().Be("the content"); - } + // Assert + contentBuilder.ToString().Should().Be("the content"); + } - [Fact] - public async Task GivenContentWithLengthTooLarge_WhenGetContentInfo_ThenItContainsAWarningMessage() + [Fact] + public async Task GivenContentWithLengthTooLarge_WhenGetContentInfo_ThenItContainsAWarningMessage() + { + // Arrange + using var response = new HttpResponseMessage { - // Arrange - using var response = new HttpResponseMessage - { - Content = new StringContent(new string(Enumerable - .Range(0, ContentFormatterOptions.MaximumReadableBytes + 1) - .Select(_ => '0') - .ToArray())) - }; - var sut = new FallbackProcessor(response.Content); - var contentBuilder = new StringBuilder(); - - // Act - await sut.GetContentInfo(contentBuilder); - - // Assert - contentBuilder.ToString().Should().Match("*too large*"); - } - - [Fact] - public async Task GivenHttpResponseWithDisposedContent_WhenGetContentInfo_ThenIsEmpty() + Content = new StringContent(new string(Enumerable + .Range(0, ContentFormatterOptions.MaximumReadableBytes + 1) + .Select(_ => '0') + .ToArray())) + }; + var sut = new FallbackProcessor(response.Content); + var contentBuilder = new StringBuilder(); + + // Act + await sut.GetContentInfo(contentBuilder); + + // Assert + contentBuilder.ToString().Should().Match("*too large*"); + } + + [Fact] + public async Task GivenHttpResponseWithDisposedContent_WhenGetContentInfo_ThenIsEmpty() + { + // Arrange + var content = new StringContent("the content"); + using var response = new HttpResponseMessage { - // Arrange - var content = new StringContent("the content"); - using var response = new HttpResponseMessage - { - Content = content - }; - var sut = new FallbackProcessor(response.Content); - var contentBuilder = new StringBuilder(); - content.Dispose(); - - // Act - await sut.GetContentInfo(contentBuilder); - - // Assert - contentBuilder.ToString().Should().Match( - @"*Content is disposed so it cannot be read.*"); - } - - [Fact] - public async Task GivenStreamResponse_WhenGetContentInfo_ThenTryToPrint() + Content = content + }; + var sut = new FallbackProcessor(response.Content); + var contentBuilder = new StringBuilder(); + content.Dispose(); + + // Act + await sut.GetContentInfo(contentBuilder); + + // Assert + contentBuilder.ToString().Should().Match( + "*Content is disposed so it cannot be read.*"); + } + + [Fact] + public async Task GivenStreamResponse_WhenGetContentInfo_ThenTryToPrint() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK) + Content = new StreamContent(new MemoryStream(new byte[1])) { - Content = new StreamContent(new MemoryStream(new byte[1])) + Headers = { - Headers = - { - ContentType = new MediaTypeHeaderValue("image/jpeg") - } + ContentType = new MediaTypeHeaderValue("image/jpeg") } - }; - var sut = new FallbackProcessor(subject.Content); - var contentBuilder = new StringBuilder(); + } + }; + var sut = new FallbackProcessor(subject.Content); + var contentBuilder = new StringBuilder(); - // Act - await sut.GetContentInfo(contentBuilder); + // Act + await sut.GetContentInfo(contentBuilder); - // Assert - contentBuilder.ToString().Should().NotBeNullOrEmpty(); - } + // Assert + contentBuilder.ToString().Should().NotBeNullOrEmpty(); + } - [Fact] - public async Task GivenByteArrayResponse_WhenGetContentInfo_ThenTryToPrint() + [Fact] + public async Task GivenByteArrayResponse_WhenGetContentInfo_ThenTryToPrint() + { + // Arrange + using var subject = new HttpResponseMessage(HttpStatusCode.OK) { - // Arrange - using var subject = new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new ByteArrayContent(new byte[1]) - }; - var sut = new FallbackProcessor(subject.Content); - var contentBuilder = new StringBuilder(); + Content = new ByteArrayContent(new byte[1]) + }; + var sut = new FallbackProcessor(subject.Content); + var contentBuilder = new StringBuilder(); - // Act - await sut.GetContentInfo(contentBuilder); + // Act + await sut.GetContentInfo(contentBuilder); - // Assert - contentBuilder.ToString().Should().NotBeNullOrEmpty(); - } + // Assert + contentBuilder.ToString().Should().NotBeNullOrEmpty(); } } diff --git a/test/FluentAssertions.Web.Tests/Internal/ContentProcessors/InternalServerErrorProcessorTests.cs b/test/FluentAssertions.Web.Tests/Internal/ContentProcessors/InternalServerErrorProcessorTests.cs index b2cdf28..f82af85 100644 --- a/test/FluentAssertions.Web.Tests/Internal/ContentProcessors/InternalServerErrorProcessorTests.cs +++ b/test/FluentAssertions.Web.Tests/Internal/ContentProcessors/InternalServerErrorProcessorTests.cs @@ -1,625 +1,623 @@ using FluentAssertions.Web.Internal.ContentProcessors; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using Xunit; -namespace FluentAssertions.Web.Tests.Internal.ContentProcessors +namespace FluentAssertions.Web.Tests.Internal.ContentProcessors; + +public class InternalServerErrorProcessorTests { - public class InternalServerErrorProcessorTests + [Fact] + public async Task GivenHttpResponseOtherThanInternalServerError_WhenGetContentInfo_ThenIsEmpty() { - [Fact] - public async Task GivenHttpResponseOtherThanInternalServerError_WhenGetContentInfo_ThenIsEmpty() + // Arrange + var response = new HttpResponseMessage { - // Arrange - var response = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK - }; - var sut = new InternalServerErrorProcessor(response, response.Content); - var contentBuilder = new StringBuilder(); - - // Act - await sut.GetContentInfo(contentBuilder); - - // Assert - contentBuilder.ToString().Should().BeEmpty(); - } + StatusCode = HttpStatusCode.OK + }; + var sut = new InternalServerErrorProcessor(response, response.Content); + var contentBuilder = new StringBuilder(); - [Fact] - public async Task GivenHttpResponseWithContentThatDoesNotDescribeAKnownError_WhenGetContentInfo_ThenIsEmpty() - { - // Arrange - var response = new HttpResponseMessage - { - StatusCode = HttpStatusCode.InternalServerError, - Content = new StringContent("the content") - }; - var sut = new InternalServerErrorProcessor(response, response.Content); - var contentBuilder = new StringBuilder(); - - // Act - await sut.GetContentInfo(contentBuilder); - - // Assert - contentBuilder.ToString().Should().BeEmpty(); - } + // Act + await sut.GetContentInfo(contentBuilder); - [Fact] - public async Task GivenHttpResponseWithDeveloperPage_WhenGetContentInfo_ThenExceptionDetailsAreExtracted() - { - // Arrange - var response = new HttpResponseMessage - { - StatusCode = HttpStatusCode.InternalServerError, - Content = new StringContent(HtmlPageInternalServerErrorResponse) - }; - var sut = new InternalServerErrorProcessor(response, response.Content); - var contentBuilder = new StringBuilder(); - - // Act - await sut.GetContentInfo(contentBuilder); - - // Assert - contentBuilder.ToString().Should() - .Match("*System.Exception: Wow!*DeveloperExceptionPageMiddleware*") - .And.NotContain(""); - } - - [Fact] - public async Task GivenHttpResponseWithRawTextDeveloperPage_WhenGetContentInfo_ThenExceptionDetailsAreExtracted() - { - // Arrange - var response = new HttpResponseMessage - { - StatusCode = HttpStatusCode.InternalServerError, - Content = new StringContent(RawTextInternalServerErrorResponse) - }; - var sut = new InternalServerErrorProcessor(response, response.Content); - var contentBuilder = new StringBuilder(); - - // Act - await sut.GetContentInfo(contentBuilder); - - // Assert - contentBuilder.ToString().Should() - .Match("*System.Exception: Wow!*DeveloperExceptionPageMiddleware*") - .And.NotContain("HEADERS"); - } + // Assert + contentBuilder.ToString().Should().BeEmpty(); + } - [Fact] - public async Task GivenHttpResponseWithDisposedContent_WhenGetContentInfo_ThenIsEmpty() + [Fact] + public async Task GivenHttpResponseWithContentThatDoesNotDescribeAKnownError_WhenGetContentInfo_ThenIsEmpty() + { + // Arrange + var response = new HttpResponseMessage { - // Arrange - var content = new StringContent(RawTextInternalServerErrorResponse); - var response = new HttpResponseMessage - { - StatusCode = HttpStatusCode.InternalServerError, - Content = content - }; - var sut = new InternalServerErrorProcessor(response, response.Content); - var contentBuilder = new StringBuilder(); - content.Dispose(); - - // Act - await sut.GetContentInfo(contentBuilder); - - // Assert - contentBuilder.ToString().Should().BeEmpty(); - } + StatusCode = HttpStatusCode.InternalServerError, + Content = new StringContent("the content") + }; + var sut = new InternalServerErrorProcessor(response, response.Content); + var contentBuilder = new StringBuilder(); - private const string HtmlPageInternalServerErrorResponse = @" - - - - Internal Server Error - - - -

    An unhandled exception occurred while processing the request.

    -
    Exception: Wow!
    -

    Sample.Api.Tests.CustomStartupConfigurationsTests+<>c.<GetException_WhenDeveloperPageIsConfigured_ShouldBeInternalServerError>b__0_2(HttpContext context, Func<Task> next) in CustomStartupConfigurationsTests.cs, line 26

    -
      -
    • - Stack -
    • -
    • - Query -
    • -
    • - Cookies -
    • -
    • - Headers -
    • -
    - -
    -
      -
    • -

      Exception: Wow!

      -
        -
      • -

        Sample.Api.Tests.CustomStartupConfigurationsTests+<>c.<GetException_WhenDeveloperPageIsConfigured_ShouldBeInternalServerError>b__0_2(HttpContext context, Func<Task> next) in CustomStartupConfigurationsTests.cs

        - - -
        -
          -
        1. {
        2. -
        3. services.AddMvc();
        4. -
        5. });
        6. -
        7. builder.Configure(app => app
        8. -
        9. .UseDeveloperExceptionPage()
        10. -
        11. .Use((context, next) => {
        12. -
        + a { + color: #1ba1e2; + text-decoration: none; + } -
          -
        1. throw new Exception("Wow!");
        2. -
        - -
          -
        1. }));
        2. -
        3. -
        4. using var testServer = new TestServer(builder);
        5. -
        6. using var client = testServer.CreateClient();
        7. -
        8. -
        9. // Act
        10. -
        -
        -
      • -
      • -

        Microsoft.AspNetCore.Builder.UseExtensions+<>c__DisplayClass0_1.<Use>b__1(HttpContext context)

        - -
      • -
      • -

        Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

        - -
      • -
      -
    • -
    • -
      -
      -
      - -
      -
      -
      System.Exception: Wow!
         at Sample.Api.Tests.CustomStartupConfigurationsTests.<>c.<GetException_WhenDeveloperPageIsConfigured_ShouldBeInternalServerError>b__0_2(HttpContext context, Func`1 next) in E:\projects\mine\FluentAssertions.Web\samples\Sample.Api.Net22.Tests\CustomStartupConfigurationsTests.cs:line 26
         at Microsoft.AspNetCore.Builder.UseExtensions.<>c__DisplayClass0_1.<Use>b__1(HttpContext context)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
      -
      -
      -
    • -
    -
    - -
    -

    No QueryString data.

    -
    - -
    -

    No cookie data.

    -
    -
    - - - - - - - - - - - - - -
    VariableValue
    Hostlocalhost
    -
    - - -"; - private const string RawTextInternalServerErrorResponse = @"System.Exception: Wow! - at Sample.Api.Tests.CustomStartupConfigurationsTests.<>c.b__0_3(HttpContext context) in E:\projects\mine\FluentAssertions.Web\samples\Sample.Api.Net30.Tests\CustomStartupConfigurationsTests.cs:line 30 - at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext) ---- End of stack trace from previous location where exception was thrown --- - at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) - -HEADERS -======= -Host: localhost -"; - } + }) + .keypress(function (e) { + if (e.which === 13) { + tab(this); + } + }); + + ns(".showRawException") + .click(function () { + var exceptionDetailId = this.getAttribute("data-exceptionDetailId"); + ns("#" + exceptionDetailId).toggle(); + }); + })(window); + //--> + + + + """; + private const string RawTextInternalServerErrorResponse = """ + System.Exception: Wow! + at Sample.Api.Tests.CustomStartupConfigurationsTests.<>c.b__0_3(HttpContext context) in E:\projects\mine\FluentAssertions.Web\samples\Sample.Api.Net30.Tests\CustomStartupConfigurationsTests.cs:line 30 + at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext) + --- End of stack trace from previous location where exception was thrown --- + at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) + + HEADERS + ======= + Host: localhost + + """; } diff --git a/test/FluentAssertions.Web.Tests/Internal/ContentProcessors/JsonProcessorTests.cs b/test/FluentAssertions.Web.Tests/Internal/ContentProcessors/JsonProcessorTests.cs index 0952e52..3622026 100644 --- a/test/FluentAssertions.Web.Tests/Internal/ContentProcessors/JsonProcessorTests.cs +++ b/test/FluentAssertions.Web.Tests/Internal/ContentProcessors/JsonProcessorTests.cs @@ -1,89 +1,86 @@ using FluentAssertions.Web.Internal.ContentProcessors; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using Xunit; -namespace FluentAssertions.Web.Tests.Internal.ContentProcessors +namespace FluentAssertions.Web.Tests.Internal.ContentProcessors; + +public class JsonProcessorTests { - public class JsonProcessorTests + [Fact] + public async Task GivenHttpResponseWithNoContent_WhenGetContentInfo_ThenIsEmpty() + { + // Arrange + using var response = new HttpResponseMessage(); + var sut = new JsonProcessor(response.Content); + var contentBuilder = new StringBuilder(); + + // Act + await sut.GetContentInfo(contentBuilder); + + // Assert + contentBuilder.ToString().Should().BeEmpty(); + } + + [Fact] + public async Task GivenContentTypeOtherThanApplicationJson_WhenGetContentInfo_ThenIsEmpty() { - [Fact] - public async Task GivenHttpResponseWithNoContent_WhenGetContentInfo_ThenIsEmpty() - { - // Arrange - using var response = new HttpResponseMessage(); - var sut = new JsonProcessor(response.Content); - var contentBuilder = new StringBuilder(); - - // Act - await sut.GetContentInfo(contentBuilder); - - // Assert - contentBuilder.ToString().Should().BeEmpty(); - } - - [Fact] - public async Task GivenContentTypeOtherThanApplicationJson_WhenGetContentInfo_ThenIsEmpty() - { - // Arrange - var content = new StringContent("", Encoding.UTF8, "application/xml"); - var sut = new JsonProcessor(content); - var contentBuilder = new StringBuilder(); - - // Act - await sut.GetContentInfo(contentBuilder); - - // Assert - contentBuilder.ToString().Should().BeEmpty(); - } - - [Fact] - public async Task GivenANonJsonContentWithAnApplicationJsonMediaType_WhenGetContentInfo_ThenItIsTheExpectedJson() - { - // Arrange - var content = new StringContent(@"giberish", Encoding.UTF8, "application/json"); - var sut = new JsonProcessor(content); - var contentBuilder = new StringBuilder(); - - // Act - await sut.GetContentInfo(contentBuilder); - - // Assert - contentBuilder.ToString().Should().Match(@"giberish"); - } - - [Fact] - public async Task GivenAJsonContentWithAnApplicationJsonMediaType_WhenGetContentInfo_ThenItIsTheExpectedJson() - { - // Arrange - var content = new StringContent(@"{ ""a"": ""json""}", Encoding.UTF8, "application/json"); - var sut = new JsonProcessor(content); - var contentBuilder = new StringBuilder(); - - // Act - await sut.GetContentInfo(contentBuilder); - - // Assert - contentBuilder.ToString().Should().Match(@"{* -*""a"": ""json""* -}*"); - } - - [Fact] - public async Task GivenHttpResponseWithDisposedContent_WhenGetContentInfo_ThenIsEmpty() - { - // Arrange - var content = new StringContent(@"giberish", Encoding.UTF8, "application/json"); - var sut = new JsonProcessor(content); - var contentBuilder = new StringBuilder(); - content.Dispose(); - - // Act - await sut.GetContentInfo(contentBuilder); - - // Assert - contentBuilder.ToString().Should().BeEmpty(); - } + // Arrange + var content = new StringContent("", Encoding.UTF8, "application/xml"); + var sut = new JsonProcessor(content); + var contentBuilder = new StringBuilder(); + + // Act + await sut.GetContentInfo(contentBuilder); + + // Assert + contentBuilder.ToString().Should().BeEmpty(); + } + + [Fact] + public async Task GivenANonJsonContentWithAnApplicationJsonMediaType_WhenGetContentInfo_ThenItIsTheExpectedJson() + { + // Arrange + var content = new StringContent("giberish", Encoding.UTF8, "application/json"); + var sut = new JsonProcessor(content); + var contentBuilder = new StringBuilder(); + + // Act + await sut.GetContentInfo(contentBuilder); + + // Assert + contentBuilder.ToString().Should().Match("giberish"); + } + + [Fact] + public async Task GivenAJsonContentWithAnApplicationJsonMediaType_WhenGetContentInfo_ThenItIsTheExpectedJson() + { + // Arrange + var content = new StringContent(/*lang=json,strict*/ """{ "a": "json"}""", Encoding.UTF8, "application/json"); + var sut = new JsonProcessor(content); + var contentBuilder = new StringBuilder(); + + // Act + await sut.GetContentInfo(contentBuilder); + + // Assert + contentBuilder.ToString().Should().Match(""" + {* + *"a": "json"* + }* + """); + } + + [Fact] + public async Task GivenHttpResponseWithDisposedContent_WhenGetContentInfo_ThenIsEmpty() + { + // Arrange + var content = new StringContent("giberish", Encoding.UTF8, "application/json"); + var sut = new JsonProcessor(content); + var contentBuilder = new StringBuilder(); + content.Dispose(); + + // Act + await sut.GetContentInfo(contentBuilder); + + // Assert + contentBuilder.ToString().Should().BeEmpty(); } } diff --git a/test/FluentAssertions.Web.Tests/Internal/HttpContentExtensionsTests.cs b/test/FluentAssertions.Web.Tests/Internal/HttpContentExtensionsTests.cs index ee6291c..37e7f89 100644 --- a/test/FluentAssertions.Web.Tests/Internal/HttpContentExtensionsTests.cs +++ b/test/FluentAssertions.Web.Tests/Internal/HttpContentExtensionsTests.cs @@ -1,169 +1,164 @@ -using FluentAssertions.Web.Internal; -using FluentAssertions.Web.Internal.Serializers; -using FluentAssertions.Web.Tests.TestModels; -using System.Collections.Generic; -using System.Net.Http; -using System.Threading.Tasks; -using Xunit; - -namespace FluentAssertions.Web.Tests.Internal +using FluentAssertions.Web.Tests.TestModels; + +namespace FluentAssertions.Web.Tests.Internal; + +public class HttpContentExtensionsTests { - public class HttpContentExtensionsTests - { - public static IEnumerable TestSerializers() => new List - { - new object[] { new SystemTextJsonSerializer() }, - new object[] { new NewtonsoftJsonSerializer() } - }; - - [Theory] - [MemberData(nameof(TestSerializers))] - public async Task Reads_A_Json_As_Expected(ISerializer serializer) - { - // Arrange - var content = new StringContent(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] - } - }"); - - // Act - var result = await content.ReadAsAsync(new + public static IEnumerable TestSerializers() => new List { - errors = new Dictionary() - }, serializer); + new object[] { new SystemTextJsonSerializer() }, + new object[] { new NewtonsoftJsonSerializer() } + }; - // Assert - result.Should().NotBeNull(); - result!.errors.Should().ContainKey("Author"); + [Theory] + [MemberData(nameof(TestSerializers))] + public async Task Reads_A_Json_As_Expected(ISerializer serializer) + { + // Arrange + var content = new StringContent(/*lang=json,strict*/ """ + { + "errors": { + "Author": [ + "The Author field is required." + ] + } } + """); - [Theory] - [MemberData(nameof(TestSerializers))] - public async Task Reads_A_Json_With_Numbered_Enum_Value(ISerializer serializer) + // Act + var result = await content.ReadAsAsync(new { - // Arrange - var content = new StringContent(@"{ ""type"" : 2 }"); + errors = new Dictionary() + }, serializer); - // Act - var result = await content.ReadAsAsync(new - { - type = default(TestEnum) - }, serializer); + // Assert + result.Should().NotBeNull(); + result!.errors.Should().ContainKey("Author"); + } - // Assert - result.Should().NotBeNull(); - result!.type.Should().Be(TestEnum.Type1); - } + [Theory] + [MemberData(nameof(TestSerializers))] + public async Task Reads_A_Json_With_Numbered_Enum_Value(ISerializer serializer) + { + // Arrange + var content = new StringContent(/*lang=json,strict*/ """{ "type" : 2 } """); - [Theory] - [MemberData(nameof(TestSerializers))] - public async Task Reads_A_Json_With_Quoted_Numbered_Enum_Value(ISerializer serializer) + // Act + var result = await content.ReadAsAsync(new { - // Arrange - var content = new StringContent(@"{ ""type"" : ""2"" }"); + type = default(TestEnum) + }, serializer); - // Act - var result = await content.ReadAsAsync(new - { - type = default(TestEnum) - }, serializer); + // Assert + result.Should().NotBeNull(); + result!.type.Should().Be(TestEnum.Type1); + } - // Assert - result.Should().NotBeNull(); - result!.type.Should().Be(TestEnum.Type1); - } + [Theory] + [MemberData(nameof(TestSerializers))] + public async Task Reads_A_Json_With_Quoted_Numbered_Enum_Value(ISerializer serializer) + { + // Arrange + var content = new StringContent(/*lang=json,strict*/ """{ "type" : "2" } """); - [Theory] - [MemberData(nameof(TestSerializers))] - public async Task Reads_A_Json_With_String_CamelCase_Enum_Value(ISerializer serializer) + // Act + var result = await content.ReadAsAsync(new { - // Arrange - var content = new StringContent(@"{ ""type"" : ""Type1"" }"); + type = default(TestEnum) + }, serializer); - // Act - var result = await content.ReadAsAsync(new - { - type = default(TestEnum) - }, serializer); + // Assert + result.Should().NotBeNull(); + result!.type.Should().Be(TestEnum.Type1); + } - // Assert - result.Should().NotBeNull(); - result!.type.Should().Be(TestEnum.Type1); - } + [Theory] + [MemberData(nameof(TestSerializers))] + public async Task Reads_A_Json_With_String_CamelCase_Enum_Value(ISerializer serializer) + { + // Arrange + var content = new StringContent(/*lang=json,strict*/ """{ "type" : "Type1" } """); - [Theory] - [MemberData(nameof(TestSerializers))] - public async Task Reads_A_Json_With_String_PascalCase_Enum_Value(ISerializer serializer) + // Act + var result = await content.ReadAsAsync(new { - // Arrange - var content = new StringContent(@"{ ""type"" : ""type2"" }"); + type = default(TestEnum) + }, serializer); - // Act - var result = await content.ReadAsAsync(new - { - type = default(TestEnum) - }, serializer); + // Assert + result.Should().NotBeNull(); + result!.type.Should().Be(TestEnum.Type1); + } - // Assert - result.Should().NotBeNull(); - result!.type.Should().Be(TestEnum.Type2); - } + [Theory] + [MemberData(nameof(TestSerializers))] + public async Task Reads_A_Json_With_String_PascalCase_Enum_Value(ISerializer serializer) + { + // Arrange + var content = new StringContent(/*lang=json,strict*/ """{ "type" : "type2" } """); - [Theory] - [MemberData(nameof(TestSerializers))] - public async Task Reads_A_Json_With_Empty_String_Enum_Value(ISerializer serializer) + // Act + var result = await content.ReadAsAsync(new { - // Arrange - var content = new StringContent(@"{ ""type"" : """" }"); + type = default(TestEnum) + }, serializer); - // Act - var result = await content.ReadAsAsync(new - { - type = default(TestEnum?) - }, serializer); + // Assert + result.Should().NotBeNull(); + result!.type.Should().Be(TestEnum.Type2); + } - // Assert - result.Should().NotBeNull(); - result!.type.Should().Be(default(TestEnum?)); - } + [Theory] + [MemberData(nameof(TestSerializers))] + public async Task Reads_A_Json_With_Empty_String_Enum_Value(ISerializer serializer) + { + // Arrange + var content = new StringContent(/*lang=json,strict*/ """{ "type" : "" } """); - [Theory] - [MemberData(nameof(TestSerializers))] - public async Task Reads_A_Json_With_Different_Property_Case(ISerializer serializer) + // Act + var result = await content.ReadAsAsync(new { - // Arrange - var content = new StringContent(@"{ ""name"" : ""John"" }"); + type = default(TestEnum?) + }, serializer); - // Act - var result = await content.ReadAsAsync(new - { - Name = default(string) - }, serializer); + // Assert + result.Should().NotBeNull(); + result!.type.Should().Be(default(TestEnum?)); + } - // Assert - result.Should().NotBeNull(); - result!.Name.Should().Be("John"); - } + [Theory] + [MemberData(nameof(TestSerializers))] + public async Task Reads_A_Json_With_Different_Property_Case(ISerializer serializer) + { + // Arrange + var content = new StringContent(/*lang=json,strict*/ """{ "name" : "John" } """); - [Theory] - [MemberData(nameof(TestSerializers))] - public async Task Reads_A_Json_With_Quoted_Integer_Value(ISerializer serializer) + // Act + var result = await content.ReadAsAsync(new { - // Arrange - var content = new StringContent(@"{ ""number"" : ""100"" }"); + Name = default(string) + }, serializer); - // Act - var result = await content.ReadAsAsync(new - { - number = default(int) - }, serializer); + // Assert + result.Should().NotBeNull(); + result!.Name.Should().Be("John"); + } - // Assert - result.Should().NotBeNull(); - result!.number.Should().Be(100); - } + [Theory] + [MemberData(nameof(TestSerializers))] + public async Task Reads_A_Json_With_Quoted_Integer_Value(ISerializer serializer) + { + // Arrange + var content = new StringContent(/*lang=json,strict*/ """{ "number" : "100" } """); + + // Act + var result = await content.ReadAsAsync(new + { + number = default(int) + }, serializer); + + // Assert + result.Should().NotBeNull(); + result!.number.Should().Be(100); } } diff --git a/test/FluentAssertions.Web.Tests/Internal/JsonExtensionsTests.cs b/test/FluentAssertions.Web.Tests/Internal/JsonExtensionsTests.cs index e8777f2..0765727 100644 --- a/test/FluentAssertions.Web.Tests/Internal/JsonExtensionsTests.cs +++ b/test/FluentAssertions.Web.Tests/Internal/JsonExtensionsTests.cs @@ -1,319 +1,346 @@ -using FluentAssertions.Web.Internal; -using System.Text.Json; -using Xunit; +namespace FluentAssertions.Web.Tests.Internal; -namespace FluentAssertions.Web.Tests.Internal +public class JsonExtensionsTests { - public class JsonExtensionsTests + #region GetStringValuesOf + [Fact] + public void GivenJson_WhenKeyExistsAndHasAnArrayOfStringValues_ThenReturnsTheStrings() { - #region GetStringValuesOf - [Fact] - public void GivenJson_WhenKeyExistsAndHasAnArrayOfStringValues_ThenReturnsTheStrings() + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."", - ""The Author length exceeds 200 characters."" - ] - } - }"); - - // Act - var result = json.GetStringValuesOf("Author"); - - // Assert - result.Should().BeEquivalentTo(new[] { "The Author field is required.", "The Author length exceeds 200 characters." }); + "errors": { + "Author": [ + "The Author field is required.", + "The Author length exceeds 200 characters." + ] + } } + """); - [Fact] - public void GivenJson_WhenKeyExistsAndHasAnArrayOfObjects_ThenReturnsAnEmptyCollection() + // Act + var result = json.GetStringValuesOf("Author"); + + // Assert + result.Should().BeEquivalentTo(new[] { "The Author field is required.", "The Author length exceeds 200 characters." }); + } + + [Fact] + public void GivenJson_WhenKeyExistsAndHasAnArrayOfObjects_ThenReturnsAnEmptyCollection() + { + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ - ""errors"": { - ""Author"": [ - {""description"" : ""The Author field is required.""}, - {""description"" : ""The Author length exceeds 200 characters.""} - ] - } - }"); - - // Act - var result = json.GetStringValuesOf("Author"); - - // Assert - result.Should().BeEmpty(); + "errors": { + "Author": [ + { "description": "The Author field is required." }, + { "description": "The Author length exceeds 200 characters." } + ] + } } + """); - [Fact] - public void GivenJson_WhenKeyExistsAndHasAnArrayOfNull_ThenReturnsAnEmptyCollection() + // Act + var result = json.GetStringValuesOf("Author"); + + // Assert + result.Should().BeEmpty(); + } + + [Fact] + public void GivenJson_WhenKeyExistsAndHasAnArrayOfNull_ThenReturnsAnEmptyCollection() + { + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ - ""errors"": { - ""Author"": [ - null, - null - ] - } - }"); - - // Act - var result = json.GetStringValuesOf("Author"); - - // Assert - result.Should().BeEmpty(); + "errors": { + "Author": [ + null, + null + ] + } } + """); - [Fact] - public void GivenJson_WhenKeyDoesNotExist_ThenReturnsEmpty() + // Act + var result = json.GetStringValuesOf("Author"); + + // Assert + result.Should().BeEmpty(); + } + + [Fact] + public void GivenJson_WhenKeyDoesNotExist_ThenReturnsEmpty() + { + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ] - } - }"); - - // Act - var result = json.GetStringValuesOf("Comment"); - - // Assert - result.Should().BeEmpty(); + "errors": { + "Author": [ + "The Author field is required." + ] + } } + """); - [Fact] - public void GivenJson_WhenKeyHasSingleValue_ThenReturnsCollection() + // Act + var result = json.GetStringValuesOf("Comment"); + + // Assert + result.Should().BeEmpty(); + } + + [Fact] + public void GivenJson_WhenKeyHasSingleValue_ThenReturnsCollection() + { + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ - ""errors"": { - ""Author"": ""The Author field is required."" - } - }"); - - // Act - var result = json.GetStringValuesOf("Author"); - - // Assert - result.Should().BeEquivalentTo(new[] { "The Author field is required." }); + "errors": { + "Author": "The Author field is required." + } } + """); - [Fact] - public void GivenJson_WhenKeyHasAComplexObject_ThenReturnsEmpty() + // Act + var result = json.GetStringValuesOf("Author"); + + // Assert + result.Should().BeEquivalentTo(new[] { "The Author field is required." }); + } + + [Fact] + public void GivenJson_WhenKeyHasAComplexObject_ThenReturnsEmpty() + { + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ - ""errors"": { - ""Author"": { ""Text"" : ""The Author field is required."" } - } - }"); - - // Act - var result = json.GetStringValuesOf("Author"); - - // Assert - result.Should().BeEmpty(); + "errors": { + "Author": { "Text": "The Author field is required." } + } } + """); - [Fact] - public void GivenJson_WhenKeyHasNullValue_ThenReturnsEmpty() + // Act + var result = json.GetStringValuesOf("Author"); + + // Assert + result.Should().BeEmpty(); + } + + [Fact] + public void GivenJson_WhenKeyHasNullValue_ThenReturnsEmpty() + { + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ - ""errors"": { - ""Author"": null - } - }"); - - // Act - var result = json.GetStringValuesOf("Author"); - - // Assert - result.Should().BeEmpty(); + "errors": { + "Author": null + } } + """); - [Fact] - public void GivenJson_WhenKeyHasTrueValue_ThenReturnsEmpty() + // Act + var result = json.GetStringValuesOf("Author"); + + // Assert + result.Should().BeEmpty(); + } + + [Fact] + public void GivenJson_WhenKeyHasTrueValue_ThenReturnsEmpty() + { + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ - ""errors"": { - ""Author"": true - } - }"); - - // Act - var result = json.GetStringValuesOf("Author"); - - // Assert - result.Should().BeEmpty(); + "errors": { + "Author": true + } } + """); + + // Act + var result = json.GetStringValuesOf("Author"); + + // Assert + result.Should().BeEmpty(); + } - [Fact] - public void GivenJson_WhenKeyHasFalseValue_ThenReturnsEmpty() + [Fact] + public void GivenJson_WhenKeyHasFalseValue_ThenReturnsEmpty() + { + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ - ""errors"": { - ""Author"": false - } - }"); - - // Act - var result = json.GetStringValuesOf("Author"); - - // Assert - result.Should().BeEmpty(); + "errors": { + "Author": false + } } - #endregion + """); + + // Act + var result = json.GetStringValuesOf("Author"); + + // Assert + result.Should().BeEmpty(); + } + #endregion - #region GetChildrenNames - [Fact] - public void GivenJsonWithAField_WhenGetChildrenKeysIsCalledWithThatField_ThenReturnsDirectKeys() + #region GetChildrenNames + [Fact] + public void GivenJsonWithAField_WhenGetChildrenKeysIsCalledWithThatField_ThenReturnsDirectKeys() + { + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ], - ""Content"": [ - ""The Content field is required."" - ] - } - }"); - - // Act - var result = json.GetChildrenNames("errors"); - - // Assert - result.Should().BeEquivalentTo("Author", "Content"); + "errors": { + "Author": [ + "The Author field is required." + ], + "Content": [ + "The Content field is required." + ] + } } + """); + + // Act + var result = json.GetChildrenNames("errors"); + + // Assert + result.Should().BeEquivalentTo("Author", "Content"); + } - [Fact] - public void GivenJsonWithAnEmptyField_WhenGetChildrenKeysIsCalledByItsParent_ThenReturnsDirectKeys() + [Fact] + public void GivenJsonWithAnEmptyField_WhenGetChildrenKeysIsCalledByItsParent_ThenReturnsDirectKeys() + { + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ - ""errors"": { - """": [ - ""The Author field is required."" - ] - } - }"); - - // Act - var result = json.GetChildrenNames("errors"); - - // Assert - result.Should().BeEquivalentTo(""); + "errors": { + "": [ + "The Author field is required." + ] + } } + """); + + // Act + var result = json.GetChildrenNames("errors"); + + // Assert + result.Should().BeEquivalentTo(""); + } - [Fact] - public void GivenJson_WhenGetChildrenKeysIsCalledWithNullOrEmpty_ThenReturnsDirectKeysOfRoot() + [Fact] + public void GivenJson_WhenGetChildrenKeysIsCalledWithNullOrEmpty_ThenReturnsDirectKeysOfRoot() + { + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ - ""Author"": [ - ""The Author field is required."" - ] - }"); - - // Act - var result = json.GetChildrenNames(""); - - // Assert - result.Should().BeEquivalentTo("Author"); + "Author": [ + "The Author field is required." + ] } + """); + + // Act + var result = json.GetChildrenNames(""); + + // Assert + result.Should().BeEquivalentTo("Author"); + } - [Fact] - public void GivenJson_WhenArrayContainsANonStringValue_ThenItExcludeFromResult() + [Fact] + public void GivenJson_WhenArrayContainsANonStringValue_ThenItExcludeFromResult() + { + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ - ""errors"": { - ""Author"": [ - ""The Author field is required."", - true, - false, - null, - [] - ] - } - }"); - - // Act - var result = json.GetStringValuesOf("Author"); - - // Assert - result.Should().BeEquivalentTo(new[] { "The Author field is required." }); + "errors": { + "Author": [ + "The Author field is required.", + true, + false, + null, + [] + ] + } } - #endregion + """); + + // Act + var result = json.GetStringValuesOf("Author"); + + // Assert + result.Should().BeEquivalentTo(new[] { "The Author field is required." }); + } + #endregion - #region GetParentKey - [Fact] - public void GivenJsonWithAFieldWithChildren_WhenGetParentKeyIsCalledWithOneOfTheChildren_ThenReturnsParent() + #region GetParentKey + [Fact] + public void GivenJsonWithAFieldWithChildren_WhenGetParentKeyIsCalledWithOneOfTheChildren_ThenReturnsParent() + { + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ ""root"" : { - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ], - ""Content"": [ - ""The Content field is required."" - ] - } - } - }"); - - // Act - var result = json.GetParentKey("content"); - - // Assert - result.Should().Be("errors"); + "root": { + "errors": { + "Author": [ + "The Author field is required." + ], + "Content": [ + "The Content field is required." + ] + } + } } + """); + + // Act + var result = json.GetParentKey("content"); + + // Assert + result.Should().Be("errors"); + } - [Fact] - public void GivenJsonWithAFieldWithChildren_WhenGetParentKeyIsCalledWithNoneOfTheChildren_ThenReturnsNull() + [Fact] + public void GivenJsonWithAFieldWithChildren_WhenGetParentKeyIsCalledWithNoneOfTheChildren_ThenReturnsNull() + { + // Arrange + using var json = JsonDocument.Parse(""" { - // Arrange - using var json = JsonDocument.Parse(@"{ ""root"" : { - ""errors"": { - ""Author"": [ - ""The Author field is required."" - ], - ""Content"": [ - ""The Content field is required."" - ] - } - } - }"); - - // Act - var result = json.GetParentKey("date"); - - // Assert - result.Should().BeNull(); + "root": { + "errors": { + "Author": [ + "The Author field is required." + ], + "Content": [ + "The Content field is required." + ] + } + } } + """); - [Fact] - public void GivenJsonAFieldAndChildren_WhenGetParentKeyIsCalledWithItself_ThenReturnsNull() - { - // Arrange - using var json = JsonDocument.Parse(@"{ ""root"" : """" }"); + // Act + var result = json.GetParentKey("date"); - // Act - var result = json.GetParentKey("root"); + // Assert + result.Should().BeNull(); + } - // Assert - result.Should().BeNull(); - } - #endregion + [Fact] + public void GivenJsonAFieldAndChildren_WhenGetParentKeyIsCalledWithItself_ThenReturnsNull() + { + // Arrange + using var json = JsonDocument.Parse("""{ "root" : "" }"""); + + // Act + var result = json.GetParentKey("root"); + + // Assert + result.Should().BeNull(); } + #endregion } \ No newline at end of file diff --git a/test/FluentAssertions.Web.Tests/SatisfyHttpResponseMessageAssertionsAsyncSpecs.cs b/test/FluentAssertions.Web.Tests/SatisfyHttpResponseMessageAssertionsAsyncSpecs.cs index 9dae0fe..888e53a 100644 --- a/test/FluentAssertions.Web.Tests/SatisfyHttpResponseMessageAssertionsAsyncSpecs.cs +++ b/test/FluentAssertions.Web.Tests/SatisfyHttpResponseMessageAssertionsAsyncSpecs.cs @@ -1,103 +1,96 @@ -using System; -using System.Net.Http; -using System.Threading.Tasks; -using Xunit; -using Xunit.Sdk; +namespace FluentAssertions.Web.Tests; -namespace FluentAssertions.Web.Tests +public class SatisfyHttpResponseMessageAssertionsAsyncSpecs { - public class SatisfyHttpResponseMessageAssertionsAsyncSpecs + [Fact] + public void When_asserting_response_with_a_certain_assertion_to_satisfy_assertions_it_should_succeed() { - [Fact] - public void When_asserting_response_with_a_certain_assertion_to_satisfy_assertions_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(); - bool completed = false; - - // Act - Action act = () => - subject.Should().Satisfy(async response => - { - await Task.Delay(10); - true.Should().BeTrue(); - completed = true; - }); - - // Assert - act.Should().NotThrow(); - completed.Should().BeTrue(); - } - - [Fact] - public void When_asserting_response_without_having_satisfiable_assertion_to_satisfy_assertions_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(); - - // Act - Action act = () => - subject.Should().Satisfy(async response => + // Arrange + using var subject = new HttpResponseMessage(); + bool completed = false; + + // Act + Action act = () => + subject.Should().Satisfy(async response => + { + await Task.Delay(10); + true.Should().BeTrue(); + completed = true; + }); + + // Assert + act.Should().NotThrow(); + completed.Should().BeTrue(); + } + + [Fact] + public void When_asserting_response_without_having_satisfiable_assertion_to_satisfy_assertions_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); + + // Act + Action act = () => + subject.Should().Satisfy(async response => + { + await Task.Delay(10); + response.Headers.AcceptRanges.Should().Contain("byte"); + + }, "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("""Expected * to satisfy one or more assertions, but it wasn't because we want to test the reason:*expected*{empty} to contain "byte"*HTTP response*"""); + } + + [Fact] + public void When_asserting_response_without_having_satisfiable_assertion_to_satisfy_several_assertions_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); + + // Act + Action act = () => + subject.Should().Satisfy( + async response => { await Task.Delay(10); response.Headers.AcceptRanges.Should().Contain("byte"); - + response.Headers.Should().BeNull(); }, "we want to test the {0}", "reason"); - // Assert - act.Should().Throw() - .WithMessage("Expected * to satisfy one or more assertions, but it wasn't because we want to test the reason:*expected*{empty} to contain \"byte\"*HTTP response*"); - } - - [Fact] - public void When_asserting_response_without_having_satisfiable_assertion_to_satisfy_several_assertions_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(); - - // Act - Action act = () => - subject.Should().Satisfy( - async response => - { - await Task.Delay(10); - response.Headers.AcceptRanges.Should().Contain("byte"); - response.Headers.Should().BeNull(); - }, "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected * to satisfy one or more assertions, but it wasn't because we want to test the reason:*expected*""byte""*expected*to be *The HTTP response was:*"); - } - - [Fact] - public void When_asserting_response_to_satisfy_against_null_assertion_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(); - - // Act - Action act = () => - subject.Should().Satisfy((Func)null!); - - // Assert - act.Should().Throw() - .WithMessage("*Cannot verify the subject satisfies a `null` assertion.*"); - } - - [Fact] - public void When_asserting_null_response_to_satisfy_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Satisfy(async response => await Task.Run(() => true.Should().BeTrue()), "because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } + // Assert + act.Should().Throw() + .WithMessage("""Expected * to satisfy one or more assertions, but it wasn't because we want to test the reason:*expected*"byte"*expected*to be *The HTTP response was:*"""); + } + + [Fact] + public void When_asserting_response_to_satisfy_against_null_assertion_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); + + // Act + Action act = () => + subject.Should().Satisfy((Func)null!); + + // Assert + act.Should().Throw() + .WithMessage("*Cannot verify the subject satisfies a `null` assertion.*"); + } + + [Fact] + public void When_asserting_null_response_to_satisfy_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Satisfy(async response => await Task.Run(() => true.Should().BeTrue()), "because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); } } \ No newline at end of file diff --git a/test/FluentAssertions.Web.Tests/SatisfyHttpResponseMessageAssertionsSpecs.cs b/test/FluentAssertions.Web.Tests/SatisfyHttpResponseMessageAssertionsSpecs.cs index 680ec57..c27bc3c 100644 --- a/test/FluentAssertions.Web.Tests/SatisfyHttpResponseMessageAssertionsSpecs.cs +++ b/test/FluentAssertions.Web.Tests/SatisfyHttpResponseMessageAssertionsSpecs.cs @@ -1,89 +1,83 @@ -using System; -using System.Net.Http; -using Xunit; -using Xunit.Sdk; +namespace FluentAssertions.Web.Tests; -namespace FluentAssertions.Web.Tests +public class SatisfyHttpResponseMessageAssertionsSpecs { - public class SatisfyHttpResponseMessageAssertionsSpecs + [Fact] + public void When_asserting_response_with_a_certain_assertion_to_satisfy_assertions_it_should_succeed() { - [Fact] - public void When_asserting_response_with_a_certain_assertion_to_satisfy_assertions_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage(); + // Arrange + using var subject = new HttpResponseMessage(); - // Act - Action act = () => - subject.Should().Satisfy(response => true.Should().BeTrue()); + // Act + Action act = () => + subject.Should().Satisfy(response => true.Should().BeTrue()); - // Assert - act.Should().NotThrow(); - } + // Assert + act.Should().NotThrow(); + } - [Fact] - public void When_asserting_response_without_having_satisfiable_assertion_to_satisfy_assertions_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(); + [Fact] + public void When_asserting_response_without_having_satisfiable_assertion_to_satisfy_assertions_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); - // Act - Action act = () => - subject.Should().Satisfy(c => c.Headers.AcceptRanges.Should().Contain("byte"), "we want to test the {0}", "reason"); + // Act + Action act = () => + subject.Should().Satisfy(c => c.Headers.AcceptRanges.Should().Contain("byte"), "we want to test the {0}", "reason"); - // Assert - act.Should().Throw() - .WithMessage("Expected * to satisfy one or more assertions, but it wasn't because we want to test the reason:*expected*{empty} to contain \"byte\"*HTTP response*"); - } + // Assert + act.Should().Throw() + .WithMessage("""Expected * to satisfy one or more assertions, but it wasn't because we want to test the reason:*expected*{empty} to contain "byte"*HTTP response*"""); + } - [Fact] - public void When_asserting_response_without_having_satisfiable_assertion_to_satisfy_several_assertions_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(); + [Fact] + public void When_asserting_response_without_having_satisfiable_assertion_to_satisfy_several_assertions_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); - // Act - Action act = () => - subject.Should().Satisfy( - response => - { - response.Headers.AcceptRanges.Should().Contain("byte"); - response.Headers.Should().BeNull(); - }, "we want to test the {0}", "reason"); + // Act + Action act = () => + subject.Should().Satisfy( + response => + { + response.Headers.AcceptRanges.Should().Contain("byte"); + response.Headers.Should().BeNull(); + }, "we want to test the {0}", "reason"); - // Assert - act.Should().Throw() - .WithMessage(@"Expected * to satisfy one or more assertions, but it wasn't because we want to test the reason:*expected*""byte""*expected*to be *The HTTP response was:*"); - } + // Assert + act.Should().Throw() + .WithMessage("""Expected * to satisfy one or more assertions, but it wasn't because we want to test the reason:*expected*"byte"*expected*to be *The HTTP response was:*"""); + } - [Fact] - public void When_asserting_response_to_satisfy_against_null_assertion_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage(); + [Fact] + public void When_asserting_response_to_satisfy_against_null_assertion_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); - // Act - Action act = () => - subject.Should().Satisfy((Action)null!); + // Act + Action act = () => + subject.Should().Satisfy((Action)null!); - // Assert - act.Should().Throw() - .WithMessage("*Cannot verify the subject satisfies a `null` assertion.*"); - } + // Assert + act.Should().Throw() + .WithMessage("*Cannot verify the subject satisfies a `null` assertion.*"); + } - [Fact] - public void When_asserting_null_response_to_satisfy_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; + [Fact] + public void When_asserting_null_response_to_satisfy_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; - // Act - Action act = () => - subject.Should().Satisfy(response => true.Should().BeTrue(), "because we want to test the failure {0}", "message"); + // Act + Action act = () => + subject.Should().Satisfy(response => true.Should().BeTrue(), "because we want to test the failure {0}", "message"); - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); } } \ No newline at end of file diff --git a/test/FluentAssertions.Web.Tests/SatisfyModelAssertionsAsyncSpecs.cs b/test/FluentAssertions.Web.Tests/SatisfyModelAssertionsAsyncSpecs.cs index c2d53e6..198533b 100644 --- a/test/FluentAssertions.Web.Tests/SatisfyModelAssertionsAsyncSpecs.cs +++ b/test/FluentAssertions.Web.Tests/SatisfyModelAssertionsAsyncSpecs.cs @@ -1,514 +1,511 @@ using FluentAssertions.Web.Tests.TestModels; -using System; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using Xunit; -using Xunit.Sdk; - -namespace FluentAssertions.Web.Tests + +namespace FluentAssertions.Web.Tests; + +public class SatisfyModelAssertionsAsyncSpecs { - public class SatisfyModelAssertionsAsyncSpecs - { - #region Typed Model + #region Typed Model - [Fact] - public void When_asserting_response_content_with_a_certain_assertion_to_satisfy_assertions_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; - bool completed = false; - - // Act - Action act = () => - subject.Should().Satisfy( - async model => - { - await Task.Delay(10); - model.Property.Should().NotBeEmpty(); - completed = true; - }); - - // Assert - act.Should().NotThrow(); - completed.Should().BeTrue(); - } - - [Fact] - public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_assertions_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().Satisfy( - async model => - { - await Task.Delay(10); - model.Property.Should().BeEmpty(); - }, "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage("Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*to be empty, but found \"Value\"*HTTP response*"); - } - - [Fact] - public void When_asserting_response_content_with_enums_serialized_as_strings_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"testEnum\" : \"Type1\"}", Encoding.UTF8, "application/json") - }; - bool completed = false; - - // Act - Action act = () => - subject.Should().Satisfy( - async model => - { - await Task.Delay(10); - model.TestEnum.Should().Be(TestEnum.Type1); - completed = true; - }); - - // Assert - act.Should().NotThrow(); - completed.Should().BeTrue(); - } - - [Fact] - public void When_asserting_response_content_with_enums_serialized_as_integers_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"testEnum\" : 2 }", Encoding.UTF8, "application/json") - }; - bool completed = false; - - // Act - Action act = () => - subject.Should().Satisfy( - async model => - { - await Task.Delay(10); - model.TestEnum.Should().Be(TestEnum.Type1); - completed = true; - }); - - // Assert - act.Should().NotThrow(); - completed.Should().BeTrue(); - } - - [Fact] - public void When_asserting_response_content_with_enums_serialized_as_integers_with_no_values_in_range_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"testEnum\" : -1 }", Encoding.UTF8, "application/json") - }; - bool completed = false; - - // Act - Action act = () => - subject.Should().Satisfy( - async model => - { - await Task.Delay(10); - model.TestEnum.Should().Be((TestEnum)(-1)); - completed = true; - }); - - // Assert - act.Should().NotThrow(); - completed.Should().BeTrue(); - } - - [Fact] - public void When_asserting_response_content_with_enums_without_having_satisfiable_assertion_to_satisfy_assertions_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"testEnum\" : -1 }", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().Satisfy( - async model => - { - await Task.Delay(10); - model.TestEnum.Should().Be(TestEnum.Type1); - }, "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage("Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*the enum to be TestEnum.Type1*, but found TestEnum.-1**HTTP response*"); - } - - [Fact] - public void When_asserting_response_with_not_a_proper_JSON_to_satisfy_assertions_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("\"True\"", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().Satisfy( - async model => - { - await Task.Delay(10); - model.Property.Should().BeNull(); - }, "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage(@"*to have a content equivalent to a model of type*, but the JSON representation could not be parsed*"); - } - - [Fact] - public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_several_assertions_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().Satisfy( - async model => - { - await Task.Delay(10); - model.Property.Should().Be("Not Value"); - model.Should().BeNull(); - }, "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*Not Value*expected*to be *The HTTP response was:*"); - } - - [Fact] - public void When_asserting_response_content_to_satisfy_against_null_assertion_it_should_throw_with_descriptive_message() + [Fact] + public void When_asserting_response_content_with_a_certain_assertion_to_satisfy_assertions_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage(); - - // Act - Action act = () => - subject.Should().Satisfy((Func)null!); + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; + bool completed = false; + + // Act + Action act = () => + subject.Should().Satisfy( + async model => + { + await Task.Delay(10); + model.Property.Should().NotBeEmpty(); + completed = true; + }); - // Assert - act.Should().Throw() - .WithMessage("*Cannot verify the subject satisfies a `null` assertion.*"); - } + // Assert + act.Should().NotThrow(); + completed.Should().BeTrue(); + } - [Fact] - public void When_asserting_null_response_content_to_be_satisfy_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Satisfy(async model => await Task.Run(() => true.Should().BeTrue()), "because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region Inferred Model - [Fact] - public void When_asserting_response_content_with_a_certain_assertion_to_satisfy_assertions_inferred_from_model_it_should_succeed() + [Fact] + public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_assertions_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; - var completed = false; + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new + // Act + Action act = () => + subject.Should().Satisfy( + async model => { - Property = default(string) - }, assertion:async model => + await Task.Delay(10); + model.Property.Should().BeEmpty(); + }, "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("""Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*to be empty, but found "Value"*HTTP response*"""); + } + + [Fact] + public void When_asserting_response_content_with_enums_serialized_as_strings_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage + { + Content = new StringContent(/*lang=json,strict*/ """{ "testEnum" : "Type1"}""", Encoding.UTF8, "application/json") + }; + bool completed = false; + + // Act + Action act = () => + subject.Should().Satisfy( + async model => { await Task.Delay(10); - model.Property.Should().NotBeEmpty(); + model.TestEnum.Should().Be(TestEnum.Type1); completed = true; }); - // Assert - act.Should().NotThrow(); - completed.Should().BeTrue(); - } + // Assert + act.Should().NotThrow(); + completed.Should().BeTrue(); + } - [Fact] - public void When_asserting_response_content_to_satisfy_against_null_given_model_type_it_should_succeed() + [Fact] + public void When_asserting_response_content_with_enums_serialized_as_integers_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; - var completed = false; + Content = new StringContent(/*lang=json,strict*/ """{ "testEnum" : 2 }""", Encoding.UTF8, "application/json") + }; + bool completed = false; + + // Act + Action act = () => + subject.Should().Satisfy( + async model => + { + await Task.Delay(10); + model.TestEnum.Should().Be(TestEnum.Type1); + completed = true; + }); - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: (TestModel?)null, async model => + // Assert + act.Should().NotThrow(); + completed.Should().BeTrue(); + } + + [Fact] + public void When_asserting_response_content_with_enums_serialized_as_integers_with_no_values_in_range_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage + { + Content = new StringContent(/*lang=json,strict*/ """{ "testEnum" : -1 }""", Encoding.UTF8, "application/json") + }; + bool completed = false; + + // Act + Action act = () => + subject.Should().Satisfy( + async model => { await Task.Delay(10); - model!.Property.Should().NotBeNullOrEmpty(); + model.TestEnum.Should().Be((TestEnum)(-1)); completed = true; }); - // Assert - act.Should().NotThrow(); - completed.Should().BeTrue(); - } + // Assert + act.Should().NotThrow(); + completed.Should().BeTrue(); + } - [Fact] - public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_assertions_inferred_from_model_it_should_throw_with_descriptive_message() + [Fact] + public void When_asserting_response_content_with_enums_without_having_satisfiable_assertion_to_satisfy_assertions_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; + Content = new StringContent(/*lang=json,strict*/ """{ "testEnum" : -1 }""", Encoding.UTF8, "application/json") + }; - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new + // Act + Action act = () => + subject.Should().Satisfy( + async model => { - Property = default(string) - }, assertion: async model => + await Task.Delay(10); + model.TestEnum.Should().Be(TestEnum.Type1); + }, "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*the enum to be TestEnum.Type1*, but found TestEnum.-1**HTTP response*"); + } + + [Fact] + public void When_asserting_response_with_not_a_proper_JSON_to_satisfy_assertions_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage + { + Content = new StringContent(""" + "True" + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().Satisfy( + async model => { await Task.Delay(10); - model.Property.Should().BeEmpty(); + model.Property.Should().BeNull(); }, "we want to test the {0}", "reason"); - // Assert - act.Should().Throw() - .WithMessage("Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*to be empty, but found \"Value\"*HTTP response*"); - } + // Assert + act.Should().Throw() + .WithMessage("*to have a content equivalent to a model of type*, but the JSON representation could not be parsed*"); + } - [Fact] - public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_several_assertions_inferred_from_model_it_should_throw_with_descriptive_message() + [Fact] + public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_several_assertions_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new + // Act + Action act = () => + subject.Should().Satisfy( + async model => { - Property = default(string) - }, assertion: async model => - { - await Task.Delay(10); - model.Property.Should().Be("Not Value"); - model.Should().BeNull(); - }, "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*Not Value*expected*to be *The HTTP response was:*"); - } - - [Fact] - public void When_asserting_response_content_with_enums_serialized_as_strings_inferred_from_model_it_should_succeed() + await Task.Delay(10); + model.Property.Should().Be("Not Value"); + model.Should().BeNull(); + }, "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("""Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*Not Value*expected*to be *The HTTP response was:*"""); + } + + [Fact] + public void When_asserting_response_content_to_satisfy_against_null_assertion_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); + + // Act + Action act = () => + subject.Should().Satisfy((Func)null!); + + // Assert + act.Should().Throw() + .WithMessage("*Cannot verify the subject satisfies a `null` assertion.*"); + } + + [Fact] + public void When_asserting_null_response_content_to_be_satisfy_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Satisfy(async model => await Task.Run(() => true.Should().BeTrue()), "because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion + + #region Inferred Model + [Fact] + public void When_asserting_response_content_with_a_certain_assertion_to_satisfy_assertions_inferred_from_model_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; + var completed = false; + + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + Property = default(string) + }, assertion:async model => { - Content = new StringContent("{ \"testEnum\" : \"Type1\"}", Encoding.UTF8, "application/json") - }; - bool completed = false; + await Task.Delay(10); + model.Property.Should().NotBeEmpty(); + completed = true; + }); + + // Assert + act.Should().NotThrow(); + completed.Should().BeTrue(); + } - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new - { - TestEnum = TestEnum.Type1 - }, assertion: async model => - { - await Task.Delay(10); - model.TestEnum.Should().Be(TestEnum.Type1); - completed = true; - }, "we want to test the {0}", "reason"); - - // Assert - act.Should().NotThrow(); - completed.Should().BeTrue(); - } - - [Fact] - public void When_asserting_response_content_with_enums_serialized_as_integers_inferred_from_model_it_should_succeed() + [Fact] + public void When_asserting_response_content_to_satisfy_against_null_given_model_type_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; + var completed = false; + + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: (TestModel?)null, async model => { - Content = new StringContent("{ \"testEnum\" : 2 }", Encoding.UTF8, "application/json") - }; - bool completed = false; + await Task.Delay(10); + model!.Property.Should().NotBeNullOrEmpty(); + completed = true; + }); + + // Assert + act.Should().NotThrow(); + completed.Should().BeTrue(); + } - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new - { - TestEnum = default(TestEnum) - }, assertion: async model => - { - await Task.Delay(10); - model.TestEnum.Should().Be(TestEnum.Type1); - completed = true; - }); - - // Assert - act.Should().NotThrow(); - completed.Should().BeTrue(); - } - - [Fact] - public void When_asserting_response_content_with_enums_serialized_as_integers_with_no_values_in_range_inferred_from_model_it_should_succeed() + [Fact] + public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_assertions_inferred_from_model_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + Property = default(string) + }, assertion: async model => { - Content = new StringContent("{ \"testEnum\" : -1 }", Encoding.UTF8, "application/json") - }; - bool completed = false; + await Task.Delay(10); + model.Property.Should().BeEmpty(); + }, "we want to test the {0}", "reason"); - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new - { - TestEnum = default(TestEnum) - }, assertion: async model => + // Assert + act.Should().Throw() + .WithMessage("""Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*to be empty, but found "Value"*HTTP response*"""); + } + + [Fact] + public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_several_assertions_inferred_from_model_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage + { + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + Property = default(string) + }, assertion: async model => + { + await Task.Delay(10); + model.Property.Should().Be("Not Value"); + model.Should().BeNull(); + }, "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*Not Value*expected*to be *The HTTP response was:*"); + } + + [Fact] + public void When_asserting_response_content_with_enums_serialized_as_strings_inferred_from_model_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage + { + Content = new StringContent(/*lang=json,strict*/ """{ "testEnum" : "Type1"}""", Encoding.UTF8, "application/json") + }; + bool completed = false; + + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + TestEnum = TestEnum.Type1 + }, assertion: async model => { await Task.Delay(10); - model.TestEnum.Should().Be((TestEnum)(-1)); + model.TestEnum.Should().Be(TestEnum.Type1); completed = true; - }); + }, "we want to test the {0}", "reason"); - // Assert - act.Should().NotThrow(); - completed.Should().BeTrue(); - } + // Assert + act.Should().NotThrow(); + completed.Should().BeTrue(); + } - [Fact] - public void When_asserting_response_content_with_enums_without_having_satisfiable_assertion_to_satisfy_assertions_inferred_from_model_it_should_throw_with_descriptive_message() + [Fact] + public void When_asserting_response_content_with_enums_serialized_as_integers_inferred_from_model_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"testEnum\" : -1 }", Encoding.UTF8, "application/json") - }; - bool completed = false; + Content = new StringContent(/*lang=json,strict*/ """{ "testEnum" : 2 }""", Encoding.UTF8, "application/json") + }; + bool completed = false; - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new - { - TestEnum = default(TestEnum) - }, assertion: async model => + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + TestEnum = default(TestEnum) + }, assertion: async model => { await Task.Delay(10); model.TestEnum.Should().Be(TestEnum.Type1); completed = true; - }, "we want to test the {0}", "reason"); + }); - // Assert - act.Should().Throw() - .WithMessage("Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*the enum to be TestEnum.Type1*, but found TestEnum.-1**HTTP response*"); - completed.Should().BeTrue(); - } + // Assert + act.Should().NotThrow(); + completed.Should().BeTrue(); + } - [Fact] - public void When_asserting_response_with_not_a_proper_JSON_to_satisfy_assertions_inferred_from_model_it_should_throw_with_descriptive_message() + [Fact] + public void When_asserting_response_content_with_enums_serialized_as_integers_with_no_values_in_range_inferred_from_model_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent(/*lang=json,strict*/ """{ "testEnum" : -1 }""", Encoding.UTF8, "application/json") + }; + bool completed = false; + + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new { - Content = new StringContent("\"True\"", Encoding.UTF8, "application/json") - }; + TestEnum = default(TestEnum) + }, assertion: async model => + { + await Task.Delay(10); + model.TestEnum.Should().Be((TestEnum)(-1)); + completed = true; + }); + + // Assert + act.Should().NotThrow(); + completed.Should().BeTrue(); + } - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new - { - Property = default(string) - }, assertion: async model => - { - await Task.Delay(10); - model.Property.Should().BeNull(); - }, "we want to test the {0}", "reason"); + [Fact] + public void When_asserting_response_content_with_enums_without_having_satisfiable_assertion_to_satisfy_assertions_inferred_from_model_it_should_throw_with_descriptive_message() + { + using var subject = new HttpResponseMessage + { + Content = new StringContent(/*lang=json,strict*/ """{ "testEnum" : -1 }""", Encoding.UTF8, "application/json") + }; + bool completed = false; - // Assert - act.Should().Throw() - .WithMessage(@"*to have a content equivalent to a model of type*, but the JSON representation could not be parsed*"); - } + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + TestEnum = default(TestEnum) + }, assertion: async model => + { + await Task.Delay(10); + model.TestEnum.Should().Be(TestEnum.Type1); + completed = true; + }, "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*the enum to be TestEnum.Type1*, but found TestEnum.-1**HTTP response*"); + completed.Should().BeTrue(); + } - [Fact] - public void When_asserting_response_content_to_satisfy_against_null_assertion_inferred_from_model_it_should_throw_with_descriptive_message() + [Fact] + public void When_asserting_response_with_not_a_proper_JSON_to_satisfy_assertions_inferred_from_model_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage(); + Content = new StringContent(""" + "True" + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + Property = default(string) + }, assertion: async model => + { + await Task.Delay(10); + model.Property.Should().BeNull(); + }, "we want to test the {0}", "reason"); - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new - { - Property = default(string) - }, null!); + // Assert + act.Should().Throw() + .WithMessage("*to have a content equivalent to a model of type*, but the JSON representation could not be parsed*"); + } + + [Fact] + public void When_asserting_response_content_to_satisfy_against_null_assertion_inferred_from_model_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); - // Assert - act.Should().Throw() - .WithMessage("*Cannot verify the subject satisfies a `null` assertion.*"); - } + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + Property = default(string) + }, null!); + // Assert + act.Should().Throw() + .WithMessage("*Cannot verify the subject satisfies a `null` assertion.*"); + } - [Fact] - public void When_asserting_null_response_content_to_be_satisfy_inferred_from_model_it_should_throw_with_descriptive_message() - { - // Arrange - HttpResponseMessage? subject = null; - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new - { - Property = default(string) - }, assertion: async model => await Task.Run(() => true.Should().BeTrue()), "because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion + [Fact] + public void When_asserting_null_response_content_to_be_satisfy_inferred_from_model_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + Property = default(string) + }, assertion: async model => await Task.Run(() => true.Should().BeTrue()), "because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); } + #endregion } \ No newline at end of file diff --git a/test/FluentAssertions.Web.Tests/SatisfyModelAssertionsSpecs.cs b/test/FluentAssertions.Web.Tests/SatisfyModelAssertionsSpecs.cs index c7f7101..26961f2 100644 --- a/test/FluentAssertions.Web.Tests/SatisfyModelAssertionsSpecs.cs +++ b/test/FluentAssertions.Web.Tests/SatisfyModelAssertionsSpecs.cs @@ -1,315 +1,347 @@ -using System; -using System.Net.Http; -using System.Text; -using Xunit; -using Xunit.Sdk; +namespace FluentAssertions.Web.Tests; -namespace FluentAssertions.Web.Tests +public class SatisfyModelAssertionsSpecs { - public class SatisfyModelAssertionsSpecs + #region Typed Model + private class Model { - #region Typed Model - private class Model - { - public string? Property { get; set; } - } + public string? Property { get; set; } + } - [Fact] - public void When_asserting_response_content_with_a_certain_assertion_to_satisfy_assertion_it_should_succeed() + [Fact] + public void When_asserting_response_content_with_a_certain_assertion_to_satisfy_assertion_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; - // Act - Action act = () => - subject.Should().Satisfy( - model => model.Property.Should().NotBeEmpty()); + // Act + Action act = () => + subject.Should().Satisfy( + model => model.Property.Should().NotBeEmpty()); - // Assert - act.Should().NotThrow(); - } + // Assert + act.Should().NotThrow(); + } - [Fact] - public void When_asserting_response_content_with_a_certain_assertion_to_twice_satisfy_assertion_it_should_succeed() + [Fact] + public void When_asserting_response_content_with_a_certain_assertion_to_twice_satisfy_assertion_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().Satisfy( - model => model.Property.Should().NotBeEmpty()) - .And.Satisfy( - model => model.Property.Should().NotBeEmpty()); - - // Assert - act.Should().NotThrow(); - } - - [Fact] - public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_assertion_it_should_throw_with_descriptive_message() + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().Satisfy( + model => model.Property.Should().NotBeEmpty()) + .And.Satisfy( + model => model.Property.Should().NotBeEmpty()); + + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_content_with_a_certain_assertion_to_satisfy_assertion_and_model_is_of_named_tuple_type_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().Satisfy<(string Property, object _)>( + model => model.Property.Should().NotBeEmpty()); - // Act - Action act = () => - subject.Should().Satisfy( - model => model.Property.Should().BeEmpty(), "we want to test the {0}", "reason"); + // Assert + act.Should().NotThrow(); + } - // Assert - act.Should().Throw() - .WithMessage("Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*to be empty, but found \"Value\"*HTTP response*"); - } - [Fact] - public void When_asserting_response_with_not_a_proper_JSON_to_satisfy_assertion_it_should_throw_with_descriptive_message() + [Fact] + public void When_asserting_response_content_with_a_certain_assertion_to_satisfy_assertion_and_model_is_of_non_named_tuple_type_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("\"True\"", Encoding.UTF8, "application/json") - }; + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; - // Act - Action act = () => - subject.Should().Satisfy( - model => model.Property.Should().BeNull(), "we want to test the {0}", "reason"); + // Act + Action act = () => + subject.Should().Satisfy>( + model => model.Item1.Should().NotBeEmpty()); - // Assert - act.Should().Throw() - .WithMessage(@"*to have a content equivalent to a model of type*, but the JSON representation could not be parsed*"); - } + // Assert + act.Should().NotThrow(); + } - [Fact] - public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_several_assertions_it_should_throw_with_descriptive_message() - { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; - - // Act - Action act = () => - subject.Should().Satisfy( - model => - { - model.Property.Should().Be("Not Value"); - model.Should().BeNull(); - }, "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*Not Value*expected*to be *The HTTP response was:*"); - } - - [Fact] - public void When_asserting_response_content_to_satisfy_against_null_assertion_it_should_throw_with_descriptive_message() + [Fact] + public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_assertion_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage(); + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; - // Act - Action act = () => - subject.Should().Satisfy(null!); + // Act + Action act = () => + subject.Should().Satisfy( + model => model.Property.Should().BeEmpty(), "we want to test the {0}", "reason"); - // Assert - act.Should().Throw() - .WithMessage("Cannot verify the subject satisfies a `null` assertion.*"); - } + // Assert + act.Should().Throw() + .WithMessage("""Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*to be empty, but found "Value"*HTTP response*"""); + } - [Fact] - public void When_asserting_null_response_content_to_be_satisfy_it_should_throw_with_descriptive_message() + [Fact] + public void When_asserting_response_with_not_a_proper_JSON_to_satisfy_assertion_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - HttpResponseMessage? subject = null; - - // Act - Action act = () => - subject.Should().Satisfy(model => true.Should().BeTrue(), "because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion - - #region Inferred Model - [Fact] - public void When_asserting_response_content_with_a_certain_assertion_to_satisfy_assertion_inferred_from_model_it_should_succeed() + Content = new StringContent(""" + "True" + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().Satisfy( + model => model.Property.Should().BeNull(), "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("*to have a content equivalent to a model of type*, but the JSON representation could not be parsed*"); + } + + [Fact] + public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_several_assertions_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new + // Act + Action act = () => + subject.Should().Satisfy( + model => { - Property = default(string) - }, assertion: model => model.Property.Should().NotBeEmpty()); + model.Property.Should().Be("Not Value"); + model.Should().BeNull(); + }, "we want to test the {0}", "reason"); - // Assert - act.Should().NotThrow(); - } + // Assert + act.Should().Throw() + .WithMessage("""Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*Not Value*expected*to be *The HTTP response was:*"""); + } - [Fact] - public void When_asserting_response_content_with_a_certain_assertion_to_twice_satisfy_assertion_inferred_from_model_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; + [Fact] + public void When_asserting_response_content_to_satisfy_against_null_assertion_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new - { - Property = default(string) - }, assertion: model => model.Property.Should().NotBeEmpty()) - .And.Satisfy(givenModelStructure: new - { - Property = default(string) - }, assertion: model => model.Property.Should().NotBeEmpty()); + // Act + Action act = () => + subject.Should().Satisfy(null!); - // Assert - act.Should().NotThrow(); - } + // Assert + act.Should().Throw() + .WithMessage("Cannot verify the subject satisfies a `null` assertion.*"); + } - [Fact] - public void When_asserting_response_content_to_satisfy_against_null_given_model_type_it_should_succeed() - { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; + [Fact] + public void When_asserting_null_response_content_to_be_satisfy_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: (Model?)null, model => model!.Property.Should().NotBeNullOrEmpty()); + // Act + Action act = () => + subject.Should().Satisfy(model => true.Should().BeTrue(), "because we want to test the failure {0}", "message"); - // Assert - act.Should().NotThrow(); - } + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); + } + #endregion - [Fact] - public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_assertion_inferred_from_model_it_should_throw_with_descriptive_message() + #region Inferred Model + [Fact] + public void When_asserting_response_content_with_a_certain_assertion_to_satisfy_assertion_inferred_from_model_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new - { - Property = default(string) - }, assertion: model => model.Property.Should().BeEmpty(), "we want to test the {0}", "reason"); + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + Property = default(string) + }, assertion: model => model.Property.Should().NotBeEmpty()); - // Assert - act.Should().Throw() - .WithMessage("Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*to be empty, but found \"Value\"*HTTP response*"); - } + // Assert + act.Should().NotThrow(); + } - [Fact] - public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_several_assertions_inferred_from_model_it_should_throw_with_descriptive_message() + [Fact] + public void When_asserting_response_content_with_a_certain_assertion_to_twice_satisfy_assertion_inferred_from_model_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + Property = default(string) + }, assertion: model => model.Property.Should().NotBeEmpty()) + .And.Satisfy(givenModelStructure: new { - Content = new StringContent("{ \"property\" : \"Value\"}", Encoding.UTF8, "application/json") - }; + Property = default(string) + }, assertion: model => model.Property.Should().NotBeEmpty()); - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new - { - Property = default(string) - }, assertion: model => - { - model.Property.Should().Be("Not Value"); - model.Should().BeNull(); - }, "we want to test the {0}", "reason"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*Not Value*expected*to be *The HTTP response was:*"); - } - - [Fact] - public void When_asserting_response_with_not_a_proper_JSON_to_satisfy_assertion_inferred_from_model_it_should_throw_with_descriptive_message() + // Assert + act.Should().NotThrow(); + } + + [Fact] + public void When_asserting_response_content_to_satisfy_against_null_given_model_type_it_should_succeed() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage - { - Content = new StringContent("\"True\"", Encoding.UTF8, "application/json") - }; + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new - { - Property = default(string) - }, assertion: model => model.Property.Should().BeNull(), "we want to test the {0}", "reason"); + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: (Model?)null, model => model!.Property.Should().NotBeNullOrEmpty()); - // Assert - act.Should().Throw() - .WithMessage(@"*to have a content equivalent to a model of type*, but the JSON representation could not be parsed*"); - } + // Assert + act.Should().NotThrow(); + } - [Fact] - public void When_asserting_response_content_to_satisfy_against_null_assertion_inferred_from_model_it_should_throw_with_descriptive_message() + [Fact] + public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_assertion_inferred_from_model_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - using var subject = new HttpResponseMessage(); + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new - { - Property = default(string) - }, null!); + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + Property = default(string) + }, assertion: model => model.Property.Should().BeEmpty(), "we want to test the {0}", "reason"); - // Assert - act.Should().Throw() - .WithMessage("Cannot verify the subject satisfies a `null` assertion.*"); - } + // Assert + act.Should().Throw() + .WithMessage("""Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*to be empty, but found "Value"*HTTP response*"""); + } + [Fact] + public void When_asserting_response_content_without_having_satisfiable_assertion_to_satisfy_several_assertions_inferred_from_model_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage + { + Content = new StringContent(/*lang=json,strict*/ """{ "property" : "Value"}""", Encoding.UTF8, "application/json") + }; + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + Property = default(string) + }, assertion: model => + { + model.Property.Should().Be("Not Value"); + model.Should().BeNull(); + }, "we want to test the {0}", "reason"); + + // Assert + act.Should().Throw() + .WithMessage("Expected * to satisfy one or more model assertions, but it wasn't because we want to test the reason:*expected*Not Value*expected*to be *The HTTP response was:*"); + } - [Fact] - public void When_asserting_null_response_content_to_be_satisfy_inferred_from_model_it_should_throw_with_descriptive_message() + [Fact] + public void When_asserting_response_with_not_a_proper_JSON_to_satisfy_assertion_inferred_from_model_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage { - // Arrange - HttpResponseMessage? subject = null; + Content = new StringContent(""" + "True" + """, Encoding.UTF8, "application/json") + }; + + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + Property = default(string) + }, assertion: model => model.Property.Should().BeNull(), "we want to test the {0}", "reason"); - // Act - Action act = () => - subject.Should().Satisfy(givenModelStructure: new - { - Property = default(string) - }, assertion: model => true.Should().BeTrue(), "because we want to test the failure {0}", "message"); - - // Assert - act.Should().Throw() - .WithMessage(@"Expected a * to assert because we want to test the failure message, but found ."); - } - #endregion + // Assert + act.Should().Throw() + .WithMessage("*to have a content equivalent to a model of type*, but the JSON representation could not be parsed*"); + } + + [Fact] + public void When_asserting_response_content_to_satisfy_against_null_assertion_inferred_from_model_it_should_throw_with_descriptive_message() + { + // Arrange + using var subject = new HttpResponseMessage(); + + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + Property = default(string) + }, null!); + + // Assert + act.Should().Throw() + .WithMessage("Cannot verify the subject satisfies a `null` assertion.*"); + } + + [Fact] + public void When_asserting_null_response_content_to_be_satisfy_inferred_from_model_it_should_throw_with_descriptive_message() + { + // Arrange + HttpResponseMessage? subject = null; + + // Act + Action act = () => + subject.Should().Satisfy(givenModelStructure: new + { + Property = default(string) + }, assertion: model => true.Should().BeTrue(), "because we want to test the failure {0}", "message"); + + // Assert + act.Should().Throw() + .WithMessage("Expected a * to assert because we want to test the failure message, but found ."); } + #endregion } \ No newline at end of file diff --git a/test/FluentAssertions.Web.Tests/TestModels/TestEnum.cs b/test/FluentAssertions.Web.Tests/TestModels/TestEnum.cs index 45926db..d07a600 100644 --- a/test/FluentAssertions.Web.Tests/TestModels/TestEnum.cs +++ b/test/FluentAssertions.Web.Tests/TestModels/TestEnum.cs @@ -1,8 +1,7 @@ -namespace FluentAssertions.Web.Tests.TestModels +namespace FluentAssertions.Web.Tests.TestModels; + +internal enum TestEnum { - internal enum TestEnum - { - Type1 = 2, - Type2 = 4 - } + Type1 = 2, + Type2 = 4 } diff --git a/test/FluentAssertions.Web.Tests/TestModels/TestModel.cs b/test/FluentAssertions.Web.Tests/TestModels/TestModel.cs index 34ddf29..7445e39 100644 --- a/test/FluentAssertions.Web.Tests/TestModels/TestModel.cs +++ b/test/FluentAssertions.Web.Tests/TestModels/TestModel.cs @@ -1,12 +1,11 @@ -namespace FluentAssertions.Web.Tests.TestModels +namespace FluentAssertions.Web.Tests.TestModels; + +internal class TestModel { - internal class TestModel - { - public string? Property { get; set; } - } + public string? Property { get; set; } +} - internal class TestModelWithEnum - { - public TestEnum TestEnum { get; set; } - } +internal class TestModelWithEnum +{ + public TestEnum TestEnum { get; set; } } \ No newline at end of file