diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockANumberOfCallsAssertions.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockANumberOfCallsAssertions.cs
index 65dc27130..87380bc8c 100644
--- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockANumberOfCallsAssertions.cs
+++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockANumberOfCallsAssertions.cs
@@ -4,11 +4,11 @@
using WireMock.Server;
// ReSharper disable once CheckNamespace
-namespace WireMock.FluentAssertions;
+namespace WireMock.AwesomeAssertions;
///
/// Provides assertion methods to verify the number of calls made to a WireMock server.
-/// This class is used in the context of FluentAssertions.
+/// This class is used in the context of AwesomeAssertions.
///
public class WireMockANumberOfCallsAssertions
{
diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.AtPath.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.AtPath.cs
new file mode 100644
index 000000000..a830e9668
--- /dev/null
+++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.AtPath.cs
@@ -0,0 +1,83 @@
+// Copyright © WireMock.Net
+
+using WireMock.Extensions;
+using WireMock.Matchers;
+
+// ReSharper disable once CheckNamespace
+namespace WireMock.AwesomeAssertions;
+
+#pragma warning disable CS1591
+public partial class WireMockAssertions
+{
+ [CustomAssertion]
+ public AndWhichConstraint AtAbsolutePath(string absolutePath, string because = "", params object[] becauseArgs)
+ {
+ _ = AtAbsolutePath(new ExactMatcher(true, absolutePath), because, becauseArgs);
+
+ return new AndWhichConstraint(this, absolutePath);
+ }
+
+ [CustomAssertion]
+ public AndWhichConstraint AtAbsolutePath(IStringMatcher absolutePathMatcher, string because = "", params object[] becauseArgs)
+ {
+ var (filter, condition) = BuildFilterAndCondition(request => absolutePathMatcher.IsPerfectMatch(request.AbsolutePath));
+
+ var absolutePath = absolutePathMatcher.GetPatterns().FirstOrDefault().GetPattern();
+
+ _chain
+ .BecauseOf(because, becauseArgs)
+ .Given(() => RequestMessages)
+ .ForCondition(requests => CallsCount == 0 || requests.Any())
+ .FailWith(
+ "Expected {context:wiremockserver} to have been called at address matching the absolute path {0}{reason}, but no calls were made.",
+ absolutePath
+ )
+ .Then
+ .ForCondition(condition)
+ .FailWith(
+ "Expected {context:wiremockserver} to have been called at address matching the absolute path {0}{reason}, but didn't find it among the calls to {1}.",
+ _ => absolutePath,
+ requests => requests.Select(request => request.AbsolutePath)
+ );
+
+ FilterRequestMessages(filter);
+
+ return new AndWhichConstraint(this, absolutePathMatcher);
+ }
+
+ [CustomAssertion]
+ public AndWhichConstraint AtPath(string path, string because = "", params object[] becauseArgs)
+ {
+ _ = AtPath(new ExactMatcher(true, path), because, becauseArgs);
+
+ return new AndWhichConstraint(this, path);
+ }
+
+ [CustomAssertion]
+ public AndWhichConstraint AtPath(IStringMatcher pathMatcher, string because = "", params object[] becauseArgs)
+ {
+ var (filter, condition) = BuildFilterAndCondition(request => pathMatcher.IsPerfectMatch(request.Path));
+
+ var path = pathMatcher.GetPatterns().FirstOrDefault().GetPattern();
+
+ _chain
+ .BecauseOf(because, becauseArgs)
+ .Given(() => RequestMessages)
+ .ForCondition(requests => CallsCount == 0 || requests.Any())
+ .FailWith(
+ "Expected {context:wiremockserver} to have been called at address matching the path {0}{reason}, but no calls were made.",
+ path
+ )
+ .Then
+ .ForCondition(condition)
+ .FailWith(
+ "Expected {context:wiremockserver} to have been called at address matching the path {0}{reason}, but didn't find it among the calls to {1}.",
+ _ => path,
+ requests => requests.Select(request => request.Path)
+ );
+
+ FilterRequestMessages(filter);
+
+ return new AndWhichConstraint(this, pathMatcher);
+ }
+}
\ No newline at end of file
diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.AtUrl.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.AtUrl.cs
index 87d8fb0f8..562716cb8 100644
--- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.AtUrl.cs
+++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.AtUrl.cs
@@ -4,7 +4,7 @@
using WireMock.Matchers;
// ReSharper disable once CheckNamespace
-namespace WireMock.FluentAssertions;
+namespace WireMock.AwesomeAssertions;
#pragma warning disable CS1591
public partial class WireMockAssertions
diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.FromClientIP.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.FromClientIP.cs
index 9c0977ed8..6e2684726 100644
--- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.FromClientIP.cs
+++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.FromClientIP.cs
@@ -4,7 +4,7 @@
using System;
// ReSharper disable once CheckNamespace
-namespace WireMock.FluentAssertions;
+namespace WireMock.AwesomeAssertions;
public partial class WireMockAssertions
{
diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.UsingMethod.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.UsingMethod.cs
index 62301d31a..e3ce6c12b 100644
--- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.UsingMethod.cs
+++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.UsingMethod.cs
@@ -5,7 +5,7 @@
using WireMock.Constants;
// ReSharper disable once CheckNamespace
-namespace WireMock.FluentAssertions;
+namespace WireMock.AwesomeAssertions;
public partial class WireMockAssertions
{
diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithBody.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithBody.cs
index bdd04a42e..c6fd9c5fa 100644
--- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithBody.cs
+++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithBody.cs
@@ -11,7 +11,7 @@
using WireMock.Models;
// ReSharper disable once CheckNamespace
-namespace WireMock.FluentAssertions;
+namespace WireMock.AwesomeAssertions;
public partial class WireMockAssertions
{
diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithHeader.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithHeader.cs
index d56427593..8293cd9d9 100644
--- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithHeader.cs
+++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithHeader.cs
@@ -3,7 +3,7 @@
#pragma warning disable CS1591
// ReSharper disable once CheckNamespace
-namespace WireMock.FluentAssertions;
+namespace WireMock.AwesomeAssertions;
public partial class WireMockAssertions
{
diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithProxy.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithProxy.cs
index 6d51b3fdf..704b23317 100644
--- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithProxy.cs
+++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithProxy.cs
@@ -4,7 +4,7 @@
using System;
// ReSharper disable once CheckNamespace
-namespace WireMock.FluentAssertions;
+namespace WireMock.AwesomeAssertions;
public partial class WireMockAssertions
{
diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.cs
index ca7a41942..e24a38410 100644
--- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.cs
+++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.cs
@@ -7,7 +7,7 @@
using WireMock.Server;
// ReSharper disable once CheckNamespace
-namespace WireMock.FluentAssertions;
+namespace WireMock.AwesomeAssertions;
public partial class WireMockAssertions
{
diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockReceivedAssertions.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockReceivedAssertions.cs
index 260a1a943..184be0e95 100644
--- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockReceivedAssertions.cs
+++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockReceivedAssertions.cs
@@ -4,7 +4,7 @@
using WireMock.Server;
// ReSharper disable once CheckNamespace
-namespace WireMock.FluentAssertions;
+namespace WireMock.AwesomeAssertions;
///
/// Contains a number of methods to assert that the is in the expected state.
diff --git a/src/WireMock.Net.AwesomeAssertions/Extensions/WireMockExtensions.cs b/src/WireMock.Net.AwesomeAssertions/Extensions/WireMockExtensions.cs
index 73e2eac76..95d6fc711 100644
--- a/src/WireMock.Net.AwesomeAssertions/Extensions/WireMockExtensions.cs
+++ b/src/WireMock.Net.AwesomeAssertions/Extensions/WireMockExtensions.cs
@@ -3,7 +3,7 @@
using WireMock.Server;
// ReSharper disable once CheckNamespace
-namespace WireMock.FluentAssertions
+namespace WireMock.AwesomeAssertions
{
///
/// Contains extension methods for custom assertions in unit tests.
diff --git a/src/WireMock.Net.FluentAssertions/Assertions/WireMockAssertions.AtPath.cs b/src/WireMock.Net.FluentAssertions/Assertions/WireMockAssertions.AtPath.cs
new file mode 100644
index 000000000..c54eb9638
--- /dev/null
+++ b/src/WireMock.Net.FluentAssertions/Assertions/WireMockAssertions.AtPath.cs
@@ -0,0 +1,83 @@
+// Copyright © WireMock.Net
+
+using WireMock.Extensions;
+using WireMock.Matchers;
+
+// ReSharper disable once CheckNamespace
+namespace WireMock.FluentAssertions;
+
+#pragma warning disable CS1591
+public partial class WireMockAssertions
+{
+ [CustomAssertion]
+ public AndWhichConstraint AtAbsolutePath(string absolutePath, string because = "", params object[] becauseArgs)
+ {
+ _ = AtAbsolutePath(new ExactMatcher(true, absolutePath), because, becauseArgs);
+
+ return new AndWhichConstraint(this, absolutePath);
+ }
+
+ [CustomAssertion]
+ public AndWhichConstraint AtAbsolutePath(IStringMatcher absolutePathMatcher, string because = "", params object[] becauseArgs)
+ {
+ var (filter, condition) = BuildFilterAndCondition(request => absolutePathMatcher.IsPerfectMatch(request.AbsolutePath));
+
+ var absolutePath = absolutePathMatcher.GetPatterns().FirstOrDefault().GetPattern();
+
+ Execute.Assertion
+ .BecauseOf(because, becauseArgs)
+ .Given(() => RequestMessages)
+ .ForCondition(requests => CallsCount == 0 || requests.Any())
+ .FailWith(
+ "Expected {context:wiremockserver} to have been called at address matching the absolute path {0}{reason}, but no calls were made.",
+ absolutePath
+ )
+ .Then
+ .ForCondition(condition)
+ .FailWith(
+ "Expected {context:wiremockserver} to have been called at address matching the absolute path {0}{reason}, but didn't find it among the calls to {1}.",
+ _ => absolutePath,
+ requests => requests.Select(request => request.AbsolutePath)
+ );
+
+ FilterRequestMessages(filter);
+
+ return new AndWhichConstraint(this, absolutePathMatcher);
+ }
+
+ [CustomAssertion]
+ public AndWhichConstraint AtPath(string path, string because = "", params object[] becauseArgs)
+ {
+ _ = AtPath(new ExactMatcher(true, path), because, becauseArgs);
+
+ return new AndWhichConstraint(this, path);
+ }
+
+ [CustomAssertion]
+ public AndWhichConstraint AtPath(IStringMatcher pathMatcher, string because = "", params object[] becauseArgs)
+ {
+ var (filter, condition) = BuildFilterAndCondition(request => pathMatcher.IsPerfectMatch(request.Path));
+
+ var path = pathMatcher.GetPatterns().FirstOrDefault().GetPattern();
+
+ Execute.Assertion
+ .BecauseOf(because, becauseArgs)
+ .Given(() => RequestMessages)
+ .ForCondition(requests => CallsCount == 0 || requests.Any())
+ .FailWith(
+ "Expected {context:wiremockserver} to have been called at address matching the path {0}{reason}, but no calls were made.",
+ path
+ )
+ .Then
+ .ForCondition(condition)
+ .FailWith(
+ "Expected {context:wiremockserver} to have been called at address matching the path {0}{reason}, but didn't find it among the calls to {1}.",
+ _ => path,
+ requests => requests.Select(request => request.Path)
+ );
+
+ FilterRequestMessages(filter);
+
+ return new AndWhichConstraint(this, pathMatcher);
+ }
+}
\ No newline at end of file
diff --git a/test/WireMock.Net.Tests/FluentAssertions/WireMockAssertionsTests.cs b/test/WireMock.Net.Tests/FluentAssertions/WireMockAssertionsTests.cs
index fecd784ed..6b152f08f 100644
--- a/test/WireMock.Net.Tests/FluentAssertions/WireMockAssertionsTests.cs
+++ b/test/WireMock.Net.Tests/FluentAssertions/WireMockAssertionsTests.cs
@@ -108,7 +108,7 @@ public async Task HaveReceivedACall_AtAbsoluteUrl_WhenACallWasMadeToAbsoluteUrl_
}
[Fact]
- public async Task HaveReceivedACall_AtAbsoluteUrlWilcardMAtcher_WhenACallWasMadeToAbsoluteUrl_Should_BeOK()
+ public async Task HaveReceivedACall_AtAbsoluteUrlWildcardMatcher_WhenACallWasMadeToAbsoluteUrl_Should_BeOK()
{
await _httpClient.GetAsync("anyurl").ConfigureAwait(false);
@@ -143,6 +143,106 @@ public async Task HaveReceivedACall_AtAbsoluteUrl_Should_ThrowWhenNoCallsMatchin
.WithMessage($"Expected _server to have been called at address matching the absolute url \"anyurl\", but didn't find it among the calls to {{\"http://localhost:{_portUsed}/\"}}.");
}
+ [Fact]
+ public async Task HaveReceivedNoCalls_AtAbsolutePath_WhenACallWasNotMadeToAbsolutePath_Should_BeOK()
+ {
+ await _httpClient.GetAsync("xxx").ConfigureAwait(false);
+
+ _server.Should()
+ .HaveReceivedNoCalls()
+ .AtAbsolutePath("anypath");
+ }
+
+ [Fact]
+ public async Task HaveReceived0Calls_AtAbsolutePath_WhenACallWasNotMadeToAbsolutePath_Should_BeOK()
+ {
+ await _httpClient.GetAsync("xxx").ConfigureAwait(false);
+
+ _server.Should()
+ .HaveReceived(0).Calls()
+ .AtAbsolutePath("anypath");
+ }
+
+ [Fact]
+ public async Task HaveReceived1Calls_AtAbsolutePath_WhenACallWasMadeToAbsolutePath_Should_BeOK()
+ {
+ await _httpClient.GetAsync("anypath").ConfigureAwait(false);
+
+ _server.Should()
+ .HaveReceived(1).Calls()
+ .AtAbsolutePath("/anypath");
+ }
+
+ [Fact]
+ public async Task HaveReceived1Calls_AtAbsolutePathUsingPost_WhenAPostCallWasMadeToAbsolutePath_Should_BeOK()
+ {
+ await _httpClient.PostAsync("anypath", new StringContent("")).ConfigureAwait(false);
+
+ _server.Should()
+ .HaveReceived(1).Calls()
+ .AtAbsolutePath("/anypath")
+ .And
+ .UsingPost();
+ }
+
+ [Fact]
+ public async Task HaveReceived2Calls_AtAbsolutePath_WhenACallWasMadeToAbsolutePath_Should_BeOK()
+ {
+ await _httpClient.GetAsync("anypath").ConfigureAwait(false);
+
+ await _httpClient.GetAsync("anypath").ConfigureAwait(false);
+
+ _server.Should()
+ .HaveReceived(2).Calls()
+ .AtAbsolutePath("/anypath");
+ }
+
+ [Fact]
+ public async Task HaveReceivedACall_AtAbsolutePath_WhenACallWasMadeToAbsolutePath_Should_BeOK()
+ {
+ await _httpClient.GetAsync("anypath").ConfigureAwait(false);
+
+ _server.Should()
+ .HaveReceivedACall()
+ .AtAbsolutePath(new WildcardMatcher("/any*"));
+ }
+
+ [Fact]
+ public async Task HaveReceivedACall_AtAbsolutePathWildcardMatcher_WhenACallWasMadeToAbsolutePath_Should_BeOK()
+ {
+ await _httpClient.GetAsync("anypath").ConfigureAwait(false);
+
+ _server.Should()
+ .HaveReceivedACall()
+ .AtAbsolutePath("/anypath");
+ }
+
+ [Fact]
+ public void HaveReceivedACall_AtAbsolutePath_Should_ThrowWhenNoCallsWereMade()
+ {
+ Action act = () => _server.Should()
+ .HaveReceivedACall()
+ .AtAbsolutePath("anypath");
+
+ act.Should()
+ .Throw()
+ .WithMessage("Expected _server to have been called at address matching the absolute path \"anypath\", but no calls were made.");
+ }
+
+ [Fact]
+ public async Task HaveReceivedACall_AtAbsolutePath_Should_ThrowWhenNoCallsMatchingTheAbsolutePathWereMade()
+ {
+ await _httpClient.GetAsync("").ConfigureAwait(false);
+
+ Action act = () => _server.Should()
+ .HaveReceivedACall()
+ .AtAbsolutePath("/anypath");
+
+ act.Should()
+ .Throw()
+ .WithMessage($"Expected _server to have been called at address matching the absolute path \"/anypath\", but didn't find it among the calls to {{\"/\"}}.");
+ }
+
[Fact]
public async Task HaveReceivedACall_WithHeader_WhenACallWasMadeWithExpectedHeader_Should_BeOK()
{