Skip to content

Commit

Permalink
refactor: set up uri matcher for reusability so we can more simply ad…
Browse files Browse the repository at this point in the history
…d other types of matchers that check portions of the URI, like path/route values, etc.
  • Loading branch information
skwasjer committed Sep 7, 2024
1 parent 5c889c7 commit cc9cf49
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 16 deletions.
5 changes: 5 additions & 0 deletions src/MockHttp/Matchers/Patterns/IPatternMatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,10 @@

internal interface IPatternMatcher<in T>
{
/// <summary>
/// Tests if the specified <paramref name="value" /> matches the pattern.
/// </summary>
/// <param name="value">The value to test.</param>
/// <returns>Returns true if the value matches the pattern; otherwise returns false.</returns>
bool IsMatch(T value);
}
14 changes: 0 additions & 14 deletions src/MockHttp/Matchers/Patterns/PatternMatcher.cs

This file was deleted.

4 changes: 2 additions & 2 deletions src/MockHttp/Matchers/Patterns/RegexPatternMatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace MockHttp.Matchers.Patterns;

internal class RegexPatternMatcher : PatternMatcher
internal class RegexPatternMatcher : IPatternMatcher<string>
{
public RegexPatternMatcher
(
Expand All @@ -24,7 +24,7 @@ public RegexPatternMatcher(Regex regex)
internal Regex Regex { get; }

/// <inheritdoc />
public override bool IsMatch(string value)
public virtual bool IsMatch(string value)
{
return Regex.IsMatch(value);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using MockHttp.Http;

namespace MockHttp.Matchers.Patterns;

internal sealed class RelativeOrAbsoluteUriPatternMatcher : UriPatternMatcher
{
private readonly Uri _originalUri;
private readonly Uri _uri;

public RelativeOrAbsoluteUriPatternMatcher(Uri uri)
{
_originalUri = uri;
_uri = uri.EnsureIsRooted();
}

public override bool IsMatch(Uri value)
{
return IsAbsoluteUriMatch(value) || IsRelativeUriMatch(value);
}

private bool IsAbsoluteUriMatch(Uri uri)
{
return _uri.IsAbsoluteUri && uri.Equals(_uri);
}

private bool IsRelativeUriMatch(Uri uri)
{
return !_uri.IsAbsoluteUri
&& uri.IsBaseOf(_uri)
&& uri.ToString().EndsWith(_uri.ToString(), StringComparison.Ordinal);
}
}
6 changes: 6 additions & 0 deletions src/MockHttp/Matchers/Patterns/UriPatternMatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace MockHttp.Matchers.Patterns;

internal abstract class UriPatternMatcher : IPatternMatcher<Uri>
{
public abstract bool IsMatch(Uri value);
}
19 changes: 19 additions & 0 deletions src/MockHttp/Matchers/Patterns/UriStringPatternMatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace MockHttp.Matchers.Patterns;

internal class UriStringPatternMatcher : UriPatternMatcher
{
private readonly Func<Uri, string> _selector;
private readonly IPatternMatcher<string> _stringPatternMatcher;

public UriStringPatternMatcher(Func<Uri, string> selector, IPatternMatcher<string> stringPatternMatcher)
{
_selector = selector ?? throw new ArgumentNullException(nameof(selector));
_stringPatternMatcher = stringPatternMatcher ?? throw new ArgumentNullException(nameof(stringPatternMatcher));
}

public override bool IsMatch(Uri value)
{
string v = _selector(value);
return _stringPatternMatcher.IsMatch(v);
}
}
59 changes: 59 additions & 0 deletions src/MockHttp/Matchers/UriMatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System.Runtime.CompilerServices;
using MockHttp.Matchers.Patterns;
using MockHttp.Responses;

namespace MockHttp.Matchers;

/// <summary>
/// Abstract URI matcher.
/// </summary>
public class UriMatcher : HttpRequestMatcher
{
private readonly IPatternMatcher<Uri> _patternMatcher;
private readonly string _name;
private readonly string _patternDescription;

/// <summary>
/// Initializes a new instance of the <see cref="UriMatcher" /> class.
/// </summary>
/// <param name="patternMatcher">A matcher implementation that validates the URI.</param>
/// <param name="patternDescription">A description of the pattern.</param>
/// <param name="name">The name of this matcher.</param>
/// <exception cref="ArgumentNullException">Thrown when a required argument is <see langword="null" />.</exception>
internal UriMatcher
(
IPatternMatcher<Uri> patternMatcher,
string patternDescription,
[CallerMemberName] string? name = null
)
{
_patternMatcher = patternMatcher ?? throw new ArgumentNullException(nameof(patternMatcher));
_patternDescription = patternDescription ?? throw new ArgumentNullException(nameof(patternDescription));

name ??= GetType().Name;
if (name.EndsWith("Matcher", StringComparison.Ordinal))
{
name = name.Remove(name.Length - "Matcher".Length);
}

_name = name;
}

/// <inheritdoc />
public override bool IsMatch(MockHttpRequestContext requestContext)
{
if (requestContext is null)
{
throw new ArgumentNullException(nameof(requestContext));
}

Uri? uri = requestContext.Request.RequestUri;
return uri is not null && _patternMatcher.IsMatch(uri);
}

/// <inheritdoc />
public override string ToString()
{
return $"{_name}: '{_patternDescription}'";
}
}

0 comments on commit cc9cf49

Please sign in to comment.