Skip to content

Commit

Permalink
Develop (#1)
Browse files Browse the repository at this point in the history
* feat: Add culture in humanize method

Use Globalization current culture in several extension methods

BREAKING CHANGE: Humanize extensions methods

* new commit because random test fail in CI

* ci: fix download artifacts

* fix: fix TUs

* fix: fix TUs

* fix ci

---------

Co-authored-by: Stéphane ANDRE (E104915) <stephane.andre_ext@michelin.com>
  • Loading branch information
sandre58 and Stéphane ANDRE (E104915) authored Aug 30, 2024
1 parent d599f93 commit 83849a6
Show file tree
Hide file tree
Showing 38 changed files with 226 additions and 286 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/create_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ jobs:
file_pattern: CHANGELOG.md

# Download artifacts
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
name: NuGet
path: Artifacts/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
steps:

# Download artifacts
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
name: NuGet
path: Artifacts/
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ tools/FAKE/
build-log.xml
Nuget.key
TestResult.xml
nuget.config

# Build results
[Bb]uild/
Expand Down
4 changes: 1 addition & 3 deletions src/MyNet.Humanizer.UnitTests/CollectionHumanizeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class SomeClass
}

[UseCulture("en")]
[Collection("UseCultureSequential")]
public class CollectionHumanizeTests
{
[Fact]
Expand Down Expand Up @@ -104,7 +105,6 @@ public void HumanizeUsesObjectDisplayFormatterWhenSeparatorIsProvided()
public void HumanizeHandlesNullItemsWithoutAnException() => Assert.Null(Record.Exception(() => new object?[] { null, null }.Humanize(", ", "and")));

[Fact]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1861:Avoid constant arrays as arguments", Justification = "It's for Unit Tests")]
public void HumanizeHandlesNullStringDisplayFormatterReturnsWithoutAnException() => Assert.Null(Record.Exception(() => new[] { "A", "B", "C" }.Humanize(_ => null, ", ", "and")));

[Fact]
Expand All @@ -114,11 +114,9 @@ public void HumanizeUsesObjectDisplayFormatterWhenSeparatorIsProvided()
public void HumanizeRunsObjectDisplayFormatterOnNulls() => Assert.Equal("1, 2 and 3", new int?[] { 1, null, 3 }.Humanize(_ => _ ?? 2, ", ", "and"));

[Fact]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1861:Avoid constant arrays as arguments", Justification = "It's for Unit Tests")]
public void HumanizeRemovesEmptyItemsByDefault() => Assert.Equal("A and C", new[] { "A", " ", "C" }.Humanize(DummyFormatter, ", ", "and"));

[Fact]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1861:Avoid constant arrays as arguments", Justification = "It's for Unit Tests")]
public void HumanizeTrimsItemsByDefault() => Assert.Equal("A, B and C", new[] { "A", " B ", "C" }.Humanize(DummyFormatter, ", ", "and"));

private static readonly Func<string, string> DummyFormatter = input => input;
Expand Down
24 changes: 13 additions & 11 deletions src/MyNet.Humanizer.UnitTests/DateTimeHumanize.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,40 @@ public static class DateTimeHumanize
{
private static readonly object LockObject = new();

private static void VerifyWithCurrentDate(string expectedString, TimeSpan deltaFromNow, CultureInfo? culture)
private static void VerifyWithCurrentDate(string expectedString, string expectedCultureName, TimeSpan deltaFromNow, CultureInfo? culture)
{
var utcNow = DateTime.UtcNow;
var localNow = DateTime.Now;

// feels like the only way to avoid breaking tests because CPU ticks over is to inject the base date
VerifyWithDate(expectedString, deltaFromNow, culture, localNow, utcNow);
VerifyWithDate(expectedString, expectedCultureName, deltaFromNow, culture, localNow, utcNow);
}

private static void VerifyWithDateInjection(string expectedString, TimeSpan deltaFromNow, CultureInfo? culture)
private static void VerifyWithDateInjection(string expectedString, string expectedCultureName, TimeSpan deltaFromNow, CultureInfo? culture)
{
var utcNow = new DateTime(2013, 6, 20, 9, 58, 22, DateTimeKind.Utc);
var now = new DateTime(2013, 6, 20, 11, 58, 22, DateTimeKind.Local);

VerifyWithDate(expectedString, deltaFromNow, culture, now, utcNow);
VerifyWithDate(expectedString, expectedCultureName, deltaFromNow, culture, now, utcNow);
}

private static void VerifyWithDate(string expectedString, TimeSpan deltaFromBase, CultureInfo? culture, DateTime? baseDate, DateTime? baseDateUtc)
private static void VerifyWithDate(string expectedString, string expectedCultureName, TimeSpan deltaFromBase, CultureInfo? culture, DateTime? baseDate, DateTime? baseDateUtc)
{
Assert.Equal(expectedCultureName, culture?.Name ?? CultureInfo.CurrentCulture.Name);

if (culture == null)
{
Assert.Equal(expectedString, baseDateUtc?.Add(deltaFromBase).Humanize(utcDate: true, dateToCompareAgainst: baseDateUtc));
Assert.Equal(expectedString, baseDate?.Add(deltaFromBase).Humanize(baseDate, utcDate: false));
Assert.Equal(expectedString, baseDate?.Add(deltaFromBase).Humanize(baseDate, utcDate: false, culture: culture));
}
else
{
Assert.Equal(expectedString, baseDateUtc?.Add(deltaFromBase).Humanize(utcDate: true, dateToCompareAgainst: baseDateUtc, culture: culture));
Assert.Equal(expectedString, baseDate?.Add(deltaFromBase).Humanize(culture, baseDate, utcDate: false));
Assert.Equal(expectedString, baseDate?.Add(deltaFromBase).Humanize(baseDate, utcDate: false, culture: culture));
}
}

public static void Verify(string expectedString, int unit, TimeUnit timeUnit, Tense tense, CultureInfo? culture = null, DateTime? baseDate = null, DateTime? baseDateUtc = null)
public static void Verify(string expectedString, string expectedCultureName, int unit, TimeUnit timeUnit, Tense tense, CultureInfo? culture = null, DateTime? baseDate = null, DateTime? baseDateUtc = null)
{
// We lock this as these tests can be multi-threaded and we're setting a static
lock (LockObject)
Expand Down Expand Up @@ -82,11 +84,11 @@ public static void Verify(string expectedString, int unit, TimeUnit timeUnit, Te

if (baseDate == null)
{
VerifyWithCurrentDate(expectedString, deltaFromNow, culture);
VerifyWithDateInjection(expectedString, deltaFromNow, culture);
VerifyWithCurrentDate(expectedString, expectedCultureName, deltaFromNow, culture);
VerifyWithDateInjection(expectedString, expectedCultureName, deltaFromNow, culture);
}
else
VerifyWithDate(expectedString, deltaFromNow, culture, baseDate, baseDateUtc);
VerifyWithDate(expectedString, expectedCultureName, deltaFromNow, culture, baseDate, baseDateUtc);
}
}
}
Expand Down
30 changes: 16 additions & 14 deletions src/MyNet.Humanizer.UnitTests/DateTimeHumanizeExtensionsFrTests.cs
Original file line number Diff line number Diff line change
@@ -1,85 +1,87 @@
// Copyright (c) Stéphane ANDRE. All Right Reserved.
// See the LICENSE file in the project root for more information.

using MyNet.Utilities.Units;
using MyNet.Humanizer.DateTimes;
using MyNet.Utilities.Units;
using Xunit;

namespace MyNet.Humanizer.UnitTests
{
[UseCulture("fr-FR")]
[UseCulture(Culture)]
[Collection("UseCultureSequential")]
public class DateTimeHumanizeExtensionsFrTests
{
public const string Culture = "fr-FR";

[Theory]
[InlineData(1, "il y a 1 seconde")]
[InlineData(2, "il y a 2 secondes")]
[InlineData(10, "il y a 10 secondes")]
public void SecondsAgo(int seconds, string expected) => DateTimeHumanize.Verify(expected, seconds, TimeUnit.Second, Tense.Past);
public void SecondsAgo(int seconds, string expected) => DateTimeHumanize.Verify(expected, Culture, seconds, TimeUnit.Second, Tense.Past);

[Theory]
[InlineData(1, "dans 1 seconde")]
[InlineData(2, "dans 2 secondes")]
[InlineData(10, "dans 10 secondes")]
public void SecondsFromNow(int seconds, string expected) => DateTimeHumanize.Verify(expected, seconds, TimeUnit.Second, Tense.Future);
public void SecondsFromNow(int seconds, string expected) => DateTimeHumanize.Verify(expected, Culture, seconds, TimeUnit.Second, Tense.Future);

[Theory]
[InlineData(1, "il y a 1 minute")]
[InlineData(2, "il y a 2 minutes")]
[InlineData(10, "il y a 10 minutes")]
[InlineData(60, "il y a 1 heure")]
public void MinutesAgo(int minutes, string expected) => DateTimeHumanize.Verify(expected, minutes, TimeUnit.Minute, Tense.Past);
public void MinutesAgo(int minutes, string expected) => DateTimeHumanize.Verify(expected, Culture, minutes, TimeUnit.Minute, Tense.Past);

[Theory]
[InlineData(1, "dans 1 minute")]
[InlineData(2, "dans 2 minutes")]
[InlineData(10, "dans 10 minutes")]
public void MinutesFromNow(int minutes, string expected) => DateTimeHumanize.Verify(expected, minutes, TimeUnit.Minute, Tense.Future);
public void MinutesFromNow(int minutes, string expected) => DateTimeHumanize.Verify(expected, Culture, minutes, TimeUnit.Minute, Tense.Future);

[Theory]
[InlineData(1, "il y a 1 heure")]
[InlineData(2, "il y a 2 heures")]
[InlineData(10, "il y a 10 heures")]
public void HoursAgo(int hours, string expected) => DateTimeHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Past);
public void HoursAgo(int hours, string expected) => DateTimeHumanize.Verify(expected, Culture, hours, TimeUnit.Hour, Tense.Past);

[Theory]
[InlineData(1, "dans 1 heure")]
[InlineData(2, "dans 2 heures")]
[InlineData(10, "dans 10 heures")]
public void HoursFromNow(int hours, string expected) => DateTimeHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Future);
public void HoursFromNow(int hours, string expected) => DateTimeHumanize.Verify(expected, Culture, hours, TimeUnit.Hour, Tense.Future);

[Theory]
[InlineData(1, "hier")]
[InlineData(2, "il y a 2 jours")]
[InlineData(10, "il y a 10 jours")]
public void DaysAgo(int days, string expected) => DateTimeHumanize.Verify(expected, days, TimeUnit.Day, Tense.Past);
public void DaysAgo(int days, string expected) => DateTimeHumanize.Verify(expected, Culture, days, TimeUnit.Day, Tense.Past);

[Theory]
[InlineData(1, "demain")]
[InlineData(2, "dans 2 jours")]
[InlineData(10, "dans 10 jours")]
public void DaysFromNow(int days, string expected) => DateTimeHumanize.Verify(expected, days, TimeUnit.Day, Tense.Future);
public void DaysFromNow(int days, string expected) => DateTimeHumanize.Verify(expected, Culture, days, TimeUnit.Day, Tense.Future);

[Theory]
[InlineData(1, "il y a 1 mois")]
[InlineData(2, "il y a 2 mois")]
[InlineData(10, "il y a 10 mois")]
public void MonthsAgo(int months, string expected) => DateTimeHumanize.Verify(expected, months, TimeUnit.Month, Tense.Past);
public void MonthsAgo(int months, string expected) => DateTimeHumanize.Verify(expected, Culture, months, TimeUnit.Month, Tense.Past);

[Theory]
[InlineData(1, "dans 1 mois")]
[InlineData(2, "dans 2 mois")]
[InlineData(10, "dans 10 mois")]
public void MonthsFromNow(int months, string expected) => DateTimeHumanize.Verify(expected, months, TimeUnit.Month, Tense.Future);
public void MonthsFromNow(int months, string expected) => DateTimeHumanize.Verify(expected, Culture, months, TimeUnit.Month, Tense.Future);

[Theory]
[InlineData(1, "il y a 1 an")]
[InlineData(2, "il y a 2 ans")]
public void YearsAgo(int years, string expected) => DateTimeHumanize.Verify(expected, years, TimeUnit.Year, Tense.Past);
public void YearsAgo(int years, string expected) => DateTimeHumanize.Verify(expected, Culture, years, TimeUnit.Year, Tense.Past);

[Theory]
[InlineData(1, "dans 1 an")]
[InlineData(2, "dans 2 ans")]
public void YearsFromNow(int years, string expected) => DateTimeHumanize.Verify(expected, years, TimeUnit.Year, Tense.Future);
public void YearsFromNow(int years, string expected) => DateTimeHumanize.Verify(expected, Culture, years, TimeUnit.Year, Tense.Future);
}
}
33 changes: 18 additions & 15 deletions src/MyNet.Humanizer.UnitTests/DateTimeHumanizeExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,25 @@

