diff --git a/Docs/pages/special-types/01-httpclient.md b/Docs/pages/special-types/01-httpclient.md index 5736da16..a6fcd61a 100644 --- a/Docs/pages/special-types/01-httpclient.md +++ b/Docs/pages/special-types/01-httpclient.md @@ -161,6 +161,7 @@ httpClient.SetupMock.Method To verify against the string content, use the following methods: +- `.WithString(Func)`: to match the string content against the given predicate - `.WithString(string)`: to match the content exactly as provided - `.WithStringMatching(string)`: to match the content using wildcard patterns - `.WithStringMatching(string).AsRegex()`: to match the content using regular expressions @@ -181,8 +182,8 @@ httpClient.SetupMock.Method To verify against the binary content, use the following methods: +- `.WithBytes(Func)`: to match the binary content against the given predicate - `.WithBytes(byte[])`: to match the content exactly as provided -- `.WithBytesContaining(byte[])`: to match the content to contain the provided byte sequence in order ```csharp httpClient.SetupMock.Method diff --git a/README.md b/README.md index e1325857..2092680e 100644 --- a/README.md +++ b/README.md @@ -1142,6 +1142,7 @@ httpClient.SetupMock.Method To verify against the string content, use the following methods: +- `.WithString(Func)`: to match the string content against the given predicate - `.WithString(string)`: to match the content exactly as provided - `.WithStringMatching(string)`: to match the content using wildcard patterns - `.WithStringMatching(string).AsRegex()`: to match the content using regular expressions @@ -1162,8 +1163,8 @@ httpClient.SetupMock.Method To verify against the binary content, use the following methods: +- `.WithBytes(Func)`: to match the binary content against the given predicate - `.WithBytes(byte[])`: to match the content exactly as provided -- `.WithBytesContaining(byte[])`: to match the content to contain the provided byte sequence in order ```csharp httpClient.SetupMock.Method diff --git a/Source/Mockolate.SourceGenerators/Entities/AttributeParameter.cs b/Source/Mockolate.SourceGenerators/Entities/AttributeParameter.cs index ea3e4ccd..5011635f 100644 --- a/Source/Mockolate.SourceGenerators/Entities/AttributeParameter.cs +++ b/Source/Mockolate.SourceGenerators/Entities/AttributeParameter.cs @@ -38,7 +38,7 @@ private static string SerializeConstantValue(TypedConstant value) { SpecialType.System_Char => $"'{value.Value}'", SpecialType.System_String => $"\"{value.Value.ToString().Replace("\"", "\\\"")}\"", - SpecialType.System_Boolean => value.Value.ToString().ToLower(), + SpecialType.System_Boolean => value.Value.ToString().ToLowerInvariant(), SpecialType.System_Double => ((double)value.Value).ToString(CultureInfo.InvariantCulture), SpecialType.System_Single => $"{((float)value.Value).ToString(CultureInfo.InvariantCulture)}F", SpecialType.System_Byte => $"(byte){value.Value}", diff --git a/Source/Mockolate/Web/ItExtensions.HttpContent.cs b/Source/Mockolate/Web/ItExtensions.HttpContent.cs index 3a1c5871..b7fc1121 100644 --- a/Source/Mockolate/Web/ItExtensions.HttpContent.cs +++ b/Source/Mockolate/Web/ItExtensions.HttpContent.cs @@ -72,6 +72,11 @@ public interface IFormDataContentParameter : IHttpContentParameter /// public interface IHttpContentParameter : IParameter, IHttpHeaderParameter { + /// + /// Expects the content to have a string body that satisfies the . + /// + IHttpContentParameter WithString(Func predicate); + /// /// Expects the content to have a string body equal to the value. /// @@ -88,9 +93,9 @@ public interface IHttpContentParameter : IParameter, IHttpHeaderPa IHttpContentParameter WithBytes(byte[] bytes); /// - /// Expects the binary content to contain the given . + /// Expects the binary content to satisfy the . /// - IHttpContentParameter WithBytesContaining(byte[] bytes); + IHttpContentParameter WithBytes(Func predicate); /// /// Expects the form data content to contain the given - pair. @@ -144,6 +149,11 @@ public void InvokeCallbacks(object? value) } } + public IHttpContentParameter WithString(Func predicate) + { + _contentMatcher = new PredicateStringMatcher(predicate); + return this; + } public IStringContentBodyParameter WithString(string expected) { @@ -157,17 +167,14 @@ public IStringContentBodyMatchingParameter WithStringMatching(string pattern) return this; } - public IHttpContentParameter WithBytes(byte[] bytes) + public IHttpContentParameter WithBytes(Func predicate) { - _contentMatcher = new BinaryMatcher(bytes, true); + _contentMatcher = new BinaryMatcher(predicate); return this; } - public IHttpContentParameter WithBytesContaining(byte[] bytes) - { - _contentMatcher = new BinaryMatcher(bytes, false); - return this; - } + public IHttpContentParameter WithBytes(byte[] bytes) + => WithBytes(b => bytes.SequenceEqual(b)); public IFormDataContentParameter WithFormData(string key, HttpFormDataValue value) { @@ -269,6 +276,19 @@ private bool Matches(HttpContent value) return true; } + private static string GetStringFromHttpContent(HttpContent content) + { +#if NET8_0_OR_GREATER + Stream stream = content.ReadAsStream(); + using StreamReader reader = new(stream, leaveOpen: true); +#else + Stream stream = content.ReadAsStreamAsync().ConfigureAwait(false).GetAwaiter().GetResult(); + using StreamReader reader = new(stream); +#endif + string stringContent = reader.ReadToEnd(); + return stringContent; + } + private interface IContentMatcher { bool Matches(HttpContent content); @@ -290,14 +310,7 @@ public StringMatcher(string value, bool isExact) public bool Matches(HttpContent content) { -#if NET8_0_OR_GREATER - Stream stream = content.ReadAsStream(); - using StreamReader reader = new(stream, leaveOpen: true); -#else - Stream stream = content.ReadAsStreamAsync().ConfigureAwait(false).GetAwaiter().GetResult(); - using StreamReader reader = new(stream); -#endif - string stringContent = reader.ReadToEnd(); + string stringContent = GetStringFromHttpContent(content); switch (_bodyMatchType) { case BodyMatchType.Exact when @@ -345,15 +358,29 @@ private enum BodyMatchType } } + private sealed class PredicateStringMatcher : IContentMatcher + { + private readonly Func _predicate; + + public PredicateStringMatcher(Func predicate) + { + _predicate = predicate; + } + + public bool Matches(HttpContent content) + { + string stringContent = GetStringFromHttpContent(content); + return _predicate.Invoke(stringContent); + } + } + private sealed class BinaryMatcher : IContentMatcher { - private readonly BodyMatchType _bodyMatchType; - private readonly byte[] _expectedBytes; + private readonly Func _predicate; - public BinaryMatcher(byte[] bytes, bool isExact) + public BinaryMatcher(Func predicate) { - _expectedBytes = bytes; - _bodyMatchType = isExact ? BodyMatchType.Exact : BodyMatchType.Contains; + _predicate = predicate; } public bool Matches(HttpContent content) @@ -366,58 +393,7 @@ public bool Matches(HttpContent content) using MemoryStream ms = new(); stream.CopyTo(ms); byte[] bytes = ms.ToArray(); - switch (_bodyMatchType) - { - case BodyMatchType.Exact when - !bytes.SequenceEqual(_expectedBytes): - return false; - case BodyMatchType.Contains when - !Contains(bytes, _expectedBytes): - return false; - } - - return true; - } - - private static bool Contains(byte[] data, byte[] otherData) - { -#if NET8_0_OR_GREATER - return data.AsSpan().IndexOf(otherData) >= 0; -#else - int dataLength = data.Length; - int otherDataLength = otherData.Length; - - if (dataLength < otherDataLength) - { - return false; - } - - for (int i = 0; i <= dataLength - otherDataLength; i++) - { - bool isMatch = true; - for (int j = 0; j < otherDataLength; j++) - { - if (data[i + j] != otherData[j]) - { - isMatch = false; - break; - } - } - - if (isMatch) - { - return true; - } - } - - return false; -#endif - } - - private enum BodyMatchType - { - Exact, - Contains, + return _predicate.Invoke(bytes); } } diff --git a/Tests/Mockolate.Api.Tests/Expected/Mockolate_net10.0.txt b/Tests/Mockolate.Api.Tests/Expected/Mockolate_net10.0.txt index c13268a6..5d4e3749 100644 --- a/Tests/Mockolate.Api.Tests/Expected/Mockolate_net10.0.txt +++ b/Tests/Mockolate.Api.Tests/Expected/Mockolate_net10.0.txt @@ -1866,14 +1866,15 @@ namespace Mockolate.Web } public interface IHttpContentParameter : Mockolate.Parameters.IParameter, Mockolate.Web.ItExtensions.IHttpHeaderParameter { + Mockolate.Web.ItExtensions.IHttpContentParameter WithBytes(System.Func predicate); Mockolate.Web.ItExtensions.IHttpContentParameter WithBytes(byte[] bytes); - Mockolate.Web.ItExtensions.IHttpContentParameter WithBytesContaining(byte[] bytes); Mockolate.Web.ItExtensions.IFormDataContentParameter WithFormData([System.Runtime.CompilerServices.TupleElementNames(new string[] { "Key", "Value"})] System.Collections.Generic.IEnumerable> values); Mockolate.Web.ItExtensions.IFormDataContentParameter WithFormData(string values); Mockolate.Web.ItExtensions.IFormDataContentParameter WithFormData(string key, Mockolate.Web.HttpFormDataValue value); Mockolate.Web.ItExtensions.IHttpContentParameter WithMediaType(string? mediaType); + Mockolate.Web.ItExtensions.IHttpContentParameter WithString(System.Func predicate); Mockolate.Web.ItExtensions.IStringContentBodyParameter WithString(string expected); Mockolate.Web.ItExtensions.IStringContentBodyMatchingParameter WithStringMatching(string pattern); } diff --git a/Tests/Mockolate.Api.Tests/Expected/Mockolate_net8.0.txt b/Tests/Mockolate.Api.Tests/Expected/Mockolate_net8.0.txt index a53441d1..efaeadf4 100644 --- a/Tests/Mockolate.Api.Tests/Expected/Mockolate_net8.0.txt +++ b/Tests/Mockolate.Api.Tests/Expected/Mockolate_net8.0.txt @@ -1865,14 +1865,15 @@ namespace Mockolate.Web } public interface IHttpContentParameter : Mockolate.Parameters.IParameter, Mockolate.Web.ItExtensions.IHttpHeaderParameter { + Mockolate.Web.ItExtensions.IHttpContentParameter WithBytes(System.Func predicate); Mockolate.Web.ItExtensions.IHttpContentParameter WithBytes(byte[] bytes); - Mockolate.Web.ItExtensions.IHttpContentParameter WithBytesContaining(byte[] bytes); Mockolate.Web.ItExtensions.IFormDataContentParameter WithFormData([System.Runtime.CompilerServices.TupleElementNames(new string[] { "Key", "Value"})] System.Collections.Generic.IEnumerable> values); Mockolate.Web.ItExtensions.IFormDataContentParameter WithFormData(string values); Mockolate.Web.ItExtensions.IFormDataContentParameter WithFormData(string key, Mockolate.Web.HttpFormDataValue value); Mockolate.Web.ItExtensions.IHttpContentParameter WithMediaType(string? mediaType); + Mockolate.Web.ItExtensions.IHttpContentParameter WithString(System.Func predicate); Mockolate.Web.ItExtensions.IStringContentBodyParameter WithString(string expected); Mockolate.Web.ItExtensions.IStringContentBodyMatchingParameter WithStringMatching(string pattern); } diff --git a/Tests/Mockolate.Api.Tests/Expected/Mockolate_netstandard2.0.txt b/Tests/Mockolate.Api.Tests/Expected/Mockolate_netstandard2.0.txt index b1c8d819..61514e96 100644 --- a/Tests/Mockolate.Api.Tests/Expected/Mockolate_netstandard2.0.txt +++ b/Tests/Mockolate.Api.Tests/Expected/Mockolate_netstandard2.0.txt @@ -1806,14 +1806,15 @@ namespace Mockolate.Web } public interface IHttpContentParameter : Mockolate.Parameters.IParameter, Mockolate.Web.ItExtensions.IHttpHeaderParameter { + Mockolate.Web.ItExtensions.IHttpContentParameter WithBytes(System.Func predicate); Mockolate.Web.ItExtensions.IHttpContentParameter WithBytes(byte[] bytes); - Mockolate.Web.ItExtensions.IHttpContentParameter WithBytesContaining(byte[] bytes); Mockolate.Web.ItExtensions.IFormDataContentParameter WithFormData([System.Runtime.CompilerServices.TupleElementNames(new string[] { "Key", "Value"})] System.Collections.Generic.IEnumerable> values); Mockolate.Web.ItExtensions.IFormDataContentParameter WithFormData(string values); Mockolate.Web.ItExtensions.IFormDataContentParameter WithFormData(string key, Mockolate.Web.HttpFormDataValue value); Mockolate.Web.ItExtensions.IHttpContentParameter WithMediaType(string? mediaType); + Mockolate.Web.ItExtensions.IHttpContentParameter WithString(System.Func predicate); Mockolate.Web.ItExtensions.IStringContentBodyParameter WithString(string expected); Mockolate.Web.ItExtensions.IStringContentBodyMatchingParameter WithStringMatching(string pattern); } diff --git a/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpContentTests.WithBytesContainingTests.cs b/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpContentTests.WithBytesContainingTests.cs deleted file mode 100644 index f26299c2..00000000 --- a/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpContentTests.WithBytesContainingTests.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Net; -using System.Net.Http; -using System.Threading; -using Mockolate.Web; - -namespace Mockolate.Tests.Web; - -public sealed partial class ItExtensionsTests -{ - public sealed partial class IsHttpContentTests - { - public sealed class WithBytesContainingTests - { - [Theory] - [InlineData(new byte[0], new byte[0], true)] - [InlineData(new byte[] { 0x1, }, new byte[] { 0x1, }, true)] - [InlineData(new byte[] { 0x1, }, new byte[] { 0x2, }, false)] - [InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x1, }, true)] - [InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x2, }, true)] - [InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x3, }, true)] - [InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x1, 0x2, }, true)] - [InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x2, 0x3, }, true)] - [InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x1, 0x3, }, false)] - [InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x1, 0x2, 0x3, }, true)] - [InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x1, 0x2, 0x3, 0x4, }, false)] - public async Task ShouldCheckForEquality(byte[] body, byte[] expected, bool expectSuccess) - { - HttpClient httpClient = Mock.Create(); - httpClient.SetupMock.Method - .PostAsync(It.IsAny(), It.IsHttpContent().WithBytesContaining(expected)) - .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)); - - HttpResponseMessage result = await httpClient.PostAsync("https://www.aweXpect.com", - new ByteArrayContent(body), - CancellationToken.None); - - await That(result.StatusCode) - .IsEqualTo(expectSuccess ? HttpStatusCode.OK : HttpStatusCode.NotImplemented); - } - } - } -} diff --git a/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpContentTests.WithBytesTests.cs b/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpContentTests.WithBytesTests.cs index 1ccd0119..e6d2b735 100644 --- a/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpContentTests.WithBytesTests.cs +++ b/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpContentTests.WithBytesTests.cs @@ -11,6 +11,28 @@ public sealed partial class IsHttpContentTests { public sealed class WithBytesTests { + [Theory] + [InlineData(new byte[0], 0x1, false)] + [InlineData(new byte[] { 0x1, }, 0x1, true)] + [InlineData(new byte[] { 0x1, }, 0x2, false)] + [InlineData(new byte[] { 0x1, 0x2, 0x3, }, 0x1, true)] + [InlineData(new byte[] { 0x1, 0x2, 0x3, }, 0x2, false)] + [InlineData(new byte[] { 0x1, 0x2, 0x3, }, 0x3, false)] + public async Task Predicate_ShouldValidatePredicate(byte[] body, byte expectedFirstByte, bool expectSuccess) + { + HttpClient httpClient = Mock.Create(); + httpClient.SetupMock.Method + .PostAsync(It.IsAny(), It.IsHttpContent().WithBytes(b => b.Length > 0 && b[0] == expectedFirstByte)) + .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)); + + HttpResponseMessage result = await httpClient.PostAsync("https://www.aweXpect.com", + new ByteArrayContent(body), + CancellationToken.None); + + await That(result.StatusCode) + .IsEqualTo(expectSuccess ? HttpStatusCode.OK : HttpStatusCode.NotImplemented); + } + [Theory] [InlineData(new byte[0], new byte[0], true)] [InlineData(new byte[] { 0x66, }, new byte[] { 0x66, }, true)] diff --git a/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpContentTests.WithStringTests.cs b/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpContentTests.WithStringTests.cs index 16f7abe1..de188ba0 100644 --- a/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpContentTests.WithStringTests.cs +++ b/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpContentTests.WithStringTests.cs @@ -1,7 +1,6 @@ using System.Net; using System.Net.Http; using System.Text; -using System.Text.RegularExpressions; using System.Threading; using Mockolate.Web; @@ -13,6 +12,28 @@ public sealed partial class IsHttpContentTests { public sealed class WithStringTests { + [Theory] + [InlineData("", true)] + [InlineData("foo", true)] + [InlineData("FOO", false)] + [InlineData("bar", true)] + [InlineData("BAR", false)] + public async Task Predicate_ShouldValidatePredicate(string content, bool expectSuccess) + { + HttpClient httpClient = Mock.Create(); + httpClient.SetupMock.Method + .PostAsync(It.IsAny(), It.IsHttpContent() + .WithString(c => c.Equals(c.ToLowerInvariant(), StringComparison.Ordinal))) + .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)); + + HttpResponseMessage result = await httpClient.PostAsync("https://www.aweXpect.com", + new StringContent(content), + CancellationToken.None); + + await That(result.StatusCode) + .IsEqualTo(expectSuccess ? HttpStatusCode.OK : HttpStatusCode.NotImplemented); + } + [Fact] public async Task ShouldNotCheckHttpContentType() { diff --git a/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpRequestMessageTests.WhoseContentIsTests.cs b/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpRequestMessageTests.WhoseContentIsTests.cs index 00c717d7..1b1ae910 100644 --- a/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpRequestMessageTests.WhoseContentIsTests.cs +++ b/Tests/Mockolate.Tests/Web/ItExtensionsTests.IsHttpRequestMessageTests.WhoseContentIsTests.cs @@ -72,11 +72,76 @@ await That(result.StatusCode) .IsEqualTo(expectSuccess ? HttpStatusCode.OK : HttpStatusCode.NotImplemented); } + [Theory] + [InlineData(new byte[0], 0x1, false)] + [InlineData(new byte[] { 0x1, }, 0x1, true)] + [InlineData(new byte[] { 0x1, }, 0x2, false)] + [InlineData(new byte[] { 0x1, 0x2, 0x3, }, 0x1, true)] + [InlineData(new byte[] { 0x1, 0x2, 0x3, }, 0x2, false)] + [InlineData(new byte[] { 0x1, 0x2, 0x3, }, 0x3, false)] + public async Task WithBytes_Predicate_ShouldValidatePredicate( + byte[] body, byte expectedFirstByte, bool expectSuccess) + { + HttpClient httpClient = Mock.Create(); + httpClient.SetupMock.Method + .SendAsync(It.IsHttpRequestMessage().WhoseContentIs(c => c.WithBytes(b => b.Length > 0 && b[0] == expectedFirstByte))) + .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)); + + HttpResponseMessage result = await httpClient.PostAsync("https://www.aweXpect.com", + new ByteArrayContent(body), + CancellationToken.None); + + await That(result.StatusCode) + .IsEqualTo(expectSuccess ? HttpStatusCode.OK : HttpStatusCode.NotImplemented); + } + + [Theory] + [InlineData(new byte[0], new byte[0], true)] + [InlineData(new byte[] { 0x66, }, new byte[] { 0x66, }, true)] + [InlineData(new byte[] { 0x66, }, new byte[] { 0x67, }, false)] + [InlineData(new byte[] { 0x66, 0x67, }, new byte[] { 0x67, }, false)] + [InlineData(new byte[] { 0x66, 0x67, }, new byte[] { 0x67, 0x68, 0x69, }, false)] + public async Task WithBytes_ShouldCheckForEquality(byte[] body, byte[] expected, bool expectSuccess) + { + HttpClient httpClient = Mock.Create(); + httpClient.SetupMock.Method + .SendAsync(It.IsHttpRequestMessage().WhoseContentIs(c => c.WithBytes(expected))) + .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)); + + HttpResponseMessage result = await httpClient.PostAsync("https://www.aweXpect.com", + new ByteArrayContent(body), + CancellationToken.None); + + await That(result.StatusCode) + .IsEqualTo(expectSuccess ? HttpStatusCode.OK : HttpStatusCode.NotImplemented); + } + + [Theory] + [InlineData("image/png", true)] + [InlineData("text/plain", false)] + [InlineData("image/gif", false)] + public async Task WithMediaType_ShouldVerifyMediaType(string mediaType, bool expectSuccess) + { + HttpClient httpClient = Mock.Create(); + httpClient.SetupMock.Method + .SendAsync(It.IsHttpRequestMessage().WhoseContentIs(c => c.WithMediaType("image/png"))) + .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)); + ByteArrayContent content = new([]); + content.Headers.ContentType = new MediaTypeHeaderValue(mediaType); + + HttpResponseMessage result = await httpClient.PostAsync("https://www.aweXpect.com", + content, + CancellationToken.None); + + await That(result.StatusCode) + .IsEqualTo(expectSuccess ? HttpStatusCode.OK : HttpStatusCode.NotImplemented); + } + [Theory] [InlineData("foo", "foo", true)] [InlineData("foo", "FOO", true)] [InlineData("foo", "bar", false)] - public async Task WithBody_IgnoringCase_ShouldCheckForCaseInsensitiveEquality(string body, + public async Task WithString_IgnoringCase_ShouldCheckForCaseInsensitiveEquality(string body, string expected, bool expectSuccess) { HttpClient httpClient = Mock.Create(); @@ -92,11 +157,33 @@ await That(result.StatusCode) .IsEqualTo(expectSuccess ? HttpStatusCode.OK : HttpStatusCode.NotImplemented); } + [Theory] + [InlineData("", true)] + [InlineData("foo", true)] + [InlineData("FOO", false)] + [InlineData("bar", true)] + [InlineData("BAR", false)] + public async Task WithString_Predicate_ShouldValidatePredicate(string content, bool expectSuccess) + { + HttpClient httpClient = Mock.Create(); + httpClient.SetupMock.Method + .SendAsync(It.IsHttpRequestMessage().WhoseContentIs(c => c + .WithString(v => v.Equals(v.ToLowerInvariant(), StringComparison.Ordinal)))) + .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)); + + HttpResponseMessage result = await httpClient.PostAsync("https://www.aweXpect.com", + new StringContent(content), + CancellationToken.None); + + await That(result.StatusCode) + .IsEqualTo(expectSuccess ? HttpStatusCode.OK : HttpStatusCode.NotImplemented); + } + [Theory] [InlineData("foo", "foo", true)] [InlineData("foo", "FOO", false)] [InlineData("foo", "bar", false)] - public async Task WithBody_ShouldCheckForEquality(string body, string expected, + public async Task WithString_ShouldCheckForEquality(string body, string expected, bool expectSuccess) { HttpClient httpClient = Mock.Create(); @@ -117,7 +204,7 @@ await That(result.StatusCode) [InlineData("foo", "F[aeiou]*", true)] [InlineData("foo", ".a.", false)] public async Task - WithBodyMatching_AsRegex_IgnoringCase_ShouldCheckForCaseInsensitiveMatchingWildcard( + WithStringMatching_AsRegex_IgnoringCase_ShouldCheckForCaseInsensitiveMatchingWildcard( string body, string pattern, bool expectSuccess) { HttpClient httpClient = Mock.Create(); @@ -138,7 +225,7 @@ await That(result.StatusCode) [InlineData("foo", "f[aeiou]*", true)] [InlineData("foo", "F[aeiou]*", false)] [InlineData("foo", ".a.", false)] - public async Task WithBodyMatching_AsRegex_ShouldCheckForMatchingWildcard( + public async Task WithStringMatching_AsRegex_ShouldCheckForMatchingWildcard( string body, string pattern, bool expectSuccess) { HttpClient httpClient = Mock.Create(); @@ -156,7 +243,7 @@ await That(result.StatusCode) } [Fact] - public async Task WithBodyMatching_AsRegex_ShouldUseProvidedOptions() + public async Task WithStringMatching_AsRegex_ShouldUseProvidedOptions() { HttpClient httpClient = Mock.Create(); httpClient.SetupMock.Method @@ -172,7 +259,7 @@ public async Task WithBodyMatching_AsRegex_ShouldUseProvidedOptions() } [Fact] - public async Task WithBodyMatching_AsRegex_ShouldUseTimeout() + public async Task WithStringMatching_AsRegex_ShouldUseTimeout() { HttpClient httpClient = Mock.Create(); httpClient.SetupMock.Method @@ -199,7 +286,7 @@ await That(Act) [InlineData("foo", "*", true)] [InlineData("foo", "F*", true)] [InlineData("foo", "*a*", false)] - public async Task WithBodyMatching_IgnoringCase_ShouldCheckForCaseInsensitiveMatchingWildcard( + public async Task WithStringMatching_IgnoringCase_ShouldCheckForCaseInsensitiveMatchingWildcard( string body, string pattern, bool expectSuccess) { HttpClient httpClient = Mock.Create(); @@ -223,7 +310,7 @@ await That(result.StatusCode) [InlineData("foo", "*", true)] [InlineData("foo", "F*", false)] [InlineData("foo", "*a*", false)] - public async Task WithBodyMatching_ShouldCheckForMatchingWildcard( + public async Task WithStringMatching_ShouldCheckForMatchingWildcard( string body, string pattern, bool expectSuccess) { HttpClient httpClient = Mock.Create(); @@ -239,160 +326,6 @@ public async Task WithBodyMatching_ShouldCheckForMatchingWildcard( await That(result.StatusCode) .IsEqualTo(expectSuccess ? HttpStatusCode.OK : HttpStatusCode.NotImplemented); } - - [Theory] - [InlineData(new byte[0], new byte[0], true)] - [InlineData(new byte[] - { - 0x66, - }, new byte[] - { - 0x66, - }, true)] - [InlineData(new byte[] - { - 0x66, - }, new byte[] - { - 0x67, - }, false)] - [InlineData(new byte[] - { - 0x66, 0x67, - }, new byte[] - { - 0x67, - }, false)] - [InlineData(new byte[] - { - 0x66, 0x67, - }, new byte[] - { - 0x67, 0x68, 0x69, - }, false)] - public async Task WithBytes_ShouldCheckForEquality(byte[] body, byte[] expected, bool expectSuccess) - { - HttpClient httpClient = Mock.Create(); - httpClient.SetupMock.Method - .SendAsync(It.IsHttpRequestMessage().WhoseContentIs(c => c.WithBytes(expected))) - .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)); - - HttpResponseMessage result = await httpClient.PostAsync("https://www.aweXpect.com", - new ByteArrayContent(body), - CancellationToken.None); - - await That(result.StatusCode) - .IsEqualTo(expectSuccess ? HttpStatusCode.OK : HttpStatusCode.NotImplemented); - } - - [Theory] - [InlineData(new byte[0], new byte[0], true)] - [InlineData(new byte[] - { - 0x1, - }, new byte[] - { - 0x1, - }, true)] - [InlineData(new byte[] - { - 0x1, - }, new byte[] - { - 0x2, - }, false)] - [InlineData(new byte[] - { - 0x1, 0x2, 0x3, - }, new byte[] - { - 0x1, - }, true)] - [InlineData(new byte[] - { - 0x1, 0x2, 0x3, - }, new byte[] - { - 0x2, - }, true)] - [InlineData(new byte[] - { - 0x1, 0x2, 0x3, - }, new byte[] - { - 0x3, - }, true)] - [InlineData(new byte[] - { - 0x1, 0x2, 0x3, - }, new byte[] - { - 0x1, 0x2, - }, true)] - [InlineData(new byte[] - { - 0x1, 0x2, 0x3, - }, new byte[] - { - 0x2, 0x3, - }, true)] - [InlineData(new byte[] - { - 0x1, 0x2, 0x3, - }, new byte[] - { - 0x1, 0x3, - }, false)] - [InlineData(new byte[] - { - 0x1, 0x2, 0x3, - }, new byte[] - { - 0x1, 0x2, 0x3, - }, true)] - [InlineData(new byte[] - { - 0x1, 0x2, 0x3, - }, new byte[] - { - 0x1, 0x2, 0x3, 0x4, - }, false)] - public async Task WithBytesContaining_ShouldCheckForEquality(byte[] body, byte[] expected, - bool expectSuccess) - { - HttpClient httpClient = Mock.Create(); - httpClient.SetupMock.Method - .SendAsync(It.IsHttpRequestMessage().WhoseContentIs(c => c.WithBytesContaining(expected))) - .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)); - - HttpResponseMessage result = await httpClient.PostAsync("https://www.aweXpect.com", - new ByteArrayContent(body), - CancellationToken.None); - - await That(result.StatusCode) - .IsEqualTo(expectSuccess ? HttpStatusCode.OK : HttpStatusCode.NotImplemented); - } - - [Theory] - [InlineData("image/png", true)] - [InlineData("text/plain", false)] - [InlineData("image/gif", false)] - public async Task WithMediaType_ShouldVerifyMediaType(string mediaType, bool expectSuccess) - { - HttpClient httpClient = Mock.Create(); - httpClient.SetupMock.Method - .SendAsync(It.IsHttpRequestMessage().WhoseContentIs(c => c.WithMediaType("image/png"))) - .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)); - ByteArrayContent content = new([]); - content.Headers.ContentType = new MediaTypeHeaderValue(mediaType); - - HttpResponseMessage result = await httpClient.PostAsync("https://www.aweXpect.com", - content, - CancellationToken.None); - - await That(result.StatusCode) - .IsEqualTo(expectSuccess ? HttpStatusCode.OK : HttpStatusCode.NotImplemented); - } } } }