Skip to content

Commit a7d8a3e

Browse files
committed
Ignore case on uri matching, unless told otherwise.
1 parent f2f9b11 commit a7d8a3e

File tree

8 files changed

+133
-24
lines changed

8 files changed

+133
-24
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
2323
- When `HttpResponseMessage.Content` is null after `IResponse.ExecuteAsync` was called, an empty `StringContent` is added (Up until .NET 6.0, since Content is always filled there).
2424
- The `HttpRequestMessage` is always added to the response, which is now possible, since we no longer allow reusing responses.
2525
- Added `ConfigureAwait(false)` to all calls, since we now use async/await in the library.
26+
- The check on request uri is now case insensitive by default, when test url's that are case sensitive set the `ignoreCase` parameter to false.
2627

2728
## [0.7] - 2022-09-22
2829
### Changed

src/TestableHttpClient/HttpRequestMessageExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ public static bool HasContentHeader(this HttpRequestMessage httpRequestMessage,
205205
/// <param name="httpRequestMessage">A <see cref="HttpRequestMessage"/> to check the correct uri on.</param>
206206
/// <param name="pattern">A pattern to match with the request uri, supports * as wildcards.</param>
207207
/// <returns>true when the request uri matches the pattern; otherwise, false.</returns>
208-
public static bool HasMatchingUri(this HttpRequestMessage httpRequestMessage, string pattern)
208+
public static bool HasMatchingUri(this HttpRequestMessage httpRequestMessage, string pattern, bool ignoreCase = true)
209209
{
210210
if (httpRequestMessage == null)
211211
{
@@ -222,7 +222,7 @@ public static bool HasMatchingUri(this HttpRequestMessage httpRequestMessage, st
222222
null => throw new ArgumentNullException(nameof(pattern)),
223223
"" => false,
224224
"*" => true,
225-
_ => StringMatcher.Matches(httpRequestMessage.RequestUri.AbsoluteUri, pattern),
225+
_ => StringMatcher.Matches(httpRequestMessage.RequestUri.AbsoluteUri, pattern, ignoreCase),
226226
};
227227
}
228228

src/TestableHttpClient/HttpRequestMessagesCheckExtensions.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ public static class HttpRequestMessagesCheckExtensions
88
/// <param name="check">The implementation that hold all the request messages.</param>
99
/// <param name="pattern">The uri pattern that is expected.</param>
1010
/// <returns>The <seealso cref="IHttpRequestMessagesCheck"/> for further assertions.</returns>
11-
public static IHttpRequestMessagesCheck WithRequestUri(this IHttpRequestMessagesCheck check, string pattern) => WithRequestUri(check, pattern, null);
11+
public static IHttpRequestMessagesCheck WithRequestUri(this IHttpRequestMessagesCheck check, string pattern) => WithRequestUri(check, pattern, true, null);
12+
13+
public static IHttpRequestMessagesCheck WithRequestUri(this IHttpRequestMessagesCheck check, string pattern, bool ignoreCase) => WithRequestUri(check, pattern, ignoreCase, null);
1214

1315
/// <summary>
1416
/// Asserts whether requests were made to a given URI based on a pattern.
@@ -17,9 +19,10 @@ public static class HttpRequestMessagesCheckExtensions
1719
/// <param name="pattern">The uri pattern that is expected.</param>
1820
/// <param name="expectedNumberOfRequests">The expected number of requests.</param>
1921
/// <returns>The <seealso cref="IHttpRequestMessagesCheck"/> for further assertions.</returns>
20-
public static IHttpRequestMessagesCheck WithRequestUri(this IHttpRequestMessagesCheck check, string pattern, int expectedNumberOfRequests) => WithRequestUri(check, pattern, (int?)expectedNumberOfRequests);
22+
public static IHttpRequestMessagesCheck WithRequestUri(this IHttpRequestMessagesCheck check, string pattern, int expectedNumberOfRequests) => WithRequestUri(check, pattern, true, (int?)expectedNumberOfRequests);
23+
public static IHttpRequestMessagesCheck WithRequestUri(this IHttpRequestMessagesCheck check, string pattern, bool ignoreCase, int expectedNumberOfRequests) => WithRequestUri(check, pattern, ignoreCase, (int?)expectedNumberOfRequests);
2124

22-
private static IHttpRequestMessagesCheck WithRequestUri(this IHttpRequestMessagesCheck check, string pattern, int? expectedNumberOfRequests)
25+
private static IHttpRequestMessagesCheck WithRequestUri(this IHttpRequestMessagesCheck check, string pattern, bool ignoreCase, int? expectedNumberOfRequests)
2326
{
2427
if (check == null)
2528
{
@@ -37,7 +40,7 @@ private static IHttpRequestMessagesCheck WithRequestUri(this IHttpRequestMessage
3740
condition = $"uri pattern '{pattern}'";
3841
}
3942

40-
return check.WithFilter(x => x.HasMatchingUri(pattern), expectedNumberOfRequests, condition);
43+
return check.WithFilter(x => x.HasMatchingUri(pattern, ignoreCase), expectedNumberOfRequests, condition);
4144
}
4245

4346
/// <summary>

src/TestableHttpClient/TestableHttpMessageHandlerAssertionExtensions.cs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,21 @@ public static IHttpRequestMessagesCheck ShouldHaveMadeRequests(this TestableHttp
4949
/// <exception cref="HttpRequestMessageAssertionException">When no requests are made</exception>
5050
[AssertionMethod]
5151
public static IHttpRequestMessagesCheck ShouldHaveMadeRequestsTo(this TestableHttpMessageHandler handler, string pattern)
52+
{
53+
return handler.ShouldHaveMadeRequestsTo(pattern, true);
54+
}
55+
56+
/// <summary>
57+
/// Validates that requests to a specific uri have been made, throws an exception when no requests were made.
58+
/// </summary>
59+
/// <param name="handler">The <see cref="TestableHttpMessageHandler"/> that should be asserted.</param>
60+
/// <param name="pattern">The uri pattern to validate against, the pattern supports *.</param>
61+
/// <param name="ignoreCase">The uri validation should ignore cases.</param>
62+
/// <returns>An <see cref="IHttpRequestMessagesCheck"/> that can be used for additional assertions.</returns>
63+
/// <exception cref="ArgumentNullException">handler is `null` or pattern is `null`</exception>
64+
/// <exception cref="HttpRequestMessageAssertionException">When no requests are made</exception>
65+
[AssertionMethod]
66+
public static IHttpRequestMessagesCheck ShouldHaveMadeRequestsTo(this TestableHttpMessageHandler handler, string pattern, bool ignoreCase)
5267
{
5368
if (handler == null)
5469
{
@@ -60,7 +75,7 @@ public static IHttpRequestMessagesCheck ShouldHaveMadeRequestsTo(this TestableHt
6075
throw new ArgumentNullException(nameof(pattern));
6176
}
6277

63-
return new HttpRequestMessageAsserter(handler.Requests, handler.Options).WithRequestUri(pattern);
78+
return new HttpRequestMessageAsserter(handler.Requests, handler.Options).WithRequestUri(pattern, ignoreCase);
6479
}
6580

6681
/// <summary>
@@ -74,6 +89,21 @@ public static IHttpRequestMessagesCheck ShouldHaveMadeRequestsTo(this TestableHt
7489
/// <exception cref="HttpRequestMessageAssertionException">When no requests are made</exception>
7590
[AssertionMethod]
7691
public static IHttpRequestMessagesCheck ShouldHaveMadeRequestsTo(this TestableHttpMessageHandler handler, string pattern, int expectedNumberOfRequests)
92+
{
93+
return handler.ShouldHaveMadeRequestsTo(pattern, true, expectedNumberOfRequests);
94+
}
95+
96+
/// <summary>
97+
/// Validates that requests to a specific uri have been made, throws an exception when no requests were made.
98+
/// </summary>
99+
/// <param name="handler">The <see cref="TestableHttpMessageHandler"/> that should be asserted.</param>
100+
/// <param name="pattern">The uri pattern to validate against, the pattern supports *.</param>
101+
/// <param name="expectedNumberOfRequests">The expected number of requests.</param>
102+
/// <returns>An <see cref="IHttpRequestMessagesCheck"/> that can be used for additional assertions.</returns>
103+
/// <exception cref="ArgumentNullException">handler is `null` or pattern is `null`</exception>
104+
/// <exception cref="HttpRequestMessageAssertionException">When no requests are made</exception>
105+
[AssertionMethod]
106+
public static IHttpRequestMessagesCheck ShouldHaveMadeRequestsTo(this TestableHttpMessageHandler handler, string pattern, bool ignoreCase, int expectedNumberOfRequests)
77107
{
78108
if (handler == null)
79109
{
@@ -85,6 +115,6 @@ public static IHttpRequestMessagesCheck ShouldHaveMadeRequestsTo(this TestableHt
85115
throw new ArgumentNullException(nameof(pattern));
86116
}
87117

88-
return new HttpRequestMessageAsserter(handler.Requests, handler.Options).WithRequestUri(pattern, expectedNumberOfRequests);
118+
return new HttpRequestMessageAsserter(handler.Requests, handler.Options).WithRequestUri(pattern, ignoreCase, expectedNumberOfRequests);
89119
}
90120
}

src/TestableHttpClient/Utils/StringMatcher.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ namespace TestableHttpClient.Utils;
44

55
internal static class StringMatcher
66
{
7-
internal static bool Matches(string value, string pattern)
7+
internal static bool Matches(string value, string pattern, bool ignoreCase = false)
88
{
99
var escapedPattern = Regex.Escape(pattern);
1010
#if NETSTANDARD2_0
1111
var regex = escapedPattern.Replace("\\*", "(.*)");
1212
#else
1313
var regex = escapedPattern.Replace("\\*", "(.*)", StringComparison.InvariantCultureIgnoreCase);
1414
#endif
15-
16-
return Regex.IsMatch(value, $"^{regex}$");
15+
RegexOptions options = ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None;
16+
return Regex.IsMatch(value, $"^{regex}$", options);
1717
}
1818
}

test/TestableHttpClient.Tests/HttpRequestMessageExtensionsTests/HasMatchingUri.cs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22

33
public partial class HttpRequestMessageExtensionsTests
44
{
5-
#nullable disable
65
[Fact]
76
public void HasMatchingUri_NullHttpRequestMessage_ThrowsArgumentNullException()
87
{
9-
HttpRequestMessage sut = null;
8+
HttpRequestMessage sut = null!;
109
var exception = Assert.Throws<ArgumentNullException>(() => sut.HasMatchingUri("*"));
1110
Assert.Equal("httpRequestMessage", exception.ParamName);
1211
}
@@ -15,10 +14,9 @@ public void HasMatchingUri_NullHttpRequestMessage_ThrowsArgumentNullException()
1514
public void HasMatchingUri_NullPattern_ThrowsArgumentNullException()
1615
{
1716
using var sut = new HttpRequestMessage { RequestUri = new Uri("https://example.com") };
18-
var exception = Assert.Throws<ArgumentNullException>(() => sut.HasMatchingUri(null));
17+
var exception = Assert.Throws<ArgumentNullException>(() => sut.HasMatchingUri(null!));
1918
Assert.Equal("pattern", exception.ParamName);
2019
}
21-
#nullable restore
2220

2321
[Fact]
2422
public void HasMatchingUri_EmptyPattern_ReturnsFalse()
@@ -43,13 +41,31 @@ public void HasMatchingUri_NullRequestUri_ReturnsFalse()
4341
[InlineData("https://example.com/*")]
4442
[InlineData("https://*/")]
4543
[InlineData("https://*/*")]
44+
[InlineData("HTTPS://Example.com/")]
45+
[InlineData("*://Example.com/")]
4646
public void HasMatchingUri_WithPatternFor_ReturnsTrue(string pattern)
4747
{
4848
using var sut = new HttpRequestMessage { RequestUri = new Uri("https://example.com") };
4949

5050
Assert.True(sut.HasMatchingUri(pattern));
5151
}
5252

53+
[Theory]
54+
[InlineData("*", true)]
55+
[InlineData("https://example.com*", true)]
56+
[InlineData("https://example.com/", true)]
57+
[InlineData("https://example.com/*", true)]
58+
[InlineData("https://*/", true)]
59+
[InlineData("https://*/*", true)]
60+
[InlineData("HTTPS://Example.com/", false)]
61+
[InlineData("*://Example.com/", false)]
62+
public void HasMatchingUri_WithPatternForAndNotIgnoringCase_ReturnsFalse(string pattern, bool expectedResult)
63+
{
64+
using var sut = new HttpRequestMessage { RequestUri = new Uri("https://example.com") };
65+
66+
Assert.Equal(expectedResult, sut.HasMatchingUri(pattern, ignoreCase: false));
67+
}
68+
5369
[Fact]
5470
public void HasMatchingUri_PatternWithMultipleWildCards_ReturnsTrue()
5571
{

test/TestableHttpClient.Tests/HttpRequestMessagesCheckExtensionsTests/WithRequestUri.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ namespace TestableHttpClient.Tests.HttpRequestMessagesCheckExtensionsTests;
44

55
public class WithRequestUri
66
{
7-
#nullable disable
87
[Fact]
98
public void WithRequestUri_WithoutNumberOfRequests_NullCheck_ThrowsArgumentNullException()
109
{
11-
IHttpRequestMessagesCheck sut = null;
10+
IHttpRequestMessagesCheck sut = null!;
1211

1312
var exception = Assert.Throws<ArgumentNullException>(() => sut.WithRequestUri("*"));
1413

@@ -18,7 +17,7 @@ public void WithRequestUri_WithoutNumberOfRequests_NullCheck_ThrowsArgumentNullE
1817
[Fact]
1918
public void WithRequestUri_WithNumberOfRequests_NullCheck_ThrowsArgumentNullException()
2019
{
21-
IHttpRequestMessagesCheck sut = null;
20+
IHttpRequestMessagesCheck sut = null!;
2221

2322
var exception = Assert.Throws<ArgumentNullException>(() => sut.WithRequestUri("*", 2));
2423

@@ -37,7 +36,6 @@ public void WithRequestUri_NullOrEmptyPattern_ThrowsArgumentNullException(string
3736
Assert.Equal("pattern", exception.ParamName);
3837
sut.Verify(x => x.WithFilter(Its.AnyPredicate(), It.IsAny<int?>(), It.IsAny<string>()), Times.Never());
3938
}
40-
#nullable restore
4139

4240
[Fact]
4341
public void WithRequestUri_WithoutNumberOfRequests_CallsWithCorrectly()
@@ -50,11 +48,21 @@ public void WithRequestUri_WithoutNumberOfRequests_CallsWithCorrectly()
5048
}
5149

5250
[Fact]
53-
public void WithRequestUri_WithNumberOfRequests_CallsWithCorrectly()
51+
public void WithRequestUri_WithoutNumberOfRequestsAndNotIgnoringCase_CallsWithCorrectly()
5452
{
5553
var sut = new Mock<IHttpRequestMessagesCheck>();
5654

57-
sut.Object.WithRequestUri("https://example.com/", 2);
55+
sut.Object.WithRequestUri("https://example.com/", ignoreCase: false);
56+
57+
sut.Verify(x => x.WithFilter(Its.AnyPredicate(), null, "uri pattern 'https://example.com/'"));
58+
}
59+
60+
[Fact]
61+
public void WithRequestUri_WithNumberOfRequestsAndNotIgnoringCase_CallsWithCorrectly()
62+
{
63+
var sut = new Mock<IHttpRequestMessagesCheck>();
64+
65+
sut.Object.WithRequestUri("https://example.com/", ignoreCase: false, 2);
5866

5967
sut.Verify(x => x.WithFilter(Its.AnyPredicate(), (int?)2, "uri pattern 'https://example.com/'"));
6068
}

test/TestableHttpClient.Tests/TestabeHttpMessageHandlerAssertionExtensionsTests/ShouldHaveMadeRequestsTo.cs

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ public void ShouldHaveMadeRequestsTo_WhenNoRequestsWereMade_ThrowsHttpRequestMes
4646
Assert.Throws<HttpRequestMessageAssertionException>(() => sut.ShouldHaveMadeRequestsTo("https://example.com/"));
4747
}
4848

49-
5049
[Fact]
5150
public void ShouldHaveMadeRequestsToWithNumberOfRequests_WhenNoRequestsWereMadeAndOneIsExpected_ThrowsHttpRequestMessageAssertionException()
5251
{
@@ -68,7 +67,7 @@ public void ShouldHaveMadeRequestsToWithNumberOfRequests_WhenNoRequestsWereMadeA
6867
}
6968

7069
[Fact]
71-
public async Task ShouldHaveMadeRequestsTo_WhenMatchinRequestsWereMade_ReturnsHttpRequestMessageAsserter()
70+
public async Task ShouldHaveMadeRequestsTo_WhenMatchingRequestsWithSameCaseWereMade_ReturnsHttpRequestMessageAsserter()
7271
{
7372
using var sut = new TestableHttpMessageHandler();
7473
using var client = new HttpClient(sut);
@@ -83,7 +82,7 @@ public async Task ShouldHaveMadeRequestsTo_WhenMatchinRequestsWereMade_ReturnsHt
8382
}
8483

8584
[Fact]
86-
public async Task ShouldHaveMadeRequestsToWithNumberOfRequests_WhenMatchinRequestsWereMade_ReturnsHttpRequestMessageAsserter()
85+
public async Task ShouldHaveMadeRequestsToWithNumberOfRequests_WhenMatchingRequestsWithSameCaseWereMade_ReturnsHttpRequestMessageAsserter()
8786
{
8887
using var sut = new TestableHttpMessageHandler();
8988
using var client = new HttpClient(sut);
@@ -96,4 +95,56 @@ public async Task ShouldHaveMadeRequestsToWithNumberOfRequests_WhenMatchinReques
9695
Assert.IsType<HttpRequestMessageAsserter>(result);
9796
Assert.Same(sut.Options, result.Options);
9897
}
98+
99+
[Fact]
100+
public async Task ShouldHaveMadeRequestsTo_WhenMatchingRequestsWithDifferentCaseWereMade_ReturnsHttpRequestMessageAsserter()
101+
{
102+
using var sut = new TestableHttpMessageHandler();
103+
using var client = new HttpClient(sut);
104+
105+
_ = await client.GetAsync(new Uri("https://Example.com/Test"));
106+
107+
var result = sut.ShouldHaveMadeRequestsTo("https://example.com/test");
108+
109+
Assert.NotNull(result);
110+
Assert.IsType<HttpRequestMessageAsserter>(result);
111+
Assert.Same(sut.Options, result.Options);
112+
}
113+
114+
[Fact]
115+
public async Task ShouldHaveMadeRequestsTo_WhenMatchingRequestsWithDifferentCaseWereMadeAndNotIgnoringCase_ThrowsException()
116+
{
117+
using var sut = new TestableHttpMessageHandler();
118+
using var client = new HttpClient(sut);
119+
120+
_ = await client.GetAsync(new Uri("https://Example.com/Test"));
121+
122+
Assert.Throws<HttpRequestMessageAssertionException>(() => sut.ShouldHaveMadeRequestsTo("https://example.com/test", ignoreCase: false));
123+
}
124+
125+
[Fact]
126+
public async Task ShouldHaveMadeRequestsToWithNumberOfRequests_WhenMatchingRequestsWithDifferentCaseWereMade_ReturnsHttpRequestMessageAsserter()
127+
{
128+
using var sut = new TestableHttpMessageHandler();
129+
using var client = new HttpClient(sut);
130+
131+
_ = await client.GetAsync(new Uri("https://Example.com/Test"));
132+
133+
var result = sut.ShouldHaveMadeRequestsTo("https://example.com/test", 1);
134+
135+
Assert.NotNull(result);
136+
Assert.IsType<HttpRequestMessageAsserter>(result);
137+
Assert.Same(sut.Options, result.Options);
138+
}
139+
140+
[Fact]
141+
public async Task ShouldHaveMadeRequestsToWithNumberOfRequests_WhenMatchingRequestsWithDifferentCaseWereMadeAndNotIgnoringCase_ShouldThrowException()
142+
{
143+
using var sut = new TestableHttpMessageHandler();
144+
using var client = new HttpClient(sut);
145+
146+
_ = await client.GetAsync(new Uri("https://Example.com/Test"));
147+
148+
Assert.Throws<HttpRequestMessageAssertionException>(() => sut.ShouldHaveMadeRequestsTo("https://example.com/test", ignoreCase: false, 1));
149+
}
99150
}

0 commit comments

Comments
 (0)