From 29b6c2d49e2fba069cbeacf2f8001a17edb6f5fe Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Mon, 30 Jun 2025 07:59:22 +0200 Subject: [PATCH] Assert dates in content editing integration tests to millisecond only (#19513) * Assert dates in content editing integration tests to millisecond only. * Add date time extension unit tests and refactor to switch statement. * Removed whitespace. --- .../Extensions/DateTimeExtensions.cs | 41 +++++---------- .../ContentEditingServiceTests.Update.cs | 10 ++-- .../Extensions/DateTimeExtensionsTests.cs | 51 +++++++++++++++++++ 3 files changed, 70 insertions(+), 32 deletions(-) create mode 100644 tests/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/DateTimeExtensionsTests.cs diff --git a/src/Umbraco.Core/Extensions/DateTimeExtensions.cs b/src/Umbraco.Core/Extensions/DateTimeExtensions.cs index 00191e5a76..9fadb6217a 100644 --- a/src/Umbraco.Core/Extensions/DateTimeExtensions.cs +++ b/src/Umbraco.Core/Extensions/DateTimeExtensions.cs @@ -5,6 +5,9 @@ using System.Globalization; namespace Umbraco.Extensions; +/// +/// Provides Extensions for . +/// public static class DateTimeExtensions { /// @@ -18,6 +21,7 @@ public static class DateTimeExtensions Hour, Minute, Second, + Millisecond, } /// @@ -35,32 +39,15 @@ public static class DateTimeExtensions /// The level to truncate the date to. /// The truncated date. public static DateTime TruncateTo(this DateTime dt, DateTruncate truncateTo) - { - if (truncateTo == DateTruncate.Year) + => truncateTo switch { - return new DateTime(dt.Year, 1, 1, 0, 0, 0, dt.Kind); - } - - if (truncateTo == DateTruncate.Month) - { - return new DateTime(dt.Year, dt.Month, 1, 0, 0, 0, dt.Kind); - } - - if (truncateTo == DateTruncate.Day) - { - return new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0, dt.Kind); - } - - if (truncateTo == DateTruncate.Hour) - { - return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, 0, 0, dt.Kind); - } - - if (truncateTo == DateTruncate.Minute) - { - return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0, dt.Kind); - } - - return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Kind); - } + DateTruncate.Year => new DateTime(dt.Year, 1, 1, 0, 0, 0, dt.Kind), + DateTruncate.Month => new DateTime(dt.Year, dt.Month, 1, 0, 0, 0, dt.Kind), + DateTruncate.Day => new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0, dt.Kind), + DateTruncate.Hour => new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, 0, 0, dt.Kind), + DateTruncate.Minute => new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0, dt.Kind), + DateTruncate.Second => new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Kind), + DateTruncate.Millisecond => new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Millisecond, dt.Kind), + _ => throw new ArgumentOutOfRangeException(nameof(truncateTo), truncateTo, "Invalid truncation level"), + }; } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Update.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Update.cs index b760d94c29..589c4a3516 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Update.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Update.cs @@ -569,7 +569,7 @@ public partial class ContentEditingServiceTests } [Test] - public async Task Updating_Single_Variant_Name_Does_Not_Change_Update_Dates_Of_Other_Vaiants() + public async Task Updating_Single_Variant_Name_Does_Not_Change_Update_Dates_Of_Other_Variants() { var contentType = await CreateVariantContentType(variantTitleAsMandatory: false); @@ -614,11 +614,11 @@ public partial class ContentEditingServiceTests void VerifyUpdate(IContent? updatedContent) { Assert.IsNotNull(updatedContent); - Assert.AreEqual(firstUpdateDateDa, updatedContent.GetUpdateDate("da-DK")); + Assert.AreEqual(firstUpdateDateDa?.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond), updatedContent.GetUpdateDate("da-DK")?.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond)); var lastUpdateDateEn = updatedContent.GetUpdateDate("en-US") ?? throw new InvalidOperationException("Expected a publish date for EN"); - Assert.Greater(lastUpdateDateEn, firstUpdateDateEn); + Assert.Greater(lastUpdateDateEn.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond), firstUpdateDateEn?.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond)); } } @@ -671,11 +671,11 @@ public partial class ContentEditingServiceTests void VerifyUpdate(IContent? updatedContent) { Assert.IsNotNull(updatedContent); - Assert.AreEqual(firstUpdateDateEn, updatedContent.GetUpdateDate("en-US")); + Assert.AreEqual(firstUpdateDateEn.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond), updatedContent.GetUpdateDate("en-US")?.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond)); var lastUpdateDateDa = updatedContent.GetUpdateDate("da-DK") ?? throw new InvalidOperationException("Expected an update date for DA"); - Assert.Greater(lastUpdateDateDa, firstUpdateDateDa); + Assert.Greater(lastUpdateDateDa.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond), firstUpdateDateDa.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond)); } } } diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/DateTimeExtensionsTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/DateTimeExtensionsTests.cs new file mode 100644 index 0000000000..deffcfa7ca --- /dev/null +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/DateTimeExtensionsTests.cs @@ -0,0 +1,51 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using NUnit.Framework; +using Umbraco.Extensions; + +namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Extensions; + +[TestFixture] +public class DateTimeExtensionsTests +{ + [Test] + public void ToIsoString_ReturnsCorrectFormat() + { + var date = new DateTime(2025, 6, 9, 14, 30, 45, DateTimeKind.Utc); + var result = date.ToIsoString(); + Assert.AreEqual("2025-06-09 14:30:45", result); + } + + [TestCase(2023, 5, 15, 14, 30, 45, 123, DateTimeExtensions.DateTruncate.Year, 2023, 1, 1, 0, 0, 0, 0)] + [TestCase(2023, 5, 15, 14, 30, 45, 123, DateTimeExtensions.DateTruncate.Month, 2023, 5, 1, 0, 0, 0, 0)] + [TestCase(2023, 5, 15, 14, 30, 45, 123, DateTimeExtensions.DateTruncate.Day, 2023, 5, 15, 0, 0, 0, 0)] + [TestCase(2023, 5, 15, 14, 30, 45, 123, DateTimeExtensions.DateTruncate.Hour, 2023, 5, 15, 14, 0, 0, 0)] + [TestCase(2023, 5, 15, 14, 30, 45, 123, DateTimeExtensions.DateTruncate.Minute, 2023, 5, 15, 14, 30, 0, 0)] + [TestCase(2023, 5, 15, 14, 30, 45, 123, DateTimeExtensions.DateTruncate.Second, 2023, 5, 15, 14, 30, 45, 0)] + [TestCase(2023, 5, 15, 14, 30, 45, 123, DateTimeExtensions.DateTruncate.Millisecond, 2023, 5, 15, 14, 30, 45, 123)] + public void TruncateTo_TruncatesCorrectly( + int year, + int month, + int day, + int hour, + int minute, + int second, + int millisecond, + DateTimeExtensions.DateTruncate truncateTo, + int expectedYear, + int expectedMonth, + int expectedDay, + int expectedHour, + int expectedMinute, + int expectedSecond, + int expectedMillisecond) + { + var date = new DateTime(year, month, day, hour, minute, second, millisecond, DateTimeKind.Utc); + var expected = new DateTime(expectedYear, expectedMonth, expectedDay, expectedHour, expectedMinute, expectedSecond, expectedMillisecond, DateTimeKind.Utc); + + var result = date.TruncateTo(truncateTo); + + Assert.AreEqual(expected, result); + } +}