diff --git a/Docs/pages/docs/expectations/11-date-time-only.md b/Docs/pages/docs/expectations/11-date-time-only.md index 5f5421533..0c1cff491 100644 --- a/Docs/pages/docs/expectations/11-date-time-only.md +++ b/Docs/pages/docs/expectations/11-date-time-only.md @@ -118,6 +118,34 @@ TimeOnly subjectB = TimeOnly.FromDateTime(DateTime.Now); await Expect.That(subjectB).IsBefore(TimeOnly.FromDateTime(DateTime.Now)).Within(TimeSpan.FromSeconds(1)); ``` +## Between + +You can verify that the `DateOnly` or `TimeOnly` is between two values: + +```csharp +DateOnly subjectA = DateOnly.FromDateTime(DateTime.Now); + +await Expect.That(subjectA).IsBetween(new DateOnly(2024, 1, 1)).And(new DateOnly(2123, 12, 31)); + +TimeOnly subjectB = TimeOnly.FromDateTime(DateTime.Now); + +await Expect.That(subjectB) + .IsBetween(TimeOnly.FromDateTime(DateTime.Now).Add(-2.Seconds())) + .And(TimeOnly.FromDateTime(DateTime.Now).Add(2.Seconds())); +``` + +You can also specify a tolerance: + +```csharp +TimeOnly subject = TimeOnly.FromDateTime(DateTime.Now); + +await Expect.That(subject) + .IsBetween(TimeOnly.FromDateTime(DateTime.Now)) + .And(TimeOnly.FromDateTime(DateTime.Now)) + .Within(2.Seconds()) + .Because("it should have taken less than two seconds"); +``` + ## Properties You can verify, the properties of the `DateTime`: diff --git a/Docs/pages/docs/expectations/12-datetime-offset.md b/Docs/pages/docs/expectations/12-datetime-offset.md index cbe4e6744..10f44d227 100644 --- a/Docs/pages/docs/expectations/12-datetime-offset.md +++ b/Docs/pages/docs/expectations/12-datetime-offset.md @@ -109,7 +109,6 @@ DateTime subject = DateTime.Now; await Expect.That(subject).IsOnOrBefore(DateTime.Now).Within(TimeSpan.FromSeconds(1)) .Because("it should have taken less than one second"); ``` -``` ## Between diff --git a/Source/aweXpect.Core/Results/BetweenResult.cs b/Source/aweXpect.Core/Results/BetweenResult.cs index 49f79eca2..de813f22d 100644 --- a/Source/aweXpect.Core/Results/BetweenResult.cs +++ b/Source/aweXpect.Core/Results/BetweenResult.cs @@ -23,7 +23,7 @@ public class BetweenResult( Func callback) { /// - /// …and . + /// …and the value. /// public TTarget And(TType maximum) => callback(maximum); diff --git a/Source/aweXpect/That/DateOnlys/ThatDateOnly.IsBetween.cs b/Source/aweXpect/That/DateOnlys/ThatDateOnly.IsBetween.cs new file mode 100644 index 000000000..7ae82cd41 --- /dev/null +++ b/Source/aweXpect/That/DateOnlys/ThatDateOnly.IsBetween.cs @@ -0,0 +1,108 @@ +#if NET8_0_OR_GREATER +using System; +using aweXpect.Core; +using aweXpect.Core.Constraints; +using aweXpect.Customization; +using aweXpect.Helpers; +using aweXpect.Options; +using aweXpect.Results; + +namespace aweXpect; + +public static partial class ThatDateOnly +{ + /// + /// Verifies that the subject is between the … + /// + public static BetweenResult>, DateOnly?> IsBetween( + this IThat source, + DateOnly? minimum) + { + TimeTolerance tolerance = new(); + return new BetweenResult>, DateOnly?>(maximum + => new TimeToleranceResult>( + source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsBetweenConstraint(it, grammars, minimum, maximum, tolerance)), + source, + tolerance)); + } + + /// + /// Verifies that the subject is not between the … + /// + public static BetweenResult>, DateOnly?> IsNotBetween( + this IThat source, + DateOnly? minimum) + { + TimeTolerance tolerance = new(); + return new BetweenResult>, DateOnly?>(maximum + => new TimeToleranceResult>( + source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsBetweenConstraint(it, grammars, minimum, maximum, tolerance).Invert()), + source, + tolerance)); + } + + private sealed class IsBetweenConstraint( + string it, + ExpectationGrammars grammars, + DateOnly? minimum, + DateOnly? maximum, + TimeTolerance tolerance) + : ConstraintResult.WithNotNullValue(it, grammars), + IValueConstraint + { + public ConstraintResult IsMetBy(DateOnly actual) + { + Actual = actual; + if (minimum is null || maximum is null) + { + Outcome = IsNegated ? Outcome.Success : Outcome.Failure; + } + else + { + TimeSpan timeTolerance = tolerance.Tolerance + ?? Customize.aweXpect.Settings().DefaultTimeComparisonTolerance.Get(); + if (IsNegated) + { + timeTolerance = timeTolerance.Negate(); + } + + Outcome = actual.AddDays((int)timeTolerance.TotalDays) >= minimum && + actual.AddDays((int)timeTolerance.Negate().TotalDays) <= maximum + ? Outcome.Success + : Outcome.Failure; + } + + return this; + } + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append("is between "); + ValueFormatters.Format(Formatter, stringBuilder, minimum); + stringBuilder.Append(" and "); + ValueFormatters.Format(Formatter, stringBuilder, maximum); + stringBuilder.Append(tolerance.ToDayString()); + } + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(It).Append(" was "); + ValueFormatters.Format(Formatter, stringBuilder, Actual); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append("is not between "); + ValueFormatters.Format(Formatter, stringBuilder, minimum); + stringBuilder.Append(" and "); + ValueFormatters.Format(Formatter, stringBuilder, maximum); + stringBuilder.Append(tolerance.ToDayString()); + } + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + => AppendNormalResult(stringBuilder, indentation); + } +} +#endif diff --git a/Source/aweXpect/That/DateOnlys/ThatNullableDateOnly.IsBetween.cs b/Source/aweXpect/That/DateOnlys/ThatNullableDateOnly.IsBetween.cs new file mode 100644 index 000000000..d11595bb0 --- /dev/null +++ b/Source/aweXpect/That/DateOnlys/ThatNullableDateOnly.IsBetween.cs @@ -0,0 +1,112 @@ +#if NET8_0_OR_GREATER +using System; +using aweXpect.Core; +using aweXpect.Core.Constraints; +using aweXpect.Customization; +using aweXpect.Helpers; +using aweXpect.Options; +using aweXpect.Results; + +namespace aweXpect; + +public static partial class ThatNullableDateOnly +{ + /// + /// Verifies that the subject is between the … + /// + public static BetweenResult>, DateOnly?> IsBetween( + this IThat source, + DateOnly? minimum) + { + TimeTolerance tolerance = new(); + return new BetweenResult>, DateOnly?>(maximum + => new TimeToleranceResult>( + source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsBetweenConstraint(it, grammars, minimum, maximum, tolerance)), + source, + tolerance)); + } + + /// + /// Verifies that the subject is not between the … + /// + public static BetweenResult>, DateOnly?> IsNotBetween( + this IThat source, + DateOnly? minimum) + { + TimeTolerance tolerance = new(); + return new BetweenResult>, DateOnly?>(maximum + => new TimeToleranceResult>( + source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsBetweenConstraint(it, grammars, minimum, maximum, tolerance).Invert()), + source, + tolerance)); + } + + private sealed class IsBetweenConstraint( + string it, + ExpectationGrammars grammars, + DateOnly? minimum, + DateOnly? maximum, + TimeTolerance tolerance) + : ConstraintResult.WithNotNullValue(it, grammars), + IValueConstraint + { + public ConstraintResult IsMetBy(DateOnly? actual) + { + Actual = actual; + if (actual is null && minimum is null && maximum is null) + { + Outcome = Outcome.Success; + } + else if (actual is null || minimum is null || maximum is null) + { + Outcome = IsNegated ? Outcome.Success : Outcome.Failure; + } + else + { + TimeSpan timeTolerance = tolerance.Tolerance + ?? Customize.aweXpect.Settings().DefaultTimeComparisonTolerance.Get(); + if (IsNegated) + { + timeTolerance = timeTolerance.Negate(); + } + + Outcome = actual.Value.AddDays((int)timeTolerance.TotalDays) >= minimum && + actual.Value.AddDays((int)timeTolerance.Negate().TotalDays) <= maximum + ? Outcome.Success + : Outcome.Failure; + } + + return this; + } + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append("is between "); + ValueFormatters.Format(Formatter, stringBuilder, minimum); + stringBuilder.Append(" and "); + ValueFormatters.Format(Formatter, stringBuilder, maximum); + stringBuilder.Append(tolerance.ToDayString()); + } + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(It).Append(" was "); + ValueFormatters.Format(Formatter, stringBuilder, Actual); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append("is not between "); + ValueFormatters.Format(Formatter, stringBuilder, minimum); + stringBuilder.Append(" and "); + ValueFormatters.Format(Formatter, stringBuilder, maximum); + stringBuilder.Append(tolerance.ToDayString()); + } + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + => AppendNormalResult(stringBuilder, indentation); + } +} +#endif diff --git a/Source/aweXpect/That/TimeOnlys/ThatNullableTimeOnly.IsBetween.cs b/Source/aweXpect/That/TimeOnlys/ThatNullableTimeOnly.IsBetween.cs new file mode 100644 index 000000000..acb0a576e --- /dev/null +++ b/Source/aweXpect/That/TimeOnlys/ThatNullableTimeOnly.IsBetween.cs @@ -0,0 +1,112 @@ +#if NET8_0_OR_GREATER +using System; +using aweXpect.Core; +using aweXpect.Core.Constraints; +using aweXpect.Customization; +using aweXpect.Helpers; +using aweXpect.Options; +using aweXpect.Results; + +namespace aweXpect; + +public static partial class ThatNullableTimeOnly +{ + /// + /// Verifies that the subject is between the … + /// + public static BetweenResult>, TimeOnly?> IsBetween( + this IThat source, + TimeOnly? minimum) + { + TimeTolerance tolerance = new(); + return new BetweenResult>, TimeOnly?>(maximum + => new TimeToleranceResult>( + source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsBetweenConstraint(it, grammars, minimum, maximum, tolerance)), + source, + tolerance)); + } + + /// + /// Verifies that the subject is not between the … + /// + public static BetweenResult>, TimeOnly?> IsNotBetween( + this IThat source, + TimeOnly? minimum) + { + TimeTolerance tolerance = new(); + return new BetweenResult>, TimeOnly?>(maximum + => new TimeToleranceResult>( + source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsBetweenConstraint(it, grammars, minimum, maximum, tolerance).Invert()), + source, + tolerance)); + } + + private sealed class IsBetweenConstraint( + string it, + ExpectationGrammars grammars, + TimeOnly? minimum, + TimeOnly? maximum, + TimeTolerance tolerance) + : ConstraintResult.WithNotNullValue(it, grammars), + IValueConstraint + { + public ConstraintResult IsMetBy(TimeOnly? actual) + { + Actual = actual; + if (actual is null && minimum is null && maximum is null) + { + Outcome = Outcome.Success; + } + else if (actual is null || minimum is null || maximum is null) + { + Outcome = IsNegated ? Outcome.Success : Outcome.Failure; + } + else + { + TimeSpan timeTolerance = tolerance.Tolerance + ?? Customize.aweXpect.Settings().DefaultTimeComparisonTolerance.Get(); + if (IsNegated) + { + timeTolerance = timeTolerance.Negate(); + } + + Outcome = actual.Value.Add(timeTolerance) >= minimum && + actual.Value.Add(timeTolerance.Negate()) <= maximum + ? Outcome.Success + : Outcome.Failure; + } + + return this; + } + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append("is between "); + ValueFormatters.Format(Formatter, stringBuilder, minimum); + stringBuilder.Append(" and "); + ValueFormatters.Format(Formatter, stringBuilder, maximum); + stringBuilder.Append(tolerance); + } + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(It).Append(" was "); + ValueFormatters.Format(Formatter, stringBuilder, Actual); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append("is not between "); + ValueFormatters.Format(Formatter, stringBuilder, minimum); + stringBuilder.Append(" and "); + ValueFormatters.Format(Formatter, stringBuilder, maximum); + stringBuilder.Append(tolerance); + } + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + => AppendNormalResult(stringBuilder, indentation); + } +} +#endif diff --git a/Source/aweXpect/That/TimeOnlys/ThatTimeOnly.IsBetween.cs b/Source/aweXpect/That/TimeOnlys/ThatTimeOnly.IsBetween.cs new file mode 100644 index 000000000..60903fecb --- /dev/null +++ b/Source/aweXpect/That/TimeOnlys/ThatTimeOnly.IsBetween.cs @@ -0,0 +1,107 @@ +#if NET8_0_OR_GREATER +using System; +using aweXpect.Core; +using aweXpect.Core.Constraints; +using aweXpect.Customization; +using aweXpect.Helpers; +using aweXpect.Options; +using aweXpect.Results; + +namespace aweXpect; + +public static partial class ThatTimeOnly +{ + /// + /// Verifies that the subject is between the … + /// + public static BetweenResult>, TimeOnly?> IsBetween( + this IThat source, + TimeOnly? minimum) + { + TimeTolerance tolerance = new(); + return new BetweenResult>, TimeOnly?>(maximum + => new TimeToleranceResult>( + source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsBetweenConstraint(it, grammars, minimum, maximum, tolerance)), + source, + tolerance)); + } + + /// + /// Verifies that the subject is not between the … + /// + public static BetweenResult>, TimeOnly?> IsNotBetween( + this IThat source, + TimeOnly? minimum) + { + TimeTolerance tolerance = new(); + return new BetweenResult>, TimeOnly?>(maximum + => new TimeToleranceResult>( + source.Get().ExpectationBuilder.AddConstraint((it, grammars) => + new IsBetweenConstraint(it, grammars, minimum, maximum, tolerance).Invert()), + source, + tolerance)); + } + + private sealed class IsBetweenConstraint( + string it, + ExpectationGrammars grammars, + TimeOnly? minimum, + TimeOnly? maximum, + TimeTolerance tolerance) + : ConstraintResult.WithNotNullValue(it, grammars), + IValueConstraint + { + public ConstraintResult IsMetBy(TimeOnly actual) + { + Actual = actual; + if (minimum is null || maximum is null) + { + Outcome = IsNegated ? Outcome.Success : Outcome.Failure; + } + else + { + TimeSpan timeTolerance = tolerance.Tolerance + ?? Customize.aweXpect.Settings().DefaultTimeComparisonTolerance.Get(); + if (IsNegated) + { + timeTolerance = timeTolerance.Negate(); + } + + Outcome = actual.Add(timeTolerance) >= minimum && actual.Add(timeTolerance.Negate()) <= maximum + ? Outcome.Success + : Outcome.Failure; + } + + return this; + } + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append("is between "); + ValueFormatters.Format(Formatter, stringBuilder, minimum); + stringBuilder.Append(" and "); + ValueFormatters.Format(Formatter, stringBuilder, maximum); + stringBuilder.Append(tolerance); + } + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(It).Append(" was "); + ValueFormatters.Format(Formatter, stringBuilder, Actual); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append("is not between "); + ValueFormatters.Format(Formatter, stringBuilder, minimum); + stringBuilder.Append(" and "); + ValueFormatters.Format(Formatter, stringBuilder, maximum); + stringBuilder.Append(tolerance); + } + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + => AppendNormalResult(stringBuilder, indentation); + } +} +#endif diff --git a/Tests/aweXpect.Api.Tests/Expected/aweXpect_net8.0.txt b/Tests/aweXpect.Api.Tests/Expected/aweXpect_net8.0.txt index 92f975821..1189b4733 100644 --- a/Tests/aweXpect.Api.Tests/Expected/aweXpect_net8.0.txt +++ b/Tests/aweXpect.Api.Tests/Expected/aweXpect_net8.0.txt @@ -184,9 +184,11 @@ namespace aweXpect public static aweXpect.Results.PropertyResult.Int HasYear(this aweXpect.Core.IThat source) { } public static aweXpect.Results.TimeToleranceResult> IsAfter(this aweXpect.Core.IThat source, System.DateOnly? expected) { } public static aweXpect.Results.TimeToleranceResult> IsBefore(this aweXpect.Core.IThat source, System.DateOnly? expected) { } + public static aweXpect.Results.BetweenResult>, System.DateOnly?> IsBetween(this aweXpect.Core.IThat source, System.DateOnly? minimum) { } public static aweXpect.Results.TimeToleranceResult> IsEqualTo(this aweXpect.Core.IThat source, System.DateOnly? expected) { } public static aweXpect.Results.TimeToleranceResult> IsNotAfter(this aweXpect.Core.IThat source, System.DateOnly? unexpected) { } public static aweXpect.Results.TimeToleranceResult> IsNotBefore(this aweXpect.Core.IThat source, System.DateOnly? unexpected) { } + public static aweXpect.Results.BetweenResult>, System.DateOnly?> IsNotBetween(this aweXpect.Core.IThat source, System.DateOnly? minimum) { } public static aweXpect.Results.TimeToleranceResult> IsNotEqualTo(this aweXpect.Core.IThat source, System.DateOnly? unexpected) { } public static aweXpect.Results.TimeToleranceResult> IsNotOnOrAfter(this aweXpect.Core.IThat source, System.DateOnly? unexpected) { } public static aweXpect.Results.TimeToleranceResult> IsNotOnOrBefore(this aweXpect.Core.IThat source, System.DateOnly? unexpected) { } @@ -517,9 +519,11 @@ namespace aweXpect public static aweXpect.Results.PropertyResult.Int HasYear(this aweXpect.Core.IThat source) { } public static aweXpect.Results.TimeToleranceResult> IsAfter(this aweXpect.Core.IThat source, System.DateOnly? expected) { } public static aweXpect.Results.TimeToleranceResult> IsBefore(this aweXpect.Core.IThat source, System.DateOnly? expected) { } + public static aweXpect.Results.BetweenResult>, System.DateOnly?> IsBetween(this aweXpect.Core.IThat source, System.DateOnly? minimum) { } public static aweXpect.Results.TimeToleranceResult> IsEqualTo(this aweXpect.Core.IThat source, System.DateOnly? expected) { } public static aweXpect.Results.TimeToleranceResult> IsNotAfter(this aweXpect.Core.IThat source, System.DateOnly? unexpected) { } public static aweXpect.Results.TimeToleranceResult> IsNotBefore(this aweXpect.Core.IThat source, System.DateOnly? unexpected) { } + public static aweXpect.Results.BetweenResult>, System.DateOnly?> IsNotBetween(this aweXpect.Core.IThat source, System.DateOnly? minimum) { } public static aweXpect.Results.TimeToleranceResult> IsNotEqualTo(this aweXpect.Core.IThat source, System.DateOnly? unexpected) { } public static aweXpect.Results.TimeToleranceResult> IsNotOnOrAfter(this aweXpect.Core.IThat source, System.DateOnly? unexpected) { } public static aweXpect.Results.TimeToleranceResult> IsNotOnOrBefore(this aweXpect.Core.IThat source, System.DateOnly? unexpected) { } @@ -636,9 +640,11 @@ namespace aweXpect public static aweXpect.Results.PropertyResult.Int HasSecond(this aweXpect.Core.IThat source) { } public static aweXpect.Results.TimeToleranceResult> IsAfter(this aweXpect.Core.IThat source, System.TimeOnly? expected) { } public static aweXpect.Results.TimeToleranceResult> IsBefore(this aweXpect.Core.IThat source, System.TimeOnly? expected) { } + public static aweXpect.Results.BetweenResult>, System.TimeOnly?> IsBetween(this aweXpect.Core.IThat source, System.TimeOnly? minimum) { } public static aweXpect.Results.TimeToleranceResult> IsEqualTo(this aweXpect.Core.IThat source, System.TimeOnly? expected) { } public static aweXpect.Results.TimeToleranceResult> IsNotAfter(this aweXpect.Core.IThat source, System.TimeOnly? unexpected) { } public static aweXpect.Results.TimeToleranceResult> IsNotBefore(this aweXpect.Core.IThat source, System.TimeOnly? unexpected) { } + public static aweXpect.Results.BetweenResult>, System.TimeOnly?> IsNotBetween(this aweXpect.Core.IThat source, System.TimeOnly? minimum) { } public static aweXpect.Results.TimeToleranceResult> IsNotEqualTo(this aweXpect.Core.IThat source, System.TimeOnly? unexpected) { } public static aweXpect.Results.TimeToleranceResult> IsNotOnOrAfter(this aweXpect.Core.IThat source, System.TimeOnly? unexpected) { } public static aweXpect.Results.TimeToleranceResult> IsNotOnOrBefore(this aweXpect.Core.IThat source, System.TimeOnly? unexpected) { } @@ -866,9 +872,11 @@ namespace aweXpect public static aweXpect.Results.PropertyResult.Int HasSecond(this aweXpect.Core.IThat source) { } public static aweXpect.Results.TimeToleranceResult> IsAfter(this aweXpect.Core.IThat source, System.TimeOnly? expected) { } public static aweXpect.Results.TimeToleranceResult> IsBefore(this aweXpect.Core.IThat source, System.TimeOnly? expected) { } + public static aweXpect.Results.BetweenResult>, System.TimeOnly?> IsBetween(this aweXpect.Core.IThat source, System.TimeOnly? minimum) { } public static aweXpect.Results.TimeToleranceResult> IsEqualTo(this aweXpect.Core.IThat source, System.TimeOnly? expected) { } public static aweXpect.Results.TimeToleranceResult> IsNotAfter(this aweXpect.Core.IThat source, System.TimeOnly? unexpected) { } public static aweXpect.Results.TimeToleranceResult> IsNotBefore(this aweXpect.Core.IThat source, System.TimeOnly? unexpected) { } + public static aweXpect.Results.BetweenResult>, System.TimeOnly?> IsNotBetween(this aweXpect.Core.IThat source, System.TimeOnly? minimum) { } public static aweXpect.Results.TimeToleranceResult> IsNotEqualTo(this aweXpect.Core.IThat source, System.TimeOnly? unexpected) { } public static aweXpect.Results.TimeToleranceResult> IsNotOnOrAfter(this aweXpect.Core.IThat source, System.TimeOnly? unexpected) { } public static aweXpect.Results.TimeToleranceResult> IsNotOnOrBefore(this aweXpect.Core.IThat source, System.TimeOnly? unexpected) { } diff --git a/Tests/aweXpect.Tests/DateOnlys/ThatDateOnly.IsBetween.Tests.cs b/Tests/aweXpect.Tests/DateOnlys/ThatDateOnly.IsBetween.Tests.cs new file mode 100644 index 000000000..e11a87bac --- /dev/null +++ b/Tests/aweXpect.Tests/DateOnlys/ThatDateOnly.IsBetween.Tests.cs @@ -0,0 +1,256 @@ +#if NET8_0_OR_GREATER +namespace aweXpect.Tests; + +public sealed partial class ThatDateOnly +{ + public sealed class IsBetween + { + public sealed class Tests + { + [Fact] + public async Task WhenMaximumIsNull_ShouldFail() + { + DateOnly subject = CurrentTime(); + DateOnly? minimum = subject; + DateOnly? maximum = null; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and , + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenMinimumIsNull_ShouldFail() + { + DateOnly subject = CurrentTime(); + DateOnly? minimum = null; + DateOnly? maximum = subject; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectAndMaximumAreMaxValue_ShouldSucceed() + { + DateOnly subject = DateOnly.MaxValue; + DateOnly minimum = CurrentTime(); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectAndMinimumAreMinValue_ShouldSucceed() + { + DateOnly subject = DateOnly.MinValue; + DateOnly minimum = DateOnly.MinValue; + DateOnly maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsBetweenMinimumAndMaximum_ShouldSucceed() + { + DateOnly subject = CurrentTime(); + DateOnly minimum = EarlierTime(); + DateOnly maximum = LaterTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsEarlierThanMinimum_ShouldFail() + { + DateOnly subject = EarlierTime(); + DateOnly minimum = CurrentTime(); + DateOnly maximum = LaterTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsLaterThanMaximum_ShouldFail() + { + DateOnly subject = LaterTime(); + DateOnly minimum = EarlierTime(); + DateOnly maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsSameAsMaximum_ShouldSucceed() + { + DateOnly subject = CurrentTime(); + DateOnly minimum = EarlierTime(); + DateOnly maximum = subject; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsSameAsMinimum_ShouldSucceed() + { + DateOnly subject = CurrentTime(); + DateOnly minimum = subject; + DateOnly maximum = LaterTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + } + + public sealed class WithinTests + { + [Fact] + public async Task WhenMaximumValueIsOutsideTheTolerance_ShouldFail() + { + DateOnly subject = LaterTime(4); + DateOnly minimum = DateOnly.MinValue; + DateOnly maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 3 days, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenMinimumValueIsOutsideTheTolerance_ShouldFail() + { + DateOnly subject = EarlierTime(4); + DateOnly minimum = CurrentTime(); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 3 days, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenNullableMaximumValueIsOutsideTheTolerance_ShouldFail() + { + DateOnly subject = CurrentTime(); + DateOnly minimum = DateOnly.MinValue; + DateOnly? maximum = LaterTime(-4); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 3 days, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenNullableMinimumValueIsOutsideTheTolerance_ShouldFail() + { + DateOnly subject = CurrentTime(); + DateOnly? minimum = EarlierTime(-4); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 3 days, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenValueIsWithinTheMaximumTolerance_ShouldSucceed() + { + DateOnly subject = LaterTime(3); + DateOnly minimum = DateOnly.MinValue; + DateOnly maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenValueIsWithinTheMinimumTolerance_ShouldSucceed() + { + DateOnly subject = EarlierTime(3); + DateOnly minimum = CurrentTime(); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).DoesNotThrow(); + } + } + } +} +#endif diff --git a/Tests/aweXpect.Tests/DateOnlys/ThatDateOnly.IsNotBetween.Tests.cs b/Tests/aweXpect.Tests/DateOnlys/ThatDateOnly.IsNotBetween.Tests.cs new file mode 100644 index 000000000..b6352f626 --- /dev/null +++ b/Tests/aweXpect.Tests/DateOnlys/ThatDateOnly.IsNotBetween.Tests.cs @@ -0,0 +1,261 @@ +#if NET8_0_OR_GREATER +namespace aweXpect.Tests; + +public sealed partial class ThatDateOnly +{ + public sealed class IsNotBetween + { + public sealed class Tests + { + [Fact] + public async Task WhenMaximumIsNull_ShouldFail() + { + DateOnly subject = CurrentTime(); + DateOnly? minimum = subject; + DateOnly? maximum = null; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and , + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenMinimumIsNull_ShouldFail() + { + DateOnly subject = CurrentTime(); + DateOnly? minimum = null; + DateOnly? maximum = subject; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectAndMaximumAreMaxValue_ShouldFail() + { + DateOnly subject = DateOnly.MaxValue; + DateOnly minimum = CurrentTime(); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectAndMinimumAreMinValue_ShouldFail() + { + DateOnly subject = DateOnly.MinValue; + DateOnly minimum = DateOnly.MinValue; + DateOnly maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsNotBetweenMinimumAndMaximum_ShouldFail() + { + DateOnly subject = CurrentTime(); + DateOnly minimum = EarlierTime(); + DateOnly maximum = LaterTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsEarlierThanMinimum_ShouldSucceed() + { + DateOnly subject = EarlierTime(); + DateOnly minimum = CurrentTime(); + DateOnly maximum = LaterTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsLaterThanMaximum_ShouldSucceed() + { + DateOnly subject = LaterTime(); + DateOnly minimum = EarlierTime(); + DateOnly maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsSameAsMaximum_ShouldFail() + { + DateOnly subject = CurrentTime(); + DateOnly minimum = EarlierTime(); + DateOnly maximum = subject; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsSameAsMinimum_ShouldFail() + { + DateOnly subject = CurrentTime(); + DateOnly minimum = subject; + DateOnly maximum = LaterTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + } + + public sealed class WithinTests + { + [Fact] + public async Task WhenMaximumValueIsOutsideTheTolerance_ShouldSucceed() + { + DateOnly subject = CurrentTime(); + DateOnly minimum = DateOnly.MinValue; + DateOnly maximum = LaterTime(2); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenMinimumValueIsOutsideTheTolerance_ShouldSucceed() + { + DateOnly subject = CurrentTime(); + DateOnly minimum = EarlierTime(2); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenNullableMaximumValueIsOutsideTheTolerance_ShouldSucceed() + { + DateOnly subject = CurrentTime(); + DateOnly minimum = DateOnly.MinValue; + DateOnly? maximum = LaterTime(2); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenNullableMinimumValueIsOutsideTheTolerance_ShouldSucceed() + { + DateOnly subject = CurrentTime(); + DateOnly? minimum = EarlierTime(2); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenValueIsWithinTheMaximumTolerance_ShouldFail() + { + DateOnly subject = EarlierTime(3); + DateOnly minimum = DateOnly.MinValue; + DateOnly maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 3 days, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenValueIsWithinTheMinimumTolerance_ShouldFail() + { + DateOnly subject = LaterTime(3); + DateOnly minimum = CurrentTime(); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 3 days, + but it was {Formatter.Format(subject)} + """); + } + } + } +} +#endif diff --git a/Tests/aweXpect.Tests/DateOnlys/ThatDateOnly.Nullable.IsBetween.Tests.cs b/Tests/aweXpect.Tests/DateOnlys/ThatDateOnly.Nullable.IsBetween.Tests.cs new file mode 100644 index 000000000..e5294518e --- /dev/null +++ b/Tests/aweXpect.Tests/DateOnlys/ThatDateOnly.Nullable.IsBetween.Tests.cs @@ -0,0 +1,259 @@ +#if NET8_0_OR_GREATER +namespace aweXpect.Tests; + +public sealed partial class ThatDateOnly +{ + public sealed partial class Nullable + { + public sealed class IsBetween + { + public sealed class Tests + { + [Fact] + public async Task WhenMaximumIsNull_ShouldFail() + { + DateOnly? subject = CurrentTime(); + DateOnly? minimum = subject; + DateOnly? maximum = null; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and , + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenMinimumIsNull_ShouldFail() + { + DateOnly? subject = CurrentTime(); + DateOnly? minimum = null; + DateOnly? maximum = subject; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectAndMaximumAreMaxValue_ShouldSucceed() + { + DateOnly? subject = DateOnly.MaxValue; + DateOnly? minimum = CurrentTime(); + DateOnly? maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectAndMinimumAreMinValue_ShouldSucceed() + { + DateOnly? subject = DateOnly.MinValue; + DateOnly? minimum = DateOnly.MinValue; + DateOnly? maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsBetweenMinimumAndMaximum_ShouldSucceed() + { + DateOnly? subject = CurrentTime(); + DateOnly? minimum = EarlierTime(); + DateOnly? maximum = LaterTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsEarlierThanMinimum_ShouldFail() + { + DateOnly? subject = EarlierTime(); + DateOnly? minimum = CurrentTime(); + DateOnly? maximum = LaterTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsLaterThanMaximum_ShouldFail() + { + DateOnly? subject = LaterTime(); + DateOnly? minimum = EarlierTime(); + DateOnly? maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsSameAsMaximum_ShouldSucceed() + { + DateOnly? subject = CurrentTime(); + DateOnly? minimum = EarlierTime(); + DateOnly? maximum = subject; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsSameAsMinimum_ShouldSucceed() + { + DateOnly? subject = CurrentTime(); + DateOnly? minimum = subject; + DateOnly? maximum = LaterTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + } + + public sealed class WithinTests + { + [Fact] + public async Task WhenMaximumValueIsOutsideTheTolerance_ShouldFail() + { + DateOnly? subject = LaterTime(4); + DateOnly minimum = DateOnly.MinValue; + DateOnly? maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 3 days, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenMinimumValueIsOutsideTheTolerance_ShouldFail() + { + DateOnly? subject = EarlierTime(4); + DateOnly? minimum = CurrentTime(); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 3 days, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenNullableMaximumValueIsOutsideTheTolerance_ShouldFail() + { + DateOnly? subject = CurrentTime(); + DateOnly minimum = DateOnly.MinValue; + DateOnly? maximum = LaterTime(-4); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 3 days, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenNullableMinimumValueIsOutsideTheTolerance_ShouldFail() + { + DateOnly? subject = CurrentTime(); + DateOnly? minimum = EarlierTime(-4); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 3 days, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenValueIsWithinTheMaximumTolerance_ShouldSucceed() + { + DateOnly? subject = LaterTime(3); + DateOnly minimum = DateOnly.MinValue; + DateOnly? maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenValueIsWithinTheMinimumTolerance_ShouldSucceed() + { + DateOnly? subject = EarlierTime(3); + DateOnly? minimum = CurrentTime(); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).DoesNotThrow(); + } + } + } + } +} +#endif diff --git a/Tests/aweXpect.Tests/DateOnlys/ThatDateOnly.Nullable.IsNotBetween.Tests.cs b/Tests/aweXpect.Tests/DateOnlys/ThatDateOnly.Nullable.IsNotBetween.Tests.cs new file mode 100644 index 000000000..98408a83c --- /dev/null +++ b/Tests/aweXpect.Tests/DateOnlys/ThatDateOnly.Nullable.IsNotBetween.Tests.cs @@ -0,0 +1,264 @@ +#if NET8_0_OR_GREATER +namespace aweXpect.Tests; + +public sealed partial class ThatDateOnly +{ + public sealed partial class Nullable + { + public sealed class IsNotBetween + { + public sealed class Tests + { + [Fact] + public async Task WhenMaximumIsNull_ShouldFail() + { + DateOnly? subject = CurrentTime(); + DateOnly? minimum = subject; + DateOnly? maximum = null; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and , + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenMinimumIsNull_ShouldFail() + { + DateOnly? subject = CurrentTime(); + DateOnly? minimum = null; + DateOnly? maximum = subject; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectAndMaximumAreMaxValue_ShouldFail() + { + DateOnly? subject = DateOnly.MaxValue; + DateOnly? minimum = CurrentTime(); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectAndMinimumAreMinValue_ShouldFail() + { + DateOnly? subject = DateOnly.MinValue; + DateOnly minimum = DateOnly.MinValue; + DateOnly? maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsEarlierThanMinimum_ShouldSucceed() + { + DateOnly? subject = EarlierTime(); + DateOnly? minimum = CurrentTime(); + DateOnly? maximum = LaterTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsLaterThanMaximum_ShouldSucceed() + { + DateOnly? subject = LaterTime(); + DateOnly? minimum = EarlierTime(); + DateOnly? maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsNotBetweenMinimumAndMaximum_ShouldFail() + { + DateOnly? subject = CurrentTime(); + DateOnly? minimum = EarlierTime(); + DateOnly? maximum = LaterTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsSameAsMaximum_ShouldFail() + { + DateOnly? subject = CurrentTime(); + DateOnly? minimum = EarlierTime(); + DateOnly? maximum = subject; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsSameAsMinimum_ShouldFail() + { + DateOnly? subject = CurrentTime(); + DateOnly? minimum = subject; + DateOnly? maximum = LaterTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + } + + public sealed class WithinTests + { + [Fact] + public async Task WhenMaximumValueIsOutsideTheTolerance_ShouldSucceed() + { + DateOnly? subject = CurrentTime(); + DateOnly minimum = DateOnly.MinValue; + DateOnly? maximum = LaterTime(2); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenMinimumValueIsOutsideTheTolerance_ShouldSucceed() + { + DateOnly? subject = CurrentTime(); + DateOnly? minimum = EarlierTime(2); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenNullableMaximumValueIsOutsideTheTolerance_ShouldSucceed() + { + DateOnly? subject = CurrentTime(); + DateOnly minimum = DateOnly.MinValue; + DateOnly? maximum = LaterTime(2); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenNullableMinimumValueIsOutsideTheTolerance_ShouldSucceed() + { + DateOnly? subject = CurrentTime(); + DateOnly? minimum = EarlierTime(2); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenValueIsWithinTheMaximumTolerance_ShouldFail() + { + DateOnly? subject = EarlierTime(3); + DateOnly minimum = DateOnly.MinValue; + DateOnly? maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 3 days, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenValueIsWithinTheMinimumTolerance_ShouldFail() + { + DateOnly? subject = LaterTime(3); + DateOnly? minimum = CurrentTime(); + DateOnly maximum = DateOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Days()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 3 days, + but it was {Formatter.Format(subject)} + """); + } + } + } + } +} +#endif diff --git a/Tests/aweXpect.Tests/TimeOnlys/ThatTimeOnly.IsBetween.Tests.cs b/Tests/aweXpect.Tests/TimeOnlys/ThatTimeOnly.IsBetween.Tests.cs new file mode 100644 index 000000000..53a3691c4 --- /dev/null +++ b/Tests/aweXpect.Tests/TimeOnlys/ThatTimeOnly.IsBetween.Tests.cs @@ -0,0 +1,256 @@ +#if NET8_0_OR_GREATER +namespace aweXpect.Tests; + +public sealed partial class ThatTimeOnly +{ + public sealed class IsBetween + { + public sealed class Tests + { + [Fact] + public async Task WhenMaximumIsNull_ShouldFail() + { + TimeOnly subject = CurrentTime(); + TimeOnly? minimum = subject; + TimeOnly? maximum = null; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and , + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenMinimumIsNull_ShouldFail() + { + TimeOnly subject = CurrentTime(); + TimeOnly? minimum = null; + TimeOnly? maximum = subject; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectAndMaximumAreMaxValue_ShouldSucceed() + { + TimeOnly subject = TimeOnly.MaxValue; + TimeOnly minimum = CurrentTime(); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectAndMinimumAreMinValue_ShouldSucceed() + { + TimeOnly subject = TimeOnly.MinValue; + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsBetweenMinimumAndMaximum_ShouldSucceed() + { + TimeOnly subject = CurrentTime(); + TimeOnly minimum = EarlierTime(); + TimeOnly maximum = LaterTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsEarlierThanMinimum_ShouldFail() + { + TimeOnly subject = EarlierTime(); + TimeOnly minimum = CurrentTime(); + TimeOnly maximum = LaterTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsLaterThanMaximum_ShouldFail() + { + TimeOnly subject = LaterTime(); + TimeOnly minimum = EarlierTime(); + TimeOnly maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsSameAsMaximum_ShouldSucceed() + { + TimeOnly subject = CurrentTime(); + TimeOnly minimum = EarlierTime(); + TimeOnly maximum = subject; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsSameAsMinimum_ShouldSucceed() + { + TimeOnly subject = CurrentTime(); + TimeOnly minimum = subject; + TimeOnly maximum = LaterTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + } + + public sealed class WithinTests + { + [Fact] + public async Task WhenMaximumValueIsOutsideTheTolerance_ShouldFail() + { + TimeOnly subject = LaterTime(4); + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 0:03, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenMinimumValueIsOutsideTheTolerance_ShouldFail() + { + TimeOnly subject = EarlierTime(4); + TimeOnly minimum = CurrentTime(); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 0:03, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenNullableMaximumValueIsOutsideTheTolerance_ShouldFail() + { + TimeOnly subject = CurrentTime(); + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly? maximum = LaterTime(-4); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 0:03, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenNullableMinimumValueIsOutsideTheTolerance_ShouldFail() + { + TimeOnly subject = CurrentTime(); + TimeOnly? minimum = EarlierTime(-4); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 0:03, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenValueIsWithinTheMaximumTolerance_ShouldSucceed() + { + TimeOnly subject = LaterTime(3); + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenValueIsWithinTheMinimumTolerance_ShouldSucceed() + { + TimeOnly subject = EarlierTime(3); + TimeOnly minimum = CurrentTime(); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).DoesNotThrow(); + } + } + } +} +#endif diff --git a/Tests/aweXpect.Tests/TimeOnlys/ThatTimeOnly.IsNotBetween.Tests.cs b/Tests/aweXpect.Tests/TimeOnlys/ThatTimeOnly.IsNotBetween.Tests.cs new file mode 100644 index 000000000..3995a0ec8 --- /dev/null +++ b/Tests/aweXpect.Tests/TimeOnlys/ThatTimeOnly.IsNotBetween.Tests.cs @@ -0,0 +1,261 @@ +#if NET8_0_OR_GREATER +namespace aweXpect.Tests; + +public sealed partial class ThatTimeOnly +{ + public sealed class IsNotBetween + { + public sealed class Tests + { + [Fact] + public async Task WhenMaximumIsNull_ShouldFail() + { + TimeOnly subject = CurrentTime(); + TimeOnly? minimum = subject; + TimeOnly? maximum = null; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and , + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenMinimumIsNull_ShouldFail() + { + TimeOnly subject = CurrentTime(); + TimeOnly? minimum = null; + TimeOnly? maximum = subject; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectAndMaximumAreMaxValue_ShouldFail() + { + TimeOnly subject = TimeOnly.MaxValue; + TimeOnly minimum = CurrentTime(); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectAndMinimumAreMinValue_ShouldFail() + { + TimeOnly subject = TimeOnly.MinValue; + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsNotBetweenMinimumAndMaximum_ShouldFail() + { + TimeOnly subject = CurrentTime(); + TimeOnly minimum = EarlierTime(); + TimeOnly maximum = LaterTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsEarlierThanMinimum_ShouldSucceed() + { + TimeOnly subject = EarlierTime(); + TimeOnly minimum = CurrentTime(); + TimeOnly maximum = LaterTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsLaterThanMaximum_ShouldSucceed() + { + TimeOnly subject = LaterTime(); + TimeOnly minimum = EarlierTime(); + TimeOnly maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsSameAsMaximum_ShouldFail() + { + TimeOnly subject = CurrentTime(); + TimeOnly minimum = EarlierTime(); + TimeOnly maximum = subject; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsSameAsMinimum_ShouldFail() + { + TimeOnly subject = CurrentTime(); + TimeOnly minimum = subject; + TimeOnly maximum = LaterTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + } + + public sealed class WithinTests + { + [Fact] + public async Task WhenMaximumValueIsOutsideTheTolerance_ShouldSucceed() + { + TimeOnly subject = CurrentTime(); + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly maximum = LaterTime(2); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenMinimumValueIsOutsideTheTolerance_ShouldSucceed() + { + TimeOnly subject = CurrentTime(); + TimeOnly minimum = EarlierTime(2); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenNullableMaximumValueIsOutsideTheTolerance_ShouldSucceed() + { + TimeOnly subject = CurrentTime(); + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly? maximum = LaterTime(2); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenNullableMinimumValueIsOutsideTheTolerance_ShouldSucceed() + { + TimeOnly subject = CurrentTime(); + TimeOnly? minimum = EarlierTime(2); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenValueIsWithinTheMaximumTolerance_ShouldFail() + { + TimeOnly subject = EarlierTime(3); + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 0:03, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenValueIsWithinTheMinimumTolerance_ShouldFail() + { + TimeOnly subject = LaterTime(3); + TimeOnly minimum = CurrentTime(); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 0:03, + but it was {Formatter.Format(subject)} + """); + } + } + } +} +#endif diff --git a/Tests/aweXpect.Tests/TimeOnlys/ThatTimeOnly.Nullable.IsBetween.Tests.cs b/Tests/aweXpect.Tests/TimeOnlys/ThatTimeOnly.Nullable.IsBetween.Tests.cs new file mode 100644 index 000000000..f31de2908 --- /dev/null +++ b/Tests/aweXpect.Tests/TimeOnlys/ThatTimeOnly.Nullable.IsBetween.Tests.cs @@ -0,0 +1,259 @@ +#if NET8_0_OR_GREATER +namespace aweXpect.Tests; + +public sealed partial class ThatTimeOnly +{ + public sealed partial class Nullable + { + public sealed class IsBetween + { + public sealed class Tests + { + [Fact] + public async Task WhenMaximumIsNull_ShouldFail() + { + TimeOnly? subject = CurrentTime(); + TimeOnly? minimum = subject; + TimeOnly? maximum = null; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and , + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenMinimumIsNull_ShouldFail() + { + TimeOnly? subject = CurrentTime(); + TimeOnly? minimum = null; + TimeOnly? maximum = subject; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectAndMaximumAreMaxValue_ShouldSucceed() + { + TimeOnly? subject = TimeOnly.MaxValue; + TimeOnly? minimum = CurrentTime(); + TimeOnly? maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectAndMinimumAreMinValue_ShouldSucceed() + { + TimeOnly? subject = TimeOnly.MinValue; + TimeOnly? minimum = TimeOnly.MinValue; + TimeOnly? maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsBetweenMinimumAndMaximum_ShouldSucceed() + { + TimeOnly? subject = CurrentTime(); + TimeOnly? minimum = EarlierTime(); + TimeOnly? maximum = LaterTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsEarlierThanMinimum_ShouldFail() + { + TimeOnly? subject = EarlierTime(); + TimeOnly? minimum = CurrentTime(); + TimeOnly? maximum = LaterTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsLaterThanMaximum_ShouldFail() + { + TimeOnly? subject = LaterTime(); + TimeOnly? minimum = EarlierTime(); + TimeOnly? maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsSameAsMaximum_ShouldSucceed() + { + TimeOnly? subject = CurrentTime(); + TimeOnly? minimum = EarlierTime(); + TimeOnly? maximum = subject; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsSameAsMinimum_ShouldSucceed() + { + TimeOnly? subject = CurrentTime(); + TimeOnly? minimum = subject; + TimeOnly? maximum = LaterTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + } + + public sealed class WithinTests + { + [Fact] + public async Task WhenMaximumValueIsOutsideTheTolerance_ShouldFail() + { + TimeOnly? subject = LaterTime(4); + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly? maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 0:03, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenMinimumValueIsOutsideTheTolerance_ShouldFail() + { + TimeOnly? subject = EarlierTime(4); + TimeOnly? minimum = CurrentTime(); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 0:03, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenNullableMaximumValueIsOutsideTheTolerance_ShouldFail() + { + TimeOnly? subject = CurrentTime(); + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly? maximum = LaterTime(-4); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 0:03, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenNullableMinimumValueIsOutsideTheTolerance_ShouldFail() + { + TimeOnly? subject = CurrentTime(); + TimeOnly? minimum = EarlierTime(-4); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 0:03, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenValueIsWithinTheMaximumTolerance_ShouldSucceed() + { + TimeOnly? subject = LaterTime(3); + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly? maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenValueIsWithinTheMinimumTolerance_ShouldSucceed() + { + TimeOnly? subject = EarlierTime(3); + TimeOnly? minimum = CurrentTime(); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).DoesNotThrow(); + } + } + } + } +} +#endif diff --git a/Tests/aweXpect.Tests/TimeOnlys/ThatTimeOnly.Nullable.IsNotBetween.Tests.cs b/Tests/aweXpect.Tests/TimeOnlys/ThatTimeOnly.Nullable.IsNotBetween.Tests.cs new file mode 100644 index 000000000..608fff743 --- /dev/null +++ b/Tests/aweXpect.Tests/TimeOnlys/ThatTimeOnly.Nullable.IsNotBetween.Tests.cs @@ -0,0 +1,264 @@ +#if NET8_0_OR_GREATER +namespace aweXpect.Tests; + +public sealed partial class ThatTimeOnly +{ + public sealed partial class Nullable + { + public sealed class IsNotBetween + { + public sealed class Tests + { + [Fact] + public async Task WhenMaximumIsNull_ShouldFail() + { + TimeOnly? subject = CurrentTime(); + TimeOnly? minimum = subject; + TimeOnly? maximum = null; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and , + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenMinimumIsNull_ShouldFail() + { + TimeOnly? subject = CurrentTime(); + TimeOnly? minimum = null; + TimeOnly? maximum = subject; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectAndMaximumAreMaxValue_ShouldFail() + { + TimeOnly? subject = TimeOnly.MaxValue; + TimeOnly? minimum = CurrentTime(); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectAndMinimumAreMinValue_ShouldFail() + { + TimeOnly? subject = TimeOnly.MinValue; + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly? maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsEarlierThanMinimum_ShouldSucceed() + { + TimeOnly? subject = EarlierTime(); + TimeOnly? minimum = CurrentTime(); + TimeOnly? maximum = LaterTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsLaterThanMaximum_ShouldSucceed() + { + TimeOnly? subject = LaterTime(); + TimeOnly? minimum = EarlierTime(); + TimeOnly? maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenSubjectIsNotBetweenMinimumAndMaximum_ShouldFail() + { + TimeOnly? subject = CurrentTime(); + TimeOnly? minimum = EarlierTime(); + TimeOnly? maximum = LaterTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsSameAsMaximum_ShouldFail() + { + TimeOnly? subject = CurrentTime(); + TimeOnly? minimum = EarlierTime(); + TimeOnly? maximum = subject; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenSubjectIsSameAsMinimum_ShouldFail() + { + TimeOnly? subject = CurrentTime(); + TimeOnly? minimum = subject; + TimeOnly? maximum = LaterTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)}, + but it was {Formatter.Format(subject)} + """); + } + } + + public sealed class WithinTests + { + [Fact] + public async Task WhenMaximumValueIsOutsideTheTolerance_ShouldSucceed() + { + TimeOnly? subject = CurrentTime(); + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly? maximum = LaterTime(2); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenMinimumValueIsOutsideTheTolerance_ShouldSucceed() + { + TimeOnly? subject = CurrentTime(); + TimeOnly? minimum = EarlierTime(2); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenNullableMaximumValueIsOutsideTheTolerance_ShouldSucceed() + { + TimeOnly? subject = CurrentTime(); + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly? maximum = LaterTime(2); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenNullableMinimumValueIsOutsideTheTolerance_ShouldSucceed() + { + TimeOnly? subject = CurrentTime(); + TimeOnly? minimum = EarlierTime(2); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenValueIsWithinTheMaximumTolerance_ShouldFail() + { + TimeOnly? subject = EarlierTime(3); + TimeOnly minimum = TimeOnly.MinValue; + TimeOnly? maximum = CurrentTime(); + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 0:03, + but it was {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenValueIsWithinTheMinimumTolerance_ShouldFail() + { + TimeOnly? subject = LaterTime(3); + TimeOnly? minimum = CurrentTime(); + TimeOnly maximum = TimeOnly.MaxValue; + + async Task Act() + => await That(subject).IsNotBetween(minimum).And(maximum) + .Within(3.Seconds()); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + is not between {Formatter.Format(minimum)} and {Formatter.Format(maximum)} ± 0:03, + but it was {Formatter.Format(subject)} + """); + } + } + } + } +} +#endif