From b089fb89f28a0821bbbdfdaa8d0bf6addef59a0c Mon Sep 17 00:00:00 2001 From: Todd Date: Wed, 28 Apr 2021 09:25:18 -0500 Subject: [PATCH] #596 testing - don't require trailing * to match URL with query --- Test/Flurl.Test/Http/TestingTests.cs | 23 +++++++++++++++++++ .../Testing/FilteredHttpTestSetup.cs | 2 +- src/Flurl.Http/Testing/HttpCallAssertion.cs | 2 +- src/Flurl.Http/Testing/Util.cs | 17 ++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Test/Flurl.Test/Http/TestingTests.cs b/Test/Flurl.Test/Http/TestingTests.cs index 137447a0..c055757d 100644 --- a/Test/Flurl.Test/Http/TestingTests.cs +++ b/Test/Flurl.Test/Http/TestingTests.cs @@ -138,6 +138,29 @@ public async Task can_respond_based_on_query_params() { Assert.AreEqual("query param conditions met!", await "http://api.com?x=1&y=2&z=3&c=yes".GetStringAsync()); } + [Test] // #596 + public async Task url_patterns_ignore_query_when_not_specified() { + HttpTest.ForCallsTo("http://api.com/1").RespondWith("one"); + HttpTest.ForCallsTo("http://api.com/2").WithAnyQueryParam().RespondWith("two"); + HttpTest.ForCallsTo("http://api.com/3").WithoutQueryParams().RespondWith("three"); + + Assert.AreEqual("one", await "http://api.com/1".GetStringAsync()); + Assert.AreEqual("one", await "http://api.com/1?x=foo&y=bar".GetStringAsync()); + + Assert.AreEqual("", await "http://api.com/2".GetStringAsync()); + Assert.AreEqual("two", await "http://api.com/2?x=foo&y=bar".GetStringAsync()); + + Assert.AreEqual("three", await "http://api.com/3".GetStringAsync()); + Assert.AreEqual("", await "http://api.com/3?x=foo&y=bar".GetStringAsync()); + + HttpTest.ShouldHaveCalled("http://api.com/1").Times(2); + HttpTest.ShouldHaveCalled("http://api.com/1").WithAnyQueryParam().Times(1); + HttpTest.ShouldHaveCalled("http://api.com/1").WithoutQueryParams().Times(1); + HttpTest.ShouldHaveCalled("http://api.com/1?x=foo").Times(1); + HttpTest.ShouldHaveCalled("http://api.com/1?x=foo").WithQueryParam("y").Times(1); + HttpTest.ShouldHaveCalled("http://api.com/1?x=foo").WithQueryParam("y", "bar").Times(1); + } + [Test] public async Task can_respond_based_on_headers() { HttpTest diff --git a/src/Flurl.Http/Testing/FilteredHttpTestSetup.cs b/src/Flurl.Http/Testing/FilteredHttpTestSetup.cs index d32f20fc..935fb637 100644 --- a/src/Flurl.Http/Testing/FilteredHttpTestSetup.cs +++ b/src/Flurl.Http/Testing/FilteredHttpTestSetup.cs @@ -21,7 +21,7 @@ public class FilteredHttpTestSetup : HttpTestSetup /// URL(s) or URL pattern(s) that this HttpTestSetup applies to. Can contain * wildcard. public FilteredHttpTestSetup(TestFlurlHttpSettings settings, params string[] urlPatterns) : base(settings) { if (urlPatterns.Any()) - With(call => urlPatterns.Any(p => Util.MatchesPattern(call.Request.Url, p))); + With(call => urlPatterns.Any(p => Util.MatchesUrlPattern(call.Request.Url, p))); } /// diff --git a/src/Flurl.Http/Testing/HttpCallAssertion.cs b/src/Flurl.Http/Testing/HttpCallAssertion.cs index cdfdb2a7..e96b0f6a 100644 --- a/src/Flurl.Http/Testing/HttpCallAssertion.cs +++ b/src/Flurl.Http/Testing/HttpCallAssertion.cs @@ -68,7 +68,7 @@ public HttpCallAssertion Without(Func match, string descrip = n /// /// Can contain * wildcard. public HttpCallAssertion WithUrlPattern(string urlPattern) { - return With(c => Util.MatchesPattern(c.Request.Url, urlPattern), $"URL pattern {urlPattern}"); + return With(c => Util.MatchesUrlPattern(c.Request.Url, urlPattern), $"URL pattern {urlPattern}"); } /// diff --git a/src/Flurl.Http/Testing/Util.cs b/src/Flurl.Http/Testing/Util.cs index 6cbad816..12c2af83 100644 --- a/src/Flurl.Http/Testing/Util.cs +++ b/src/Flurl.Http/Testing/Util.cs @@ -90,6 +90,23 @@ private static bool MatchesValueOrPattern(object valueToMatch, object value) { return valueToMatch?.ToInvariantString() == value?.ToInvariantString(); } + /// + /// same as MatchesPattern, but doesn't require trailing * to ignore query string + /// + internal static bool MatchesUrlPattern(string url, string pattern) { + if (MatchesPattern(url, pattern)) + return true; + if (pattern.OrdinalEndsWith("*")) + return false; + if (pattern.OrdinalContains("?")) + return MatchesPattern(url, pattern + "&*"); + else + return MatchesPattern(url, pattern + "?*"); + } + + /// + /// match simple patterns with * wildcard + /// internal static bool MatchesPattern(string textToCheck, string pattern) { // avoid regex'ing in simple cases if (string.IsNullOrEmpty(pattern) || pattern == "*") return true;