From 95ce7af805ae2f8bcdda238f6fcaf1f95130b33a Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 22 Jun 2021 14:59:34 +0100 Subject: [PATCH 01/22] HEEDLS-526 Create RegistrationData; make DelegateRegistrationData a subclass; add and update helper methods and tests --- .../Helpers/RegistrationMappingHelperTests.cs | 67 +++++++++++++++++-- .../Models/RegistrationDataTests.cs | 56 ++++++++++++++++ .../Helpers/RegistrationMappingHelper.cs | 48 ++++++++----- .../Models/DelegateRegistrationData.cs | 29 +------- .../Models/RegistrationData.cs | 37 ++++++++++ 5 files changed, 190 insertions(+), 47 deletions(-) create mode 100644 DigitalLearningSolutions.Web.Tests/Models/RegistrationDataTests.cs create mode 100644 DigitalLearningSolutions.Web/Models/RegistrationData.cs diff --git a/DigitalLearningSolutions.Web.Tests/Helpers/RegistrationMappingHelperTests.cs b/DigitalLearningSolutions.Web.Tests/Helpers/RegistrationMappingHelperTests.cs index 871262c706..1550437a35 100644 --- a/DigitalLearningSolutions.Web.Tests/Helpers/RegistrationMappingHelperTests.cs +++ b/DigitalLearningSolutions.Web.Tests/Helpers/RegistrationMappingHelperTests.cs @@ -22,7 +22,7 @@ public class RegistrationMappingHelperTests public void MapToDelegateRegistrationModel_returns_correct_DelegateRegistrationModel() { // Given - var data = SampleData(); + var data = SampleDelegateRegistrationData(); // When var result = RegistrationMappingHelper.MapToDelegateRegistrationModel(data); @@ -43,7 +43,23 @@ public void MapToDelegateRegistrationModel_returns_correct_DelegateRegistrationM public void MapDataToPersonalInformation_returns_correct_ViewModel() { // Given - var data = SampleData(); + var data = SampleRegistrationData(); + + // When + var result = RegistrationMappingHelper.MapDataToPersonalInformation(data); + + // Then + result.FirstName.Should().Be(FirstName); + result.LastName.Should().Be(LastName); + result.Email.Should().Be(Email); + result.Centre.Should().Be(CentreId); + } + + [Test] + public void MapDelegateDataToPersonalInformation_returns_correct_ViewModel() + { + // Given + var data = SampleDelegateRegistrationData(); // When var result = RegistrationMappingHelper.MapDataToPersonalInformation(data); @@ -60,7 +76,20 @@ public void MapDataToPersonalInformation_returns_correct_ViewModel() public void MapDataToLearnerInformation_returns_correct_ViewModel() { // Given - var data = SampleData(); + var data = SampleRegistrationData(); + + // When + var result = RegistrationMappingHelper.MapDataToLearnerInformation(data); + + // Then + result.JobGroup.Should().Be(JobGroupId); + } + + [Test] + public void MapDelegateDataToLearnerInformation_returns_correct_ViewModel() + { + // Given + var data = SampleDelegateRegistrationData(); // When var result = RegistrationMappingHelper.MapDataToLearnerInformation(data); @@ -76,7 +105,22 @@ public void MapDataToLearnerInformation_returns_correct_ViewModel() public void MapDataToSummary_returns_correct_ViewModel() { // Given - var data = SampleData(); + var data = SampleRegistrationData(); + + // When + var result = RegistrationMappingHelper.MapDataToSummary(data); + + // Then + result.FirstName.Should().Be(FirstName); + result.LastName.Should().Be(LastName); + result.Email.Should().Be(Email); + } + + [Test] + public void MapDelegateDataToSummary_returns_correct_ViewModel() + { + // Given + var data = SampleDelegateRegistrationData(); // When var result = RegistrationMappingHelper.MapDataToSummary(data); @@ -87,7 +131,20 @@ public void MapDataToSummary_returns_correct_ViewModel() result.Email.Should().Be(Email); } - private static DelegateRegistrationData SampleData() + private static RegistrationData SampleRegistrationData() + { + return new RegistrationData + { + FirstName = FirstName, + LastName = LastName, + Email = Email, + Centre = CentreId, + JobGroup = JobGroupId, + PasswordHash = PasswordHash + }; + } + + private static DelegateRegistrationData SampleDelegateRegistrationData() { return new DelegateRegistrationData { diff --git a/DigitalLearningSolutions.Web.Tests/Models/RegistrationDataTests.cs b/DigitalLearningSolutions.Web.Tests/Models/RegistrationDataTests.cs new file mode 100644 index 0000000000..14a91ee584 --- /dev/null +++ b/DigitalLearningSolutions.Web.Tests/Models/RegistrationDataTests.cs @@ -0,0 +1,56 @@ +namespace DigitalLearningSolutions.Web.Tests.Models +{ + using DigitalLearningSolutions.Web.Models; + using DigitalLearningSolutions.Web.ViewModels.Register; + using FluentAssertions; + using NUnit.Framework; + + internal class RegistrationDataTests + { + private const string FirstName = "Test"; + private const string LastName = "User"; + private const string Email = "test@email.com"; + private const int CentreId = 5; + private const int JobGroupId = 10; + + [Test] + public void SetPersonalInformation_sets_data_correctly() + { + // Given + var model = new PersonalInformationViewModel + { + FirstName = FirstName, + LastName = LastName, + Centre = CentreId, + Email = Email + }; + var data = new RegistrationData(); + + // When + data.SetPersonalInformation(model); + + // Then + data.FirstName.Should().Be(FirstName); + data.LastName.Should().Be(LastName); + data.Email.Should().Be(Email); + data.Centre.Should().Be(CentreId); + } + + [Test] + public void SetLearnerInformation_sets_data_correctly() + { + // Given + var model = new LearnerInformationViewModel + { + JobGroup = JobGroupId + }; + var data = new RegistrationData(); + + // When + data.SetLearnerInformation(model); + + // Then + data.JobGroup.Should().Be(JobGroupId); + } + } +} diff --git a/DigitalLearningSolutions.Web/Helpers/RegistrationMappingHelper.cs b/DigitalLearningSolutions.Web/Helpers/RegistrationMappingHelper.cs index 154ef84fd2..36c22b34cf 100644 --- a/DigitalLearningSolutions.Web/Helpers/RegistrationMappingHelper.cs +++ b/DigitalLearningSolutions.Web/Helpers/RegistrationMappingHelper.cs @@ -24,43 +24,59 @@ public static DelegateRegistrationModel MapToDelegateRegistrationModel(DelegateR ); } - public static SummaryViewModel MapDataToSummary(DelegateRegistrationData data) + public static SummaryViewModel MapDataToSummary(RegistrationData data) { return new SummaryViewModel { FirstName = data.FirstName!, LastName = data.LastName!, - Email = data.Email!, - IsCentreSpecificRegistration = data.IsCentreSpecificRegistration + Email = data.Email! }; } - public static PersonalInformationViewModel MapDataToPersonalInformation(DelegateRegistrationData data) + public static SummaryViewModel MapDataToSummary(DelegateRegistrationData data) + { + var model = MapDataToSummary((RegistrationData)data); + model.IsCentreSpecificRegistration = data.IsCentreSpecificRegistration; + return model; + } + + public static PersonalInformationViewModel MapDataToPersonalInformation(RegistrationData data) { return new PersonalInformationViewModel { FirstName = data.FirstName, LastName = data.LastName, Centre = data.Centre, - Email = data.Email, - IsCentreSpecificRegistration = data.IsCentreSpecificRegistration + Email = data.Email }; } - public static LearnerInformationViewModel MapDataToLearnerInformation( - DelegateRegistrationData data - ) + public static PersonalInformationViewModel MapDataToPersonalInformation(DelegateRegistrationData data) + { + var model = MapDataToPersonalInformation((RegistrationData)data); + model.IsCentreSpecificRegistration = data.IsCentreSpecificRegistration; + return model; + } + + public static LearnerInformationViewModel MapDataToLearnerInformation(RegistrationData data) { return new LearnerInformationViewModel { - JobGroup = data.JobGroup, - Answer1 = data.Answer1, - Answer2 = data.Answer2, - Answer3 = data.Answer3, - Answer4 = data.Answer4, - Answer5 = data.Answer5, - Answer6 = data.Answer6 + JobGroup = data.JobGroup }; } + + public static LearnerInformationViewModel MapDataToLearnerInformation(DelegateRegistrationData data) + { + var model = MapDataToLearnerInformation((RegistrationData)data); + model.Answer1 = data.Answer1; + model.Answer2 = data.Answer2; + model.Answer3 = data.Answer3; + model.Answer4 = data.Answer4; + model.Answer5 = data.Answer5; + model.Answer6 = data.Answer6; + return model; + } } } diff --git a/DigitalLearningSolutions.Web/Models/DelegateRegistrationData.cs b/DigitalLearningSolutions.Web/Models/DelegateRegistrationData.cs index 149438028d..6bb17bf0aa 100644 --- a/DigitalLearningSolutions.Web/Models/DelegateRegistrationData.cs +++ b/DigitalLearningSolutions.Web/Models/DelegateRegistrationData.cs @@ -1,42 +1,19 @@ namespace DigitalLearningSolutions.Web.Models { - using System; using DigitalLearningSolutions.Web.ViewModels.Register; - public class DelegateRegistrationData + public class DelegateRegistrationData : RegistrationData { - public DelegateRegistrationData() - { - Id = new Guid(); - } - - public Guid Id { get; set; } - - public string? FirstName { get; set; } - public string? LastName { get; set; } - public string? Email { get; set; } - public int? Centre { get; set; } public bool IsCentreSpecificRegistration { get; set; } - public int? JobGroup { get; set; } public string? Answer1 { get; set; } public string? Answer2 { get; set; } public string? Answer3 { get; set; } public string? Answer4 { get; set; } public string? Answer5 { get; set; } public string? Answer6 { get; set; } - - public string? PasswordHash { get; set; } - - public void SetPersonalInformation(PersonalInformationViewModel model) - { - Centre = model.Centre; - Email = model.Email; - FirstName = model.FirstName; - LastName = model.LastName; - } - - public void SetLearnerInformation(LearnerInformationViewModel model) + + public new void SetLearnerInformation(LearnerInformationViewModel model) { JobGroup = model.JobGroup; Answer1 = model.Answer1; diff --git a/DigitalLearningSolutions.Web/Models/RegistrationData.cs b/DigitalLearningSolutions.Web/Models/RegistrationData.cs new file mode 100644 index 0000000000..546be3c5da --- /dev/null +++ b/DigitalLearningSolutions.Web/Models/RegistrationData.cs @@ -0,0 +1,37 @@ +namespace DigitalLearningSolutions.Web.Models +{ + using System; + using DigitalLearningSolutions.Web.ViewModels.Register; + + public class RegistrationData + { + public RegistrationData() + { + Id = new Guid(); + } + + public Guid Id { get; set; } + + public string? FirstName { get; set; } + public string? LastName { get; set; } + public string? Email { get; set; } + public int? Centre { get; set; } + + public int? JobGroup { get; set; } + + public string? PasswordHash { get; set; } + + public void SetPersonalInformation(PersonalInformationViewModel model) + { + Centre = model.Centre; + Email = model.Email; + FirstName = model.FirstName; + LastName = model.LastName; + } + + public void SetLearnerInformation(LearnerInformationViewModel model) + { + JobGroup = model.JobGroup; + } + } +} From 2bc90bb8b28aaf04d2f726bcf3948e9c459164d9 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 22 Jun 2021 17:07:10 +0100 Subject: [PATCH 02/22] HEEDLS-526 Create RegisterAdminController with Index and PersonalInfo; create PersonalInfo page --- .../Controllers/RegisterAdminController.cs | 104 ++++++++++++++++++ DigitalLearningSolutions.Web/Startup.cs | 1 + .../RegisterAdmin/PersonalInformation.cshtml | 57 ++++++++++ 3 files changed, 162 insertions(+) create mode 100644 DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs create mode 100644 DigitalLearningSolutions.Web/Views/RegisterAdmin/PersonalInformation.cshtml diff --git a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs new file mode 100644 index 0000000000..5b5d258d7b --- /dev/null +++ b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs @@ -0,0 +1,104 @@ +namespace DigitalLearningSolutions.Web.Controllers +{ + using System; + using DigitalLearningSolutions.Data.DataServices; + using DigitalLearningSolutions.Web.Extensions; + using DigitalLearningSolutions.Web.Helpers; + using DigitalLearningSolutions.Web.Models; + using DigitalLearningSolutions.Web.ServiceFilter; + using DigitalLearningSolutions.Web.ViewModels.Register; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + + public class RegisterAdminController : Controller + { + private const string CookieName = "RegistrationData"; + private readonly ICentresDataService centresDataService; + + public RegisterAdminController( + ICentresDataService centresDataService + ) + { + this.centresDataService = centresDataService; + } + + public IActionResult Index(int? centreId = null) + { + if (User.Identity.IsAuthenticated) + { + return RedirectToAction("Index", "Home"); + } + + if (!centreId.HasValue || centresDataService.GetCentreName(centreId.Value) == null) + { + return NotFound(); + } + + // TODO: Check if registering admin account is allowed + + SetAdminRegistrationData(centreId.Value); + + return RedirectToAction("PersonalInformation"); + } + + [ServiceFilter(typeof(RedirectEmptySessionData))] + [HttpGet] + public IActionResult PersonalInformation() + { + var data = TempData.Peek()!; + + var model = RegistrationMappingHelper.MapDataToPersonalInformation(data); + PopulatePersonalInformationExtraFields(model); + + // TODO: Validate Email Address? + + return View(model); + } + + [ServiceFilter(typeof(RedirectEmptySessionData))] + [HttpPost] + public IActionResult PersonalInformation(PersonalInformationViewModel model) + { + // TODO: Validate Email Address + + if (!ModelState.IsValid) + { + PopulatePersonalInformationExtraFields(model); + return View(model); + } + + var data = TempData.Peek()!; + + data.SetPersonalInformation(model); + TempData.Set(data); + + return new OkResult(); + } + + private void SetAdminRegistrationData(int centreId) + { + var adminRegistrationData = new RegistrationData + { + Centre = centreId + }; + var id = adminRegistrationData.Id; + + Response.Cookies.Append( + CookieName, + id.ToString(), + new CookieOptions + { + Expires = DateTimeOffset.UtcNow.AddDays(30) + } + ); + + TempData.Clear(); + TempData.Set(adminRegistrationData); + } + + private void PopulatePersonalInformationExtraFields(PersonalInformationViewModel model) + { + model.CentreName = centresDataService.GetCentreName(model.Centre!.Value); + } + } +} diff --git a/DigitalLearningSolutions.Web/Startup.cs b/DigitalLearningSolutions.Web/Startup.cs index aafa372a5c..f4ae38feb8 100644 --- a/DigitalLearningSolutions.Web/Startup.cs +++ b/DigitalLearningSolutions.Web/Startup.cs @@ -168,6 +168,7 @@ public void ConfigureServices(IServiceCollection services) private static void RegisterWebServiceFilters(IServiceCollection services) { + services.AddScoped>(); services.AddScoped>(); services.AddScoped>(); services.AddScoped>(); diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/PersonalInformation.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/PersonalInformation.cshtml new file mode 100644 index 0000000000..3b3ca6b8a2 --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/PersonalInformation.cshtml @@ -0,0 +1,57 @@ +@using DigitalLearningSolutions.Web.ViewModels.Register +@model PersonalInformationViewModel +@{ + var errorHasOccurred = !ViewData.ModelState.IsValid; + ViewData["Title"] = errorHasOccurred ? "Error: Register" : "Register"; +} + +
+
+
+ + @if (errorHasOccurred) { + + } + +

Register

+ +

+ Please enter your personal details to start the registration process + for an admin account at @Model.CentreName. +

+ + + + + + + + + + +
+
From 951ad67ff507f480f6e7054389eeb1dee0d45cb2 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 22 Jun 2021 17:29:46 +0100 Subject: [PATCH 03/22] HEEDLS-526 Add RegisterAdmin LearnerInformation page --- .../Controllers/RegisterAdminController.cs | 47 ++++++++++++++++++- .../RegisterAdmin/LearnerInformation.cshtml | 37 +++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 DigitalLearningSolutions.Web/Views/RegisterAdmin/LearnerInformation.cshtml diff --git a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs index 5b5d258d7b..cdb63d29c0 100644 --- a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs +++ b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs @@ -14,12 +14,15 @@ public class RegisterAdminController : Controller { private const string CookieName = "RegistrationData"; private readonly ICentresDataService centresDataService; + private readonly IJobGroupsDataService jobGroupsDataService; public RegisterAdminController( - ICentresDataService centresDataService + ICentresDataService centresDataService, + IJobGroupsDataService jobGroupsDataService ) { this.centresDataService = centresDataService; + this.jobGroupsDataService = jobGroupsDataService; } public IActionResult Index(int? centreId = null) @@ -72,7 +75,37 @@ public IActionResult PersonalInformation(PersonalInformationViewModel model) data.SetPersonalInformation(model); TempData.Set(data); - return new OkResult(); + return RedirectToAction("LearnerInformation"); + } + + [ServiceFilter(typeof(RedirectEmptySessionData))] + [HttpGet] + public IActionResult LearnerInformation() + { + var data = TempData.Peek()!; + + var model = RegistrationMappingHelper.MapDataToLearnerInformation(data); + PopulateLearnerInformationExtraFields(model); + + return View(model); + } + + [ServiceFilter(typeof(RedirectEmptySessionData))] + [HttpPost] + public IActionResult LearnerInformation(LearnerInformationViewModel model) + { + var data = TempData.Peek()!; + + if (!ModelState.IsValid) + { + PopulateLearnerInformationExtraFields(model); + return View(model); + } + + data.SetLearnerInformation(model); + TempData.Set(data); + + return new EmptyResult(); } private void SetAdminRegistrationData(int centreId) @@ -100,5 +133,15 @@ private void PopulatePersonalInformationExtraFields(PersonalInformationViewModel { model.CentreName = centresDataService.GetCentreName(model.Centre!.Value); } + + private void PopulateLearnerInformationExtraFields( + LearnerInformationViewModel model + ) + { + model.JobGroupOptions = SelectListHelper.MapOptionsToSelectListItems( + jobGroupsDataService.GetJobGroupsAlphabetical(), + model.JobGroup + ); + } } } diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/LearnerInformation.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/LearnerInformation.cshtml new file mode 100644 index 0000000000..2d9bbaa8a9 --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/LearnerInformation.cshtml @@ -0,0 +1,37 @@ +@using DigitalLearningSolutions.Web.ViewModels.Register +@model LearnerInformationViewModel + +@{ + var errorHasOccurred = !ViewData.ModelState.IsValid; + ViewData["Title"] = errorHasOccurred ? "Error: Register - Learner information" : "Register - Learner information"; +} + +
+
+
+ + @if (errorHasOccurred) { + + } + +
+

