Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 19 additions & 17 deletions Src/FluentAssertions/Primitives/DateTimeOffsetRangeAssertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,13 @@ public AndConstraint<TAssertions> Before(DateTimeOffset target, string because =
{
TimeSpan actual = target - subject.Value;

if (!predicate.IsMatchedBy(actual, timeSpan))
{
Execute.Assertion
.BecauseOf(because, becauseArgs)
.FailWith(
"Expected {context:the date and time} to be " + predicate.DisplayText +
" {1} before {2}{reason}, but {0} differs {3}.", subject, timeSpan, target, actual);
}
Execute.Assertion
.ForCondition(predicate.IsMatchedBy(actual, timeSpan))
.BecauseOf(because, becauseArgs)
.FailWith(
"Expected {context:the date and time} {0} to be " + predicate.DisplayText +
" {1} before {2}{reason}, but it is " + PositionRelativeToTarget(subject.Value, target) + " by {3}.",
subject, timeSpan, target, actual.Duration());
}

return new AndConstraint<TAssertions>(parentAssertions);
Expand Down Expand Up @@ -112,18 +111,21 @@ public AndConstraint<TAssertions> After(DateTimeOffset target, string because =
{
TimeSpan actual = subject.Value - target;

if (!predicate.IsMatchedBy(actual, timeSpan))
{
Execute.Assertion
.BecauseOf(because, becauseArgs)
.FailWith(
"Expected {context:the date and time} to be " + predicate.DisplayText +
" {0} after {1}{reason}, but {2} differs {3}.",
timeSpan, target, subject, actual);
}
Execute.Assertion
.ForCondition(predicate.IsMatchedBy(actual, timeSpan))
.BecauseOf(because, becauseArgs)
.FailWith(
"Expected {context:the date and time} {0} to be " + predicate.DisplayText +
" {1} after {2}{reason}, but it is " + PositionRelativeToTarget(subject.Value, target) + " by {3}.",
subject, timeSpan, target, actual.Duration());
}

return new AndConstraint<TAssertions>(parentAssertions);
}

private static string PositionRelativeToTarget(DateTimeOffset actual, DateTimeOffset target)
{
return actual - target >= TimeSpan.Zero ? "ahead" : "behind";
}
}
}
37 changes: 19 additions & 18 deletions Src/FluentAssertions/Primitives/DateTimeRangeAssertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,13 @@ public AndConstraint<TAssertions> Before(DateTime target, string because = "",
{
TimeSpan actual = target - subject.Value;

if (!predicate.IsMatchedBy(actual, timeSpan))
{
Execute.Assertion
.BecauseOf(because, becauseArgs)
.FailWith(
"Expected date and/or time {0} to be " + predicate.DisplayText +
" {1} before {2}{reason}, but it differs {3}.",
subject, timeSpan, target, actual);
}
Execute.Assertion
.ForCondition(predicate.IsMatchedBy(actual, timeSpan))
.BecauseOf(because, becauseArgs)
.FailWith(
"Expected {context:the date and time} {0} to be " + predicate.DisplayText +
" {1} before {2}{reason}, but it is " + PositionRelativeToTarget(subject.Value, target) + " by {3}.",
subject, timeSpan, target, actual.Duration());
}

return new AndConstraint<TAssertions>(parentAssertions);
Expand Down Expand Up @@ -116,18 +114,21 @@ public AndConstraint<TAssertions> After(DateTime target, string because = "",
{
TimeSpan actual = subject.Value - target;

if (!predicate.IsMatchedBy(actual, timeSpan))
{
Execute.Assertion
.BecauseOf(because, becauseArgs)
.FailWith(
"Expected date and/or time {0} to be " + predicate.DisplayText +
" {1} after {2}{reason}, but it differs {3}.",
subject, timeSpan, target, actual);
}
Execute.Assertion
.ForCondition(predicate.IsMatchedBy(actual, timeSpan))
.BecauseOf(because, becauseArgs)
.FailWith(
"Expected {context:the date and time} {0} to be " + predicate.DisplayText +
" {1} after {2}{reason}, but it is " + PositionRelativeToTarget(subject.Value, target) + " by {3}.",
subject, timeSpan, target, actual.Duration());
}

return new AndConstraint<TAssertions>(parentAssertions);
}

private static string PositionRelativeToTarget(DateTime actual, DateTime target)
{
return actual - target >= TimeSpan.Zero ? "ahead" : "behind";
}
}
}
2 changes: 1 addition & 1 deletion Src/FluentAssertions/Primitives/TimeSpanPredicate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public TimeSpanPredicate(Func<TimeSpan, TimeSpan, bool> lambda, string displayTe

public bool IsMatchedBy(TimeSpan actual, TimeSpan expected)
{
return lambda(actual, expected);
return lambda(actual, expected) && actual >= TimeSpan.Zero;
}
}
}
168 changes: 163 additions & 5 deletions Tests/FluentAssertions.Specs/Primitives/DateTimeAssertionSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1750,7 +1750,7 @@ public void When_date_is_not_more_than_the_required_one_day_before_another_it_sh

