From 42817a560ed7a199d923fdd18e0d98d3233e903b Mon Sep 17 00:00:00 2001 From: James Gunn Date: Fri, 9 Dec 2022 18:43:30 +0000 Subject: [PATCH] Use DateOnly as our base type for Date Input (#249) Up until now we've had our own Date type for use with the Date Input component. Now that we have access to a built-in one - DateOnly - our's is going away. For now it's [Obsolete]d with a view to removing it in the final 1.0 release. --- .../LocalDateDateInputModelConverter.cs | 8 +-- src/GovUk.Frontend.AspNetCore/Date.cs | 37 ++++++++----- .../DateDateInputModelConverter.cs | 16 ++++-- .../DateInputModelConverter.cs | 4 +- .../DateOnlyDateInputModelConverter.cs | 14 +++++ .../DateTimeDateInputModelConverter.cs | 9 ++-- .../GovUkFrontendAspNetCoreOptions.cs | 3 +- .../ModelBinding/DateInputModelBinder.cs | 4 +- .../TagHelpers/DateInputTagHelper.cs | 13 ++--- .../TagHelpers/ErrorSummaryItemTagHelper.cs | 2 +- .../DateInputTests.cs | 8 +-- .../DateDateInputModelConverterTests.cs | 17 +++--- .../DateOnlyDateInputModelConverterTests.cs | 54 +++++++++++++++++++ .../DateTimeDateInputModelConverterTests.cs | 16 +++--- .../ModelBinding/DateInputModelBinderTests.cs | 14 ++--- .../TagHelpers/DateInputTagHelperTests.cs | 38 ++++++------- .../ErrorSummaryItemTagHelperTests.cs | 2 +- 17 files changed, 173 insertions(+), 86 deletions(-) create mode 100644 src/GovUk.Frontend.AspNetCore/DateOnlyDateInputModelConverter.cs create mode 100644 test/GovUk.Frontend.AspNetCore.Tests/DateOnlyDateInputModelConverterTests.cs diff --git a/samples/Samples.DateInput/LocalDateDateInputModelConverter.cs b/samples/Samples.DateInput/LocalDateDateInputModelConverter.cs index aefa041d..84f3cd1e 100644 --- a/samples/Samples.DateInput/LocalDateDateInputModelConverter.cs +++ b/samples/Samples.DateInput/LocalDateDateInputModelConverter.cs @@ -6,19 +6,19 @@ namespace Samples.DateInput { public class LocalDateDateInputModelConverter : DateInputModelConverter { - public override bool CanConvertModelType(Type modelType) => modelType == typeof(LocalDate) || modelType == typeof(LocalDate?); + public override bool CanConvertModelType(Type modelType) => modelType == typeof(LocalDate); - public override object CreateModelFromDate(Type modelType, Date date) + public override object CreateModelFromDate(Type modelType, DateOnly date) { return new LocalDate(date.Year, date.Month, date.Day); } - public override Date? GetDateFromModel(Type modelType, object model) + public override DateOnly? GetDateFromModel(Type modelType, object model) { var localDate = (LocalDate?)model; return localDate.HasValue ? - new Date(localDate.Value.Year, localDate.Value.Month, localDate.Value.Day) : + new DateOnly(localDate.Value.Year, localDate.Value.Month, localDate.Value.Day) : null; } } diff --git a/src/GovUk.Frontend.AspNetCore/Date.cs b/src/GovUk.Frontend.AspNetCore/Date.cs index 543f5250..ab9030ed 100644 --- a/src/GovUk.Frontend.AspNetCore/Date.cs +++ b/src/GovUk.Frontend.AspNetCore/Date.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Runtime.InteropServices; namespace GovUk.Frontend.AspNetCore @@ -6,10 +7,12 @@ namespace GovUk.Frontend.AspNetCore /// /// Represents a date. /// + [Obsolete("Use DateOnly instead.", error: false)] + [EditorBrowsable(EditorBrowsableState.Never)] [StructLayout(LayoutKind.Auto)] public readonly struct Date : IComparable, IComparable, IEquatable { - private readonly DateTime _dt; + private readonly DateOnly _d; /// /// Creates a new instance of the structure to the specified year, month and day. @@ -18,34 +21,40 @@ namespace GovUk.Frontend.AspNetCore /// The month (1 through 12). /// The day (1 through the number of days in ). public Date(int year, int month, int day) - : this(new DateTime(year, month, day)) + : this(new DateOnly(year, month, day)) { } - private Date(DateTime dateTime) + private Date(DateOnly date) { - _dt = dateTime; + _d = date; } /// /// Gets the current date. /// - public static Date Today => new(DateTime.Today); + public static Date Today => new(DateOnly.FromDateTime(DateTime.Today)); /// /// Gets the day component of the date. /// - public int Day => _dt.Day; + public int Day => _d.Day; /// /// Gets the month component of the date. /// - public int Month => _dt.Month; + public int Month => _d.Month; /// /// Gets the year component of the date. /// - public int Year => _dt.Year; + public int Year => _d.Year; + + /// + /// Converts the specified to a . + /// + /// The to convert. + public static implicit operator DateOnly(Date date) => date._d; /// /// Determines whether two specified instances of are equal. @@ -69,7 +78,7 @@ private Date(DateTime dateTime) /// The first object to compare. /// The second object to compare. /// if left is earlier than right; otherwise, . - public static bool operator <(Date left, Date right) => left._dt < right._dt; + public static bool operator <(Date left, Date right) => left._d < right._d; /// /// Determines whether one specified represents a date that is the same as or earlier than another specified . @@ -77,7 +86,7 @@ private Date(DateTime dateTime) /// The first object to compare. /// The second object to compare. /// if left is the same as or earlier than right; otherwise, . - public static bool operator <=(Date left, Date right) => left._dt <= right._dt; + public static bool operator <=(Date left, Date right) => left._d <= right._d; /// /// Determines whether one specified is later than another specified . @@ -85,7 +94,7 @@ private Date(DateTime dateTime) /// The first object to compare. /// The second object to compare. /// if left is later than right; otherwise, . - public static bool operator >(Date left, Date right) => left._dt > right._dt; + public static bool operator >(Date left, Date right) => left._d > right._d; /// /// Determines whether one specified represents a date that is the same as or later than another specified . @@ -93,7 +102,7 @@ private Date(DateTime dateTime) /// The first object to compare. /// The second object to compare. /// if left is the same as or later than right; otherwise, . - public static bool operator >=(Date left, Date right) => left._dt >= right._dt; + public static bool operator >=(Date left, Date right) => left._d >= right._d; /// public int CompareTo(object? value) @@ -112,7 +121,7 @@ public int CompareTo(object? value) } /// - public int CompareTo(Date value) => _dt.CompareTo(value); + public int CompareTo(Date value) => _d.CompareTo(value); /// public override bool Equals(object? obj) => obj is Date date && Equals(date); @@ -128,7 +137,7 @@ public int CompareTo(object? value) /// /// The instance. /// The instance composed of the date part of the specified input time instance. - public static Date FromDateTime(DateTime value) => new(value); + public static Date FromDateTime(DateTime value) => new(value.Year, value.Minute, value.Day); /// /// Returns a that is set to the date of this instance. diff --git a/src/GovUk.Frontend.AspNetCore/DateDateInputModelConverter.cs b/src/GovUk.Frontend.AspNetCore/DateDateInputModelConverter.cs index c48c6883..b67fba61 100644 --- a/src/GovUk.Frontend.AspNetCore/DateDateInputModelConverter.cs +++ b/src/GovUk.Frontend.AspNetCore/DateDateInputModelConverter.cs @@ -1,14 +1,22 @@ +#pragma warning disable CS0618 // Type or member is obsolete using System; namespace GovUk.Frontend.AspNetCore { internal class DateDateInputModelConverter : DateInputModelConverter { - public override bool CanConvertModelType(Type modelType) => - modelType == typeof(Date) || modelType == typeof(Date?); + public override bool CanConvertModelType(Type modelType) => modelType == typeof(Date); - public override object CreateModelFromDate(Type modelType, Date date) => date; + public override object CreateModelFromDate(Type modelType, DateOnly date) => new Date(date.Year, date.Month, date.Day); - public override Date? GetDateFromModel(Type modelType, object model) => (Date?)model; + public override DateOnly? GetDateFromModel(Type modelType, object model) + { + if (model is null) + { + return null; + } + + return (Date)model; + } } } diff --git a/src/GovUk.Frontend.AspNetCore/DateInputModelConverter.cs b/src/GovUk.Frontend.AspNetCore/DateInputModelConverter.cs index fa9d579b..4bee7117 100644 --- a/src/GovUk.Frontend.AspNetCore/DateInputModelConverter.cs +++ b/src/GovUk.Frontend.AspNetCore/DateInputModelConverter.cs @@ -20,7 +20,7 @@ public abstract class DateInputModelConverter /// The model type to convert to. /// The instance to convert. /// An instance of that represents the argument. - public abstract object CreateModelFromDate(Type modelType, Date date); + public abstract object CreateModelFromDate(Type modelType, DateOnly date); /// /// Converts to instance of . @@ -28,7 +28,7 @@ public abstract class DateInputModelConverter /// The model type to convert from. /// The model instance to convert. /// The converted model instance. - public abstract Date? GetDateFromModel(Type modelType, object model); + public abstract DateOnly? GetDateFromModel(Type modelType, object model); /// /// Creates an instance of the specified model type from a set of parse errors. diff --git a/src/GovUk.Frontend.AspNetCore/DateOnlyDateInputModelConverter.cs b/src/GovUk.Frontend.AspNetCore/DateOnlyDateInputModelConverter.cs new file mode 100644 index 00000000..01b4461c --- /dev/null +++ b/src/GovUk.Frontend.AspNetCore/DateOnlyDateInputModelConverter.cs @@ -0,0 +1,14 @@ +#nullable enable +using System; + +namespace GovUk.Frontend.AspNetCore +{ + internal class DateOnlyDateInputModelConverter : DateInputModelConverter + { + public override bool CanConvertModelType(Type modelType) => modelType == typeof(DateOnly); + + public override object CreateModelFromDate(Type modelType, DateOnly date) => date; + + public override DateOnly? GetDateFromModel(Type modelType, object model) => (DateOnly?)model; + } +} diff --git a/src/GovUk.Frontend.AspNetCore/DateTimeDateInputModelConverter.cs b/src/GovUk.Frontend.AspNetCore/DateTimeDateInputModelConverter.cs index e1e7e297..68f4e39b 100644 --- a/src/GovUk.Frontend.AspNetCore/DateTimeDateInputModelConverter.cs +++ b/src/GovUk.Frontend.AspNetCore/DateTimeDateInputModelConverter.cs @@ -4,19 +4,18 @@ namespace GovUk.Frontend.AspNetCore { internal class DateTimeDateInputModelConverter : DateInputModelConverter { - public override bool CanConvertModelType(Type modelType) => - modelType == typeof(DateTime) || modelType == typeof(DateTime?); + public override bool CanConvertModelType(Type modelType) => modelType == typeof(DateTime); - public override object CreateModelFromDate(Type modelType, Date date) => new DateTime(date.Year, date.Month, date.Day); + public override object CreateModelFromDate(Type modelType, DateOnly date) => new DateTime(date.Year, date.Month, date.Day); - public override Date? GetDateFromModel(Type modelType, object model) + public override DateOnly? GetDateFromModel(Type modelType, object model) { if (model is null) { return null; } - return Date.FromDateTime((DateTime)model); + return DateOnly.FromDateTime((DateTime)model); } } } diff --git a/src/GovUk.Frontend.AspNetCore/GovUkFrontendAspNetCoreOptions.cs b/src/GovUk.Frontend.AspNetCore/GovUkFrontendAspNetCoreOptions.cs index 53a22919..945806d5 100644 --- a/src/GovUk.Frontend.AspNetCore/GovUkFrontendAspNetCoreOptions.cs +++ b/src/GovUk.Frontend.AspNetCore/GovUkFrontendAspNetCoreOptions.cs @@ -21,7 +21,8 @@ public GovUkFrontendAspNetCoreOptions() DateInputModelConverters = new List() { new DateDateInputModelConverter(), - new DateTimeDateInputModelConverter() + new DateTimeDateInputModelConverter(), + new DateOnlyDateInputModelConverter() }; PrependErrorSummaryToForms = true; diff --git a/src/GovUk.Frontend.AspNetCore/ModelBinding/DateInputModelBinder.cs b/src/GovUk.Frontend.AspNetCore/ModelBinding/DateInputModelBinder.cs index 6f97f5ef..f14bd91f 100644 --- a/src/GovUk.Frontend.AspNetCore/ModelBinding/DateInputModelBinder.cs +++ b/src/GovUk.Frontend.AspNetCore/ModelBinding/DateInputModelBinder.cs @@ -24,7 +24,7 @@ public Task BindModelAsync(ModelBindingContext bindingContext) { Guard.ArgumentNotNull(nameof(bindingContext), bindingContext); - var modelType = bindingContext.ModelType; + var modelType = bindingContext.ModelMetadata.UnderlyingOrModelType; if (!_dateInputModelConverter.CanConvertModelType(modelType)) { throw new InvalidOperationException($"Cannot bind {modelType.Name}."); @@ -118,7 +118,7 @@ internal static string GetModelStateErrorMessage(DateInputParseErrors parseError } // internal for testing - internal static DateInputParseErrors Parse(string? day, string? month, string? year, out Date? date) + internal static DateInputParseErrors Parse(string? day, string? month, string? year, out DateOnly? date) { day ??= string.Empty; month ??= string.Empty; diff --git a/src/GovUk.Frontend.AspNetCore/TagHelpers/DateInputTagHelper.cs b/src/GovUk.Frontend.AspNetCore/TagHelpers/DateInputTagHelper.cs index 4f8751c2..5f32aa4c 100644 --- a/src/GovUk.Frontend.AspNetCore/TagHelpers/DateInputTagHelper.cs +++ b/src/GovUk.Frontend.AspNetCore/TagHelpers/DateInputTagHelper.cs @@ -4,6 +4,7 @@ using GovUk.Frontend.AspNetCore.HtmlGeneration; using GovUk.Frontend.AspNetCore.ModelBinding; using Microsoft.AspNetCore.Html; +using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.Extensions.Options; @@ -244,7 +245,7 @@ private TagBuilder GenerateDateInput(DateInputContext dateInputContext, bool hav DateInputAttributes.ToAttributeDictionary()); DateInputItem CreateDateInputItem( - Func getComponentFromValue, + Func getComponentFromValue, string defaultLabel, string defaultName, string defaultClass, @@ -316,7 +317,7 @@ DateInputItem CreateDateInputItem( } } - Date? GetValueAsDate() + DateOnly? GetValueAsDate() { if (Value is null) { @@ -337,12 +338,12 @@ DateInputItem CreateDateInputItem( return null; } - Date? GetValueFromModel() + DateOnly? GetValueFromModel() { Debug.Assert(AspFor != null); var modelValue = AspFor!.Model; - var modelType = AspFor.ModelExplorer.ModelType; + var underlyingModelType = Nullable.GetUnderlyingType(AspFor.ModelExplorer.ModelType) ?? AspFor.ModelExplorer.ModelType; if (modelValue is null) { @@ -353,9 +354,9 @@ DateInputItem CreateDateInputItem( foreach (var converter in dateInputModelConverters) { - if (converter.CanConvertModelType(modelType)) + if (converter.CanConvertModelType(underlyingModelType)) { - return converter.GetDateFromModel(modelType, modelValue); + return converter.GetDateFromModel(underlyingModelType, modelValue); } } diff --git a/src/GovUk.Frontend.AspNetCore/TagHelpers/ErrorSummaryItemTagHelper.cs b/src/GovUk.Frontend.AspNetCore/TagHelpers/ErrorSummaryItemTagHelper.cs index fcb0a2bb..e0289b67 100644 --- a/src/GovUk.Frontend.AspNetCore/TagHelpers/ErrorSummaryItemTagHelper.cs +++ b/src/GovUk.Frontend.AspNetCore/TagHelpers/ErrorSummaryItemTagHelper.cs @@ -167,7 +167,7 @@ bool IsModelExpressionForDate() { Debug.Assert(AspFor != null); - var modelType = AspFor!.Metadata.ModelType; + var modelType = Nullable.GetUnderlyingType(AspFor!.Metadata.ModelType) ?? AspFor!.Metadata.ModelType; return _options.DateInputModelConverters.Any(c => c.CanConvertModelType(modelType)); } } diff --git a/test/GovUk.Frontend.AspNetCore.IntegrationTests/DateInputTests.cs b/test/GovUk.Frontend.AspNetCore.IntegrationTests/DateInputTests.cs index 92ee565b..fcd6c53c 100644 --- a/test/GovUk.Frontend.AspNetCore.IntegrationTests/DateInputTests.cs +++ b/test/GovUk.Frontend.AspNetCore.IntegrationTests/DateInputTests.cs @@ -247,7 +247,7 @@ public class DateInputsTestsModel { [Display(Name = "Date of birth")] [Required(ErrorMessage = "Enter your date of birth")] - public Date? Date { get; set; } + public DateOnly? Date { get; set; } [Display(Name = "Date of birth")] [Required(ErrorMessage = "Enter your date of birth")] @@ -272,9 +272,9 @@ public class CustomDateTypeConverter : DateInputModelConverter { public override bool CanConvertModelType(Type modelType) => modelType == typeof(CustomDateType); - public override object CreateModelFromDate(Type modelType, Date date) => new CustomDateType(date.Year, date.Month, date.Day); + public override object CreateModelFromDate(Type modelType, DateOnly date) => new CustomDateType(date.Year, date.Month, date.Day); - public override Date? GetDateFromModel(Type modelType, object model) + public override DateOnly? GetDateFromModel(Type modelType, object model) { if (model is null) { @@ -282,7 +282,7 @@ public class CustomDateTypeConverter : DateInputModelConverter } var cdt = (CustomDateType)model; - return new Date(cdt.Y, cdt.M, cdt.D); + return new DateOnly(cdt.Y, cdt.M, cdt.D); } } } diff --git a/test/GovUk.Frontend.AspNetCore.Tests/DateDateInputModelConverterTests.cs b/test/GovUk.Frontend.AspNetCore.Tests/DateDateInputModelConverterTests.cs index 0a0b0408..879a3215 100644 --- a/test/GovUk.Frontend.AspNetCore.Tests/DateDateInputModelConverterTests.cs +++ b/test/GovUk.Frontend.AspNetCore.Tests/DateDateInputModelConverterTests.cs @@ -1,3 +1,4 @@ +#pragma warning disable CS0618 // Type or member is obsolete using System; using Xunit; @@ -9,7 +10,7 @@ public class DateDateInputModelConverterTests [MemberData(nameof(CreateDateFromElementsData))] public void CreateDateFromComponents_ReturnsExpectedResult( Type modelType, - Date date, + DateOnly date, object expectedResult) { // Arrange @@ -27,7 +28,7 @@ public void CreateDateFromComponents_ReturnsExpectedResult( public void GetDateFromModel_ReturnsExpectedResult( Type modelType, object model, - Date? expectedResult) + DateOnly? expectedResult) { // Arrange var converter = new DateDateInputModelConverter(); @@ -39,16 +40,16 @@ public void GetDateFromModel_ReturnsExpectedResult( Assert.Equal(expectedResult, result); } - public static TheoryData CreateDateFromElementsData { get; } = new TheoryData() + public static TheoryData CreateDateFromElementsData { get; } = new() { - { typeof(Date), new Date(2020, 4, 1), new Date(2020, 4, 1) }, - { typeof(Date?), new Date(2020, 4, 1), (Date?)new Date(2020, 4, 1) } + { typeof(Date), new DateOnly(2020, 4, 1), new Date(2020, 4, 1) }, + { typeof(Date?), new DateOnly(2020, 4, 1), (Date?)new Date(2020, 4, 1) } }; - public static TheoryData GetDateFromModelData { get; } = new TheoryData() + public static TheoryData GetDateFromModelData { get; } = new() { - { typeof(Date), new Date(2020, 4, 1), new Date(2020, 4, 1) }, - { typeof(Date?), (Date?)new Date(2020, 4, 1), new Date(2020, 4, 1) } + { typeof(Date), new Date(2020, 4, 1), new DateOnly(2020, 4, 1) }, + { typeof(Date?), (Date?)new Date(2020, 4, 1), new Date(2020, 4, 1) }, }; } } diff --git a/test/GovUk.Frontend.AspNetCore.Tests/DateOnlyDateInputModelConverterTests.cs b/test/GovUk.Frontend.AspNetCore.Tests/DateOnlyDateInputModelConverterTests.cs new file mode 100644 index 00000000..120acd75 --- /dev/null +++ b/test/GovUk.Frontend.AspNetCore.Tests/DateOnlyDateInputModelConverterTests.cs @@ -0,0 +1,54 @@ +using System; +using Xunit; + +namespace GovUk.Frontend.AspNetCore.Tests +{ + public class DateOnlyDateInputModelConverterTests + { + [Theory] + [MemberData(nameof(CreateDateFromElementsData))] + public void CreateDateFromComponents_ReturnsExpectedResult( + Type modelType, + DateOnly date, + object expectedResult) + { + // Arrange + var converter = new DateOnlyDateInputModelConverter(); + + // Act + var result = converter.CreateModelFromDate(modelType, date); + + // Assert + Assert.Equal(expectedResult, result); + } + + [Theory] + [MemberData(nameof(GetDateFromModelData))] + public void GetDateFromModel_ReturnsExpectedResult( + Type modelType, + object model, + DateOnly? expectedResult) + { + // Arrange + var converter = new DateOnlyDateInputModelConverter(); + + // Act + var result = converter.GetDateFromModel(modelType, model); + + // Assert + Assert.Equal(expectedResult, result); + } + + public static TheoryData CreateDateFromElementsData { get; } = new() + { + { typeof(DateOnly), new DateOnly(2020, 4, 1), new DateOnly(2020, 4, 1) }, + { typeof(DateOnly?), new DateOnly(2020, 4, 1), (DateOnly?)new DateOnly(2020, 4, 1) } + }; + + public static TheoryData GetDateFromModelData { get; } = new() + { + { typeof(DateOnly), new DateOnly(2020, 4, 1), new DateOnly(2020, 4, 1) }, + { typeof(DateOnly?), (DateOnly?)new DateOnly(2020, 4, 1), new DateOnly(2020, 4, 1) }, + }; + } +} diff --git a/test/GovUk.Frontend.AspNetCore.Tests/DateTimeDateInputModelConverterTests.cs b/test/GovUk.Frontend.AspNetCore.Tests/DateTimeDateInputModelConverterTests.cs index e8589861..885debf9 100644 --- a/test/GovUk.Frontend.AspNetCore.Tests/DateTimeDateInputModelConverterTests.cs +++ b/test/GovUk.Frontend.AspNetCore.Tests/DateTimeDateInputModelConverterTests.cs @@ -9,7 +9,7 @@ public class DateTimeDateInputModelConverterTests [MemberData(nameof(CreateModelFromDateData))] public void CreateModelFromDate_ReturnsExpectedResult( Type modelType, - Date date, + DateOnly date, object expectedResult) { // Arrange @@ -27,7 +27,7 @@ public void CreateModelFromDate_ReturnsExpectedResult( public void GetDateFromModel_ReturnsExpectedResult( Type modelType, object model, - Date? expectedResult) + DateOnly? expectedResult) { // Arrange var converter = new DateTimeDateInputModelConverter(); @@ -39,16 +39,16 @@ public void GetDateFromModel_ReturnsExpectedResult( Assert.Equal(expectedResult, result); } - public static TheoryData CreateModelFromDateData { get; } = new TheoryData() + public static TheoryData CreateModelFromDateData { get; } = new() { - { typeof(DateTime), new Date(2020, 4, 1), new DateTime(2020, 4, 1) }, - { typeof(DateTime?), new Date(2020, 4, 1), (DateTime?)new DateTime(2020, 4, 1) } + { typeof(DateTime), new DateOnly(2020, 4, 1), new DateTime(2020, 4, 1) }, + { typeof(DateTime?), new DateOnly(2020, 4, 1), (DateTime?)new DateTime(2020, 4, 1) } }; - public static TheoryData GetDateFromModelData { get; } = new TheoryData() + public static TheoryData GetDateFromModelData { get; } = new() { - { typeof(DateTime), new DateTime(2020, 4, 1), new Date(2020, 4, 1) }, - { typeof(DateTime?), (DateTime?)new DateTime(2020, 4, 1), new Date(2020, 4, 1) } + { typeof(DateTime), new DateTime(2020, 4, 1), new DateOnly(2020, 4, 1) }, + { typeof(DateTime?), (DateTime?)new DateTime(2020, 4, 1), new DateOnly(2020, 4, 1) }, }; } } diff --git a/test/GovUk.Frontend.AspNetCore.Tests/ModelBinding/DateInputModelBinderTests.cs b/test/GovUk.Frontend.AspNetCore.Tests/ModelBinding/DateInputModelBinderTests.cs index b7d6f5e3..e7d8cc2e 100644 --- a/test/GovUk.Frontend.AspNetCore.Tests/ModelBinding/DateInputModelBinderTests.cs +++ b/test/GovUk.Frontend.AspNetCore.Tests/ModelBinding/DateInputModelBinderTests.cs @@ -19,7 +19,7 @@ public class DateInputModelBinderTests public async Task BindModelAsync_AllComponentsEmpty_DoesNotBind() { // Arrange - var modelType = typeof(Date); + var modelType = typeof(DateOnly); ModelBindingContext bindingContext = new DefaultModelBindingContext() { @@ -46,7 +46,7 @@ public async Task BindModelAsync_AllComponentsEmpty_DoesNotBind() public async Task BindModelAsync_AllComponentsProvided_PassesValuesToConverterAndBindsResult() { // Arrange - var modelType = typeof(Date); + var modelType = typeof(DateOnly); ModelBindingContext bindingContext = new DefaultModelBindingContext() { @@ -66,8 +66,8 @@ public async Task BindModelAsync_AllComponentsProvided_PassesValuesToConverterAn converterMock.Setup(mock => mock.CanConvertModelType(modelType)).Returns(true); converterMock - .Setup(mock => mock.CreateModelFromDate(modelType, new Date(2020, 4, 1))) - .Returns(new Date(2020, 4, 1)) + .Setup(mock => mock.CreateModelFromDate(modelType, new DateOnly(2020, 4, 1))) + .Returns(new DateOnly(2020, 4, 1)) .Verifiable(); var modelBinder = new DateInputModelBinder(converterMock.Object); @@ -80,7 +80,7 @@ public async Task BindModelAsync_AllComponentsProvided_PassesValuesToConverterAn Assert.True(bindingContext.Result.IsModelSet); - var date = Assert.IsType(bindingContext.Result.Model); + var date = Assert.IsType(bindingContext.Result.Model); Assert.Equal(2020, date.Year); Assert.Equal(4, date.Month); Assert.Equal(1, date.Day); @@ -108,7 +108,7 @@ public async Task BindModelAsync_AllComponentsProvided_PassesValuesToConverterAn public async Task BindModelAsync_MissingOrInvalidComponents_FailsBinding(string day, string month, string year) { // Arrange - var modelType = typeof(Date); + var modelType = typeof(DateOnly); var valueProvider = new SimpleValueProvider(); @@ -275,7 +275,7 @@ private static ActionContext CreateActionContextWithServices() private class DisplayNameModelMetadata : ModelMetadata { public DisplayNameModelMetadata(string displayName) - : base(ModelMetadataIdentity.ForType(typeof(Date?))) + : base(ModelMetadataIdentity.ForType(typeof(DateOnly?))) { DisplayName = displayName; } diff --git a/test/GovUk.Frontend.AspNetCore.Tests/TagHelpers/DateInputTagHelperTests.cs b/test/GovUk.Frontend.AspNetCore.Tests/TagHelpers/DateInputTagHelperTests.cs index 30b9adf4..8f5e745d 100644 --- a/test/GovUk.Frontend.AspNetCore.Tests/TagHelpers/DateInputTagHelperTests.cs +++ b/test/GovUk.Frontend.AspNetCore.Tests/TagHelpers/DateInputTagHelperTests.cs @@ -42,7 +42,7 @@ public async Task ProcessAsync_WithValue_GeneratesExpectedOutput() { Id = "my-id", NamePrefix = "my-name", - Value = new Date(2020, 4, 1) + Value = new DateOnly(2020, 4, 1) }; // Act @@ -95,7 +95,7 @@ public async Task ProcessAsync_WithAspFor_GeneratesExpectedOutput() return Task.FromResult(tagHelperContent); }); - var modelExplorer = new EmptyModelMetadataProvider().GetModelExplorerForType(typeof(Model), new Model() { Date = new Date(2020, 4, 1) }) + var modelExplorer = new EmptyModelMetadataProvider().GetModelExplorerForType(typeof(Model), new Model() { Date = new DateOnly(2020, 4, 1) }) .GetExplorerForProperty(nameof(Model.Date)); var viewContext = new ViewContext(); @@ -158,7 +158,7 @@ public async Task ProcessAsync_WithAspForAndValue_UsesValueAttribute() return Task.FromResult(tagHelperContent); }); - var modelExplorer = new EmptyModelMetadataProvider().GetModelExplorerForType(typeof(Model), new Model() { Date = new Date(2020, 4, 1) }) + var modelExplorer = new EmptyModelMetadataProvider().GetModelExplorerForType(typeof(Model), new Model() { Date = new DateOnly(2020, 4, 1) }) .GetExplorerForProperty(nameof(Model.Date)); var viewContext = new ViewContext(); @@ -169,7 +169,7 @@ public async Task ProcessAsync_WithAspForAndValue_UsesValueAttribute() Id = "my-id", NamePrefix = "my-name", ViewContext = viewContext, - Value = new Date(2022, 5, 3) + Value = new DateOnly(2022, 5, 3) }; // Act @@ -235,7 +235,7 @@ public async Task ProcessAsync_WithFieldset_GeneratesExpectedOutput() DescribedBy = "describedby", Id = "my-id", NamePrefix = "my-name", - Value = new Date(2020, 4, 1) + Value = new DateOnly(2020, 4, 1) }; // Act @@ -372,7 +372,7 @@ public async Task ProcessAsync_WithHint_GeneratesExpectedOutput() { Id = "my-id", NamePrefix = "my-name", - Value = new Date(2020, 4, 1) + Value = new DateOnly(2020, 4, 1) }; // Act @@ -433,7 +433,7 @@ public async Task ProcessAsync_WithErrorMessage_GeneratesExpectedOutput() { Id = "my-id", NamePrefix = "my-name", - Value = new Date(2020, 4, 1) + Value = new DateOnly(2020, 4, 1) }; // Act @@ -495,7 +495,7 @@ public async Task ProcessAsync_WithHintAndErrorMessage_GeneratesExpectedOutput() { Id = "my-id", NamePrefix = "my-name", - Value = new Date(2020, 4, 1) + Value = new DateOnly(2020, 4, 1) }; // Act @@ -560,7 +560,7 @@ public async Task ProcessAsync_WithOverridenItemId_GeneratesExpectedItem() { Id = "my-id", NamePrefix = "my-name", - Value = new Date(2020, 4, 1) + Value = new DateOnly(2020, 4, 1) }; // Act @@ -604,7 +604,7 @@ public async Task ProcessAsync_WithOverridenItemName_GeneratesExpectedItem() { Id = "my-id", NamePrefix = "my-name", - Value = new Date(2020, 4, 1) + Value = new DateOnly(2020, 4, 1) }; // Act @@ -646,7 +646,7 @@ public async Task ProcessAsync_WithOverridenItemLabel_GeneratesExpectedItem() { Id = "my-id", NamePrefix = "my-name", - Value = new Date(2020, 4, 1) + Value = new DateOnly(2020, 4, 1) }; // Act @@ -853,7 +853,7 @@ public async Task ProcessAsync_HaveErrorClassesWhenErrorSpecified( Id = "my-id", DescribedBy = "describedby", NamePrefix = "my-name", - Value = new Date(2020, 4, 1) + Value = new DateOnly(2020, 4, 1) }; // Act @@ -921,7 +921,7 @@ public async Task ProcessAsync_ErrorItemsNotSpecifiedAndErrorsFromModelBinder_In return Task.FromResult(tagHelperContent); }); - var modelExplorer = new EmptyModelMetadataProvider().GetModelExplorerForType(typeof(Model), new Model() { Date = new Date(2020, 4, 1) }) + var modelExplorer = new EmptyModelMetadataProvider().GetModelExplorerForType(typeof(Model), new Model() { Date = new DateOnly(2020, 4, 1) }) .GetExplorerForProperty(nameof(Model.Date)); var viewContext = new ViewContext(); @@ -989,7 +989,7 @@ public async Task ProcessAsync_ErrorItemsSpecifiedAndErrorsFromModelBinder_UsesS return Task.FromResult(tagHelperContent); }); - var modelExplorer = new EmptyModelMetadataProvider().GetModelExplorerForType(typeof(Model), new Model() { Date = new Date(2020, 4, 1) }) + var modelExplorer = new EmptyModelMetadataProvider().GetModelExplorerForType(typeof(Model), new Model() { Date = new DateOnly(2020, 4, 1) }) .GetExplorerForProperty(nameof(Model.Date)); var viewContext = new ViewContext(); @@ -1069,7 +1069,7 @@ public async Task ProcessAsync_WithError_AddsErrorWithCorrectFieldIdToFormErrorC Id = "my-id", DescribedBy = "describedby", NamePrefix = "my-name", - Value = new Date(2020, 4, 1) + Value = new DateOnly(2020, 4, 1) }; // Act @@ -1098,7 +1098,7 @@ private static void SetModelErrors( private class Model { - public Date? Date { get; set; } + public DateOnly? Date { get; set; } public CustomDateType? CustomDate { get; set; } } @@ -1120,9 +1120,9 @@ private class CustomDateTypeConverter : DateInputModelConverter { public override bool CanConvertModelType(Type modelType) => modelType == typeof(CustomDateType); - public override object CreateModelFromDate(Type modelType, Date date) => new CustomDateType(date.Year, date.Month, date.Day); + public override object CreateModelFromDate(Type modelType, DateOnly date) => new CustomDateType(date.Year, date.Month, date.Day); - public override Date? GetDateFromModel(Type modelType, object model) + public override DateOnly? GetDateFromModel(Type modelType, object model) { if (model is null) { @@ -1130,7 +1130,7 @@ private class CustomDateTypeConverter : DateInputModelConverter } var cdt = (CustomDateType)model; - return new Date(cdt.Y, cdt.M, cdt.D); + return new DateOnly(cdt.Y, cdt.M, cdt.D); } } } diff --git a/test/GovUk.Frontend.AspNetCore.Tests/TagHelpers/ErrorSummaryItemTagHelperTests.cs b/test/GovUk.Frontend.AspNetCore.Tests/TagHelpers/ErrorSummaryItemTagHelperTests.cs index 13c96a04..bfe9ce90 100644 --- a/test/GovUk.Frontend.AspNetCore.Tests/TagHelpers/ErrorSummaryItemTagHelperTests.cs +++ b/test/GovUk.Frontend.AspNetCore.Tests/TagHelpers/ErrorSummaryItemTagHelperTests.cs @@ -454,7 +454,7 @@ public async Task ProcessAsync_NoHrefAttributeOrAspFor_SetsNullHrefOnItem() private class Model { - public Date? Date { get; set; } + public DateOnly? Date { get; set; } public string? Field { get; set; } } }