Learner information

+
+ + + + + + + + +
+
From 433a9a5ae4a59b02ab0af9106e83623cdb73cbcb Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 22 Jun 2021 17:38:14 +0100 Subject: [PATCH 04/22] HEEDLS-526 Add RegisterAdmin Password page --- .../Controllers/RegisterAdminController.cs | 28 +++++++++++ .../Views/RegisterAdmin/Password.cshtml | 46 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml diff --git a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs index cdb63d29c0..75a7264bfb 100644 --- a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs +++ b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs @@ -2,10 +2,12 @@ namespace DigitalLearningSolutions.Web.Controllers { using System; using DigitalLearningSolutions.Data.DataServices; + using DigitalLearningSolutions.Data.Services; using DigitalLearningSolutions.Web.Extensions; using DigitalLearningSolutions.Web.Helpers; using DigitalLearningSolutions.Web.Models; using DigitalLearningSolutions.Web.ServiceFilter; + using DigitalLearningSolutions.Web.ViewModels.Common; using DigitalLearningSolutions.Web.ViewModels.Register; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -14,14 +16,17 @@ public class RegisterAdminController : Controller { private const string CookieName = "RegistrationData"; private readonly ICentresDataService centresDataService; + private readonly ICryptoService cryptoService; private readonly IJobGroupsDataService jobGroupsDataService; public RegisterAdminController( ICentresDataService centresDataService, + ICryptoService cryptoService, IJobGroupsDataService jobGroupsDataService ) { this.centresDataService = centresDataService; + this.cryptoService = cryptoService; this.jobGroupsDataService = jobGroupsDataService; } @@ -105,6 +110,29 @@ public IActionResult LearnerInformation(LearnerInformationViewModel model) data.SetLearnerInformation(model); TempData.Set(data); + return RedirectToAction("Password"); + } + + [ServiceFilter(typeof(RedirectEmptySessionData))] + [HttpGet] + public IActionResult Password() + { + return View(new PasswordViewModel()); + } + + [ServiceFilter(typeof(RedirectEmptySessionData))] + [HttpPost] + public IActionResult Password(PasswordViewModel model) + { + if (!ModelState.IsValid) + { + return View(model); + } + + var data = TempData.Peek()!; + data.PasswordHash = cryptoService.GetPasswordHash(model.Password!); + TempData.Set(data); + return new EmptyResult(); } diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml new file mode 100644 index 0000000000..2b5d89818d --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml @@ -0,0 +1,46 @@ +@using DigitalLearningSolutions.Web.ViewModels.Common +@model PasswordViewModel + +@{ + var errorHasOccurred = !ViewData.ModelState.IsValid; + ViewData["Title"] = errorHasOccurred ? "Error: Register - Password" : "Register - Password"; +} + +
+
+
+ + @if (errorHasOccurred) { + + } + +
+

Create password

+
+ + + + + + + + + +
+
From fe1f4121fa88f53e314c8ea7f33e039b8e7d99c2 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 22 Jun 2021 17:45:38 +0100 Subject: [PATCH 05/22] HEEDLS-526 Add RegisterAdmin Summary page --- .../Controllers/RegisterAdminController.cs | 35 ++++++ .../Views/RegisterAdmin/Summary.cshtml | 107 ++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml diff --git a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs index 75a7264bfb..5205eaa8ed 100644 --- a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs +++ b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs @@ -133,6 +133,35 @@ public IActionResult Password(PasswordViewModel model) data.PasswordHash = cryptoService.GetPasswordHash(model.Password!); TempData.Set(data); + return RedirectToAction("Summary"); + } + + [ServiceFilter(typeof(RedirectEmptySessionData))] + [HttpGet] + public IActionResult Summary() + { + var data = TempData.Peek()!; + var model = RegistrationMappingHelper.MapDataToSummary(data); + PopulateSummaryExtraFields(model, data); + return View(model); + } + + [ServiceFilter(typeof(RedirectEmptySessionData))] + [HttpPost] + public IActionResult Summary(SummaryViewModel model) + { + var data = TempData.Peek()!; + + if (!ModelState.IsValid) + { + var viewModel = RegistrationMappingHelper.MapDataToSummary(data); + PopulateSummaryExtraFields(viewModel, data); + viewModel.Terms = model.Terms; + return View(viewModel); + } + + // TODO: register admin details and notification preferences in database + return new EmptyResult(); } @@ -171,5 +200,11 @@ LearnerInformationViewModel model model.JobGroup ); } + + private void PopulateSummaryExtraFields(SummaryViewModel model, RegistrationData data) + { + model.Centre = centresDataService.GetCentreName((int)data.Centre!); + model.JobGroup = jobGroupsDataService.GetJobGroupName((int)data.JobGroup!); + } } } diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml new file mode 100644 index 0000000000..f8807ae76f --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml @@ -0,0 +1,107 @@ +@using DigitalLearningSolutions.Web.ViewModels.Register +@model SummaryViewModel +@{ + var errorHasOccurred = !ViewData.ModelState.IsValid; + ViewData["Title"] = errorHasOccurred ? "Error: Register - Summary" : "Register - Summary"; + var termsError = ViewData.ModelState["Terms"]?.Errors?.Count > 0; + var termsFormErrorClass = termsError ? "nhsuk-form-group--error" : ""; +} + +
+
+ @if (errorHasOccurred) { + + } + +
+

Summary

+
+ +
+
+
+ Centre +
+
+ @Model.Centre +
+
+
+
+
+
+ First name +
+
+ @Model.FirstName +
+
+ + Change first name + +
+
+
+
+ Last name +
+
+ @Model.LastName +
+
+ + Change last name + +
+
+
+
+ Email +
+
+ @Model.Email +
+
+ + Change email address + +
+
+
+
+ Job group +
+
+ @Model.JobGroup +
+
+ + Change job group + +
+
+
+ +
+
+
+ @if (termsError) { + + Error: @ViewData.ModelState["Terms"].Errors[0].ErrorMessage + + } +
+
+ + +
+
+
+
+ + +
+
+
From d59233029e57da3cb2f12eeb331f61804babff33 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 22 Jun 2021 18:15:19 +0100 Subject: [PATCH 06/22] HEEDLS-526 Add RegisterAdmin Confirmation page --- .../Controllers/RegisterAdminController.cs | 8 +++++++- .../Views/RegisterAdmin/Confirmation.cshtml | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 DigitalLearningSolutions.Web/Views/RegisterAdmin/Confirmation.cshtml diff --git a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs index 5205eaa8ed..c5b5e06db1 100644 --- a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs +++ b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs @@ -162,7 +162,13 @@ public IActionResult Summary(SummaryViewModel model) // TODO: register admin details and notification preferences in database - return new EmptyResult(); + return RedirectToAction("Confirmation"); + } + + [HttpGet] + public IActionResult Confirmation() + { + return View(); } private void SetAdminRegistrationData(int centreId) diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Confirmation.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Confirmation.cshtml new file mode 100644 index 0000000000..edce4d763b --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Confirmation.cshtml @@ -0,0 +1,16 @@ +@{ + ViewData["Title"] = "Registration Confirmation"; +} + +
+
+

+ Admin registration complete +

+

+ Your email address matched details stored with the centre, so your centre manager account has successfully been created. +

+ + +
+
From a36387c8aa74820dd275594eed94214786da67a1 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Wed, 23 Jun 2021 12:23:15 +0100 Subject: [PATCH 07/22] HEEDLS-526 Add method to get AutoRegister values to CentreDataService; add test --- .../DataServices/CentresDataServiceTests.cs | 13 ++++++++++++- .../DataServices/CentresDataService.cs | 14 +++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/DigitalLearningSolutions.Data.Tests/DataServices/CentresDataServiceTests.cs b/DigitalLearningSolutions.Data.Tests/DataServices/CentresDataServiceTests.cs index ed898f39d5..bd000b4ae9 100644 --- a/DigitalLearningSolutions.Data.Tests/DataServices/CentresDataServiceTests.cs +++ b/DigitalLearningSolutions.Data.Tests/DataServices/CentresDataServiceTests.cs @@ -1,4 +1,4 @@ -namespace DigitalLearningSolutions.Data.Tests.DataServices +namespace DigitalLearningSolutions.Data.Tests.DataServices { using System; using System.Linq; @@ -230,5 +230,16 @@ public void UpdateCentreWebsiteDetails_updates_centre() transaction.Dispose(); } } + + [Test] + public void GetCentreAutoRegisterValues_should_return_correct_values() + { + // When + var result = centresDataService.GetCentreAutoRegisterValues(2); + + // Then + result.autoRegistered.Should().Be(true); + result.autoRegisterManagerEmail.Should().Be(".vhrnaui@bywdskc"); + } } } diff --git a/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs b/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs index 403b3e5940..08a5d6b3a5 100644 --- a/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs @@ -1,4 +1,4 @@ -namespace DigitalLearningSolutions.Data.DataServices +namespace DigitalLearningSolutions.Data.DataServices { using System; using System.Collections.Generic; @@ -41,6 +41,7 @@ void UpdateCentreWebsiteDetails (string firstName, string lastName, string email) GetCentreManagerDetails(int centreId); string[] GetCentreIpPrefixes(int centreId); + (bool autoRegistered, string? autoRegisterManagerEmail) GetCentreAutoRegisterValues(int centreId); } public class CentresDataService : ICentresDataService @@ -246,5 +247,16 @@ FROM Centres var ipPrefixes = ipPrefixString?.Split(',', StringSplitOptions.RemoveEmptyEntries); return ipPrefixes ?? new string[0]; } + + public (bool autoRegistered, string? autoRegisterManagerEmail) GetCentreAutoRegisterValues(int centreId) + { + var info = connection.QueryFirstOrDefault<(bool, string?)>( + @"SELECT AutoRegistered, AutoRegisterManagerEmail + FROM Centres + WHERE CentreID = @centreId", + new { centreId } + ); + return info; + } } } From c6022f98afee9100cd094813b1c82c6c55ef500f Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Wed, 23 Jun 2021 12:24:40 +0100 Subject: [PATCH 08/22] HEEDLS-526 Check if admin register is allowed for centre on Index GET; write tests --- .../Register/RegisterAdminControllerTests.cs | 129 ++++++++++++++++++ .../Controllers/RegisterAdminController.cs | 15 +- 2 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs diff --git a/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs b/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs new file mode 100644 index 0000000000..9dcc5bd178 --- /dev/null +++ b/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs @@ -0,0 +1,129 @@ +namespace DigitalLearningSolutions.Web.Tests.Controllers.Register +{ + using DigitalLearningSolutions.Data.DataServices; + using DigitalLearningSolutions.Data.Services; + using DigitalLearningSolutions.Web.Controllers; + using DigitalLearningSolutions.Web.Extensions; + using DigitalLearningSolutions.Web.Models; + using DigitalLearningSolutions.Web.Tests.ControllerHelpers; + using FakeItEasy; + using FluentAssertions; + using FluentAssertions.AspNetCore.Mvc; + using NUnit.Framework; + + public class RegisterAdminControllerTests + { + private ICentresDataService centresDataService = null!; + private RegisterAdminController controller = null!; + private ICryptoService cryptoService = null!; + private IJobGroupsDataService jobGroupsDataService = null!; + private IUserService userService = null!; + + [SetUp] + public void Setup() + { + centresDataService = A.Fake(); + cryptoService = A.Fake(); + jobGroupsDataService = A.Fake(); + userService = A.Fake(); + controller = new RegisterAdminController(centresDataService, cryptoService, jobGroupsDataService) + .WithDefaultContext() + .WithMockTempData(); + } + + [Test] + public void IndexGet_with_no_centreId_param_shows_error() + { + // When + var result = controller.Index(); + + // Then + result.Should().BeNotFoundResult(); + } + + [Test] + public void IndexGet_with_invalid_centreId_param_shows_error() + { + // Given + const int centreId = 7; + A.CallTo(() => centresDataService.GetCentreName(centreId)).Returns(null); + + // When + var result = controller.Index(centreId); + + // Then + A.CallTo(() => centresDataService.GetCentreName(centreId)).MustHaveHappened(1, Times.Exactly); + result.Should().BeNotFoundResult(); + } + + [Test] + public void IndexGet_with_centre_autoregistered_true_shows_error() + { + // Given + const int centreId = 7; + A.CallTo(() => centresDataService.GetCentreName(centreId)).Returns("My centre"); + A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).Returns((true, "email@email")); + + // When + var result = controller.Index(centreId); + + // Then + A.CallTo(() => centresDataService.GetCentreName(centreId)).MustHaveHappened(1, Times.Exactly); + A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).MustHaveHappened(1, Times.Exactly); + result.Should().BeNotFoundResult(); + } + + [Test] + public void IndexGet_with_centre_autoregisteremail_null_shows_error() + { + // Given + const int centreId = 7; + A.CallTo(() => centresDataService.GetCentreName(centreId)).Returns("Some centre"); + A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).Returns((false, null)); + + // When + var result = controller.Index(centreId); + + // Then + A.CallTo(() => centresDataService.GetCentreName(centreId)).MustHaveHappened(1, Times.Exactly); + A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).MustHaveHappened(1, Times.Exactly); + result.Should().BeNotFoundResult(); + } + + [Test] + public void IndexGet_with_centre_autoregisteremail_empty_shows_error() + { + // Given + const int centreId = 7; + A.CallTo(() => centresDataService.GetCentreName(centreId)).Returns("Some centre"); + A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).Returns((false, string.Empty)); + + // When + var result = controller.Index(centreId); + + // Then + A.CallTo(() => centresDataService.GetCentreName(centreId)).MustHaveHappened(1, Times.Exactly); + A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).MustHaveHappened(1, Times.Exactly); + result.Should().BeNotFoundResult(); + } + + [Test] + public void IndexGet_with_allowed_admin_registration_sets_data_correctly() + { + // Given + const int centreId = 7; + A.CallTo(() => centresDataService.GetCentreName(centreId)).Returns("Some centre"); + A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).Returns((false, "email@email")); + + // When + var result = controller.Index(centreId); + + // Then + A.CallTo(() => centresDataService.GetCentreName(centreId)).MustHaveHappened(1, Times.Exactly); + A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).MustHaveHappened(1, Times.Exactly); + var data = controller.TempData.Peek()!; + data.Centre.Should().Be(centreId); + result.Should().BeRedirectToActionResult().WithActionName("PersonalInformation"); + } + } +} diff --git a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs index c5b5e06db1..0286445465 100644 --- a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs +++ b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs @@ -37,13 +37,11 @@ public IActionResult Index(int? centreId = null) return RedirectToAction("Index", "Home"); } - if (!centreId.HasValue || centresDataService.GetCentreName(centreId.Value) == null) + if (!centreId.HasValue || !CheckRegisterAdminAllowed(centreId.Value)) { return NotFound(); } - // TODO: Check if registering admin account is allowed - SetAdminRegistrationData(centreId.Value); return RedirectToAction("PersonalInformation"); @@ -171,6 +169,17 @@ public IActionResult Confirmation() return View(); } + private bool CheckRegisterAdminAllowed(int centreId) + { + if (centresDataService.GetCentreName(centreId) == null) + { + return false; + } + + var (autoRegistered, autoRegisterManagerEmail) = centresDataService.GetCentreAutoRegisterValues(centreId); + return !autoRegistered && !string.IsNullOrWhiteSpace(autoRegisterManagerEmail); + } + private void SetAdminRegistrationData(int centreId) { var adminRegistrationData = new RegistrationData From 2e9405b3e4e7a8a3c3d73e51e6493c2d782a8688 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Wed, 23 Jun 2021 13:18:06 +0100 Subject: [PATCH 09/22] HEEDLS-526 Add admin email address validation on PersonalInformation page; write tests --- .../Register/RegisterAdminControllerTests.cs | 91 ++++++++++++++++++- .../Controllers/RegisterAdminController.cs | 40 +++++++- 2 files changed, 123 insertions(+), 8 deletions(-) diff --git a/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs b/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs index 9dcc5bd178..b3e0431faa 100644 --- a/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs +++ b/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs @@ -1,11 +1,13 @@ namespace DigitalLearningSolutions.Web.Tests.Controllers.Register { using DigitalLearningSolutions.Data.DataServices; + using DigitalLearningSolutions.Data.Models.User; using DigitalLearningSolutions.Data.Services; using DigitalLearningSolutions.Web.Controllers; using DigitalLearningSolutions.Web.Extensions; using DigitalLearningSolutions.Web.Models; using DigitalLearningSolutions.Web.Tests.ControllerHelpers; + using DigitalLearningSolutions.Web.ViewModels.Register; using FakeItEasy; using FluentAssertions; using FluentAssertions.AspNetCore.Mvc; @@ -17,7 +19,7 @@ public class RegisterAdminControllerTests private RegisterAdminController controller = null!; private ICryptoService cryptoService = null!; private IJobGroupsDataService jobGroupsDataService = null!; - private IUserService userService = null!; + private IUserDataService userDataService = null!; [SetUp] public void Setup() @@ -25,8 +27,13 @@ public void Setup() centresDataService = A.Fake(); cryptoService = A.Fake(); jobGroupsDataService = A.Fake(); - userService = A.Fake(); - controller = new RegisterAdminController(centresDataService, cryptoService, jobGroupsDataService) + userDataService = A.Fake(); + controller = new RegisterAdminController( + centresDataService, + cryptoService, + jobGroupsDataService, + userDataService + ) .WithDefaultContext() .WithMockTempData(); } @@ -125,5 +132,83 @@ public void IndexGet_with_allowed_admin_registration_sets_data_correctly() data.Centre.Should().Be(centreId); result.Should().BeRedirectToActionResult().WithActionName("PersonalInformation"); } + + [Test] + public void PersonalInformationPost_with_wrong_autoregisteremail_for_centre_fails_validation() + { + // Given + const int centreId = 7; + var model = new PersonalInformationViewModel + { + FirstName = "Test", + LastName = "User", + Centre = centreId, + Email = "wrong@email" + }; + var data = new RegistrationData { Centre = centreId }; + controller.TempData.Set(data); + A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).Returns((false, "right@email")); + + // When + var result = controller.PersonalInformation(model); + + // Then + A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).MustHaveHappened(1, Times.Exactly); + result.Should().BeViewResult().WithDefaultViewName(); + } + + [Test] + public void PersonalInformationPost_with_email_already_in_use_fails_validation() + { + // Given + const int centreId = 7; + const string email = "right@email"; + var model = new PersonalInformationViewModel + { + FirstName = "Test", + LastName = "User", + Centre = centreId, + Email = email + }; + var data = new RegistrationData { Centre = centreId }; + controller.TempData.Set(data); + A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).Returns((false, email)); + A.CallTo(() => userDataService.GetAdminUserByEmailAddress(email)).Returns(new AdminUser()); + + // When + var result = controller.PersonalInformation(model); + + // Then + A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).MustHaveHappened(1, Times.Exactly); + A.CallTo(() => userDataService.GetAdminUserByEmailAddress(email)).MustHaveHappened(1, Times.Exactly); + result.Should().BeViewResult().WithDefaultViewName(); + } + + [Test] + public void PersonalInformationPost_with_correct_unique_email_is_allowed() + { + // Given + const int centreId = 7; + const string email = "right@email"; + var model = new PersonalInformationViewModel + { + FirstName = "Test", + LastName = "User", + Centre = centreId, + Email = email + }; + var data = new RegistrationData { Centre = centreId }; + controller.TempData.Set(data); + A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).Returns((false, email)); + A.CallTo(() => userDataService.GetAdminUserByEmailAddress(email)).Returns(null); + + // When + var result = controller.PersonalInformation(model); + + // Then + A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).MustHaveHappened(1, Times.Exactly); + A.CallTo(() => userDataService.GetAdminUserByEmailAddress(email)).MustHaveHappened(1, Times.Exactly); + result.Should().BeRedirectToActionResult().WithActionName("LearnerInformation"); + } } } diff --git a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs index 0286445465..81af960946 100644 --- a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs +++ b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs @@ -18,16 +18,19 @@ public class RegisterAdminController : Controller private readonly ICentresDataService centresDataService; private readonly ICryptoService cryptoService; private readonly IJobGroupsDataService jobGroupsDataService; + private readonly IUserDataService userDataService; public RegisterAdminController( ICentresDataService centresDataService, ICryptoService cryptoService, - IJobGroupsDataService jobGroupsDataService + IJobGroupsDataService jobGroupsDataService, + IUserDataService userDataService ) { this.centresDataService = centresDataService; this.cryptoService = cryptoService; this.jobGroupsDataService = jobGroupsDataService; + this.userDataService = userDataService; } public IActionResult Index(int? centreId = null) @@ -56,7 +59,7 @@ public IActionResult PersonalInformation() var model = RegistrationMappingHelper.MapDataToPersonalInformation(data); PopulatePersonalInformationExtraFields(model); - // TODO: Validate Email Address? + ValidateEmailAddress(model.Email, data.Centre!.Value); return View(model); } @@ -65,7 +68,9 @@ public IActionResult PersonalInformation() [HttpPost] public IActionResult PersonalInformation(PersonalInformationViewModel model) { - // TODO: Validate Email Address + var data = TempData.Peek()!; + + ValidateEmailAddress(model.Email, data.Centre!.Value); if (!ModelState.IsValid) { @@ -73,8 +78,6 @@ public IActionResult PersonalInformation(PersonalInformationViewModel model) return View(model); } - var data = TempData.Peek()!; - data.SetPersonalInformation(model); TempData.Set(data); @@ -201,6 +204,33 @@ private void SetAdminRegistrationData(int centreId) TempData.Set(adminRegistrationData); } + private void ValidateEmailAddress(string? email, int centreId) + { + if (email == null) + { + return; + } + + var (_, autoRegisterManagerEmail) = centresDataService.GetCentreAutoRegisterValues(centreId); + if (!email.Equals(autoRegisterManagerEmail)) + { + ModelState.AddModelError( + nameof(PersonalInformationViewModel.Email), + "This email address does not match the one held by the centre" + ); + } + + var adminUser = userDataService.GetAdminUserByEmailAddress(email); + + if (adminUser != null) + { + ModelState.AddModelError( + nameof(PersonalInformationViewModel.Email), + "An admin user with this email address is already registered" + ); + } + } + private void PopulatePersonalInformationExtraFields(PersonalInformationViewModel model) { model.CentreName = centresDataService.GetCentreName(model.Centre!.Value); From 861709880d9b007e11290a1341b8c3d80d20882f Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Wed, 23 Jun 2021 13:53:39 +0100 Subject: [PATCH 10/22] HEEDLS-526 Fix incorrect back links, update titles on RegisterAdmin pages --- .../Views/RegisterAdmin/LearnerInformation.cshtml | 4 ++-- .../Views/RegisterAdmin/Password.cshtml | 4 ++-- .../Views/RegisterAdmin/PersonalInformation.cshtml | 2 +- .../Views/RegisterAdmin/Summary.cshtml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/LearnerInformation.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/LearnerInformation.cshtml index 2d9bbaa8a9..34da186411 100644 --- a/DigitalLearningSolutions.Web/Views/RegisterAdmin/LearnerInformation.cshtml +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/LearnerInformation.cshtml @@ -3,7 +3,7 @@ @{ var errorHasOccurred = !ViewData.ModelState.IsValid; - ViewData["Title"] = errorHasOccurred ? "Error: Register - Learner information" : "Register - Learner information"; + ViewData["Title"] = errorHasOccurred ? "Error: Register Admin - Learner information" : "Register Admin - Learner information"; }
@@ -32,6 +32,6 @@ - +
diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml index 2b5d89818d..b05451c6ca 100644 --- a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml @@ -3,7 +3,7 @@ @{ var errorHasOccurred = !ViewData.ModelState.IsValid; - ViewData["Title"] = errorHasOccurred ? "Error: Register - Password" : "Register - Password"; + ViewData["Title"] = errorHasOccurred ? "Error: Register - Password Admin" : "Register - Password Admin"; }
@@ -41,6 +41,6 @@ - +
diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/PersonalInformation.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/PersonalInformation.cshtml index 3b3ca6b8a2..cd7b6134da 100644 --- a/DigitalLearningSolutions.Web/Views/RegisterAdmin/PersonalInformation.cshtml +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/PersonalInformation.cshtml @@ -2,7 +2,7 @@ @model PersonalInformationViewModel @{ var errorHasOccurred = !ViewData.ModelState.IsValid; - ViewData["Title"] = errorHasOccurred ? "Error: Register" : "Register"; + ViewData["Title"] = errorHasOccurred ? "Error: Register Admin" : "Register Admin"; }
diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml index f8807ae76f..a96cde59d2 100644 --- a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml @@ -2,7 +2,7 @@ @model SummaryViewModel @{ var errorHasOccurred = !ViewData.ModelState.IsValid; - ViewData["Title"] = errorHasOccurred ? "Error: Register - Summary" : "Register - Summary"; + ViewData["Title"] = errorHasOccurred ? "Error: Register Admin - Summary" : "Register Admin - Summary"; var termsError = ViewData.ModelState["Terms"]?.Errors?.Count > 0; var termsFormErrorClass = termsError ? "nhsuk-form-group--error" : ""; } From b359703630e14a4374ce616a84d2a4402f9180fd Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Wed, 23 Jun 2021 14:19:57 +0100 Subject: [PATCH 11/22] HEEDLS-526 Use email from model, not data, for validation --- .../Controllers/RegisterAdminController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs index 81af960946..86b989b798 100644 --- a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs +++ b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs @@ -59,7 +59,7 @@ public IActionResult PersonalInformation() var model = RegistrationMappingHelper.MapDataToPersonalInformation(data); PopulatePersonalInformationExtraFields(model); - ValidateEmailAddress(model.Email, data.Centre!.Value); + ValidateEmailAddress(model.Email, model.Centre!.Value); return View(model); } @@ -70,7 +70,7 @@ public IActionResult PersonalInformation(PersonalInformationViewModel model) { var data = TempData.Peek()!; - ValidateEmailAddress(model.Email, data.Centre!.Value); + ValidateEmailAddress(model.Email, model.Centre!.Value); if (!ModelState.IsValid) { From 29b995c420ff0f2b390ebfd0f8178742bbd06c89 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Fri, 25 Jun 2021 11:43:06 +0100 Subject: [PATCH 12/22] HEEDLS-526 Update tests and encoding --- .../DataServices/CentresDataServiceTests.cs | 2 +- .../DataServices/CentresDataService.cs | 2 +- .../Controllers/Register/RegisterAdminControllerTests.cs | 5 +++++ .../Controllers/RegisterAdminController.cs | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/DigitalLearningSolutions.Data.Tests/DataServices/CentresDataServiceTests.cs b/DigitalLearningSolutions.Data.Tests/DataServices/CentresDataServiceTests.cs index bd000b4ae9..799ba9a9d5 100644 --- a/DigitalLearningSolutions.Data.Tests/DataServices/CentresDataServiceTests.cs +++ b/DigitalLearningSolutions.Data.Tests/DataServices/CentresDataServiceTests.cs @@ -1,4 +1,4 @@ -namespace DigitalLearningSolutions.Data.Tests.DataServices +namespace DigitalLearningSolutions.Data.Tests.DataServices { using System; using System.Linq; diff --git a/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs b/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs index 08a5d6b3a5..2d24779442 100644 --- a/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs @@ -1,4 +1,4 @@ -namespace DigitalLearningSolutions.Data.DataServices +namespace DigitalLearningSolutions.Data.DataServices { using System; using System.Collections.Generic; diff --git a/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs b/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs index b3e0431faa..4f3ccb5616 100644 --- a/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs +++ b/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs @@ -11,6 +11,7 @@ using FakeItEasy; using FluentAssertions; using FluentAssertions.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.ModelBinding; using NUnit.Framework; public class RegisterAdminControllerTests @@ -154,6 +155,8 @@ public void PersonalInformationPost_with_wrong_autoregisteremail_for_centre_fail // Then A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).MustHaveHappened(1, Times.Exactly); + controller.ModelState[nameof(PersonalInformationViewModel.Email)].ValidationState.Should() + .Be(ModelValidationState.Invalid); result.Should().BeViewResult().WithDefaultViewName(); } @@ -181,6 +184,8 @@ public void PersonalInformationPost_with_email_already_in_use_fails_validation() // Then A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).MustHaveHappened(1, Times.Exactly); A.CallTo(() => userDataService.GetAdminUserByEmailAddress(email)).MustHaveHappened(1, Times.Exactly); + controller.ModelState[nameof(PersonalInformationViewModel.Email)].ValidationState.Should() + .Be(ModelValidationState.Invalid); result.Should().BeViewResult().WithDefaultViewName(); } diff --git a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs index 86b989b798..2ccdc34cd5 100644 --- a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs +++ b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs @@ -1,4 +1,4 @@ -namespace DigitalLearningSolutions.Web.Controllers +namespace DigitalLearningSolutions.Web.Controllers { using System; using DigitalLearningSolutions.Data.DataServices; @@ -161,7 +161,7 @@ public IActionResult Summary(SummaryViewModel model) return View(viewModel); } - // TODO: register admin details and notification preferences in database + // TODO: (HEEDLS-527) register admin details and notification preferences in database return RedirectToAction("Confirmation"); } From 1deb1b6442aad5274e0fb345e0fef134e4c87e86 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Mon, 28 Jun 2021 12:16:53 +0100 Subject: [PATCH 13/22] HEEDLS-526 Extract T&Cs form group into view component --- .../TermsConditionsViewComponent.cs | 32 +++++++++++++++++++ .../Common/TermsConditionsViewModel.cs | 26 +++++++++++++++ .../Views/Register/Summary.cshtml | 19 +---------- .../Views/RegisterAdmin/Summary.cshtml | 21 +----------- .../Components/TermsConditions/Default.cshtml | 20 ++++++++++++ 5 files changed, 80 insertions(+), 38 deletions(-) create mode 100644 DigitalLearningSolutions.Web/ViewComponents/TermsConditionsViewComponent.cs create mode 100644 DigitalLearningSolutions.Web/ViewModels/Common/TermsConditionsViewModel.cs create mode 100644 DigitalLearningSolutions.Web/Views/Shared/Components/TermsConditions/Default.cshtml diff --git a/DigitalLearningSolutions.Web/ViewComponents/TermsConditionsViewComponent.cs b/DigitalLearningSolutions.Web/ViewComponents/TermsConditionsViewComponent.cs new file mode 100644 index 0000000000..becfc97292 --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewComponents/TermsConditionsViewComponent.cs @@ -0,0 +1,32 @@ +namespace DigitalLearningSolutions.Web.ViewComponents +{ + using DigitalLearningSolutions.Web.ViewModels.Common; + using Microsoft.AspNetCore.Mvc; + + public class TermsConditionsViewComponent : ViewComponent + { + /// + /// Render Terms and Conditions checkbox view component. + /// + /// + /// + public IViewComponentResult Invoke( + string aspFor + ) + { + var model = ViewData.Model; + + var property = model.GetType().GetProperty(aspFor); + var valueToSet = property?.GetValue(model)?.ToString(); + var errorMessage = ViewData.ModelState[property?.Name]?.Errors[0]?.ErrorMessage; + + var tcViewModel = new TermsConditionsViewModel( + aspFor, + aspFor, + valueToSet, + errorMessage + ); + return View(tcViewModel); + } + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/Common/TermsConditionsViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/Common/TermsConditionsViewModel.cs new file mode 100644 index 0000000000..75995fed0c --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/Common/TermsConditionsViewModel.cs @@ -0,0 +1,26 @@ +namespace DigitalLearningSolutions.Web.ViewModels.Common +{ + public class TermsConditionsViewModel + { + public readonly bool HasError; + + public TermsConditionsViewModel( + string id, + string name, + string? value, + string? errorMessage + ) + { + Id = id; + Name = name; + Value = value; + ErrorMessage = errorMessage; + HasError = errorMessage != null; + } + + public string Id { get; set; } + public string Name { get; set; } + public string? Value { get; set; } + public string? ErrorMessage { get; set; } + } +} diff --git a/DigitalLearningSolutions.Web/Views/Register/Summary.cshtml b/DigitalLearningSolutions.Web/Views/Register/Summary.cshtml index bff951284d..16dee076db 100644 --- a/DigitalLearningSolutions.Web/Views/Register/Summary.cshtml +++ b/DigitalLearningSolutions.Web/Views/Register/Summary.cshtml @@ -104,24 +104,7 @@
-
-
- @if (termsError) { - - Error: @ViewData.ModelState["Terms"].Errors[0].ErrorMessage - - } -
-
- - -
-
-
-
- +
diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml index a96cde59d2..d629207f0c 100644 --- a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml @@ -3,8 +3,6 @@ @{ var errorHasOccurred = !ViewData.ModelState.IsValid; ViewData["Title"] = errorHasOccurred ? "Error: Register Admin - Summary" : "Register Admin - Summary"; - var termsError = ViewData.ModelState["Terms"]?.Errors?.Count > 0; - var termsFormErrorClass = termsError ? "nhsuk-form-group--error" : ""; }
@@ -83,24 +81,7 @@
-
-
- @if (termsError) { - - Error: @ViewData.ModelState["Terms"].Errors[0].ErrorMessage - - } -
-
- - -
-
-
-
- +
diff --git a/DigitalLearningSolutions.Web/Views/Shared/Components/TermsConditions/Default.cshtml b/DigitalLearningSolutions.Web/Views/Shared/Components/TermsConditions/Default.cshtml new file mode 100644 index 0000000000..021448e34a --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/Shared/Components/TermsConditions/Default.cshtml @@ -0,0 +1,20 @@ +@using DigitalLearningSolutions.Web.ViewModels.Common +@model TermsConditionsViewModel + +
+
+ @if (Model.HasError) { + + Error: @Model.ErrorMessage + + } +
+
+ + +
+
+
+
From b733e351e50e553190b1d218b4ad9003720318e7 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Mon, 28 Jun 2021 13:44:49 +0100 Subject: [PATCH 14/22] HEEDLS-526 Add type to PersonalInformation vc-text-inputs; fix page title --- .../Views/Register/PersonalInformation.cshtml | 4 ++-- .../Views/RegisterAdmin/Password.cshtml | 2 +- .../Views/RegisterAdmin/PersonalInformation.cshtml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/DigitalLearningSolutions.Web/Views/Register/PersonalInformation.cshtml b/DigitalLearningSolutions.Web/Views/Register/PersonalInformation.cshtml index 3ec478c206..c3366f4495 100644 --- a/DigitalLearningSolutions.Web/Views/Register/PersonalInformation.cshtml +++ b/DigitalLearningSolutions.Web/Views/Register/PersonalInformation.cshtml @@ -54,7 +54,7 @@ asp-for="FirstName" label="First name" populate-with-current-value="true" - type="" + type="text" spell-check="false" hint-text="" autocomplete="given-name" @@ -64,7 +64,7 @@ asp-for="LastName" label="Last name" populate-with-current-value="true" - type="" + type="text" spell-check="false" hint-text="" autocomplete="family-name" diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml index b05451c6ca..148e85deb3 100644 --- a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml @@ -3,7 +3,7 @@ @{ var errorHasOccurred = !ViewData.ModelState.IsValid; - ViewData["Title"] = errorHasOccurred ? "Error: Register - Password Admin" : "Register - Password Admin"; + ViewData["Title"] = errorHasOccurred ? "Error: Register Admin - Password" : "Register Admin - Password"; }
diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/PersonalInformation.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/PersonalInformation.cshtml index cd7b6134da..631d13d64b 100644 --- a/DigitalLearningSolutions.Web/Views/RegisterAdmin/PersonalInformation.cshtml +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/PersonalInformation.cshtml @@ -25,7 +25,7 @@ asp-for="FirstName" label="First name" populate-with-current-value="true" - type="" + type="text" spell-check="false" hint-text="" autocomplete="given-name" @@ -35,7 +35,7 @@ asp-for="LastName" label="Last name" populate-with-current-value="true" - type="" + type="text" spell-check="false" hint-text="" autocomplete="family-name" From ea89b87d036c786e678accff32cdb04c73a27ba7 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Mon, 28 Jun 2021 17:35:03 +0100 Subject: [PATCH 15/22] HEEDLS-526 Add NavMenuItems to AdminReg views; fix layout/spacing to match normal registration --- .editorconfig | 1 + .../Views/Register/Summary.cshtml | 5 +- .../Views/RegisterAdmin/Confirmation.cshtml | 4 + .../RegisterAdmin/LearnerInformation.cshtml | 17 ++-- .../Views/RegisterAdmin/Password.cshtml | 16 ++-- .../RegisterAdmin/PersonalInformation.cshtml | 77 ++++++++++--------- .../Views/RegisterAdmin/Summary.cshtml | 4 + 7 files changed, 68 insertions(+), 56 deletions(-) diff --git a/.editorconfig b/.editorconfig index 9d9a800041..3a9709f8cd 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,6 +5,7 @@ end_of_line = crlf indent_style = space insert_final_newline = true trim_trailing_whitespace = true +encoding = utf-8-bom # ReSharper properties resharper_csharp_wrap_after_declaration_lpar = true diff --git a/DigitalLearningSolutions.Web/Views/Register/Summary.cshtml b/DigitalLearningSolutions.Web/Views/Register/Summary.cshtml index 85b08b466b..b796635c60 100644 --- a/DigitalLearningSolutions.Web/Views/Register/Summary.cshtml +++ b/DigitalLearningSolutions.Web/Views/Register/Summary.cshtml @@ -1,11 +1,8 @@ -@using DigitalLearningSolutions.Web.ViewModels.MyAccount -@using DigitalLearningSolutions.Web.ViewModels.Register +@using DigitalLearningSolutions.Web.ViewModels.Register @model SummaryViewModel @{ var errorHasOccurred = !ViewData.ModelState.IsValid; ViewData["Title"] = errorHasOccurred ? "Error: Register - Summary" : "Register - Summary"; - var termsError = ViewData.ModelState["Terms"]?.Errors?.Count > 0; - var termsFormErrorClass = termsError ? "nhsuk-form-group--error" : ""; } @section NavMenuItems { diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Confirmation.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Confirmation.cshtml index edce4d763b..6fec4427c7 100644 --- a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Confirmation.cshtml +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Confirmation.cshtml @@ -2,6 +2,10 @@ ViewData["Title"] = "Registration Confirmation"; } +@section NavMenuItems { + +} +

diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/LearnerInformation.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/LearnerInformation.cshtml index 34da186411..4f645c1e64 100644 --- a/DigitalLearningSolutions.Web/Views/RegisterAdmin/LearnerInformation.cshtml +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/LearnerInformation.cshtml @@ -6,17 +6,19 @@ ViewData["Title"] = errorHasOccurred ? "Error: Register Admin - Learner information" : "Register Admin - Learner information"; } +@section NavMenuItems { + +} +
-
+ @if (errorHasOccurred) { + + } - @if (errorHasOccurred) { - - } +

Learner information

-
-

Learner information

-
+ - diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml index 148e85deb3..b71d8c1d14 100644 --- a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Password.cshtml @@ -6,17 +6,19 @@ ViewData["Title"] = errorHasOccurred ? "Error: Register Admin - Password" : "Register Admin - Password"; } +@section NavMenuItems { + +} +
-
+ @if (errorHasOccurred) { + + } - @if (errorHasOccurred) { - - } +

Create password

-
-

Create password

-
+ +} +
@@ -13,43 +17,42 @@ } -

