diff --git a/src/MockHttp/Extensions/RequestMatchingExtensions.cs b/src/MockHttp/Extensions/RequestMatchingExtensions.cs index 2f4aba6a..7038c877 100644 --- a/src/MockHttp/Extensions/RequestMatchingExtensions.cs +++ b/src/MockHttp/Extensions/RequestMatchingExtensions.cs @@ -6,6 +6,8 @@ using System.Text; using MockHttp.Http; using MockHttp.Matchers; +using MockHttp.Matchers.Patterns; +using static MockHttp.Http.UriExtensions; namespace MockHttp; @@ -14,13 +16,30 @@ namespace MockHttp; /// public static class RequestMatchingExtensions { + private static bool ContainsWildcard(this string value) + { + if (value is null) + { + throw new ArgumentNullException(nameof(value)); + } + +#if NETSTANDARD2_0 || NETFRAMEWORK + return value.Contains("*"); +#else + return value.Contains('*', StringComparison.InvariantCultureIgnoreCase); +#endif + } + /// /// Matches a request by specified . /// /// The request matching builder instance. /// The request URI or a URI wildcard. + /// to allow wildcards, or if exact matching. /// The request matching builder instance. - public static RequestMatching RequestUri(this RequestMatching builder, string requestUri) +#pragma warning disable CA1054 + public static RequestMatching RequestUri(this RequestMatching builder, string requestUri, bool allowWildcards = true) +#pragma warning restore CA1054 { if (builder is null) { @@ -32,7 +51,9 @@ public static RequestMatching RequestUri(this RequestMatching builder, string re throw new ArgumentNullException(nameof(requestUri)); } - return builder.With(new RequestUriMatcher(requestUri, true)); + return allowWildcards && requestUri.ContainsWildcard() + ? builder.With(new UriMatcher(new UriStringPatternMatcher(uri => uri.ToString(), new WildcardPatternMatcher(requestUri)), requestUri)) + : builder.RequestUri(new Uri(requestUri, DotNetRelativeOrAbsolute)); } /// @@ -53,7 +74,7 @@ public static RequestMatching RequestUri(this RequestMatching builder, Uri reque throw new ArgumentNullException(nameof(requestUri)); } - return builder.With(new RequestUriMatcher(requestUri)); + return builder.With(new UriMatcher(new RelativeOrAbsoluteUriPatternMatcher(requestUri), requestUri.ToString())); } /// diff --git a/src/MockHttp/Matchers/RequestUriMatcher.cs b/src/MockHttp/Matchers/RequestUriMatcher.cs deleted file mode 100644 index 782e810c..00000000 --- a/src/MockHttp/Matchers/RequestUriMatcher.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System.Diagnostics; -using MockHttp.Http; -using MockHttp.Matchers.Patterns; -using MockHttp.Responses; -using static MockHttp.Http.UriExtensions; - -namespace MockHttp.Matchers; - -/// -/// Matches a request by the request URI. -/// -public class RequestUriMatcher : HttpRequestMatcher -{ - [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private readonly Uri _requestUri = default!; - [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private readonly string _formattedUri; - [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private readonly WildcardPatternMatcher? _uriPatternMatcher; - - /// - /// Initializes a new instance of the class using specified . - /// - /// The request URI. - public RequestUriMatcher(Uri uri) - { - _requestUri = uri.EnsureIsRooted(); - _formattedUri = _requestUri.ToString(); - } - - /// - /// Initializes a new instance of the class using specified . - /// - /// The request URI or a URI wildcard. - /// to allow wildcards, or if exact matching. - public RequestUriMatcher(string uriString, bool allowWildcards = true) - { - _formattedUri = uriString ?? throw new ArgumentNullException(nameof(uriString)); - - if (allowWildcards -#if NETSTANDARD2_0 || NETFRAMEWORK - && uriString.Contains("*") -#else - && uriString.Contains('*', StringComparison.InvariantCultureIgnoreCase) -#endif - ) - { - _uriPatternMatcher = new WildcardPatternMatcher(uriString); - } - else - { - // If no wildcards, then must be actual uri. - _requestUri = new Uri(uriString, DotNetRelativeOrAbsolute).EnsureIsRooted(); - _formattedUri = _requestUri.ToString(); - } - } - - /// - public override bool IsMatch(MockHttpRequestContext requestContext) - { - if (requestContext is null) - { - throw new ArgumentNullException(nameof(requestContext)); - } - - Uri? requestUri = requestContext.Request.RequestUri; - if (requestUri is null) - { - return false; - } - - if (_uriPatternMatcher is null) - { - return IsAbsoluteUriMatch(requestUri) || IsRelativeUriMatch(requestUri); - } - - return _uriPatternMatcher.IsMatch(requestUri.ToString()); - } - - private bool IsAbsoluteUriMatch(Uri uri) - { - return _requestUri.IsAbsoluteUri && uri.Equals(_requestUri); - } - - private bool IsRelativeUriMatch(Uri uri) - { - return !_requestUri.IsAbsoluteUri - && uri.IsBaseOf(_requestUri) - && uri.ToString().EndsWith(_requestUri.ToString(), StringComparison.Ordinal); - } - - /// - public override string ToString() - { - return $"RequestUri: '{_formattedUri}'"; - } -} diff --git a/test/MockHttp.Tests/Extensions/RequestMatchingExtensionsTests.cs b/test/MockHttp.Tests/Extensions/RequestMatchingExtensionsTests.cs index 4ba231e0..bd876f64 100644 --- a/test/MockHttp.Tests/Extensions/RequestMatchingExtensionsTests.cs +++ b/test/MockHttp.Tests/Extensions/RequestMatchingExtensionsTests.cs @@ -1,4 +1,5 @@ -using System.Collections.Specialized; +using System; +using System.Collections.Specialized; using System.Linq.Expressions; using System.Net.Http.Headers; using System.Text; @@ -6,6 +7,7 @@ using MockHttp.Http; using MockHttp.Matchers; using MockHttp.Responses; +using static MockHttp.Http.UriExtensions; namespace MockHttp.Extensions; @@ -20,33 +22,184 @@ protected RequestMatchingExtensionsTests() public class RequestUri : RequestMatchingExtensionsTests { - [Fact] - public async Task When_configuring_requestUri_as_string_should_match() + [Theory] + [InlineData("relative.htm", true, "http://127.0.0.1/relative.htm", true)] + [InlineData("relative.htm", true, "http://127.0.0.1/relative.htm?query=string", false)] + [InlineData("relative.htm", false, "http://127.0.0.1/relative.htm", true)] + [InlineData("relative.htm", false, "http://127.0.0.1/relative.htm?query=string", false)] + + [InlineData("/relative.htm", true, "http://127.0.0.1/relative.htm", true)] + [InlineData("/relative.htm", true, "http://127.0.0.1/relative.htm?query=string", false)] + [InlineData("/relative.htm", false, "http://127.0.0.1/relative.htm", true)] + [InlineData("/relative.htm", false, "http://127.0.0.1/relative.htm?query=string", false)] + + [InlineData("relative.htm?query=string", true, "http://127.0.0.1/relative.htm?query=string", true)] + [InlineData("relative.htm?query=string", false, "http://127.0.0.1/relative.htm?query=string", true)] + [InlineData("http://127.0.0.1/absolute.htm?query=string", true, "http://127.0.0.1/absolute.htm?query=string", true)] + [InlineData("http://127.0.0.1/absolute.htm?query=string", false, "http://127.0.0.1/absolute.htm?query=string", true)] + + [InlineData("/folder/relative.htm", true, "http://127.0.0.1/relative.htm", false)] + [InlineData("/folder/relative.htm", true, "http://127.0.0.1/relative.htm?query=string", false)] + [InlineData("/folder/relative.htm", false, "http://127.0.0.1/relative.htm", false)] + [InlineData("/folder/relative.htm", false, "http://127.0.0.1/relative.htm?query=string", false)] + + [InlineData("relative.htm", true, "http://127.0.0.1/folder/relative.htm", false)] + [InlineData("relative.htm", true, "http://127.0.0.1/folder/relative.htm?query=string", false)] + [InlineData("relative.htm", false, "http://127.0.0.1/folder/relative.htm", false)] + [InlineData("relative.htm", false, "http://127.0.0.1/folder/relative.htm?query=string", false)] + + [InlineData("folder/relative.htm", true, "http://127.0.0.1/folder/relative.htm", true)] + [InlineData("folder/relative.htm", true, "http://127.0.0.1/folder/relative.htm?query=string", false)] + [InlineData("folder/relative.htm", false, "http://127.0.0.1/folder/relative.htm", true)] + [InlineData("folder/relative.htm", false, "http://127.0.0.1/folder/relative.htm?query=string", false)] + + [InlineData("/folder/relative.htm", true, "http://127.0.0.1/folder/relative.htm", true)] + [InlineData("/folder/relative.htm", true, "http://127.0.0.1/folder/relative.htm?query=string", false)] + [InlineData("/folder/relative.htm", false, "http://127.0.0.1/folder/relative.htm", true)] + [InlineData("/folder/relative.htm", false, "http://127.0.0.1/folder/relative.htm?query=string", false)] + + [InlineData("http://127.0.0.1/absolute.htm", true, "http://127.0.0.1/absolute.htm", true)] + [InlineData("http://127.0.0.1/absolute.htm", true, "http://127.0.0.1/absolute.htm?query=string", false)] + [InlineData("http://127.0.0.1/absolute.htm", false, "http://127.0.0.1/absolute.htm", true)] + [InlineData("http://127.0.0.1/absolute.htm", false, "http://127.0.0.1/absolute.htm?query=string", false)] + + [InlineData("http://127.0.0.1/absolute.htm", true, "http://127.0.0.1/folder/absolute.htm", false)] + [InlineData("http://127.0.0.1/absolute.htm", true, "http://127.0.0.1/folder/absolute.htm?query=string", false)] + [InlineData("http://127.0.0.1/absolute.htm", false, "http://127.0.0.1/folder/absolute.htm", false)] + [InlineData("http://127.0.0.1/absolute.htm", false, "http://127.0.0.1/folder/absolute.htm?query=string", false)] + + [InlineData("http://127.0.0.1/folder/absolute.htm", true, "http://127.0.0.1/folder/absolute.htm", true)] + [InlineData("http://127.0.0.1/folder/absolute.htm", true, "http://127.0.0.1/folder/absolute.htm?query=string", false)] + [InlineData("http://127.0.0.1/folder/absolute.htm", false, "http://127.0.0.1/folder/absolute.htm", true)] + [InlineData("http://127.0.0.1/folder/absolute.htm", false, "http://127.0.0.1/folder/absolute.htm?query=string", false)] + + [InlineData("*.htm", true, "http://127.0.0.1/relative.htm", true)] + [InlineData("*.htm", true, "http://127.0.0.1/relative.htm?query=string", false)] + [InlineData("*.htm", false, "http://127.0.0.1/relative.htm", false)] + + [InlineData("*/relative.htm", true, "http://127.0.0.1/relative.htm", true)] + [InlineData("*/relative.htm", true, "http://127.0.0.1/relative.htm?query=string", false)] + [InlineData("*/relative.htm", false, "http://127.0.0.1/relative.htm", false)] + + [InlineData("/*/relative.htm", true, "http://127.0.0.1/folder/relative.htm", false)] + [InlineData("/*/relative.htm", true, "http://127.0.0.1/folder/relative.htm?query=string", false)] + [InlineData("/*/relative.htm", false, "http://127.0.0.1/folder/relative.htm", false)] + + [InlineData("/*/relative.htm", true, "http://127.0.0.1/relative.htm", false)] + [InlineData("/*/relative.htm", true, "http://127.0.0.1/relative.htm?query=string", false)] + [InlineData("/*/relative.htm", false, "http://127.0.0.1/relative.htm", false)] + + [InlineData("/folder/*.htm", true, "http://127.0.0.1/folder/relative.htm", false)] + [InlineData("/folder/*.htm", true, "http://127.0.0.1/folder/relative.htm?query=string", false)] + [InlineData("/folder/*.htm", false, "http://127.0.0.1/folder/relative.htm", false)] + + [InlineData("*/folder/*.htm", true, "http://127.0.0.1/folder/relative.htm", true)] + [InlineData("*/folder/*.htm", true, "http://127.0.0.1/folder/relative.htm?query=string", false)] + [InlineData("*/folder/*.htm", false, "http://127.0.0.1/folder/relative.htm", false)] + + [InlineData("/folder/*.htm", true, "http://127.0.0.1/relative.htm", false)] + [InlineData("/folder/*.htm", true, "http://127.0.0.1/relative.htm?query=string", false)] + [InlineData("/folder/*.htm", false, "http://127.0.0.1/relative.htm", false)] + + [InlineData("/*/*/relative.*", true, "http://127.0.0.1/folder1/folder2/relative.htm", false)] + [InlineData("/*/*/relative.*", true, "http://127.0.0.1/folder1/folder2/relative.htm?query=string", false)] + [InlineData("/*/*/relative.*", false, "http://127.0.0.1/folder1/folder2/relative.htm", false)] + + [InlineData("*/folder1/*/relative.*", true, "http://127.0.0.1/folder1/folder2/relative.htm", true)] + [InlineData("*/folder1/*/relative.*", true, "http://127.0.0.1/folder1/folder2/relative.htm?query=string", true)] + [InlineData("*/folder1/*/relative.*", false, "http://127.0.0.1/folder1/folder2/relative.htm", false)] + + [InlineData("/*/*/relative.*", true, "http://127.0.0.1/folder1/relative.htm", false)] + [InlineData("/*/*/relative.*", true, "http://127.0.0.1/folder1/relative.htm?query=string", false)] + [InlineData("/*/*/relative.*", false, "http://127.0.0.1/folder1/relative.htm", false)] + + [InlineData("http://127.0.0.1/*.htm", true, "http://127.0.0.1/absolute.htm", true)] + [InlineData("http://127.0.0.1/*.htm", true, "http://127.0.0.1/absolute.htm?query=string", false)] + [InlineData("http://127.0.0.1/*.htm", false, "http://127.0.0.1/absolute.htm", false)] + + [InlineData("http://127.0.0.1/*.htm", true, "http://127.0.0.1/folder/absolute.htm", true)] + [InlineData("http://127.0.0.1/*.htm", true, "http://127.0.0.1/folder/absolute.htm?query=string", false)] + [InlineData("http://127.0.0.1/*.htm", false, "http://127.0.0.1/folder/absolute.htm", false)] + public async Task When_configuring_requestUri_as_string_it_should_match(string uriString, bool allowWildcards, string requestUri, bool isMatch) { - var request = new HttpRequestMessage { RequestUri = new Uri("http://127.0.0.1/") }; + var request = new HttpRequestMessage { RequestUri = new Uri(requestUri, UriKind.Absolute) }; // Act - _sut.RequestUri("http://127.0.0.1/"); + _sut.RequestUri(uriString, allowWildcards); IReadOnlyCollection matchers = _sut.Build(); // Assert - matchers.Should().HaveCount(1).And.AllBeOfType(); - (await matchers.AnyAsync(new MockHttpRequestContext(request))).Should().BeTrue(); + matchers.Should().HaveCount(1).And.AllBeAssignableTo(); + (await matchers.AnyAsync(new MockHttpRequestContext(request))).Should().Be(isMatch); } - [Fact] - public async Task When_configuring_requestUri_as_uri_should_match() + [Theory] + [InlineData("", UriKind.Relative, "http://127.0.0.1/", true)] + [InlineData("relative.htm", UriKind.Relative, "http://127.0.0.1/relative.htm", true)] + [InlineData("/folder/relative.htm", UriKind.Relative, "http://127.0.0.1/relative.htm", false)] + [InlineData("relative.htm", UriKind.Relative, "http://127.0.0.1/folder/relative.htm", false)] + [InlineData("folder/relative.htm", UriKind.Relative, "http://127.0.0.1/folder/relative.htm", true)] + [InlineData("/folder/relative.htm", UriKind.Relative, "http://127.0.0.1/folder/relative.htm", true)] + [InlineData("http://127.0.0.1/absolute.htm", UriKind.Absolute, "http://127.0.0.1/absolute.htm", true)] + [InlineData("http://127.0.0.1/absolute.htm", UriKind.Absolute, "http://127.0.0.1/folder/absolute.htm", false)] + public async Task When_configuring_requestUri_as_uri_it_should_match(string matchUri, UriKind uriKind, string requestUri, bool isMatch) { - var uri = new Uri("http://127.0.0.1/"); - var request = new HttpRequestMessage { RequestUri = new Uri("http://127.0.0.1/") }; + var uri = new Uri(matchUri, uriKind); + var request = new HttpRequestMessage { RequestUri = new Uri(requestUri, UriKind.Absolute) }; // Act _sut.RequestUri(uri); IReadOnlyCollection matchers = _sut.Build(); // Assert - matchers.Should().HaveCount(1).And.AllBeOfType(); - (await matchers.AnyAsync(new MockHttpRequestContext(request))).Should().BeTrue(); + matchers.Should().HaveCount(1).And.AllBeAssignableTo(); + (await matchers.AnyAsync(new MockHttpRequestContext(request))).Should().Be(isMatch); + } + + [Theory] + [InlineData("*/controller/*", false)] + [InlineData("*/controller/*", true)] + [InlineData("file.jpg", true)] + [InlineData("file.jpg", false)] + [InlineData("http://0.0.0.0/path/file.jpg", true)] + [InlineData("http://0.0.0.0/path/file.jpg", false)] + public void When_formatting_uriString_matcher_it_should_return_human_readable_representation(string uriString, bool allowWildcards) + { + string expectedText = $"RequestUri: '{uriString}'"; + + // Act + _sut.RequestUri(uriString, allowWildcards); + IReadOnlyCollection matchers = _sut.Build(); + string displayText = matchers.Should() + .ContainSingle() + .Which.Should() + .BeAssignableTo() + .Which.ToString(); + + // Assert + displayText.Should().Be(expectedText); + } + + [Theory] + [InlineData("*/controller/*")] + [InlineData("file.jpg")] + [InlineData("http://0.0.0.0/path/file.jpg")] + public void When_formatting_uri_matcher_it_should_return_human_readable_representation(string uriString) + { + string expectedText = $"RequestUri: '{uriString}'"; + var uri = new Uri(uriString, DotNetRelativeOrAbsolute); + + // Act + _sut.RequestUri(uri); + IReadOnlyCollection matchers = _sut.Build(); + string displayText = matchers.Should() + .ContainSingle() + .Which.Should() + .BeAssignableTo() + .Which.ToString(); + + // Assert + displayText.Should().Be(expectedText); } } @@ -692,7 +845,8 @@ public void Given_null_argument_when_executing_method_it_should_throw(params obj DelegateTestCase.Create( RequestMatchingExtensions.RequestUri, instance, - uri.ToString()), + uri.ToString(), + true), DelegateTestCase.Create( RequestMatchingExtensions.RequestUri, instance, diff --git a/test/MockHttp.Tests/Matchers/AnyMatcherTests.cs b/test/MockHttp.Tests/Matchers/AnyMatcherTests.cs index 2491861a..2615588b 100644 --- a/test/MockHttp.Tests/Matchers/AnyMatcherTests.cs +++ b/test/MockHttp.Tests/Matchers/AnyMatcherTests.cs @@ -18,8 +18,8 @@ public AnyMatcherTests() [InlineData("url2")] public async Task Given_request_uri_equals_one_of_the_matchers_when_matching_should_match(string requestUrl) { - _matchers.Add(new RequestUriMatcher("*url1")); - _matchers.Add(new RequestUriMatcher("*url2")); + _matchers.Add(new BoolMatcher(requestUrl == "url1")); + _matchers.Add(new BoolMatcher(requestUrl == "url2")); var request = new HttpRequestMessage(HttpMethod.Get, requestUrl); @@ -32,8 +32,8 @@ public async Task Given_request_uri_equals_one_of_the_matchers_when_matching_sho [Fact] public async Task Given_request_uri_matches_none_of_the_matchers_when_matching_should_not_match() { - _matchers.Add(new RequestUriMatcher("http://127.0.0.1/")); - _matchers.Add(new RequestUriMatcher("http://127.0.0.2/")); + _matchers.Add(new BoolMatcher(false)); + _matchers.Add(new BoolMatcher(false)); var request = new HttpRequestMessage(HttpMethod.Get, "http://127.0.0.3/"); diff --git a/test/MockHttp.Tests/Matchers/BoolMatcher.cs b/test/MockHttp.Tests/Matchers/BoolMatcher.cs new file mode 100644 index 00000000..7ff182da --- /dev/null +++ b/test/MockHttp.Tests/Matchers/BoolMatcher.cs @@ -0,0 +1,23 @@ +using MockHttp.Responses; + +namespace MockHttp.Matchers; + +internal sealed class BoolMatcher : HttpRequestMatcher +{ + private readonly bool _shouldMatch; + + public BoolMatcher(bool shouldMatch) + { + _shouldMatch = shouldMatch; + } + + public override bool IsMatch(MockHttpRequestContext requestContext) + { + return _shouldMatch; + } + + public override string ToString() + { + throw new NotImplementedException(); + } +} diff --git a/test/MockHttp.Tests/Matchers/RequestUriMatcherTests.cs b/test/MockHttp.Tests/Matchers/RequestUriMatcherTests.cs deleted file mode 100644 index 0a0943ad..00000000 --- a/test/MockHttp.Tests/Matchers/RequestUriMatcherTests.cs +++ /dev/null @@ -1,109 +0,0 @@ -using MockHttp.Responses; - -namespace MockHttp.Matchers; - -public class RequestUriMatcherTests -{ - [Theory] - [InlineData("", UriKind.Relative, "http://127.0.0.1/", true)] - [InlineData("relative.htm", UriKind.Relative, "http://127.0.0.1/relative.htm", true)] - [InlineData("/folder/relative.htm", UriKind.Relative, "http://127.0.0.1/relative.htm", false)] - [InlineData("relative.htm", UriKind.Relative, "http://127.0.0.1/folder/relative.htm", false)] - [InlineData("folder/relative.htm", UriKind.Relative, "http://127.0.0.1/folder/relative.htm", true)] - [InlineData("/folder/relative.htm", UriKind.Relative, "http://127.0.0.1/folder/relative.htm", true)] - [InlineData("http://127.0.0.1/absolute.htm", UriKind.Absolute, "http://127.0.0.1/absolute.htm", true)] - [InlineData("http://127.0.0.1/absolute.htm", UriKind.Absolute, "http://127.0.0.1/folder/absolute.htm", false)] - public void Given_uri_when_matching_should_match(string matchUri, UriKind uriKind, string requestUri, bool isMatch) - { - var request = new HttpRequestMessage { RequestUri = new Uri(requestUri, UriKind.Absolute) }; - var sut = new RequestUriMatcher(new Uri(matchUri, uriKind)); - - // Act & assert - sut.IsMatch(new MockHttpRequestContext(request)).Should().Be(isMatch); - } - - [Theory] - [InlineData("relative.htm", true, "http://127.0.0.1/relative.htm", true)] - [InlineData("/folder/relative.htm", true, "http://127.0.0.1/relative.htm", false)] - [InlineData("relative.htm", true, "http://127.0.0.1/folder/relative.htm", false)] - [InlineData("folder/relative.htm", true, "http://127.0.0.1/folder/relative.htm", true)] - [InlineData("/folder/relative.htm", true, "http://127.0.0.1/folder/relative.htm", true)] - [InlineData("http://127.0.0.1/absolute.htm", true, "http://127.0.0.1/absolute.htm", true)] - [InlineData("http://127.0.0.1/absolute.htm", true, "http://127.0.0.1/folder/absolute.htm", false)] - [InlineData("*.htm", true, "http://127.0.0.1/relative.htm", true)] - [InlineData("*/relative.htm", true, "http://127.0.0.1/relative.htm", true)] - [InlineData("/*/relative.htm", true, "http://127.0.0.1/folder/relative.htm", false)] - [InlineData("/*/relative.htm", true, "http://127.0.0.1/relative.htm", false)] - [InlineData("/folder/*.htm", true, "http://127.0.0.1/folder/relative.htm", false)] - [InlineData("*/folder/*.htm", true, "http://127.0.0.1/folder/relative.htm", true)] - [InlineData("/folder/*.htm", true, "http://127.0.0.1/relative.htm", false)] - [InlineData("/*/*/relative.*", true, "http://127.0.0.1/folder1/folder2/relative.htm", false)] - [InlineData("*/folder1/*/relative.*", true, "http://127.0.0.1/folder1/folder2/relative.htm", true)] - [InlineData("/*/*/relative.*", true, "http://127.0.0.1/folder1/relative.htm", false)] - [InlineData("http://127.0.0.1/*.htm", true, "http://127.0.0.1/absolute.htm", true)] - [InlineData("http://127.0.0.1/*.htm", true, "http://127.0.0.1/folder/absolute.htm", true)] - public void Given_uriString_when_matching_should_match(string uriString, bool hasWildcard, string requestUri, bool isMatch) - { - var request = new HttpRequestMessage { RequestUri = new Uri(requestUri, UriKind.Absolute) }; - var sut = new RequestUriMatcher(uriString, hasWildcard); - - // Act & assert - sut.IsMatch(new MockHttpRequestContext(request)).Should().Be(isMatch); - } - - [Fact] - public void Given_null_uri_when_creating_matcher_should_throw() - { - Uri? uri = null; - - // Act - Func act = () => new RequestUriMatcher(uri!); - - // Assert - act.Should() - .Throw() - .WithParameterName(nameof(uri)); - } - - [Fact] - public void Given_null_uriString_when_creating_matcher_should_throw() - { - string? uriString = null; - - // Act - Func act = () => new RequestUriMatcher(uriString!, false); - - // Assert - act.Should() - .Throw() - .WithParameterName(nameof(uriString)); - } - - [Fact] - public void When_formatting_should_return_human_readable_representation() - { - const string expectedText = "RequestUri: '*/controller/*'"; - var sut = new RequestUriMatcher("*/controller/*"); - - // Act - string displayText = sut.ToString(); - - // Assert - displayText.Should().Be(expectedText); - } - - [Fact] - public void Given_null_context_when_matching_it_should_throw() - { - var sut = new RequestUriMatcher("*/controller/*"); - MockHttpRequestContext? requestContext = null; - - // Act - Action act = () => sut.IsMatch(requestContext!); - - // Assert - act.Should() - .Throw() - .WithParameterName(nameof(requestContext)); - } -}