namespace MyNet.Humanizer.UnitTests
{
[UseCulture("en-US")]
[UseCulture(Culture)]
[Collection("UseCultureSequential")]
public class DateTimeHumanizeExtensionsTests
{
public const string Culture = "en-US";

[Theory]
[InlineData(1, "1 second ago")]
[InlineData(10, "10 seconds ago")]
[InlineData(59, "59 seconds ago")]
[InlineData(60, "1 minute ago")]
public void SecondsAgo(int seconds, string expected) => DateTimeHumanize.Verify(expected, seconds, TimeUnit.Second, Tense.Past);
public void SecondsAgo(int seconds, string expected) => DateTimeHumanize.Verify(expected, Culture, seconds, TimeUnit.Second, Tense.Past);

[Theory]
[InlineData(1, "1 second from now")]
[InlineData(10, "10 seconds from now")]
[InlineData(59, "59 seconds from now")]
[InlineData(60, "1 minute from now")]
public void SecondsFromNow(int seconds, string expected) => DateTimeHumanize.Verify(expected, seconds, TimeUnit.Second, Tense.Future);
public void SecondsFromNow(int seconds, string expected) => DateTimeHumanize.Verify(expected, Culture, seconds, TimeUnit.Second, Tense.Future);

[Theory]
[InlineData(1, "1 minute ago")]
Expand All @@ -35,7 +38,7 @@ public class DateTimeHumanizeExtensionsTests
[InlineData(60, "1 hour ago")]
[InlineData(119, "2 hours ago")]
[InlineData(120, "2 hours ago")]
public void MinutesAgo(int minutes, string expected) => DateTimeHumanize.Verify(expected, minutes, TimeUnit.Minute, Tense.Past);
public void MinutesAgo(int minutes, string expected) => DateTimeHumanize.Verify(expected, Culture, minutes, TimeUnit.Minute, Tense.Past);

[Theory]
[InlineData(1, "1 minute from now")]
Expand All @@ -44,21 +47,21 @@ public class DateTimeHumanizeExtensionsTests
[InlineData(45, "45 minutes from now")]
[InlineData(119, "2 hours from now")]
[InlineData(120, "2 hours from now")]
public void MinutesFromNow(int minutes, string expected) => DateTimeHumanize.Verify(expected, minutes, TimeUnit.Minute, Tense.Future);
public void MinutesFromNow(int minutes, string expected) => DateTimeHumanize.Verify(expected, Culture, minutes, TimeUnit.Minute, Tense.Future);

[Theory]
[InlineData(1, "1 hour ago")]
[InlineData(10, "10 hours ago")]
[InlineData(23, "23 hours ago")]
[InlineData(24, "yesterday")]
public void HoursAgo(int hours, string expected) => DateTimeHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Past);
public void HoursAgo(int hours, string expected) => DateTimeHumanize.Verify(expected, Culture, hours, TimeUnit.Hour, Tense.Past);

[Theory]
[InlineData(1, "1 hour from now")]
[InlineData(10, "10 hours from now")]
[InlineData(23, "23 hours from now")]
[InlineData(24, "tomorrow")]
public void HoursFromNow(int hours, string expected) => DateTimeHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Future);
public void HoursFromNow(int hours, string expected) => DateTimeHumanize.Verify(expected, Culture, hours, TimeUnit.Hour, Tense.Future);

