Skip to content

Commit

Permalink
chore: restore public API compatibility. Some stuff was removed/chang…
Browse files Browse the repository at this point in the history
…ed in #110, and claimed in PR that the public API did not change, which is not true. (#113)
  • Loading branch information
skwasjer authored Sep 9, 2024
1 parent 56ee517 commit 5753c8d
Show file tree
Hide file tree
Showing 3 changed files with 222 additions and 1 deletion.
16 changes: 15 additions & 1 deletion src/MockHttp/Extensions/RequestMatchingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,19 @@ private static bool ContainsWildcard(this string value)
#endif
}

/// <summary>
/// Matches a request by specified <paramref name="requestUri" />.
/// </summary>
/// <param name="builder">The request matching builder instance.</param>
/// <param name="requestUri">The request URI or a URI wildcard.</param>
/// <returns>The request matching builder instance.</returns>
#pragma warning disable CA1054
public static RequestMatching RequestUri(this RequestMatching builder, string requestUri)
#pragma warning restore CA1054
{
return builder.RequestUri(requestUri, true);
}

/// <summary>
/// Matches a request by specified <paramref name="requestUri" />.
/// </summary>
Expand All @@ -38,7 +51,8 @@ private static bool ContainsWildcard(this string value)
/// <param name="allowWildcards"><see langword="true" /> to allow wildcards, or <see langword="false" /> if exact matching.</param>
/// <returns>The request matching builder instance.</returns>
#pragma warning disable CA1054
public static RequestMatching RequestUri(this RequestMatching builder, string requestUri, bool allowWildcards = true)
// For now, keep this internal. For coverage, and most likely, the API will change so then we'd have more to deprecate (using patterns).
internal static RequestMatching RequestUri(this RequestMatching builder, string requestUri, bool allowWildcards)
#pragma warning restore CA1054
{
if (requestUri is null)
Expand Down
98 changes: 98 additions & 0 deletions src/MockHttp/Matchers/RequestUriMatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using System.Diagnostics;
using MockHttp.Http;
using MockHttp.Patterns;
using MockHttp.Responses;
using static MockHttp.Http.UriExtensions;

namespace MockHttp.Matchers;

/// <summary>
/// Matches a request by the request URI.
/// </summary>
[Obsolete($"Replaced with {nameof(UriMatcher)}. Will be removed in next major release.")]
public class RequestUriMatcher : HttpRequestMatcher
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly Uri _requestUri = default!;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly string _formattedUri;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly WildcardPattern? _uriPatternMatcher;

/// <summary>
/// Initializes a new instance of the <see cref="RequestUriMatcher" /> class using specified <paramref name="uri" />.
/// </summary>
/// <param name="uri">The request URI.</param>
public RequestUriMatcher(Uri uri)
{
_requestUri = uri.EnsureIsRooted();
_formattedUri = _requestUri.ToString();
}

/// <summary>
/// Initializes a new instance of the <see cref="RequestUriMatcher" /> class using specified <paramref name="uriString" />.
/// </summary>
/// <param name="uriString">The request URI or a URI wildcard.</param>
/// <param name="allowWildcards"><see langword="true" /> to allow wildcards, or <see langword="false" /> if exact matching.</param>
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 = WildcardPattern.Create(uriString);
}
else
{
// If no wildcards, then must be actual uri.
_requestUri = new Uri(uriString, DotNetRelativeOrAbsolute).EnsureIsRooted();
_formattedUri = _requestUri.ToString();
}
}

/// <inheritdoc />
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.Value.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);
}

/// <inheritdoc />
public override string ToString()
{
return $"RequestUri: '{_formattedUri}'";
}
}
109 changes: 109 additions & 0 deletions test/MockHttp.Tests/Matchers/RequestUriMatcherTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
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<RequestUriMatcher> act = () => new RequestUriMatcher(uri!);

// Assert
act.Should()
.Throw<ArgumentNullException>()
.WithParameterName(nameof(uri));
}

[Fact]
public void Given_null_uriString_when_creating_matcher_should_throw()
{
string? uriString = null;

// Act
Func<RequestUriMatcher> act = () => new RequestUriMatcher(uriString!, false);

// Assert
act.Should()
.Throw<ArgumentNullException>()
.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<ArgumentNullException>()
.WithParameterName(nameof(requestContext));
}
}

0 comments on commit 5753c8d

Please sign in to comment.