// Assert
act.Should().Throw<XunitException>().WithMessage(
"Expected date and/or time <2009-10-01> to be more than 1d before <2009-10-02> because we like that, but it differs 1d.");
"Expected subject <2009-10-01> to be more than 1d before <2009-10-02> because we like that, but it is behind by 1d.");
}

[Fact]
Expand All @@ -1776,7 +1776,7 @@ public void When_date_is_not_at_least_one_day_before_another_it_should_throw()

// Assert
act.Should().Throw<XunitException>().WithMessage(
"Expected date and/or time <2009-10-01 01:00:00> to be at least 1d before <2009-10-02> because we like that, but it differs 23h.");
"Expected subject <2009-10-01 01:00:00> to be at least 1d before <2009-10-02> because we like that, but it is behind by 23h.");
}

[Fact]
Expand All @@ -1803,7 +1803,7 @@ public void When_time_is_not_at_exactly_20_minutes_before_another_time_it_should

// Assert
act.Should().Throw<XunitException>().WithMessage(
"Expected date and/or time <12:36:00> to be exactly 20m before <12:55:00> because 20 minutes is enough, but it differs 19m.");
"Expected subject <12:36:00> to be exactly 20m before <12:55:00> because 20 minutes is enough, but it is behind by 19m.");
}

[Fact]
Expand All @@ -1830,7 +1830,7 @@ public void When_date_is_not_within_50_hours_before_another_date_it_should_throw

// Assert
act.Should().Throw<XunitException>().WithMessage(
"Expected date and/or time <2010-04-08 09:59:59> to be within 2d and 2h before <2010-04-10 12:00:00> because 50 hours is enough, but it differs 2d, 2h and 1s.");
"Expected subject <2010-04-08 09:59:59> to be within 2d and 2h before <2010-04-10 12:00:00> because 50 hours is enough, but it is behind by 2d, 2h and 1s.");
}

[Fact]
Expand Down Expand Up @@ -1888,7 +1888,7 @@ public void When_time_is_not_less_than_30s_after_another_time_it_should_throw()

// Assert
act.Should().Throw<XunitException>().WithMessage(
"Expected date and/or time <12:01:00> to be less than 30s after <12:00:30> because 30s is the max, but it differs 30s.");
"Expected subject <12:01:00> to be less than 30s after <12:00:30> because 30s is the max, but it is ahead by 30s.");
}

[Fact]
Expand All @@ -1902,6 +1902,164 @@ public void When_time_is_less_than_30s_after_another_time_it_should_not_throw()
subject.Should().BeLessThan(TimeSpan.FromSeconds(30)).After(target);
}

[Fact]
public void When_asserting_subject_be_more_than_10_seconds_after_target_but_subject_is_before_target_it_should_throw()
{
// Arrange
var expectation = 1.January(0001).At(0, 0, 30);
var subject = 1.January(0001).At(0, 0, 15);

// Act
Action action = () => subject.Should().BeMoreThan(10.Seconds()).After(expectation);

// Assert
action.Should().Throw<XunitException>()
.WithMessage("Expected subject <00:00:15> to be more than 10s after <00:00:30>, but it is behind by 15s.");
}

[Theory]
[InlineData(30, 20)] // edge case
[InlineData(30, 15)]
public void When_asserting_subject_be_at_least_10_seconds_after_target_but_subject_is_before_target_it_should_throw(int targetSeconds, int subjectSeconds)
{
// Arrange
var expectation = 1.January(0001).At(0, 0, targetSeconds);
var subject = 1.January(0001).At(0, 0, subjectSeconds);

// Act
Action action = () => subject.Should().BeAtLeast(10.Seconds()).After(expectation);

// Assert
action.Should().Throw<XunitException>()
.WithMessage($"Expected subject <00:00:{subjectSeconds}> to be at least 10s after <00:00:30>, but it is behind by {Math.Abs(subjectSeconds - targetSeconds)}s.");
}

[Fact]
public void When_asserting_subject_be_exactly_10_seconds_after_target_but_subject_is_before_target_it_should_throw()
{
// Arrange
var expectation = 1.January(0001).At(0, 0, 30);
var subject = 1.January(0001).At(0, 0, 20);

// Ac
Action action = () => subject.Should().BeExactly(10.Seconds()).After(expectation);

// Assert
action.Should().Throw<XunitException>()
.WithMessage("Expected subject <00:00:20> to be exactly 10s after <00:00:30>, but it is behind by 10s.");
}