[Theory]
[InlineData(35, "tomorrow")]
Expand All @@ -69,46 +72,46 @@ public void HoursFromNowNotTomorrow(int hours, string expected)
var utcNow = new DateTime(2014, 6, 28, 9, 58, 22, DateTimeKind.Utc);
var now = new DateTime(2014, 6, 28, 9, 58, 22, DateTimeKind.Local);

DateTimeHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Future, null, now, utcNow);
DateTimeHumanize.Verify(expected, Culture, hours, TimeUnit.Hour, Tense.Future, null, now, utcNow);
}

[Theory]
[InlineData(1, "yesterday")]
[InlineData(10, "10 days ago")]
[InlineData(27, "4 weeks ago")]
[InlineData(32, "5 weeks ago")]
public void DaysAgo(int days, string expected) => DateTimeHumanize.Verify(expected, days, TimeUnit.Day, Tense.Past);
public void DaysAgo(int days, string expected) => DateTimeHumanize.Verify(expected, Culture, days, TimeUnit.Day, Tense.Past);

[Theory]
[InlineData(1, "tomorrow")]
[InlineData(10, "10 days from now")]
[InlineData(27, "4 weeks from now")]
[InlineData(32, "5 weeks from now")]
public void DaysFromNow(int days, string expected) => DateTimeHumanize.Verify(expected, days, TimeUnit.Day, Tense.Future);
public void DaysFromNow(int days, string expected) => DateTimeHumanize.Verify(expected, Culture, days, TimeUnit.Day, Tense.Future);

