diff --git a/Directory.Packages.props b/Directory.Packages.props index 5b42060..f1f5974 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,7 +4,7 @@ - + diff --git a/Source/aweXpect.Web/ThatUri.HasDefaultPort.cs b/Source/aweXpect.Web/ThatUri.HasDefaultPort.cs new file mode 100644 index 0000000..9367829 --- /dev/null +++ b/Source/aweXpect.Web/ThatUri.HasDefaultPort.cs @@ -0,0 +1,61 @@ +using System; +using System.Text; +using aweXpect.Core; +using aweXpect.Core.Constraints; +using aweXpect.Helpers; +using aweXpect.Results; + +namespace aweXpect; + +#nullable enable +public static partial class ThatUri +{ + /// + /// Verifies that the subject has the default port for the used scheme. + /// + /// + /// + /// + public static AndOrResult> HasDefaultPort(this IThat source) + => new(source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new HasDefaultPortConstraint(it, grammars)), + source); + + /// + /// Verifies that the subject does not have the default port for the used scheme. + /// + /// + /// + /// + public static AndOrResult> DoesNotHaveDefaultPort(this IThat source) + => new(source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new HasDefaultPortConstraint(it, grammars).Invert()), + source); + + private sealed class HasDefaultPortConstraint(string it, ExpectationGrammars grammars) + : ConstraintResult.WithValue(grammars), + IValueConstraint + { + public ConstraintResult IsMetBy(Uri actual) + { + Actual = actual; + Outcome = actual.IsDefaultPort ? Outcome.Success : Outcome.Failure; + return this; + } + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("has the default port for the used scheme"); + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(it).Append(" was "); + Formatter.Format(stringBuilder, Actual); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("does not have the default port for the used scheme"); + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + => AppendNormalResult(stringBuilder, indentation); + } +} diff --git a/Source/aweXpect.Web/ThatUri.IsAbsolute.cs b/Source/aweXpect.Web/ThatUri.IsAbsolute.cs new file mode 100644 index 0000000..db1f342 --- /dev/null +++ b/Source/aweXpect.Web/ThatUri.IsAbsolute.cs @@ -0,0 +1,61 @@ +using System; +using System.Text; +using aweXpect.Core; +using aweXpect.Core.Constraints; +using aweXpect.Helpers; +using aweXpect.Results; + +namespace aweXpect; + +#nullable enable +public static partial class ThatUri +{ + /// + /// Verifies that the subject is an absolute URI. + /// + /// + /// + /// + public static AndOrResult> IsAbsolute(this IThat source) + => new(source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsAbsoluteConstraint(it, grammars)), + source); + + /// + /// Verifies that the subject is not an absolute URI. + /// + /// + /// + /// + public static AndOrResult> IsNotAbsolute(this IThat source) + => new(source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsAbsoluteConstraint(it, grammars).Invert()), + source); + + private sealed class IsAbsoluteConstraint(string it, ExpectationGrammars grammars) + : ConstraintResult.WithValue(grammars), + IValueConstraint + { + public ConstraintResult IsMetBy(Uri actual) + { + Actual = actual; + Outcome = actual.IsAbsoluteUri ? Outcome.Success : Outcome.Failure; + return this; + } + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("is an absolute URI"); + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(it).Append(" was "); + Formatter.Format(stringBuilder, Actual); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("is not an absolute URI"); + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + => AppendNormalResult(stringBuilder, indentation); + } +} diff --git a/Source/aweXpect.Web/ThatUri.IsFile.cs b/Source/aweXpect.Web/ThatUri.IsFile.cs new file mode 100644 index 0000000..af65b0c --- /dev/null +++ b/Source/aweXpect.Web/ThatUri.IsFile.cs @@ -0,0 +1,61 @@ +using System; +using System.Text; +using aweXpect.Core; +using aweXpect.Core.Constraints; +using aweXpect.Helpers; +using aweXpect.Results; + +namespace aweXpect; + +#nullable enable +public static partial class ThatUri +{ + /// + /// Verifies that the subject is a file URI. + /// + /// + /// + /// + public static AndOrResult> IsFile(this IThat source) + => new(source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsFileConstraint(it, grammars)), + source); + + /// + /// Verifies that the subject is not a file URI. + /// + /// + /// + /// + public static AndOrResult> IsNotFile(this IThat source) + => new(source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsFileConstraint(it, grammars).Invert()), + source); + + private sealed class IsFileConstraint(string it, ExpectationGrammars grammars) + : ConstraintResult.WithValue(grammars), + IValueConstraint + { + public ConstraintResult IsMetBy(Uri actual) + { + Actual = actual; + Outcome = actual.IsFile ? Outcome.Success : Outcome.Failure; + return this; + } + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("is a file URI"); + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(it).Append(" was "); + Formatter.Format(stringBuilder, Actual); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("is not a file URI"); + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + => AppendNormalResult(stringBuilder, indentation); + } +} diff --git a/Source/aweXpect.Web/ThatUri.IsLoopback.cs b/Source/aweXpect.Web/ThatUri.IsLoopback.cs new file mode 100644 index 0000000..5d38ec0 --- /dev/null +++ b/Source/aweXpect.Web/ThatUri.IsLoopback.cs @@ -0,0 +1,61 @@ +using System; +using System.Text; +using aweXpect.Core; +using aweXpect.Core.Constraints; +using aweXpect.Helpers; +using aweXpect.Results; + +namespace aweXpect; + +#nullable enable +public static partial class ThatUri +{ + /// + /// Verifies that the subject references the local host. + /// + /// + /// + /// + public static AndOrResult> IsLoopback(this IThat source) + => new(source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsLoopbackConstraint(it, grammars)), + source); + + /// + /// Verifies that the subject does not reference the local host. + /// + /// + /// + /// + public static AndOrResult> IsNotLoopback(this IThat source) + => new(source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsLoopbackConstraint(it, grammars).Invert()), + source); + + private sealed class IsLoopbackConstraint(string it, ExpectationGrammars grammars) + : ConstraintResult.WithValue(grammars), + IValueConstraint + { + public ConstraintResult IsMetBy(Uri actual) + { + Actual = actual; + Outcome = actual.IsLoopback ? Outcome.Success : Outcome.Failure; + return this; + } + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("references the local host"); + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(it).Append(" was "); + Formatter.Format(stringBuilder, Actual); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("does not reference the local host"); + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + => AppendNormalResult(stringBuilder, indentation); + } +} diff --git a/Source/aweXpect.Web/ThatUri.IsUnc.cs b/Source/aweXpect.Web/ThatUri.IsUnc.cs new file mode 100644 index 0000000..93db6a6 --- /dev/null +++ b/Source/aweXpect.Web/ThatUri.IsUnc.cs @@ -0,0 +1,61 @@ +using System; +using System.Text; +using aweXpect.Core; +using aweXpect.Core.Constraints; +using aweXpect.Helpers; +using aweXpect.Results; + +namespace aweXpect; + +#nullable enable +public static partial class ThatUri +{ + /// + /// Verifies that the subject is an UNC path. + /// + /// + /// + /// + public static AndOrResult> IsUnc(this IThat source) + => new(source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsUncConstraint(it, grammars)), + source); + + /// + /// Verifies that the subject is not an UNC path. + /// + /// + /// + /// + public static AndOrResult> IsNotUnc(this IThat source) + => new(source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsUncConstraint(it, grammars).Invert()), + source); + + private sealed class IsUncConstraint(string it, ExpectationGrammars grammars) + : ConstraintResult.WithValue(grammars), + IValueConstraint + { + public ConstraintResult IsMetBy(Uri actual) + { + Actual = actual; + Outcome = actual.IsUnc ? Outcome.Success : Outcome.Failure; + return this; + } + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("is an UNC path"); + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(it).Append(" was "); + Formatter.Format(stringBuilder, Actual); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("is not an UNC path"); + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + => AppendNormalResult(stringBuilder, indentation); + } +} diff --git a/Source/aweXpect.Web/ThatUri.cs b/Source/aweXpect.Web/ThatUri.cs new file mode 100644 index 0000000..38e88bc --- /dev/null +++ b/Source/aweXpect.Web/ThatUri.cs @@ -0,0 +1,8 @@ +using System; + +namespace aweXpect; + +/// +/// Expectations on values. +/// +public static partial class ThatUri; diff --git a/Tests/aweXpect.Web.Api.Tests/Expected/aweXpect.Web_net8.0.txt b/Tests/aweXpect.Web.Api.Tests/Expected/aweXpect.Web_net8.0.txt index 9106d06..87fc4e9 100644 --- a/Tests/aweXpect.Web.Api.Tests/Expected/aweXpect.Web_net8.0.txt +++ b/Tests/aweXpect.Web.Api.Tests/Expected/aweXpect.Web_net8.0.txt @@ -25,6 +25,19 @@ namespace aweXpect public static aweXpect.Web.Results.StatusCodeResult HasStatusCode(this aweXpect.Core.IThat source) { } public static aweXpect.Results.AndOrResult> HasStatusCode(this aweXpect.Core.IThat source, System.Net.HttpStatusCode? expected) { } } + public static class ThatUri + { + public static aweXpect.Results.AndOrResult> DoesNotHaveDefaultPort(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> HasDefaultPort(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsAbsolute(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsFile(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsLoopback(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsNotAbsolute(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsNotFile(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsNotLoopback(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsNotUnc(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsUnc(this aweXpect.Core.IThat source) { } + } } namespace aweXpect.Web.ContentProcessors { diff --git a/Tests/aweXpect.Web.Api.Tests/Expected/aweXpect.Web_netstandard2.0.txt b/Tests/aweXpect.Web.Api.Tests/Expected/aweXpect.Web_netstandard2.0.txt index bee5b18..9918e60 100644 --- a/Tests/aweXpect.Web.Api.Tests/Expected/aweXpect.Web_netstandard2.0.txt +++ b/Tests/aweXpect.Web.Api.Tests/Expected/aweXpect.Web_netstandard2.0.txt @@ -25,6 +25,19 @@ namespace aweXpect public static aweXpect.Web.Results.StatusCodeResult HasStatusCode(this aweXpect.Core.IThat source) { } public static aweXpect.Results.AndOrResult> HasStatusCode(this aweXpect.Core.IThat source, System.Net.HttpStatusCode? expected) { } } + public static class ThatUri + { + public static aweXpect.Results.AndOrResult> DoesNotHaveDefaultPort(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> HasDefaultPort(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsAbsolute(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsFile(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsLoopback(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsNotAbsolute(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsNotFile(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsNotLoopback(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsNotUnc(this aweXpect.Core.IThat source) { } + public static aweXpect.Results.AndOrResult> IsUnc(this aweXpect.Core.IThat source) { } + } } namespace aweXpect.Web.ContentProcessors { diff --git a/Tests/aweXpect.Web.Tests/ThatUri.DoesNotHaveDefaultPort.Tests.cs b/Tests/aweXpect.Web.Tests/ThatUri.DoesNotHaveDefaultPort.Tests.cs new file mode 100644 index 0000000..29c8228 --- /dev/null +++ b/Tests/aweXpect.Web.Tests/ThatUri.DoesNotHaveDefaultPort.Tests.cs @@ -0,0 +1,77 @@ +namespace aweXpect.Tests; + +public sealed partial class ThatUri +{ + public sealed class DoesNotHaveDefaultPort + { + public sealed class Tests + { + [Theory] + [InlineData("https://www.awexpect.com:80")] + [InlineData("http://www.example.com:443")] + public async Task WhenSubjectDoesNotHaveTheDefaultPort_ShouldSucceed(string uriString) + { + Uri subject = new(uriString); + + async Task Act() + => await That(subject).DoesNotHaveDefaultPort(); + + await That(Act).DoesNotThrow(); + } + + [Theory] + [InlineData("https://www.awexpect.com")] + [InlineData("https://www.awexpect.com:443")] + [InlineData("http://www.example.com:80")] + public async Task WhenSubjectHasTheDefaultPort_ShouldFail(string uriString) + { + Uri subject = new(uriString); + + async Task Act() + => await That(subject).DoesNotHaveDefaultPort(); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + does not have the default port for the used scheme, + but it was {subject} + """); + } + } + + public sealed class NegatedTests + { + [Theory] + [InlineData("https://www.awexpect.com:80")] + [InlineData("http://www.example.com:443")] + public async Task WhenSubjectDoesNotHaveTheDefaultPort_ShouldFail(string uriString) + { + Uri subject = new(uriString); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.DoesNotHaveDefaultPort()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + has the default port for the used scheme, + but it was {subject} + """); + } + + [Theory] + [InlineData("https://www.awexpect.com")] + [InlineData("https://www.awexpect.com:443")] + [InlineData("http://www.example.com:80")] + public async Task WhenSubjectHasTheDefaultPort_ShouldSucceed(string uriString) + { + Uri subject = new(uriString); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.DoesNotHaveDefaultPort()); + + await That(Act).DoesNotThrow(); + } + } + } +} diff --git a/Tests/aweXpect.Web.Tests/ThatUri.HasDefaultPort.Tests.cs b/Tests/aweXpect.Web.Tests/ThatUri.HasDefaultPort.Tests.cs new file mode 100644 index 0000000..5db5e5a --- /dev/null +++ b/Tests/aweXpect.Web.Tests/ThatUri.HasDefaultPort.Tests.cs @@ -0,0 +1,77 @@ +namespace aweXpect.Tests; + +public sealed partial class ThatUri +{ + public sealed class HasDefaultPort + { + public sealed class Tests + { + [Theory] + [InlineData("https://www.awexpect.com:80")] + [InlineData("http://www.example.com:443")] + public async Task WhenSubjectDoesNotHaveTheDefaultPort_ShouldFail(string uriString) + { + Uri subject = new(uriString); + + async Task Act() + => await That(subject).HasDefaultPort(); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + has the default port for the used scheme, + but it was {subject} + """); + } + + [Theory] + [InlineData("https://www.awexpect.com")] + [InlineData("https://www.awexpect.com:443")] + [InlineData("http://www.example.com:80")] + public async Task WhenSubjectHasTheDefaultPort_ShouldSucceed(string uriString) + { + Uri subject = new(uriString); + + async Task Act() + => await That(subject).HasDefaultPort(); + + await That(Act).DoesNotThrow(); + } + } + + public sealed class NegatedTests + { + [Theory] + [InlineData("https://www.awexpect.com:80")] + [InlineData("http://www.example.com:443")] + public async Task WhenSubjectDoesNotHaveTheDefaultPort_ShouldSucceed(string uriString) + { + Uri subject = new(uriString); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.HasDefaultPort()); + + await That(Act).DoesNotThrow(); + } + + [Theory] + [InlineData("https://www.awexpect.com")] + [InlineData("https://www.awexpect.com:443")] + [InlineData("http://www.example.com:80")] + public async Task WhenSubjectHasTheDefaultPort_ShouldFail(string uriString) + { + Uri subject = new(uriString); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.HasDefaultPort()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + does not have the default port for the used scheme, + but it was {subject} + """); + } + } + } +} diff --git a/Tests/aweXpect.Web.Tests/ThatUri.IsAbsolute.Tests.cs b/Tests/aweXpect.Web.Tests/ThatUri.IsAbsolute.Tests.cs new file mode 100644 index 0000000..7d95f46 --- /dev/null +++ b/Tests/aweXpect.Web.Tests/ThatUri.IsAbsolute.Tests.cs @@ -0,0 +1,69 @@ +namespace aweXpect.Tests; + +public sealed partial class ThatUri +{ + public sealed class IsAbsolute + { + public sealed class Tests + { + [Fact] + public async Task WhenSubjectIsAbsolute_ShouldSucceed() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).IsAbsolute(); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsNotAbsolute_ShouldFail() + { + Uri subject = new Uri("https://www.awexpect.com") + .MakeRelativeUri(new Uri("https://www.awexpect.com/foo/bar")); + + async Task Act() + => await That(subject).IsAbsolute(); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + is an absolute URI, + but it was foo/bar + """); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenSubjectIsAbsolute_ShouldFail() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsAbsolute()); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + is not an absolute URI, + but it was https://www.awexpect.com/ + """); + } + + [Fact] + public async Task WhenSubjectIsNotAbsolute_ShouldSucceed() + { + Uri subject = new Uri("https://www.awexpect.com") + .MakeRelativeUri(new Uri("https://www.awexpect.com/foo/bar")); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsAbsolute()); + + await That(Act).DoesNotThrow(); + } + } + } +} diff --git a/Tests/aweXpect.Web.Tests/ThatUri.IsFile.Tests.cs b/Tests/aweXpect.Web.Tests/ThatUri.IsFile.Tests.cs new file mode 100644 index 0000000..ac4a575 --- /dev/null +++ b/Tests/aweXpect.Web.Tests/ThatUri.IsFile.Tests.cs @@ -0,0 +1,67 @@ +namespace aweXpect.Tests; + +public sealed partial class ThatUri +{ + public sealed class IsFile + { + public sealed class Tests + { + [Fact] + public async Task WhenSubjectIsAFileUri_ShouldSucceed() + { + Uri subject = new("file://server/filename.ext"); + + async Task Act() + => await That(subject).IsFile(); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsNotAFileUri_ShouldFail() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).IsFile(); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + is a file URI, + but it was https://www.awexpect.com/ + """); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenSubjectIsAFileUri_ShouldFail() + { + Uri subject = new("file://server/filename.ext"); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsFile()); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + is not a file URI, + but it was file://server/filename.ext + """); + } + + [Fact] + public async Task WhenSubjectIsNotAFileUri_ShouldSucceed() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsFile()); + + await That(Act).DoesNotThrow(); + } + } + } +} diff --git a/Tests/aweXpect.Web.Tests/ThatUri.IsLoopback.Tests.cs b/Tests/aweXpect.Web.Tests/ThatUri.IsLoopback.Tests.cs new file mode 100644 index 0000000..dbdf7ad --- /dev/null +++ b/Tests/aweXpect.Web.Tests/ThatUri.IsLoopback.Tests.cs @@ -0,0 +1,73 @@ +namespace aweXpect.Tests; + +public sealed partial class ThatUri +{ + public sealed class IsLoopback + { + public sealed class Tests + { + [Theory] + [InlineData("127.0.0.1")] + [InlineData("loopback")] + [InlineData("localhost")] + public async Task WhenSubjectIsLoopback_ShouldSucceed(string uriString) + { + Uri subject = new UriBuilder(uriString).Uri; + + async Task Act() + => await That(subject).IsLoopback(); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsNotLoopback_ShouldFail() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).IsLoopback(); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + references the local host, + but it was https://www.awexpect.com/ + """); + } + } + + public sealed class NegatedTests + { + [Theory] + [InlineData("127.0.0.1")] + [InlineData("loopback")] + [InlineData("localhost")] + public async Task WhenSubjectIsLoopback_ShouldFail(string uriString) + { + Uri subject = new UriBuilder(uriString).Uri; + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsLoopback()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + does not reference the local host, + but it was {subject} + """); + } + + [Fact] + public async Task WhenSubjectIsNotLoopback_ShouldSucceed() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsLoopback()); + + await That(Act).DoesNotThrow(); + } + } + } +} diff --git a/Tests/aweXpect.Web.Tests/ThatUri.IsNotAbsolute.Tests.cs b/Tests/aweXpect.Web.Tests/ThatUri.IsNotAbsolute.Tests.cs new file mode 100644 index 0000000..e3fd08d --- /dev/null +++ b/Tests/aweXpect.Web.Tests/ThatUri.IsNotAbsolute.Tests.cs @@ -0,0 +1,69 @@ +namespace aweXpect.Tests; + +public sealed partial class ThatUri +{ + public sealed class IsNotAbsolute + { + public sealed class Tests + { + [Fact] + public async Task WhenSubjectIsAbsolute_ShouldFail() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).IsNotAbsolute(); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + is not an absolute URI, + but it was https://www.awexpect.com/ + """); + } + + [Fact] + public async Task WhenSubjectIsNotAbsolute_ShouldSucceed() + { + Uri subject = new Uri("https://www.awexpect.com") + .MakeRelativeUri(new Uri("https://www.awexpect.com/foo/bar")); + + async Task Act() + => await That(subject).IsNotAbsolute(); + + await That(Act).DoesNotThrow(); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenSubjectIsAbsolute_ShouldSucceed() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsNotAbsolute()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsNotAbsolute_ShouldFail() + { + Uri subject = new Uri("https://www.awexpect.com") + .MakeRelativeUri(new Uri("https://www.awexpect.com/foo/bar")); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsNotAbsolute()); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + is an absolute URI, + but it was foo/bar + """); + } + } + } +} diff --git a/Tests/aweXpect.Web.Tests/ThatUri.IsNotFile.Tests.cs b/Tests/aweXpect.Web.Tests/ThatUri.IsNotFile.Tests.cs new file mode 100644 index 0000000..dc6e665 --- /dev/null +++ b/Tests/aweXpect.Web.Tests/ThatUri.IsNotFile.Tests.cs @@ -0,0 +1,67 @@ +namespace aweXpect.Tests; + +public sealed partial class ThatUri +{ + public sealed class IsNotFile + { + public sealed class Tests + { + [Fact] + public async Task WhenSubjectIsAFileUri_ShouldFail() + { + Uri subject = new("file://server/filename.ext"); + + async Task Act() + => await That(subject).IsNotFile(); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + is not a file URI, + but it was file://server/filename.ext + """); + } + + [Fact] + public async Task WhenSubjectIsNotAFileUri_ShouldSucceed() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).IsNotFile(); + + await That(Act).DoesNotThrow(); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenSubjectIsAFileUri_ShouldSucceed() + { + Uri subject = new("file://server/filename.ext"); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsNotFile()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsNotAFileUri_ShouldFail() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsNotFile()); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + is a file URI, + but it was https://www.awexpect.com/ + """); + } + } + } +} diff --git a/Tests/aweXpect.Web.Tests/ThatUri.IsNotLoopback.Tests.cs b/Tests/aweXpect.Web.Tests/ThatUri.IsNotLoopback.Tests.cs new file mode 100644 index 0000000..0d1964d --- /dev/null +++ b/Tests/aweXpect.Web.Tests/ThatUri.IsNotLoopback.Tests.cs @@ -0,0 +1,73 @@ +namespace aweXpect.Tests; + +public sealed partial class ThatUri +{ + public sealed class IsNotLoopback + { + public sealed class Tests + { + [Theory] + [InlineData("127.0.0.1")] + [InlineData("loopback")] + [InlineData("localhost")] + public async Task WhenSubjectIsNotLoopback_ShouldFail(string uriString) + { + Uri subject = new UriBuilder(uriString).Uri; + + async Task Act() + => await That(subject).IsNotLoopback(); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + does not reference the local host, + but it was {subject} + """); + } + + [Fact] + public async Task WhenSubjectIsNotLoopback_ShouldSucceed() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).IsNotLoopback(); + + await That(Act).DoesNotThrow(); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenSubjectIsNotLoopback_ShouldFail() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsNotLoopback()); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + references the local host, + but it was https://www.awexpect.com/ + """); + } + + [Theory] + [InlineData("127.0.0.1")] + [InlineData("loopback")] + [InlineData("localhost")] + public async Task WhenSubjectIsNotLoopback_ShouldSucceed(string uriString) + { + Uri subject = new UriBuilder(uriString).Uri; + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsNotLoopback()); + + await That(Act).DoesNotThrow(); + } + } + } +} diff --git a/Tests/aweXpect.Web.Tests/ThatUri.IsNotUnc.Tests.cs b/Tests/aweXpect.Web.Tests/ThatUri.IsNotUnc.Tests.cs new file mode 100644 index 0000000..1e1e93c --- /dev/null +++ b/Tests/aweXpect.Web.Tests/ThatUri.IsNotUnc.Tests.cs @@ -0,0 +1,67 @@ +namespace aweXpect.Tests; + +public sealed partial class ThatUri +{ + public sealed class IsNotUnc + { + public sealed class Tests + { + [Fact] + public async Task WhenSubjectIsNotUnc_ShouldFail() + { + Uri subject = new("file://server/filename.ext"); + + async Task Act() + => await That(subject).IsNotUnc(); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + is not an UNC path, + but it was file://server/filename.ext + """); + } + + [Fact] + public async Task WhenSubjectIsNotUnc_ShouldSucceed() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).IsNotUnc(); + + await That(Act).DoesNotThrow(); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenSubjectIsNotUnc_ShouldFail() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsNotUnc()); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + is an UNC path, + but it was https://www.awexpect.com/ + """); + } + + [Fact] + public async Task WhenSubjectIsNotUnc_ShouldSucceed() + { + Uri subject = new("file://server/filename.ext"); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsNotUnc()); + + await That(Act).DoesNotThrow(); + } + } + } +} diff --git a/Tests/aweXpect.Web.Tests/ThatUri.IsUnc.Tests.cs b/Tests/aweXpect.Web.Tests/ThatUri.IsUnc.Tests.cs new file mode 100644 index 0000000..451e56d --- /dev/null +++ b/Tests/aweXpect.Web.Tests/ThatUri.IsUnc.Tests.cs @@ -0,0 +1,67 @@ +namespace aweXpect.Tests; + +public sealed partial class ThatUri +{ + public sealed class IsUnc + { + public sealed class Tests + { + [Fact] + public async Task WhenSubjectIsNotUnc_ShouldFail() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).IsUnc(); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + is an UNC path, + but it was https://www.awexpect.com/ + """); + } + + [Fact] + public async Task WhenSubjectIsUnc_ShouldSucceed() + { + Uri subject = new("file://server/filename.ext"); + + async Task Act() + => await That(subject).IsUnc(); + + await That(Act).DoesNotThrow(); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenSubjectIsNotUnc_ShouldSucceed() + { + Uri subject = new("https://www.awexpect.com"); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsUnc()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsUnc_ShouldFail() + { + Uri subject = new("file://server/filename.ext"); + + async Task Act() + => await That(subject).DoesNotComplyWith(it => it.IsUnc()); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + is not an UNC path, + but it was file://server/filename.ext + """); + } + } + } +} diff --git a/Tests/aweXpect.Web.Tests/ThatUri.cs b/Tests/aweXpect.Web.Tests/ThatUri.cs new file mode 100644 index 0000000..ce35534 --- /dev/null +++ b/Tests/aweXpect.Web.Tests/ThatUri.cs @@ -0,0 +1,4 @@ +namespace aweXpect.Tests; + +// ReSharper disable once ClassNeverInstantiated.Global +public sealed partial class ThatUri;