Skip to content

Commit

Permalink
Adding support for .NET6 DateOnly struct (#1844)
Browse files Browse the repository at this point in the history
  • Loading branch information
iliashkolyar committed Mar 13, 2022
1 parent f7d85f4 commit 1349525
Show file tree
Hide file tree
Showing 8 changed files with 1,529 additions and 0 deletions.
36 changes: 36 additions & 0 deletions Src/FluentAssertions/AssertionExtensions.cs
Expand Up @@ -434,6 +434,30 @@ public static NullableDateTimeOffsetAssertions Should(this DateTimeOffset? actua
return new NullableDateTimeOffsetAssertions(actualValue);
}

#if NET6_0_OR_GREATER

/// <summary>
/// Returns an <see cref="DateOnlyAssertions"/> object that can be used to assert the
/// current <see cref="DateOnly"/>.
/// </summary>
[Pure]
public static DateOnlyAssertions Should(this DateOnly actualValue)
{
return new DateOnlyAssertions(actualValue);
}

/// <summary>
/// Returns an <see cref="NullableDateOnlyAssertions"/> object that can be used to assert the
/// current nullable <see cref="DateOnly"/>.
/// </summary>
[Pure]
public static NullableDateOnlyAssertions Should(this DateOnly? actualValue)
{
return new NullableDateOnlyAssertions(actualValue);
}

#endif

/// <summary>
/// Returns an <see cref="ComparableTypeAssertions{T}"/> object that can be used to assert the
/// current <see cref="IComparable{T}"/>.
Expand Down Expand Up @@ -892,6 +916,18 @@ public static void Should<TAssertions>(this DateTimeOffsetAssertions<TAssertions
InvalidShouldCall();
}

#if NET6_0_OR_GREATER

/// <inheritdoc cref="Should(ExecutionTimeAssertions)" />
[Obsolete("You are asserting the 'AndConstraint' itself. Remove the 'Should()' method directly following 'And'", error: true)]
public static void Should<TAssertions>(this DateOnlyAssertions<TAssertions> _)
where TAssertions : DateOnlyAssertions<TAssertions>
{
InvalidShouldCall();
}

#endif

/// <summary>
/// You are asserting the <see cref="AndConstraint{T}"/> itself. Remove the <c>Should()</c> method directly following <c>And</c>.
/// </summary>
Expand Down
30 changes: 30 additions & 0 deletions Src/FluentAssertions/Formatting/DateOnlyValueFormatter.cs
@@ -0,0 +1,30 @@
using System;
using System.Globalization;

#if NET6_0_OR_GREATER

namespace FluentAssertions.Formatting
{
public class DateOnlyValueFormatter : IValueFormatter
{
/// <summary>
/// Indicates whether the current <see cref="IValueFormatter"/> can handle the specified <paramref name="value"/>.
/// </summary>
/// <param name="value">The value for which to create a <see cref="string"/>.</param>
/// <returns>
/// <c>true</c> if the current <see cref="IValueFormatter"/> can handle the specified value; otherwise, <c>false</c>.
/// </returns>
public bool CanHandle(object value)
{
return value is DateOnly;
}

public void Format(object value, FormattedObjectGraph formattedGraph, FormattingContext context, FormatChild formatChild)
{
var dateOnly = (DateOnly)value;
formattedGraph.AddFragment(dateOnly.ToString("<yyyy-MM-dd>", CultureInfo.InvariantCulture));
}
}
}

#endif
3 changes: 3 additions & 0 deletions Src/FluentAssertions/Formatting/Formatter.cs
Expand Up @@ -31,6 +31,9 @@ public static class Formatter
new NullValueFormatter(),
new GuidValueFormatter(),
new DateTimeOffsetValueFormatter(),
#if NET6_0_OR_GREATER
new DateOnlyValueFormatter(),
#endif
new TimeSpanValueFormatter(),
new Int32ValueFormatter(),
new Int64ValueFormatter(),
Expand Down
519 changes: 519 additions & 0 deletions Src/FluentAssertions/Primitives/DateOnlyAssertions.cs

Large diffs are not rendered by default.

105 changes: 105 additions & 0 deletions Src/FluentAssertions/Primitives/NullableDateOnlyAssertions.cs
@@ -0,0 +1,105 @@
using System;
using System.Diagnostics;
using FluentAssertions.Execution;

#if NET6_0_OR_GREATER

namespace FluentAssertions.Primitives
{
/// <summary>
/// Contains a number of methods to assert that a nullable <see cref="DateOnly"/> or
/// </summary>
[DebuggerNonUserCode]
public class NullableDateOnlyAssertions : NullableDateOnlyAssertions<NullableDateOnlyAssertions>
{
public NullableDateOnlyAssertions(DateOnly? expected)
: base(expected)
{
}
}

/// <summary>
/// Contains a number of methods to assert that a nullable <see cref="DateOnly"/> or
/// </summary>
[DebuggerNonUserCode]
public class NullableDateOnlyAssertions<TAssertions> : DateOnlyAssertions<TAssertions>
where TAssertions : NullableDateOnlyAssertions<TAssertions>
{
public NullableDateOnlyAssertions(DateOnly? expected)
: base(expected)
{
}

/// <summary>
/// Asserts that a nullable <see cref="DateOnly"/> value is not <c>null</c>.
/// </summary>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])"/> explaining why the assertion
/// is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
/// </param>
/// <param name="becauseArgs">
/// Zero or more objects to format using the placeholders in <paramref name="because" />.
/// </param>
public AndConstraint<TAssertions> HaveValue(string because = "", params object[] becauseArgs)
{
Execute.Assertion
.ForCondition(Subject.HasValue)
.BecauseOf(because, becauseArgs)
.FailWith("Expected {context:nullable date} to have a value{reason}, but found {0}.", Subject);

return new AndConstraint<TAssertions>((TAssertions)this);
}

/// <summary>
/// Asserts that a nullable <see cref="DateOnly"/> value is not <c>null</c>.
/// </summary>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])"/> explaining why the assertion
/// is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
/// </param>
/// <param name="becauseArgs">
/// Zero or more objects to format using the placeholders in <paramref name="because" />.
/// </param>
public AndConstraint<TAssertions> NotBeNull(string because = "", params object[] becauseArgs)
{
return HaveValue(because, becauseArgs);
}

/// <summary>
/// Asserts that a nullable <see cref="DateOnly"/> value is <c>null</c>.
/// </summary>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])"/> explaining why the assertion
/// is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
/// </param>
/// <param name="becauseArgs">
/// Zero or more objects to format using the placeholders in <paramref name="because" />.
/// </param>
public AndConstraint<TAssertions> NotHaveValue(string because = "", params object[] becauseArgs)
{
Execute.Assertion
.ForCondition(!Subject.HasValue)
.BecauseOf(because, becauseArgs)
.FailWith("Did not expect {context:nullable date} to have a value{reason}, but found {0}.", Subject);

return new AndConstraint<TAssertions>((TAssertions)this);
}

/// <summary>
/// Asserts that a nullable <see cref="DateOnly"/> value is <c>null</c>.
/// </summary>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])"/> explaining why the assertion
/// is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
/// </param>
/// <param name="becauseArgs">
/// Zero or more objects to format using the placeholders in <paramref name="because" />.
/// </param>
public AndConstraint<TAssertions> BeNull(string because = "", params object[] becauseArgs)
{
return NotHaveValue(because, becauseArgs);
}
}
}

#endif
Expand Up @@ -58,6 +58,8 @@ namespace FluentAssertions
public static FluentAssertions.Specialized.ActionAssertions Should(this System.Action action) { }
public static FluentAssertions.Collections.StringCollectionAssertions Should(this System.Collections.Generic.IEnumerable<string> @this) { }
public static FluentAssertions.Data.DataColumnAssertions Should(this System.Data.DataColumn actualValue) { }
public static FluentAssertions.Primitives.DateOnlyAssertions Should(this System.DateOnly actualValue) { }
public static FluentAssertions.Primitives.NullableDateOnlyAssertions Should(this System.DateOnly? actualValue) { }
public static FluentAssertions.Primitives.DateTimeAssertions Should(this System.DateTime actualValue) { }
public static FluentAssertions.Primitives.NullableDateTimeAssertions Should(this System.DateTime? actualValue) { }
public static FluentAssertions.Primitives.DateTimeOffsetAssertions Should(this System.DateTimeOffset actualValue) { }
Expand Down Expand Up @@ -110,6 +112,10 @@ namespace FluentAssertions
where TAssertions : FluentAssertions.Primitives.BooleanAssertions<TAssertions> { }
[System.Obsolete("You are asserting the \'AndConstraint\' itself. Remove the \'Should()\' method direct" +
"ly following \'And\'", true)]
public static void Should<TAssertions>(this FluentAssertions.Primitives.DateOnlyAssertions<TAssertions> _)
where TAssertions : FluentAssertions.Primitives.DateOnlyAssertions<TAssertions> { }
[System.Obsolete("You are asserting the \'AndConstraint\' itself. Remove the \'Should()\' method direct" +
"ly following \'And\'", true)]
public static void Should<TAssertions>(this FluentAssertions.Primitives.DateTimeAssertions<TAssertions> _)
where TAssertions : FluentAssertions.Primitives.DateTimeAssertions<TAssertions> { }
[System.Obsolete("You are asserting the \'AndConstraint\' itself. Remove the \'Should()\' method direct" +
Expand Down Expand Up @@ -1436,6 +1442,12 @@ namespace FluentAssertions.Formatting
public bool CanHandle(object value) { }
public void Format(object value, FluentAssertions.Formatting.FormattedObjectGraph formattedGraph, FluentAssertions.Formatting.FormattingContext context, FluentAssertions.Formatting.FormatChild formatChild) { }
}
public class DateOnlyValueFormatter : FluentAssertions.Formatting.IValueFormatter
{
public DateOnlyValueFormatter() { }
public bool CanHandle(object value) { }
public void Format(object value, FluentAssertions.Formatting.FormattedObjectGraph formattedGraph, FluentAssertions.Formatting.FormattingContext context, FluentAssertions.Formatting.FormatChild formatChild) { }
}
public class DateTimeOffsetValueFormatter : FluentAssertions.Formatting.IValueFormatter
{
public DateTimeOffsetValueFormatter() { }
Expand Down Expand Up @@ -1755,6 +1767,39 @@ namespace FluentAssertions.Primitives
public override bool Equals(object obj) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(bool unexpected, string because = "", params object[] becauseArgs) { }
}
public class DateOnlyAssertions : FluentAssertions.Primitives.DateOnlyAssertions<FluentAssertions.Primitives.DateOnlyAssertions>
{
public DateOnlyAssertions(System.DateOnly? value) { }
}
public class DateOnlyAssertions<TAssertions>
where TAssertions : FluentAssertions.Primitives.DateOnlyAssertions<TAssertions>
{
public DateOnlyAssertions(System.DateOnly? value) { }
public System.DateOnly? Subject { get; }
public FluentAssertions.AndConstraint<TAssertions> Be(System.DateOnly expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> Be(System.DateOnly? expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeAfter(System.DateOnly expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeBefore(System.DateOnly expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeOnOrAfter(System.DateOnly expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeOnOrBefore(System.DateOnly expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(params System.DateOnly[] validValues) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(params System.Nullable<System.DateOnly>[] validValues) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(System.Collections.Generic.IEnumerable<System.DateOnly> validValues, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(System.Collections.Generic.IEnumerable<System.DateOnly?> validValues, string because = "", params object[] becauseArgs) { }
public override bool Equals(object obj) { }
public FluentAssertions.AndConstraint<TAssertions> HaveDay(int expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> HaveMonth(int expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> HaveYear(int expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(System.DateOnly unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(System.DateOnly? unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBeAfter(System.DateOnly unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBeBefore(System.DateOnly unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBeOnOrAfter(System.DateOnly unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBeOnOrBefore(System.DateOnly unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveDay(int unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveMonth(int unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveYear(int unexpected, string because = "", params object[] becauseArgs) { }
}
public class DateTimeAssertions : FluentAssertions.Primitives.DateTimeAssertions<FluentAssertions.Primitives.DateTimeAssertions>
{
public DateTimeAssertions(System.DateTime? value) { }
Expand Down Expand Up @@ -1956,6 +2001,19 @@ namespace FluentAssertions.Primitives
public FluentAssertions.AndConstraint<TAssertions> NotBeTrue(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveValue(string because = "", params object[] becauseArgs) { }
}
public class NullableDateOnlyAssertions : FluentAssertions.Primitives.NullableDateOnlyAssertions<FluentAssertions.Primitives.NullableDateOnlyAssertions>
{
public NullableDateOnlyAssertions(System.DateOnly? expected) { }
}
public class NullableDateOnlyAssertions<TAssertions> : FluentAssertions.Primitives.DateOnlyAssertions<TAssertions>
where TAssertions : FluentAssertions.Primitives.NullableDateOnlyAssertions<TAssertions>
{
public NullableDateOnlyAssertions(System.DateOnly? expected) { }
public FluentAssertions.AndConstraint<TAssertions> BeNull(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> HaveValue(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBeNull(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveValue(string because = "", params object[] becauseArgs) { }
}
public class NullableDateTimeAssertions : FluentAssertions.Primitives.NullableDateTimeAssertions<FluentAssertions.Primitives.NullableDateTimeAssertions>
{
public NullableDateTimeAssertions(System.DateTime? expected) { }
Expand Down

0 comments on commit 1349525

Please sign in to comment.