Register

- -

- Please enter your personal details to start the registration process - for an admin account at @Model.CentreName. -

- - - - - - - +
+

Register

+ +

+ Please enter your personal details to start the registration process + for an admin account at @Model.CentreName. +

+ +
+ + + + + + diff --git a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml index d629207f0c..14b8ab3a4d 100644 --- a/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml +++ b/DigitalLearningSolutions.Web/Views/RegisterAdmin/Summary.cshtml @@ -5,6 +5,10 @@ ViewData["Title"] = errorHasOccurred ? "Error: Register Admin - Summary" : "Register Admin - Summary"; } +@section NavMenuItems { + +} +
@if (errorHasOccurred) { From 379c10499bc8fbdd8a2900915c9e9ad302f4a331 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Mon, 28 Jun 2021 17:40:25 +0100 Subject: [PATCH 16/22] HEEDLS-526 Use virtual & override SetLearnerInformation instead of declaring new in subclass --- DigitalLearningSolutions.Web/Models/DelegateRegistrationData.cs | 2 +- DigitalLearningSolutions.Web/Models/RegistrationData.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DigitalLearningSolutions.Web/Models/DelegateRegistrationData.cs b/DigitalLearningSolutions.Web/Models/DelegateRegistrationData.cs index 6bb17bf0aa..53bb3fa599 100644 --- a/DigitalLearningSolutions.Web/Models/DelegateRegistrationData.cs +++ b/DigitalLearningSolutions.Web/Models/DelegateRegistrationData.cs @@ -13,7 +13,7 @@ public class DelegateRegistrationData : RegistrationData public string? Answer5 { get; set; } public string? Answer6 { get; set; } - public new void SetLearnerInformation(LearnerInformationViewModel model) + public override void SetLearnerInformation(LearnerInformationViewModel model) { JobGroup = model.JobGroup; Answer1 = model.Answer1; diff --git a/DigitalLearningSolutions.Web/Models/RegistrationData.cs b/DigitalLearningSolutions.Web/Models/RegistrationData.cs index 546be3c5da..1a5db79376 100644 --- a/DigitalLearningSolutions.Web/Models/RegistrationData.cs +++ b/DigitalLearningSolutions.Web/Models/RegistrationData.cs @@ -29,7 +29,7 @@ public void SetPersonalInformation(PersonalInformationViewModel model) LastName = model.LastName; } - public void SetLearnerInformation(LearnerInformationViewModel model) + public virtual void SetLearnerInformation(LearnerInformationViewModel model) { JobGroup = model.JobGroup; } From 56a9aafdd8fc4a400cbbb819870464cb9f5e12d7 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Mon, 28 Jun 2021 18:03:51 +0100 Subject: [PATCH 17/22] HEEDLS-526 Rename helper methods in RegisterAdminController --- .../Controllers/RegisterAdminController.cs | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs index 2ccdc34cd5..25bb5609ec 100644 --- a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs +++ b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs @@ -14,7 +14,7 @@ public class RegisterAdminController : Controller { - private const string CookieName = "RegistrationData"; + private const string CookieName = "AdminRegistrationData"; private readonly ICentresDataService centresDataService; private readonly ICryptoService cryptoService; private readonly IJobGroupsDataService jobGroupsDataService; @@ -40,7 +40,7 @@ public IActionResult Index(int? centreId = null) return RedirectToAction("Index", "Home"); } - if (!centreId.HasValue || !CheckRegisterAdminAllowed(centreId.Value)) + if (!centreId.HasValue || !IsRegisterAdminAllowed(centreId.Value)) { return NotFound(); } @@ -57,7 +57,7 @@ public IActionResult PersonalInformation() var data = TempData.Peek()!; var model = RegistrationMappingHelper.MapDataToPersonalInformation(data); - PopulatePersonalInformationExtraFields(model); + SetCentreName(model); ValidateEmailAddress(model.Email, model.Centre!.Value); @@ -74,7 +74,7 @@ public IActionResult PersonalInformation(PersonalInformationViewModel model) if (!ModelState.IsValid) { - PopulatePersonalInformationExtraFields(model); + SetCentreName(model); return View(model); } @@ -91,7 +91,7 @@ public IActionResult LearnerInformation() var data = TempData.Peek()!; var model = RegistrationMappingHelper.MapDataToLearnerInformation(data); - PopulateLearnerInformationExtraFields(model); + SetJobGroupOptions(model); return View(model); } @@ -104,7 +104,7 @@ public IActionResult LearnerInformation(LearnerInformationViewModel model) if (!ModelState.IsValid) { - PopulateLearnerInformationExtraFields(model); + SetJobGroupOptions(model); return View(model); } @@ -172,7 +172,7 @@ public IActionResult Confirmation() return View(); } - private bool CheckRegisterAdminAllowed(int centreId) + private bool IsRegisterAdminAllowed(int centreId) { if (centresDataService.GetCentreName(centreId) == null) { @@ -231,14 +231,12 @@ private void ValidateEmailAddress(string? email, int centreId) } } - private void PopulatePersonalInformationExtraFields(PersonalInformationViewModel model) + private void SetCentreName(PersonalInformationViewModel model) { model.CentreName = centresDataService.GetCentreName(model.Centre!.Value); } - private void PopulateLearnerInformationExtraFields( - LearnerInformationViewModel model - ) + private void SetJobGroupOptions(LearnerInformationViewModel model) { model.JobGroupOptions = SelectListHelper.MapOptionsToSelectListItems( jobGroupsDataService.GetJobGroupsAlphabetical(), From 24ee69c7e71ac9bf5e2efa4518be8e1ba0ec6e89 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Mon, 28 Jun 2021 18:12:06 +0100 Subject: [PATCH 18/22] HEEDLS-526 Add RegistrationData constructor accepting a centreId --- .../Controllers/Register/RegisterAdminControllerTests.cs | 6 +++--- .../Controllers/RegisterAdminController.cs | 5 +---- DigitalLearningSolutions.Web/Models/RegistrationData.cs | 6 ++++++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs b/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs index 4f3ccb5616..ae96711e1d 100644 --- a/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs +++ b/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterAdminControllerTests.cs @@ -146,7 +146,7 @@ public void PersonalInformationPost_with_wrong_autoregisteremail_for_centre_fail Centre = centreId, Email = "wrong@email" }; - var data = new RegistrationData { Centre = centreId }; + var data = new RegistrationData(centreId); controller.TempData.Set(data); A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).Returns((false, "right@email")); @@ -173,7 +173,7 @@ public void PersonalInformationPost_with_email_already_in_use_fails_validation() Centre = centreId, Email = email }; - var data = new RegistrationData { Centre = centreId }; + var data = new RegistrationData(centreId); controller.TempData.Set(data); A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).Returns((false, email)); A.CallTo(() => userDataService.GetAdminUserByEmailAddress(email)).Returns(new AdminUser()); @@ -202,7 +202,7 @@ public void PersonalInformationPost_with_correct_unique_email_is_allowed() Centre = centreId, Email = email }; - var data = new RegistrationData { Centre = centreId }; + var data = new RegistrationData(centreId); controller.TempData.Set(data); A.CallTo(() => centresDataService.GetCentreAutoRegisterValues(centreId)).Returns((false, email)); A.CallTo(() => userDataService.GetAdminUserByEmailAddress(email)).Returns(null); diff --git a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs index 25bb5609ec..f132c3aa6a 100644 --- a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs +++ b/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs @@ -185,10 +185,7 @@ private bool IsRegisterAdminAllowed(int centreId) private void SetAdminRegistrationData(int centreId) { - var adminRegistrationData = new RegistrationData - { - Centre = centreId - }; + var adminRegistrationData = new RegistrationData(centreId); var id = adminRegistrationData.Id; Response.Cookies.Append( diff --git a/DigitalLearningSolutions.Web/Models/RegistrationData.cs b/DigitalLearningSolutions.Web/Models/RegistrationData.cs index 1a5db79376..4359d8da4f 100644 --- a/DigitalLearningSolutions.Web/Models/RegistrationData.cs +++ b/DigitalLearningSolutions.Web/Models/RegistrationData.cs @@ -10,6 +10,12 @@ public RegistrationData() Id = new Guid(); } + public RegistrationData(int? centreId) + { + Id = new Guid(); + Centre = centreId; + } + public Guid Id { get; set; } public string? FirstName { get; set; } From e9063fa1d17fa2775068dcb5bc87f7b899e1d9d0 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Mon, 28 Jun 2021 18:51:44 +0100 Subject: [PATCH 19/22] HEEDLS-526 Create Controllers/Register folder; minor cosmetic changes --- .../DataServices/CentresDataServiceTests.cs | 2 +- .../DataServices/CentresDataService.cs | 3 +-- .../Controllers/{ => Register}/RegisterAdminController.cs | 0 .../Controllers/{ => Register}/RegisterController.cs | 0 4 files changed, 2 insertions(+), 3 deletions(-) rename DigitalLearningSolutions.Web/Controllers/{ => Register}/RegisterAdminController.cs (100%) rename DigitalLearningSolutions.Web/Controllers/{ => Register}/RegisterController.cs (100%) diff --git a/DigitalLearningSolutions.Data.Tests/DataServices/CentresDataServiceTests.cs b/DigitalLearningSolutions.Data.Tests/DataServices/CentresDataServiceTests.cs index 799ba9a9d5..a88805dcba 100644 --- a/DigitalLearningSolutions.Data.Tests/DataServices/CentresDataServiceTests.cs +++ b/DigitalLearningSolutions.Data.Tests/DataServices/CentresDataServiceTests.cs @@ -238,7 +238,7 @@ public void GetCentreAutoRegisterValues_should_return_correct_values() var result = centresDataService.GetCentreAutoRegisterValues(2); // Then - result.autoRegistered.Should().Be(true); + result.autoRegistered.Should().BeTrue(); result.autoRegisterManagerEmail.Should().Be(".vhrnaui@bywdskc"); } } diff --git a/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs b/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs index 2d24779442..ea52455fa3 100644 --- a/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs @@ -250,13 +250,12 @@ FROM Centres public (bool autoRegistered, string? autoRegisterManagerEmail) GetCentreAutoRegisterValues(int centreId) { - var info = connection.QueryFirstOrDefault<(bool, string?)>( + return connection.QueryFirstOrDefault<(bool, string?)>( @"SELECT AutoRegistered, AutoRegisterManagerEmail FROM Centres WHERE CentreID = @centreId", new { centreId } ); - return info; } } } diff --git a/DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs b/DigitalLearningSolutions.Web/Controllers/Register/RegisterAdminController.cs similarity index 100% rename from DigitalLearningSolutions.Web/Controllers/RegisterAdminController.cs rename to DigitalLearningSolutions.Web/Controllers/Register/RegisterAdminController.cs diff --git a/DigitalLearningSolutions.Web/Controllers/RegisterController.cs b/DigitalLearningSolutions.Web/Controllers/Register/RegisterController.cs similarity index 100% rename from DigitalLearningSolutions.Web/Controllers/RegisterController.cs rename to DigitalLearningSolutions.Web/Controllers/Register/RegisterController.cs From cc09014f8342390abcd352d1253c64496d999f48 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 29 Jun 2021 10:44:01 +0100 Subject: [PATCH 20/22] HEEDLS-526 Move register mapping helpers into viewmodel constructors; update controllers and tests --- .../Helpers/RegistrationMappingHelperTests.cs | 92 ------------------- .../LearnerInformationViewModelTests.cs | 80 ++++++++++++++++ .../PersonalInformationViewModelTests.cs | 84 +++++++++++++++++ .../Register/SummaryViewModelTests.cs | 81 ++++++++++++++++ .../Register/RegisterAdminController.cs | 8 +- .../Register/RegisterController.cs | 9 +- .../Helpers/RegistrationMappingHelper.cs | 56 ----------- .../Register/LearnerInformationViewModel.cs | 18 ++++ .../Register/PersonalInformationViewModel.cs | 16 ++++ .../ViewModels/Register/SummaryViewModel.cs | 15 +++ 10 files changed, 302 insertions(+), 157 deletions(-) create mode 100644 DigitalLearningSolutions.Web.Tests/ViewModels/Register/LearnerInformationViewModelTests.cs create mode 100644 DigitalLearningSolutions.Web.Tests/ViewModels/Register/PersonalInformationViewModelTests.cs create mode 100644 DigitalLearningSolutions.Web.Tests/ViewModels/Register/SummaryViewModelTests.cs diff --git a/DigitalLearningSolutions.Web.Tests/Helpers/RegistrationMappingHelperTests.cs b/DigitalLearningSolutions.Web.Tests/Helpers/RegistrationMappingHelperTests.cs index 1550437a35..16f272b716 100644 --- a/DigitalLearningSolutions.Web.Tests/Helpers/RegistrationMappingHelperTests.cs +++ b/DigitalLearningSolutions.Web.Tests/Helpers/RegistrationMappingHelperTests.cs @@ -39,98 +39,6 @@ public void MapToDelegateRegistrationModel_returns_correct_DelegateRegistrationM result.Answer3.Should().Be(Answer3); } - [Test] - public void MapDataToPersonalInformation_returns_correct_ViewModel() - { - // Given - var data = SampleRegistrationData(); - - // When - var result = RegistrationMappingHelper.MapDataToPersonalInformation(data); - - // Then - result.FirstName.Should().Be(FirstName); - result.LastName.Should().Be(LastName); - result.Email.Should().Be(Email); - result.Centre.Should().Be(CentreId); - } - - [Test] - public void MapDelegateDataToPersonalInformation_returns_correct_ViewModel() - { - // Given - var data = SampleDelegateRegistrationData(); - - // When - var result = RegistrationMappingHelper.MapDataToPersonalInformation(data); - - // Then - result.FirstName.Should().Be(FirstName); - result.LastName.Should().Be(LastName); - result.Email.Should().Be(Email); - result.Centre.Should().Be(CentreId); - result.IsCentreSpecificRegistration.Should().Be(IsCentreSpecificRegistration); - } - - [Test] - public void MapDataToLearnerInformation_returns_correct_ViewModel() - { - // Given - var data = SampleRegistrationData(); - - // When - var result = RegistrationMappingHelper.MapDataToLearnerInformation(data); - - // Then - result.JobGroup.Should().Be(JobGroupId); - } - - [Test] - public void MapDelegateDataToLearnerInformation_returns_correct_ViewModel() - { - // Given - var data = SampleDelegateRegistrationData(); - - // When - var result = RegistrationMappingHelper.MapDataToLearnerInformation(data); - - // Then - result.JobGroup.Should().Be(JobGroupId); - result.Answer1.Should().Be(Answer1); - result.Answer2.Should().Be(Answer2); - result.Answer3.Should().Be(Answer3); - } - - [Test] - public void MapDataToSummary_returns_correct_ViewModel() - { - // Given - var data = SampleRegistrationData(); - - // When - var result = RegistrationMappingHelper.MapDataToSummary(data); - - // Then - result.FirstName.Should().Be(FirstName); - result.LastName.Should().Be(LastName); - result.Email.Should().Be(Email); - } - - [Test] - public void MapDelegateDataToSummary_returns_correct_ViewModel() - { - // Given - var data = SampleDelegateRegistrationData(); - - // When - var result = RegistrationMappingHelper.MapDataToSummary(data); - - // Then - result.FirstName.Should().Be(FirstName); - result.LastName.Should().Be(LastName); - result.Email.Should().Be(Email); - } - private static RegistrationData SampleRegistrationData() { return new RegistrationData diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/Register/LearnerInformationViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/Register/LearnerInformationViewModelTests.cs new file mode 100644 index 0000000000..67706cc557 --- /dev/null +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/Register/LearnerInformationViewModelTests.cs @@ -0,0 +1,80 @@ +namespace DigitalLearningSolutions.Web.Tests.ViewModels.Register +{ + using DigitalLearningSolutions.Web.Models; + using DigitalLearningSolutions.Web.ViewModels.Register; + using FluentAssertions; + using NUnit.Framework; + + public class LearnerInformationViewModelTests + { + private const string FirstName = "Test"; + private const string LastName = "User"; + private const string Email = "test@email.com"; + private const int CentreId = 5; + private const int JobGroupId = 10; + private const string PasswordHash = "password hash"; + private const string Answer1 = "a1"; + private const string Answer2 = "a2"; + private const string Answer3 = "a3"; + private const bool IsCentreSpecificRegistration = true; + + [Test] + public void LearnerInformation_constructor_using_data_populates_viewmodel_correctly() + { + // Given + var data = SampleRegistrationData(); + + // When + var result = new LearnerInformationViewModel(data); + + // Then + result.JobGroup.Should().Be(JobGroupId); + } + + [Test] + public void LearnerInformation_constructor_using_delegate_data_populates_viewmodel_correctly() + { + // Given + var data = SampleDelegateRegistrationData(); + + // When + var result = new LearnerInformationViewModel(data); + + // Then + result.JobGroup.Should().Be(JobGroupId); + result.Answer1.Should().Be(Answer1); + result.Answer2.Should().Be(Answer2); + result.Answer3.Should().Be(Answer3); + } + + private static RegistrationData SampleRegistrationData() + { + return new RegistrationData + { + FirstName = FirstName, + LastName = LastName, + Email = Email, + Centre = CentreId, + JobGroup = JobGroupId, + PasswordHash = PasswordHash + }; + } + + private static DelegateRegistrationData SampleDelegateRegistrationData() + { + return new DelegateRegistrationData + { + FirstName = FirstName, + LastName = LastName, + Email = Email, + Centre = CentreId, + JobGroup = JobGroupId, + PasswordHash = PasswordHash, + Answer1 = Answer1, + Answer2 = Answer2, + Answer3 = Answer3, + IsCentreSpecificRegistration = IsCentreSpecificRegistration + }; + } + } +} diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/Register/PersonalInformationViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/Register/PersonalInformationViewModelTests.cs new file mode 100644 index 0000000000..6357e75994 --- /dev/null +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/Register/PersonalInformationViewModelTests.cs @@ -0,0 +1,84 @@ +namespace DigitalLearningSolutions.Web.Tests.ViewModels.Register +{ + using DigitalLearningSolutions.Web.Models; + using DigitalLearningSolutions.Web.ViewModels.Register; + using FluentAssertions; + using NUnit.Framework; + + public class PersonalInformationViewModelTests + { + private const string FirstName = "Test"; + private const string LastName = "User"; + private const string Email = "test@email.com"; + private const int CentreId = 5; + private const int JobGroupId = 10; + private const string PasswordHash = "password hash"; + private const string Answer1 = "a1"; + private const string Answer2 = "a2"; + private const string Answer3 = "a3"; + private const bool IsCentreSpecificRegistration = true; + + [Test] + public void PersonalInformation_constructor_using_data_populates_viewmodel_correctly() + { + // Given + var data = SampleRegistrationData(); + + // When + var result = new PersonalInformationViewModel(data); + + // Then + result.FirstName.Should().Be(FirstName); + result.LastName.Should().Be(LastName); + result.Email.Should().Be(Email); + result.Centre.Should().Be(CentreId); + } + + [Test] + public void PersonalInformation_constructor_using_delegate_data_populates_viewmodel_correctly() + { + // Given + var data = SampleDelegateRegistrationData(); + + // When + var result = new PersonalInformationViewModel(data); + + // Then + result.FirstName.Should().Be(FirstName); + result.LastName.Should().Be(LastName); + result.Email.Should().Be(Email); + result.Centre.Should().Be(CentreId); + result.IsCentreSpecificRegistration.Should().Be(IsCentreSpecificRegistration); + } + + private static RegistrationData SampleRegistrationData() + { + return new RegistrationData + { + FirstName = FirstName, + LastName = LastName, + Email = Email, + Centre = CentreId, + JobGroup = JobGroupId, + PasswordHash = PasswordHash + }; + } + + private static DelegateRegistrationData SampleDelegateRegistrationData() + { + return new DelegateRegistrationData + { + FirstName = FirstName, + LastName = LastName, + Email = Email, + Centre = CentreId, + JobGroup = JobGroupId, + PasswordHash = PasswordHash, + Answer1 = Answer1, + Answer2 = Answer2, + Answer3 = Answer3, + IsCentreSpecificRegistration = IsCentreSpecificRegistration + }; + } + } +} diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/Register/SummaryViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/Register/SummaryViewModelTests.cs new file mode 100644 index 0000000000..f6be368048 --- /dev/null +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/Register/SummaryViewModelTests.cs @@ -0,0 +1,81 @@ +namespace DigitalLearningSolutions.Web.Tests.ViewModels.Register +{ + using DigitalLearningSolutions.Web.Models; + using DigitalLearningSolutions.Web.ViewModels.Register; + using FluentAssertions; + using NUnit.Framework; + + public class SummaryViewModelTests + { + private const string FirstName = "Test"; + private const string LastName = "User"; + private const string Email = "test@email.com"; + private const int CentreId = 5; + private const int JobGroupId = 10; + private const string PasswordHash = "password hash"; + private const string Answer1 = "a1"; + private const string Answer2 = "a2"; + private const string Answer3 = "a3"; + private const bool IsCentreSpecificRegistration = true; + + [Test] + public void Summary_constructor_using_data_populates_viewmodel_correctly() + { + // Given + var data = SampleRegistrationData(); + + // When + var result = new SummaryViewModel(data); + + // Then + result.FirstName.Should().Be(FirstName); + result.LastName.Should().Be(LastName); + result.Email.Should().Be(Email); + } + + [Test] + public void Summary_constructor_using_delegate_data_populates_viewmodel_correctly() + { + // Given + var data = SampleDelegateRegistrationData(); + + // When + var result = new SummaryViewModel(data); + + // Then + result.FirstName.Should().Be(FirstName); + result.LastName.Should().Be(LastName); + result.Email.Should().Be(Email); + } + + private static RegistrationData SampleRegistrationData() + { + return new RegistrationData + { + FirstName = FirstName, + LastName = LastName, + Email = Email, + Centre = CentreId, + JobGroup = JobGroupId, + PasswordHash = PasswordHash + }; + } + + private static DelegateRegistrationData SampleDelegateRegistrationData() + { + return new DelegateRegistrationData + { + FirstName = FirstName, + LastName = LastName, + Email = Email, + Centre = CentreId, + JobGroup = JobGroupId, + PasswordHash = PasswordHash, + Answer1 = Answer1, + Answer2 = Answer2, + Answer3 = Answer3, + IsCentreSpecificRegistration = IsCentreSpecificRegistration + }; + } + } +} diff --git a/DigitalLearningSolutions.Web/Controllers/Register/RegisterAdminController.cs b/DigitalLearningSolutions.Web/Controllers/Register/RegisterAdminController.cs index f132c3aa6a..e591fbfcd2 100644 --- a/DigitalLearningSolutions.Web/Controllers/Register/RegisterAdminController.cs +++ b/DigitalLearningSolutions.Web/Controllers/Register/RegisterAdminController.cs @@ -56,7 +56,7 @@ public IActionResult PersonalInformation() { var data = TempData.Peek()!; - var model = RegistrationMappingHelper.MapDataToPersonalInformation(data); + var model = new PersonalInformationViewModel(data); SetCentreName(model); ValidateEmailAddress(model.Email, model.Centre!.Value); @@ -90,7 +90,7 @@ public IActionResult LearnerInformation() { var data = TempData.Peek()!; - var model = RegistrationMappingHelper.MapDataToLearnerInformation(data); + var model = new LearnerInformationViewModel(data); SetJobGroupOptions(model); return View(model); @@ -142,7 +142,7 @@ public IActionResult Password(PasswordViewModel model) public IActionResult Summary() { var data = TempData.Peek()!; - var model = RegistrationMappingHelper.MapDataToSummary(data); + var model = new SummaryViewModel(data); PopulateSummaryExtraFields(model, data); return View(model); } @@ -155,7 +155,7 @@ public IActionResult Summary(SummaryViewModel model) if (!ModelState.IsValid) { - var viewModel = RegistrationMappingHelper.MapDataToSummary(data); + var viewModel = new SummaryViewModel(data); PopulateSummaryExtraFields(viewModel, data); viewModel.Terms = model.Terms; return View(viewModel); diff --git a/DigitalLearningSolutions.Web/Controllers/Register/RegisterController.cs b/DigitalLearningSolutions.Web/Controllers/Register/RegisterController.cs index 74624f4f40..5142ffbb04 100644 --- a/DigitalLearningSolutions.Web/Controllers/Register/RegisterController.cs +++ b/DigitalLearningSolutions.Web/Controllers/Register/RegisterController.cs @@ -10,7 +10,6 @@ namespace DigitalLearningSolutions.Web.Controllers using DigitalLearningSolutions.Web.Models; using DigitalLearningSolutions.Web.ServiceFilter; using DigitalLearningSolutions.Web.ViewModels.Common; - using DigitalLearningSolutions.Web.ViewModels.MyAccount; using DigitalLearningSolutions.Web.ViewModels.Register; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -65,7 +64,7 @@ public IActionResult PersonalInformation() { var data = TempData.Peek()!; - var model = RegistrationMappingHelper.MapDataToPersonalInformation(data); + var model = new PersonalInformationViewModel(data); PopulatePersonalInformationExtraFields(model); // Check this email and centre combination doesn't already exist in case we were redirected @@ -111,7 +110,7 @@ public IActionResult LearnerInformation() return RedirectToAction("Index"); } - var model = RegistrationMappingHelper.MapDataToLearnerInformation(data); + var model = new LearnerInformationViewModel(data); PopulateLearnerInformationExtraFields(model, data); return View(model); } @@ -180,7 +179,7 @@ public IActionResult Password(PasswordViewModel model) public IActionResult Summary() { var data = TempData.Peek()!; - var viewModel = RegistrationMappingHelper.MapDataToSummary(data); + var viewModel = new SummaryViewModel(data); PopulateSummaryExtraFields(viewModel, data); return View(viewModel); } @@ -198,7 +197,7 @@ public IActionResult Summary(SummaryViewModel model) if (!ModelState.IsValid) { - var viewModel = RegistrationMappingHelper.MapDataToSummary(data); + var viewModel = new SummaryViewModel(data); PopulateSummaryExtraFields(viewModel, data); viewModel.Terms = model.Terms; return View(viewModel); diff --git a/DigitalLearningSolutions.Web/Helpers/RegistrationMappingHelper.cs b/DigitalLearningSolutions.Web/Helpers/RegistrationMappingHelper.cs index 36c22b34cf..4a6a814dc6 100644 --- a/DigitalLearningSolutions.Web/Helpers/RegistrationMappingHelper.cs +++ b/DigitalLearningSolutions.Web/Helpers/RegistrationMappingHelper.cs @@ -2,7 +2,6 @@ { using DigitalLearningSolutions.Data.Models.Register; using DigitalLearningSolutions.Web.Models; - using DigitalLearningSolutions.Web.ViewModels.Register; public static class RegistrationMappingHelper { @@ -23,60 +22,5 @@ public static DelegateRegistrationModel MapToDelegateRegistrationModel(DelegateR data.Answer6 ); } - - public static SummaryViewModel MapDataToSummary(RegistrationData data) - { - return new SummaryViewModel - { - FirstName = data.FirstName!, - LastName = data.LastName!, - Email = data.Email! - }; - } - - public static SummaryViewModel MapDataToSummary(DelegateRegistrationData data) - { - var model = MapDataToSummary((RegistrationData)data); - model.IsCentreSpecificRegistration = data.IsCentreSpecificRegistration; - return model; - } - - public static PersonalInformationViewModel MapDataToPersonalInformation(RegistrationData data) - { - return new PersonalInformationViewModel - { - FirstName = data.FirstName, - LastName = data.LastName, - Centre = data.Centre, - Email = data.Email - }; - } - - public static PersonalInformationViewModel MapDataToPersonalInformation(DelegateRegistrationData data) - { - var model = MapDataToPersonalInformation((RegistrationData)data); - model.IsCentreSpecificRegistration = data.IsCentreSpecificRegistration; - return model; - } - - public static LearnerInformationViewModel MapDataToLearnerInformation(RegistrationData data) - { - return new LearnerInformationViewModel - { - JobGroup = data.JobGroup - }; - } - - public static LearnerInformationViewModel MapDataToLearnerInformation(DelegateRegistrationData data) - { - var model = MapDataToLearnerInformation((RegistrationData)data); - model.Answer1 = data.Answer1; - model.Answer2 = data.Answer2; - model.Answer3 = data.Answer3; - model.Answer4 = data.Answer4; - model.Answer5 = data.Answer5; - model.Answer6 = data.Answer6; - return model; - } } } diff --git a/DigitalLearningSolutions.Web/ViewModels/Register/LearnerInformationViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/Register/LearnerInformationViewModel.cs index 4878219897..6336b593d5 100644 --- a/DigitalLearningSolutions.Web/ViewModels/Register/LearnerInformationViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/Register/LearnerInformationViewModel.cs @@ -2,11 +2,29 @@ { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; + using DigitalLearningSolutions.Web.Models; using DigitalLearningSolutions.Web.ViewModels.Common; using Microsoft.AspNetCore.Mvc.Rendering; public class LearnerInformationViewModel { + public LearnerInformationViewModel() { } + + public LearnerInformationViewModel(RegistrationData data) + { + JobGroup = data.JobGroup; + } + + public LearnerInformationViewModel(DelegateRegistrationData data) : this((RegistrationData)data) + { + Answer1 = data.Answer1; + Answer2 = data.Answer2; + Answer3 = data.Answer3; + Answer4 = data.Answer4; + Answer5 = data.Answer5; + Answer6 = data.Answer6; + } + [Required(ErrorMessage = "Select a job group")] public int? JobGroup { get; set; } diff --git a/DigitalLearningSolutions.Web/ViewModels/Register/PersonalInformationViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/Register/PersonalInformationViewModel.cs index 54d9616aae..0f4dd5f0b8 100644 --- a/DigitalLearningSolutions.Web/ViewModels/Register/PersonalInformationViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/Register/PersonalInformationViewModel.cs @@ -3,10 +3,26 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using DigitalLearningSolutions.Web.Attributes; + using DigitalLearningSolutions.Web.Models; using Microsoft.AspNetCore.Mvc.Rendering; public class PersonalInformationViewModel { + public PersonalInformationViewModel() { } + + public PersonalInformationViewModel(RegistrationData data) + { + FirstName = data.FirstName; + LastName = data.LastName; + Centre = data.Centre; + Email = data.Email; + } + + public PersonalInformationViewModel(DelegateRegistrationData data) : this((RegistrationData)data) + { + IsCentreSpecificRegistration = data.IsCentreSpecificRegistration; + } + [Required(ErrorMessage = "Enter your first name")] [MaxLength(250, ErrorMessage = "First name must be 250 characters or fewer")] public string? FirstName { get; set; } diff --git a/DigitalLearningSolutions.Web/ViewModels/Register/SummaryViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/Register/SummaryViewModel.cs index 2f0e76a7c5..85fcba949f 100644 --- a/DigitalLearningSolutions.Web/ViewModels/Register/SummaryViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/Register/SummaryViewModel.cs @@ -2,10 +2,25 @@ { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; + using DigitalLearningSolutions.Web.Models; using DigitalLearningSolutions.Web.ViewModels.Common; public class SummaryViewModel : IValidatableObject { + public SummaryViewModel() { } + + public SummaryViewModel(RegistrationData data) + { + FirstName = data.FirstName; + LastName = data.LastName; + Email = data.Email; + } + + public SummaryViewModel(DelegateRegistrationData data) : this((RegistrationData)data) + { + IsCentreSpecificRegistration = data.IsCentreSpecificRegistration; + } + public string? FirstName { get; set; } public string? LastName { get; set; } public string? Email { get; set; } From 82105debdd126b132c3b794ee2e5416a4211fe81 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 29 Jun 2021 11:10:42 +0100 Subject: [PATCH 21/22] HEEDLS-526 Refactor registration data mapping helper tests --- .../Helpers/RegistrationMappingHelperTests.cs | 63 ++++-------------- .../TestHelpers/RegistrationDataHelper.cs | 48 ++++++++++++++ .../LearnerInformationViewModelTests.cs | 57 +++------------- .../PersonalInformationViewModelTests.cs | 65 ++++--------------- .../Register/SummaryViewModelTests.cs | 59 +++-------------- 5 files changed, 88 insertions(+), 204 deletions(-) create mode 100644 DigitalLearningSolutions.Web.Tests/TestHelpers/RegistrationDataHelper.cs diff --git a/DigitalLearningSolutions.Web.Tests/Helpers/RegistrationMappingHelperTests.cs b/DigitalLearningSolutions.Web.Tests/Helpers/RegistrationMappingHelperTests.cs index 16f272b716..e602ca899c 100644 --- a/DigitalLearningSolutions.Web.Tests/Helpers/RegistrationMappingHelperTests.cs +++ b/DigitalLearningSolutions.Web.Tests/Helpers/RegistrationMappingHelperTests.cs @@ -1,72 +1,31 @@ namespace DigitalLearningSolutions.Web.Tests.Helpers { using DigitalLearningSolutions.Web.Helpers; - using DigitalLearningSolutions.Web.Models; + using DigitalLearningSolutions.Web.Tests.TestHelpers; using FluentAssertions; using NUnit.Framework; public class RegistrationMappingHelperTests { - private const string FirstName = "Test"; - private const string LastName = "User"; - private const string Email = "test@email.com"; - private const int CentreId = 5; - private const int JobGroupId = 10; - private const string PasswordHash = "password hash"; - private const string Answer1 = "a1"; - private const string Answer2 = "a2"; - private const string Answer3 = "a3"; - private const bool IsCentreSpecificRegistration = true; - [Test] public void MapToDelegateRegistrationModel_returns_correct_DelegateRegistrationModel() { // Given - var data = SampleDelegateRegistrationData(); + var data = RegistrationDataHelper.SampleDelegateRegistrationData(); // When var result = RegistrationMappingHelper.MapToDelegateRegistrationModel(data); // Then - result.FirstName.Should().Be(FirstName); - result.LastName.Should().Be(LastName); - result.Email.Should().Be(Email); - result.Centre.Should().Be(CentreId); - result.JobGroup.Should().Be(JobGroupId); - result.PasswordHash.Should().Be(PasswordHash); - result.Answer1.Should().Be(Answer1); - result.Answer2.Should().Be(Answer2); - result.Answer3.Should().Be(Answer3); - } - - private static RegistrationData SampleRegistrationData() - { - return new RegistrationData - { - FirstName = FirstName, - LastName = LastName, - Email = Email, - Centre = CentreId, - JobGroup = JobGroupId, - PasswordHash = PasswordHash - }; - } - - private static DelegateRegistrationData SampleDelegateRegistrationData() - { - return new DelegateRegistrationData - { - FirstName = FirstName, - LastName = LastName, - Email = Email, - Centre = CentreId, - JobGroup = JobGroupId, - PasswordHash = PasswordHash, - Answer1 = Answer1, - Answer2 = Answer2, - Answer3 = Answer3, - IsCentreSpecificRegistration = IsCentreSpecificRegistration - }; + result.FirstName.Should().Be(data.FirstName); + result.LastName.Should().Be(data.LastName); + result.Email.Should().Be(data.Email); + result.Centre.Should().Be(data.Centre); + result.JobGroup.Should().Be(data.JobGroup); + result.PasswordHash.Should().Be(data.PasswordHash); + result.Answer1.Should().Be(data.Answer1); + result.Answer2.Should().Be(data.Answer2); + result.Answer3.Should().Be(data.Answer3); } } } diff --git a/DigitalLearningSolutions.Web.Tests/TestHelpers/RegistrationDataHelper.cs b/DigitalLearningSolutions.Web.Tests/TestHelpers/RegistrationDataHelper.cs new file mode 100644 index 0000000000..1634803087 --- /dev/null +++ b/DigitalLearningSolutions.Web.Tests/TestHelpers/RegistrationDataHelper.cs @@ -0,0 +1,48 @@ +namespace DigitalLearningSolutions.Web.Tests.TestHelpers +{ + using DigitalLearningSolutions.Web.Models; + + public static class RegistrationDataHelper + { + private const string FirstName = "Test"; + private const string LastName = "User"; + private const string Email = "test@email.com"; + private const int CentreId = 5; + private const int JobGroupId = 10; + private const string PasswordHash = "password hash"; + private const string Answer1 = "a1"; + private const string Answer2 = "a2"; + private const string Answer3 = "a3"; + private const bool IsCentreSpecificRegistration = true; + + public static DelegateRegistrationData SampleDelegateRegistrationData() + { + return new DelegateRegistrationData + { + FirstName = FirstName, + LastName = LastName, + Email = Email, + Centre = CentreId, + JobGroup = JobGroupId, + PasswordHash = PasswordHash, + Answer1 = Answer1, + Answer2 = Answer2, + Answer3 = Answer3, + IsCentreSpecificRegistration = IsCentreSpecificRegistration + }; + } + + public static RegistrationData SampleRegistrationData() + { + return new RegistrationData + { + FirstName = FirstName, + LastName = LastName, + Email = Email, + Centre = CentreId, + JobGroup = JobGroupId, + PasswordHash = PasswordHash + }; + } + } +} diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/Register/LearnerInformationViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/Register/LearnerInformationViewModelTests.cs index 67706cc557..d70a579db9 100644 --- a/DigitalLearningSolutions.Web.Tests/ViewModels/Register/LearnerInformationViewModelTests.cs +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/Register/LearnerInformationViewModelTests.cs @@ -1,80 +1,39 @@ namespace DigitalLearningSolutions.Web.Tests.ViewModels.Register { - using DigitalLearningSolutions.Web.Models; + using DigitalLearningSolutions.Web.Tests.TestHelpers; using DigitalLearningSolutions.Web.ViewModels.Register; using FluentAssertions; using NUnit.Framework; public class LearnerInformationViewModelTests { - private const string FirstName = "Test"; - private const string LastName = "User"; - private const string Email = "test@email.com"; - private const int CentreId = 5; - private const int JobGroupId = 10; - private const string PasswordHash = "password hash"; - private const string Answer1 = "a1"; - private const string Answer2 = "a2"; - private const string Answer3 = "a3"; - private const bool IsCentreSpecificRegistration = true; - [Test] public void LearnerInformation_constructor_using_data_populates_viewmodel_correctly() { // Given - var data = SampleRegistrationData(); + var data = RegistrationDataHelper.SampleRegistrationData(); // When var result = new LearnerInformationViewModel(data); // Then - result.JobGroup.Should().Be(JobGroupId); + result.JobGroup.Should().Be(data.JobGroup); } [Test] public void LearnerInformation_constructor_using_delegate_data_populates_viewmodel_correctly() { // Given - var data = SampleDelegateRegistrationData(); + var data = RegistrationDataHelper.SampleDelegateRegistrationData(); // When var result = new LearnerInformationViewModel(data); // Then - result.JobGroup.Should().Be(JobGroupId); - result.Answer1.Should().Be(Answer1); - result.Answer2.Should().Be(Answer2); - result.Answer3.Should().Be(Answer3); - } - - private static RegistrationData SampleRegistrationData() - { - return new RegistrationData - { - FirstName = FirstName, - LastName = LastName, - Email = Email, - Centre = CentreId, - JobGroup = JobGroupId, - PasswordHash = PasswordHash - }; - } - - private static DelegateRegistrationData SampleDelegateRegistrationData() - { - return new DelegateRegistrationData - { - FirstName = FirstName, - LastName = LastName, - Email = Email, - Centre = CentreId, - JobGroup = JobGroupId, - PasswordHash = PasswordHash, - Answer1 = Answer1, - Answer2 = Answer2, - Answer3 = Answer3, - IsCentreSpecificRegistration = IsCentreSpecificRegistration - }; + result.JobGroup.Should().Be(data.JobGroup); + result.Answer1.Should().Be(data.Answer1); + result.Answer2.Should().Be(data.Answer2); + result.Answer3.Should().Be(data.Answer3); } } } diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/Register/PersonalInformationViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/Register/PersonalInformationViewModelTests.cs index 6357e75994..4bc011216e 100644 --- a/DigitalLearningSolutions.Web.Tests/ViewModels/Register/PersonalInformationViewModelTests.cs +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/Register/PersonalInformationViewModelTests.cs @@ -1,84 +1,43 @@ namespace DigitalLearningSolutions.Web.Tests.ViewModels.Register { - using DigitalLearningSolutions.Web.Models; + using DigitalLearningSolutions.Web.Tests.TestHelpers; using DigitalLearningSolutions.Web.ViewModels.Register; using FluentAssertions; using NUnit.Framework; public class PersonalInformationViewModelTests { - private const string FirstName = "Test"; - private const string LastName = "User"; - private const string Email = "test@email.com"; - private const int CentreId = 5; - private const int JobGroupId = 10; - private const string PasswordHash = "password hash"; - private const string Answer1 = "a1"; - private const string Answer2 = "a2"; - private const string Answer3 = "a3"; - private const bool IsCentreSpecificRegistration = true; - [Test] public void PersonalInformation_constructor_using_data_populates_viewmodel_correctly() { // Given - var data = SampleRegistrationData(); + var data = RegistrationDataHelper.SampleRegistrationData(); // When var result = new PersonalInformationViewModel(data); // Then - result.FirstName.Should().Be(FirstName); - result.LastName.Should().Be(LastName); - result.Email.Should().Be(Email); - result.Centre.Should().Be(CentreId); + result.FirstName.Should().Be(data.FirstName); + result.LastName.Should().Be(data.LastName); + result.Email.Should().Be(data.Email); + result.Centre.Should().Be(data.Centre); } [Test] public void PersonalInformation_constructor_using_delegate_data_populates_viewmodel_correctly() { // Given - var data = SampleDelegateRegistrationData(); + var data = RegistrationDataHelper.SampleDelegateRegistrationData(); // When var result = new PersonalInformationViewModel(data); // Then - result.FirstName.Should().Be(FirstName); - result.LastName.Should().Be(LastName); - result.Email.Should().Be(Email); - result.Centre.Should().Be(CentreId); - result.IsCentreSpecificRegistration.Should().Be(IsCentreSpecificRegistration); - } - - private static RegistrationData SampleRegistrationData() - { - return new RegistrationData - { - FirstName = FirstName, - LastName = LastName, - Email = Email, - Centre = CentreId, - JobGroup = JobGroupId, - PasswordHash = PasswordHash - }; - } - - private static DelegateRegistrationData SampleDelegateRegistrationData() - { - return new DelegateRegistrationData - { - FirstName = FirstName, - LastName = LastName, - Email = Email, - Centre = CentreId, - JobGroup = JobGroupId, - PasswordHash = PasswordHash, - Answer1 = Answer1, - Answer2 = Answer2, - Answer3 = Answer3, - IsCentreSpecificRegistration = IsCentreSpecificRegistration - }; + result.FirstName.Should().Be(data.FirstName); + result.LastName.Should().Be(data.LastName); + result.Email.Should().Be(data.Email); + result.Centre.Should().Be(data.Centre); + result.IsCentreSpecificRegistration.Should().Be(data.IsCentreSpecificRegistration); } } } diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/Register/SummaryViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/Register/SummaryViewModelTests.cs index f6be368048..2a77ece6e8 100644 --- a/DigitalLearningSolutions.Web.Tests/ViewModels/Register/SummaryViewModelTests.cs +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/Register/SummaryViewModelTests.cs @@ -1,81 +1,40 @@ namespace DigitalLearningSolutions.Web.Tests.ViewModels.Register { - using DigitalLearningSolutions.Web.Models; + using DigitalLearningSolutions.Web.Tests.TestHelpers; using DigitalLearningSolutions.Web.ViewModels.Register; using FluentAssertions; using NUnit.Framework; public class SummaryViewModelTests { - private const string FirstName = "Test"; - private const string LastName = "User"; - private const string Email = "test@email.com"; - private const int CentreId = 5; - private const int JobGroupId = 10; - private const string PasswordHash = "password hash"; - private const string Answer1 = "a1"; - private const string Answer2 = "a2"; - private const string Answer3 = "a3"; - private const bool IsCentreSpecificRegistration = true; - [Test] public void Summary_constructor_using_data_populates_viewmodel_correctly() { // Given - var data = SampleRegistrationData(); + var data = RegistrationDataHelper.SampleRegistrationData(); // When var result = new SummaryViewModel(data); // Then - result.FirstName.Should().Be(FirstName); - result.LastName.Should().Be(LastName); - result.Email.Should().Be(Email); + result.FirstName.Should().Be(data.FirstName); + result.LastName.Should().Be(data.LastName); + result.Email.Should().Be(data.Email); } [Test] public void Summary_constructor_using_delegate_data_populates_viewmodel_correctly() { // Given - var data = SampleDelegateRegistrationData(); + var data = RegistrationDataHelper.SampleDelegateRegistrationData(); // When var result = new SummaryViewModel(data); // Then - result.FirstName.Should().Be(FirstName); - result.LastName.Should().Be(LastName); - result.Email.Should().Be(Email); - } - - private static RegistrationData SampleRegistrationData() - { - return new RegistrationData - { - FirstName = FirstName, - LastName = LastName, - Email = Email, - Centre = CentreId, - JobGroup = JobGroupId, - PasswordHash = PasswordHash - }; - } - - private static DelegateRegistrationData SampleDelegateRegistrationData() - { - return new DelegateRegistrationData - { - FirstName = FirstName, - LastName = LastName, - Email = Email, - Centre = CentreId, - JobGroup = JobGroupId, - PasswordHash = PasswordHash, - Answer1 = Answer1, - Answer2 = Answer2, - Answer3 = Answer3, - IsCentreSpecificRegistration = IsCentreSpecificRegistration - }; + result.FirstName.Should().Be(data.FirstName); + result.LastName.Should().Be(data.LastName); + result.Email.Should().Be(data.Email); } } } From a201845fd238de9e0199af495a287723de287537 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 29 Jun 2021 13:19:11 +0100 Subject: [PATCH 22/22] HEEDLS-526 Minor syntax change --- .../Controllers/Register/RegisterAdminController.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DigitalLearningSolutions.Web/Controllers/Register/RegisterAdminController.cs b/DigitalLearningSolutions.Web/Controllers/Register/RegisterAdminController.cs index e591fbfcd2..85a726d0bb 100644 --- a/DigitalLearningSolutions.Web/Controllers/Register/RegisterAdminController.cs +++ b/DigitalLearningSolutions.Web/Controllers/Register/RegisterAdminController.cs @@ -208,7 +208,8 @@ private void ValidateEmailAddress(string? email, int centreId) return; } - var (_, autoRegisterManagerEmail) = centresDataService.GetCentreAutoRegisterValues(centreId); + var autoRegisterManagerEmail = + centresDataService.GetCentreAutoRegisterValues(centreId).autoRegisterManagerEmail; if (!email.Equals(autoRegisterManagerEmail)) { ModelState.AddModelError(