[Theory]
[InlineData(1, "1 month ago")]
[InlineData(10, "10 months ago")]
[InlineData(11, "11 months ago")]
[InlineData(12, "1 year ago")]
public void MonthsAgo(int months, string expected) => DateTimeHumanize.Verify(expected, months, TimeUnit.Month, Tense.Past);
public void MonthsAgo(int months, string expected) => DateTimeHumanize.Verify(expected, Culture, months, TimeUnit.Month, Tense.Past);

[Theory]
[InlineData(1, "1 month from now")]
[InlineData(10, "10 months from now")]
[InlineData(11, "11 months from now")]
[InlineData(12, "1 year from now")]
public void MonthsFromNow(int months, string expected) => DateTimeHumanize.Verify(expected, months, TimeUnit.Month, Tense.Future);
public void MonthsFromNow(int months, string expected) => DateTimeHumanize.Verify(expected, Culture, months, TimeUnit.Month, Tense.Future);

[Theory]
[InlineData(1, "1 year ago")]
[InlineData(2, "2 years ago")]
public void YearsAgo(int years, string expected) => DateTimeHumanize.Verify(expected, years, TimeUnit.Year, Tense.Past);
public void YearsAgo(int years, string expected) => DateTimeHumanize.Verify(expected, Culture, years, TimeUnit.Year, Tense.Past);

