diff --git a/src/Nox.Types/Types/Year/TypeOptions/YearTypeOptions.cs b/src/Nox.Types/Types/Year/TypeOptions/YearTypeOptions.cs new file mode 100644 index 0000000..b9c8d3c --- /dev/null +++ b/src/Nox.Types/Types/Year/TypeOptions/YearTypeOptions.cs @@ -0,0 +1,11 @@ + +namespace Nox.Types; + +public class YearTypeOptions +{ + public static readonly ushort MinYearValue = 1900; + public static readonly ushort MaxYearValue = 3000; + public ushort MinValue { get; set; } = MinYearValue; + public ushort MaxValue { get; set; } = MaxYearValue; + public bool AllowFutureOnly { get; set; } = false; +} diff --git a/src/Nox.Types/Types/Year/Year.cs b/src/Nox.Types/Types/Year/Year.cs index 5cccbe7..7f94079 100644 --- a/src/Nox.Types/Types/Year/Year.cs +++ b/src/Nox.Types/Types/Year/Year.cs @@ -1,3 +1,5 @@ +using System; + namespace Nox.Types; /// @@ -5,15 +7,34 @@ namespace Nox.Types; /// public sealed class Year : ValueObject { - /// - /// The minimum valid year value. - /// - private const ushort MinYearValue = 1; + private YearTypeOptions _yearTypeOptions = new(); + + public Year() { Value = 0; } /// - /// The maximum valid year value. + /// Creates a new instance of using the specified /// - private const ushort MaxYearValue = 9999; + /// The number to create the with + /// The containing constraints for the value object + /// + /// + public static Year From(ushort value, YearTypeOptions options) + { + var newObject = new Year + { + Value = value, + _yearTypeOptions = options + }; + + var validationResult = newObject.Validate(); + + if (!validationResult.IsValid) + { + throw new TypeValidationException(validationResult.Errors); + } + + return newObject; + } /// /// Validates the object. @@ -23,10 +44,22 @@ internal override ValidationResult Validate() { var result = base.Validate(); - if (Value is < MinYearValue or > MaxYearValue) + if (Value < _yearTypeOptions.MinValue) + { + result.Errors.Add(new ValidationFailure(nameof(Value), $"Could not create a Nox Year type as value {Value} is less than the minimum specified value of {_yearTypeOptions.MinValue}")); + } + + if (Value > _yearTypeOptions.MaxValue) { - result.Errors.Add(new ValidationFailure(nameof(Value), $"Could not create a Nox Year type with unsupported value '{Value}'. The value must be between {MinYearValue} and {MaxYearValue}.")); + result.Errors.Add(new ValidationFailure(nameof(Value), $"Could not create a Nox Year type a value {Value} is greater than the maximum specified value of {_yearTypeOptions.MaxValue}")); } + + if (_yearTypeOptions.AllowFutureOnly && Value < DateTime.Now.Year) + { + result.Errors.Add(new ValidationFailure(nameof(Value), $"Could not create a Nox Year type a value {Value} is less than the current year")); + } + + return result; } diff --git a/tests/Nox.Types.Tests/Types/Year/YearTests.cs b/tests/Nox.Types.Tests/Types/Year/YearTests.cs index 9972800..bb89407 100644 --- a/tests/Nox.Types.Tests/Types/Year/YearTests.cs +++ b/tests/Nox.Types.Tests/Types/Year/YearTests.cs @@ -5,7 +5,7 @@ public class YearTests [Fact] public void Year_Constructor_ReturnsSameValue() { - var testYear = (ushort)1; + var testYear = (ushort)1900; var number = Year.From(testYear); @@ -14,8 +14,10 @@ public void Year_Constructor_ReturnsSameValue() [Theory] [InlineData((ushort)0)] - [InlineData((ushort)(19999))] - public void Year_Constructor_WithoutRangeYear_ThrowsValidationException(ushort value) + [InlineData((ushort)(100))] + [InlineData((ushort)(1889))] + [InlineData((ushort)(1880))] + public void Year_Constructor_WithValueLess_ThanMinimiunSpecified_ThrowsValidationException(ushort value) { // Arrange & Act var exception = Assert.Throws(() => _ = @@ -23,16 +25,32 @@ public void Year_Constructor_WithoutRangeYear_ThrowsValidationException(ushort v ); // Assert - Assert.Equal($"Could not create a Nox Year type with unsupported value '{value}'. The value must be between 1 and 9999.", exception.Errors.First().ErrorMessage); + Assert.Equal($"Could not create a Nox Year type as value {value} is less than the minimum specified value of 1900", exception.Errors.First().ErrorMessage); + } + + [Theory] + [InlineData((ushort)3001)] + [InlineData((ushort)(4001))] + [InlineData((ushort)(5000))] + [InlineData((ushort)(9999))] + public void Year_Constructor_WithValueGreater_ThanMaximunSpecified_ThrowsValidationException(ushort value) + { + // Arrange & Act + var exception = Assert.Throws(() => _ = + Year.From(value) + ); + + // Assert + Assert.Equal($"Could not create a Nox Year type a value {value} is greater than the maximum specified value of 3000", exception.Errors.First().ErrorMessage); } [Fact] public void Year_Equal_Tests() { // Arrange - var year1 = Year.From(1); + var year1 = Year.From(1900); - var year2 = Year.From(1); + var year2 = Year.From(1900); // Assert Assert.Equal(year1, year2); @@ -42,9 +60,9 @@ public void Year_Equal_Tests() public void Year_NotEqual_Tests() { // Arrange - var year1 = Year.From(1); + var year1 = Year.From(2000); - var year2 = Year.From(2); + var year2 = Year.From(2002); // Assert Assert.NotEqual(year1, year2); @@ -55,11 +73,41 @@ public void Year_NotEqual_Tests() public void Year_ToString_ReturnsString() { // Arrange - var year = Year.From(1); - var year2 = Year.From(199); + var year = Year.From(1900); + var year2 = Year.From(1990); // Assert - Assert.Equal("0001", year.ToString()); - Assert.Equal("0199", year2.ToString()); + Assert.Equal("1900", year.ToString()); + Assert.Equal("1990", year2.ToString()); + } + + [Fact] + public void Year_Constructor_SpecifyingAllowFutureOnly_WithPassYearInput_ThrowsException() + { + var yearValue = (ushort)2020; + + Assert.Throws(() => _ = + Year.From(yearValue, new YearTypeOptions { AllowFutureOnly = true }) + ); + } + + [Fact] + public void Year_Constructor_SpecifyingMaxValue_WithGreaterValueInput_ThrowsException() + { + var yearValue = (ushort)1900; + + Assert.Throws(() => _ = + Year.From(yearValue, new YearTypeOptions { MaxValue = 10 }) + ); + } + + [Fact] + public void Year_Constructor_SpecifyingMinValue_WithLesserValueInput_ThrowsException() + { + var yearValue = (ushort)1; + + Assert.Throws(() => _ = + Year.From(yearValue, new YearTypeOptions { MinValue = 50 }) + ); } } \ No newline at end of file