[Theory]
[InlineData(30, 20)] // edge case
[InlineData(30, 25)]
public void When_asserting_subject_be_within_10_seconds_after_target_but_subject_is_before_target_it_should_throw(int targetSeconds, int subjectSeconds)
{
// Arrange
var expectation = 1.January(0001).At(0, 0, targetSeconds);
var subject = 1.January(0001).At(0, 0, subjectSeconds);

// Act
Action action = () => subject.Should().BeWithin(10.Seconds()).After(expectation);

// Assert
action.Should().Throw<XunitException>()
.WithMessage($"Expected subject <00:00:{subjectSeconds}> to be within 10s after <00:00:30>, but it is behind by {Math.Abs(subjectSeconds - targetSeconds)}s.");
}

[Fact]
public void When_asserting_subject_be_less_than_10_seconds_after_target_but_subject_is_before_target_it_should_throw()
{
// Arrange
var expectation = 1.January(0001).At(0, 0, 30);
var subject = 1.January(0001).At(0, 0, 25);

// Act
Action action = () => subject.Should().BeLessThan(10.Seconds()).After(expectation);

// Assert
action.Should().Throw<XunitException>()
.WithMessage("Expected subject <00:00:25> to be less than 10s after <00:00:30>, but it is behind by 5s.");
}

[Fact]
public void When_asserting_subject_be_more_than_10_seconds_before_target_but_subject_is_after_target_it_should_throw()
{
// Arrange
var expectation = 1.January(0001).At(0, 0, 30);
var subject = 1.January(0001).At(0, 0, 45);

// Act
Action action = () => subject.Should().BeMoreThan(10.Seconds()).Before(expectation);

// Assert
action.Should().Throw<XunitException>()
.WithMessage("Expected subject <00:00:45> to be more than 10s before <00:00:30>, but it is ahead by 15s.");
}

[Theory]
[InlineData(30, 40)] // edge case
[InlineData(30, 45)]
public void When_asserting_subject_be_at_least_10_seconds_before_target_but_subject_is_after_target_it_should_throw(int targetSeconds, int subjectSeconds)
{
// Arrange
var expectation = 1.January(0001).At(0, 0, targetSeconds);
var subject = 1.January(0001).At(0, 0, subjectSeconds);

// Act
Action action = () => subject.Should().BeAtLeast(10.Seconds()).Before(expectation);

// Assert
action.Should().Throw<XunitException>()
.WithMessage($"Expected subject <00:00:{subjectSeconds}> to be at least 10s before <00:00:30>, but it is ahead by {Math.Abs(subjectSeconds - targetSeconds)}s.");
}

[Fact]
public void When_asserting_subject_be_exactly_10_seconds_before_target_but_subject_is_after_target_it_should_throw()
{
// Arrange
var expectation = 1.January(0001).At(0, 0, 30);
var subject = 1.January(0001).At(0, 0, 40);

// Act
Action action = () => subject.Should().BeExactly(10.Seconds()).Before(expectation);

// Assert
action.Should().Throw<XunitException>()
.WithMessage("Expected subject <00:00:40> to be exactly 10s before <00:00:30>, but it is ahead by 10s.");
}

[Theory]
[InlineData(30, 40)] // edge case
[InlineData(30, 35)]
public void When_asserting_subject_be_within_10_seconds_before_target_but_subject_is_after_target_it_should_throw(int targetSeconds, int subjectSeconds)
{
// Arrange
var expectation = 1.January(0001).At(0, 0, targetSeconds);
var subject = 1.January(0001).At(0, 0, subjectSeconds);

// Act
Action action = () => subject.Should().BeWithin(10.Seconds()).Before(expectation);

// Assert
action.Should().Throw<XunitException>()
.WithMessage($"Expected subject <00:00:{subjectSeconds}> to be within 10s before <00:00:30>, but it is ahead by {Math.Abs(subjectSeconds - targetSeconds)}s.");
}

[Fact]
public void When_asserting_subject_be_less_than_10_seconds_before_target_but_subject_is_after_target_it_should_throw()
{
// Arrange
var expectation = 1.January(0001).At(0, 0, 30);
var subject = 1.January(0001).At(0, 0, 45);

// Act
Action action = () => subject.Should().BeLessThan(10.Seconds()).Before(expectation);

// Assert
action.Should().Throw<XunitException>()
.WithMessage("Expected subject <00:00:45> to be less than 10s before <00:00:30>, but it is ahead by 15s.");
}

#endregion

[Fact]
Expand Down
Loading