[Theory]
[InlineData(1, "1 year from now")]
[InlineData(2, "2 years from now")]
public void YearsFromNow(int years, string expected) => DateTimeHumanize.Verify(expected, years, TimeUnit.Year, Tense.Future);
public void YearsFromNow(int years, string expected) => DateTimeHumanize.Verify(expected, Culture, years, TimeUnit.Year, Tense.Future);

[Fact]
public void Never()
Expand All @@ -128,6 +131,6 @@ public void Nullable_ExpectSame()
[Theory]
[InlineData(1, TimeUnit.Year, Tense.Future, "en-US", "1 year from now")]
[InlineData(40, TimeUnit.Second, Tense.Past, "fr-FR", "il y a 40 secondes")]
public void CanSpecifyCultureExplicitly(int unit, TimeUnit timeUnit, Tense tense, string culture, string expected) => DateTimeHumanize.Verify(expected, unit, timeUnit, tense, culture: new CultureInfo(culture));
public void CanSpecifyCultureExplicitly(int unit, TimeUnit timeUnit, Tense tense, string culture, string expected) => DateTimeHumanize.Verify(expected, culture, unit, timeUnit, tense, culture: new CultureInfo(culture));
}
}
2 changes: 1 addition & 1 deletion src/MyNet.Humanizer.UnitTests/DehumanizeToEnumTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace MyNet.Humanizer.UnitTests
public class DehumanizeToEnumTests
{
[Fact]
public void ThrowsForEnumNoMatch() => _ = Assert.Throws<NoMatchFoundException>(() => EnumTestsResources.MemberWithDescriptionAttribute.DehumanizeTo<Dummy>());
public void ThrowsForEnumNoMatch() => _ = Assert.Throws<NoMatchFoundException>(() => EnumTestsResources.MemberWithDescriptionAttribute.DehumanizeTo<Dummy>(onNoMatch: OnNoMatch.ThrowsException));

[Fact]
public void DehumanizeMembersWithoutDescriptionAttribute() => Assert.Equal(EnumUnderTest.MemberWithoutDescriptionAttribute, EnumUnderTest.MemberWithoutDescriptionAttribute.ToString().DehumanizeTo<EnumUnderTest>());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace MyNet.Humanizer.UnitTests
{
[UseCulture("en-US")]
[Collection("UseCultureSequential")]
public class MetricNumeralExtensionsTests
{
// Return a sequence of -24 -> 26
Expand Down
Loading

0 comments on commit 83849a6

Please sign in to comment.