-
Notifications
You must be signed in to change notification settings - Fork 1
HEEDLS-553 Date Input Validation #497
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
457f4d4
HEEDLS-553 Refactor DateInput VC; make WelcomeEmail VM validatable
ibrahimmunir14 5ae2b27
HEEDLS-553 Write New DateValidator helper class; use to perform date …
ibrahimmunir14 c3d357d
HEEDLS-553 Rename old DateValidator to OldDateValidator
ibrahimmunir14 936eb3c
HEEDLS-553 Rename NewDateValidator to DateValidator; write DataValida…
ibrahimmunir14 4a51fbc
HEEDLS-553 Refactor DateValidator, check date ranges before attemptin…
ibrahimmunir14 52d1e55
HEEDLS-553 Move error border logic into DateInput VC; update VC to ac…
ibrahimmunir14 5aa884e
HEEDLS-553 Improve DateValidator error messages for missing values in…
ibrahimmunir14 be9b4ca
HEEDLS-553 Use numeric text instead of number input; invert if; wordi…
ibrahimmunir14 bbd18aa
HEEDLS-553 Fix test
ibrahimmunir14 f501199
HEEDLS-553 Move DateValidators to Helpers; error message wording chan…
ibrahimmunir14 8db4528
HEEDLS-553 Make DateValidator error messages more specific for invali…
ibrahimmunir14 629a8a1
HEEDLS-553 Move ToValidationResultsList into DateValidationResult; ad…
ibrahimmunir14 5bc2599
HEEDLS-553 Add tests for DateValidationResult
ibrahimmunir14 eb5a5f2
HEEDLS-553 Simplify a ToValidationResultList test
ibrahimmunir14 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
386 changes: 237 additions & 149 deletions
386
DigitalLearningSolutions.Web.Tests/ControllerHelpers/DateValidatorTests.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,149 +1,237 @@ | ||
| namespace DigitalLearningSolutions.Web.Tests.ControllerHelpers | ||
| { | ||
| using DigitalLearningSolutions.Web.ControllerHelpers; | ||
| using FluentAssertions; | ||
| using NUnit.Framework; | ||
|
|
||
| public class DateValidatorTests | ||
| { | ||
| [Test] | ||
| public void Date_validator_returns_valid_for_valid_date() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(1, 1, 3020); | ||
|
|
||
| // Then | ||
| result.DateValid.Should().BeTrue(); | ||
| result.DayValid.Should().BeTrue(); | ||
| result.MonthValid.Should().BeTrue(); | ||
| result.YearValid.Should().BeTrue(); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Date_validator_returns_valid_for_empty_date() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(0, 0, 0); | ||
|
|
||
| // Then | ||
| result.DateValid.Should().BeTrue(); | ||
| result.DayValid.Should().BeTrue(); | ||
| result.MonthValid.Should().BeTrue(); | ||
| result.YearValid.Should().BeTrue(); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Date_validator_returns_invalid_for_a_date_with_day_missing() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(0, 1, 2020); | ||
|
|
||
| // Then | ||
| result.DateValid.Should().BeFalse(); | ||
| result.DayValid.Should().BeFalse(); | ||
| result.ErrorMessage.Should().Be("Complete by date must include a day"); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Date_validator_returns_invalid_for_a_date_with_day_and_month_missing() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(0, 0, 2020); | ||
|
|
||
| // Then | ||
| result.DateValid.Should().BeFalse(); | ||
| result.DayValid.Should().BeFalse(); | ||
| result.ErrorMessage.Should().Be("Complete by date must include a day and month"); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Date_validator_returns_invalid_for_a_date_with_day_and_year_missing() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(0, 1, 0); | ||
|
|
||
| // Then | ||
| result.DateValid.Should().BeFalse(); | ||
| result.DayValid.Should().BeFalse(); | ||
| result.MonthValid.Should().BeFalse(); | ||
| result.YearValid.Should().BeFalse(); | ||
| result.ErrorMessage.Should().Be("Complete by date must include a day and year"); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Date_validator_returns_invalid_for_a_date_with_month_missing() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(1, 0, 2020); | ||
|
|
||
| // Then | ||
| result.DateValid.Should().BeFalse(); | ||
| result.MonthValid.Should().BeFalse(); | ||
| result.ErrorMessage.Should().Be("Complete by date must include a month"); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Date_validator_returns_invalid_for_a_date_with_month_and_year_missing() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(1, 0, 0); | ||
|
|
||
| // Then | ||
| result.DateValid.Should().BeFalse(); | ||
| result.DayValid.Should().BeFalse(); | ||
| result.MonthValid.Should().BeFalse(); | ||
| result.YearValid.Should().BeFalse(); | ||
| result.ErrorMessage.Should().Be("Complete by date must include a month and year"); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Date_validator_returns_invalid_for_a_date_with_bad_day() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(32, 1, 2020); | ||
|
|
||
| // Then | ||
| result.DateValid.Should().BeFalse(); | ||
| result.DayValid.Should().BeFalse(); | ||
| result.ErrorMessage.Should().Be("Complete by date must be a real date"); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Date_validator_returns_invalid_for_a_date_with_bad_month() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(31, 13, 2020); | ||
|
|
||
| // Then | ||
| result.DateValid.Should().BeFalse(); | ||
| result.MonthValid.Should().BeFalse(); | ||
| result.ErrorMessage.Should().Be("Complete by date must be a real date"); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Date_validator_returns_invalid_for_a_date_with_bad_year() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(31, 1, 20201); | ||
|
|
||
| // Then | ||
| result.DateValid.Should().BeFalse(); | ||
| result.YearValid.Should().BeFalse(); | ||
| result.ErrorMessage.Should().Be("Complete by date must be a real date"); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Date_validator_returns_invalid_for_a_date_with_bad_date() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(31, 2, 2020); | ||
|
|
||
| // Then | ||
| result.DateValid.Should().BeFalse(); | ||
| result.DayValid.Should().BeFalse(); | ||
| result.MonthValid.Should().BeFalse(); | ||
| result.YearValid.Should().BeFalse(); | ||
| result.ErrorMessage.Should().Be("Complete by date must be a real date"); | ||
| } | ||
| } | ||
| } | ||
| namespace DigitalLearningSolutions.Web.Tests.ControllerHelpers | ||
| { | ||
| using System.Linq; | ||
| using DigitalLearningSolutions.Web.Helpers; | ||
| using FluentAssertions; | ||
| using NUnit.Framework; | ||
|
|
||
| public class DateValidatorTests | ||
| { | ||
| [Test] | ||
| public void ValidateDate_returns_valid_for_valid_date() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(1, 1, 3000); | ||
|
|
||
| // Then | ||
| result.HasDayError.Should().BeFalse(); | ||
| result.HasMonthError.Should().BeFalse(); | ||
| result.HasYearError.Should().BeFalse(); | ||
| result.ErrorMessage.Should().BeNull(); | ||
| } | ||
|
|
||
| [Test] | ||
| public void ValidateDate_returns_valid_for_empty_non_required_date() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(null, null, null, required: false); | ||
|
|
||
| // Then | ||
| result.HasDayError.Should().BeFalse(); | ||
| result.HasMonthError.Should().BeFalse(); | ||
| result.HasYearError.Should().BeFalse(); | ||
| result.ErrorMessage.Should().BeNull(); | ||
| } | ||
|
|
||
| [Test] | ||
| public void ValidateDate_returns_appropriate_error_for_empty_required_date() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(null, null, null, required: true); | ||
|
|
||
| // Then | ||
| result.HasDayError.Should().BeTrue(); | ||
| result.HasMonthError.Should().BeTrue(); | ||
| result.HasYearError.Should().BeTrue(); | ||
| result.ErrorMessage.Should().Be("Date is required"); | ||
| } | ||
|
|
||
| [TestCase(null, 1, 3000, "a day")] | ||
| [TestCase(1, null, 3000, "a month")] | ||
| [TestCase(1, 1, null, "a year")] | ||
| [TestCase(null, null, 3000, "a day and a month")] | ||
| [TestCase(null, 1, null, "a day and a year")] | ||
| [TestCase(1, null, null, "a month and a year")] | ||
| public void ValidateDate_returns_appropriate_error_if_some_values_missing( | ||
| int? day, | ||
| int? month, | ||
| int? year, | ||
| string errorMessageEnding | ||
| ) | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(day, month, year); | ||
|
|
||
| // Then | ||
| result.HasDayError.Should().Be(!day.HasValue); | ||
| result.HasMonthError.Should().Be(!month.HasValue); | ||
| result.HasYearError.Should().Be(!year.HasValue); | ||
| result.ErrorMessage.Should().Be("Date must include " + errorMessageEnding); | ||
| } | ||
|
|
||
| [Test] | ||
| public void ValidateDate_returns_appropriate_error_if_all_values_invalid() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(0, 0, 0, required: true); | ||
|
|
||
| // Then | ||
| result.HasDayError.Should().BeTrue(); | ||
| result.HasMonthError.Should().BeTrue(); | ||
| result.HasYearError.Should().BeTrue(); | ||
| result.ErrorMessage.Should().Be("Date must be a real date"); | ||
| } | ||
|
|
||
| [TestCase(0, 1, 3000, true, false, false, "day")] | ||
| [TestCase(32, 1, 3000, true, false, false, "day")] | ||
| [TestCase(1, 0, 3000, false, true, false, "month")] | ||
| [TestCase(1, 13, 3000, false, true, false, "month")] | ||
| [TestCase(1, 1, 0, false, false, true, "year")] | ||
| [TestCase(1, 1, 10000, false, false, true, "year")] | ||
| [TestCase(0, 0, 3000, true, true, false, "day and month")] | ||
| [TestCase(0, 1, 0, true, false, true, "day and year")] | ||
| [TestCase(1, 0, 0, false, true, true, "month and year")] | ||
| public void ValidateDate_returns_appropriate_error_if_some_values_invalid( | ||
| int day, | ||
| int month, | ||
| int year, | ||
| bool dayError, | ||
| bool monthError, | ||
| bool yearError, | ||
| string errorMessageEnding | ||
| ) | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(day, month, year); | ||
|
|
||
| // Then | ||
| result.HasDayError.Should().Be(dayError); | ||
| result.HasMonthError.Should().Be(monthError); | ||
| result.HasYearError.Should().Be(yearError); | ||
| result.ErrorMessage.Should().Be("Date must include a real " + errorMessageEnding); | ||
| } | ||
|
|
||
| [Test] | ||
| public void ValidateDate_returns_appropriate_error_if_date_not_real() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(30, 2, 3000); | ||
|
|
||
| // Then | ||
| result.HasDayError.Should().BeTrue(); | ||
| result.HasMonthError.Should().BeTrue(); | ||
| result.HasYearError.Should().BeTrue(); | ||
| result.ErrorMessage.Should().Be("Date must be a real date"); | ||
| } | ||
|
|
||
| [Test] | ||
| public void ValidateDate_returns_appropriate_error_if_date_not_in_future() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(1, 1, 2000); | ||
|
|
||
| // Then | ||
| result.HasDayError.Should().BeTrue(); | ||
| result.HasMonthError.Should().BeTrue(); | ||
| result.HasYearError.Should().BeTrue(); | ||
| result.ErrorMessage.Should().Be("Date must be in the future"); | ||
| } | ||
|
|
||
| [Test] | ||
| public void ValidateDate_uses_name_correctly_in_error_message() | ||
| { | ||
| // When | ||
| var result = DateValidator.ValidateDate(null, null, null, "What's required", true); | ||
|
|
||
| // Then | ||
| result.HasDayError.Should().BeTrue(); | ||
| result.HasMonthError.Should().BeTrue(); | ||
| result.HasYearError.Should().BeTrue(); | ||
| result.ErrorMessage.Should().Be("What's required is required"); | ||
| } | ||
|
|
||
| [TestCase(true, false, false, "Day")] | ||
| [TestCase(false, true, false, "Month")] | ||
| [TestCase(false, false, true, "Year")] | ||
| [TestCase(true, true, false, "Day", "Month")] | ||
| [TestCase(true, false, true, "Day", "Year")] | ||
| [TestCase(false, true, true, "Month", "Year")] | ||
| [TestCase(true, true, true, "Day", "Month", "Year")] | ||
| public void ToValidationResultList_includes_one_error_for_each_erroneous_part_of_date( | ||
| bool hasDayError, | ||
| bool hasMonthError, | ||
| bool hasYearError, | ||
| params string[] errorMemberNames | ||
| ) | ||
| { | ||
| // Given | ||
| var dateValidationResult = new DateValidator.DateValidationResult( | ||
| hasDayError, | ||
| hasMonthError, | ||
| hasYearError, | ||
| "msg" | ||
| ); | ||
|
|
||
| // When | ||
| var result = dateValidationResult.ToValidationResultList("Day", "Month", "Year"); | ||
|
|
||
| // Then | ||
| result.Should().HaveCount(errorMemberNames.Length); | ||
| foreach (var memberName in errorMemberNames) | ||
| { | ||
| result.Should().Contain( | ||
| validationResult => | ||
| validationResult.MemberNames.Count() == 1 && validationResult.MemberNames.Contains(memberName) | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| [Test] | ||
| public void ToValidationResultList_includes_errors_in_appropriate_order() | ||
| { | ||
| // Given | ||
| var dateValidationResult = new DateValidator.DateValidationResult(true, true, true, "msg"); | ||
|
|
||
| // When | ||
| var result = dateValidationResult.ToValidationResultList("Day", "Month", "Year"); | ||
|
|
||
| // Then | ||
| result[0].MemberNames.Should().Contain("Day"); | ||
| result[1].MemberNames.Should().Contain("Month"); | ||
| result[2].MemberNames.Should().Contain("Year"); | ||
| } | ||
|
|
||
| [Test] | ||
| public void ToValidationResultList_only_includes_message_for_first_erroneous_part_of_date() | ||
| { | ||
| // Given | ||
| const string errorMessage = "msg"; | ||
| var dateValidationResult = new DateValidator.DateValidationResult(false, true, true, errorMessage); | ||
|
|
||
| // When | ||
| var result = dateValidationResult.ToValidationResultList("Day", "Month", "Year"); | ||
|
|
||
| // Then | ||
| result[0].ErrorMessage.Should().Be(errorMessage); | ||
| result[1].ErrorMessage.Should().Be(string.Empty); | ||
| } | ||
|
|
||
| [Test] | ||
| public void ToValidationResultList_uses_correct_member_names_for_errors() | ||
| { | ||
| // Given | ||
| var dateValidationResult = new DateValidator.DateValidationResult(true, true, true, "msg"); | ||
| const string dayId = "TheDay"; | ||
| const string monthId = "TheMonth"; | ||
| const string yearId = "TheYear"; | ||
|
|
||
| // When | ||
| var result = dateValidationResult.ToValidationResultList(dayId, monthId, yearId); | ||
|
|
||
| // Then | ||
| result[0].MemberNames.Should().Contain(dayId); | ||
| result[1].MemberNames.Should().Contain(monthId); | ||
| result[2].MemberNames.Should().Contain(yearId); | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.