From fc2e4ab8d517fb08263e71f9a0eabe14e98fbb77 Mon Sep 17 00:00:00 2001 From: Andrew Horth Date: Tue, 13 Aug 2024 13:40:52 +0100 Subject: [PATCH] Add check to see if user requesting a TRN is intending to do an NPQ --- .../AuthorizeAccessLinkGenerator.cs | 6 + .../Pages/RequestTrn/Email.cshtml | 2 +- .../Pages/RequestTrn/Index.cshtml | 2 +- .../Pages/RequestTrn/NotEligible.cshtml | 15 ++ .../Pages/RequestTrn/NotEligible.cshtml.cs | 24 ++++ .../Pages/RequestTrn/NpqCheck.cshtml | 25 ++++ .../Pages/RequestTrn/NpqCheck.cshtml.cs | 44 ++++++ .../RequestTrn/RequestTrnJourneyState.cs | 1 + .../RequestTrnTests.cs | 132 ++++++++++-------- .../PageTests/RequestTrn/NotEligibleTests.cs | 91 ++++++++++++ .../PageTests/RequestTrn/NpqCheckTests.cs | 130 +++++++++++++++++ 11 files changed, 412 insertions(+), 60 deletions(-) create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NotEligible.cshtml create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NotEligible.cshtml.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NpqCheck.cshtml create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NpqCheck.cshtml.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.Tests/PageTests/RequestTrn/NotEligibleTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.Tests/PageTests/RequestTrn/NpqCheckTests.cs diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/AuthorizeAccessLinkGenerator.cs b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/AuthorizeAccessLinkGenerator.cs index 573866095a..654fc53822 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/AuthorizeAccessLinkGenerator.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/AuthorizeAccessLinkGenerator.cs @@ -38,6 +38,12 @@ public string SignOut(JourneyInstanceId journeyInstanceId) => public string RequestTrn(JourneyInstanceId journeyInstanceId) => GetRequiredPathByPage("/RequestTrn/Index", journeyInstanceId: journeyInstanceId); + public string RequestTrnNpqCheck(JourneyInstanceId journeyInstanceId) => + GetRequiredPathByPage("/RequestTrn/NpqCheck", journeyInstanceId: journeyInstanceId); + + public string RequestTrnNotEligible(JourneyInstanceId journeyInstanceId) => + GetRequiredPathByPage("/RequestTrn/NotEligible", journeyInstanceId: journeyInstanceId); + public string RequestTrnEmail(JourneyInstanceId journeyInstanceId, bool? fromCheckAnswers = null) => GetRequiredPathByPage("/RequestTrn/Email", routeValues: new { fromCheckAnswers }, journeyInstanceId: journeyInstanceId); diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/Email.cshtml b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/Email.cshtml index 99cf42a398..7f4f8120ec 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/Email.cshtml +++ b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/Email.cshtml @@ -5,7 +5,7 @@ } @section BeforeContent { - + }
diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/Index.cshtml b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/Index.cshtml index eae2903d56..3bcb3dba0e 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/Index.cshtml +++ b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/Index.cshtml @@ -24,4 +24,4 @@
-Start now +Start now diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NotEligible.cshtml b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NotEligible.cshtml new file mode 100644 index 0000000000..b118ef7e41 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NotEligible.cshtml @@ -0,0 +1,15 @@ +@page "/request-trn/not-eligible" +@model TeachingRecordSystem.AuthorizeAccess.Pages.RequestTrn.NotEligibleModel +@{ + ViewBag.Title = "You cannot use this service to get a TRN"; +} + +@section BeforeContent { + +} + +
+
+

@ViewBag.Title

+
+
diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NotEligible.cshtml.cs b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NotEligible.cshtml.cs new file mode 100644 index 0000000000..8771963a06 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NotEligible.cshtml.cs @@ -0,0 +1,24 @@ +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc.RazorPages; +using TeachingRecordSystem.UiCommon.FormFlow; + +namespace TeachingRecordSystem.AuthorizeAccess.Pages.RequestTrn; + +[Journey(RequestTrnJourneyState.JourneyName), RequireJourneyInstance] +public class NotEligibleModel(AuthorizeAccessLinkGenerator linkGenerator) : PageModel +{ + public JourneyInstance? JourneyInstance { get; set; } + + public override void OnPageHandlerExecuting(PageHandlerExecutingContext context) + { + var state = JourneyInstance!.State; + if (state.HasPendingTrnRequest) + { + context.Result = Redirect(linkGenerator.RequestTrnSubmitted(JourneyInstance!.InstanceId)); + } + else if (state.IsPlanningToTakeAnNpq is null) + { + context.Result = Redirect(linkGenerator.RequestTrnNpqCheck(JourneyInstance!.InstanceId)); + } + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NpqCheck.cshtml b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NpqCheck.cshtml new file mode 100644 index 0000000000..9982e6b89c --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NpqCheck.cshtml @@ -0,0 +1,25 @@ +@page "/request-trn/npq-check" +@model TeachingRecordSystem.AuthorizeAccess.Pages.RequestTrn.NpqCheckModel +@{ + ViewBag.Title = Html.DisplayNameFor(m => m.IsPlanningToTakeAnNpq); +} + +@section BeforeContent { + +} + +
+
+
+ + + + Yes + No + + + + Continue +
+
+
diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NpqCheck.cshtml.cs b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NpqCheck.cshtml.cs new file mode 100644 index 0000000000..c63eec3135 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/NpqCheck.cshtml.cs @@ -0,0 +1,44 @@ +using System.ComponentModel.DataAnnotations; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc.RazorPages; +using TeachingRecordSystem.UiCommon.FormFlow; + +namespace TeachingRecordSystem.AuthorizeAccess.Pages.RequestTrn; + +[Journey(RequestTrnJourneyState.JourneyName), RequireJourneyInstance] +public class NpqCheckModel(AuthorizeAccessLinkGenerator linkGenerator) : PageModel +{ + public JourneyInstance? JourneyInstance { get; set; } + + [BindProperty] + [Display(Name = "Do you plan on taking a national professional qualification (NPQ)?")] + [Required(ErrorMessage = "Tell us whether you plan on taking a national professional qualification (NPQ)")] + public bool? IsPlanningToTakeAnNpq { get; set; } + + public async Task OnPost() + { + if (!ModelState.IsValid) + { + return this.PageWithErrors(); + } + + await JourneyInstance!.UpdateStateAsync(state => state.IsPlanningToTakeAnNpq = IsPlanningToTakeAnNpq); + + return IsPlanningToTakeAnNpq == true ? + Redirect(linkGenerator.RequestTrnEmail(JourneyInstance!.InstanceId)) : + Redirect(linkGenerator.RequestTrnNotEligible(JourneyInstance.InstanceId)); + } + + public override void OnPageHandlerExecuting(PageHandlerExecutingContext context) + { + var state = JourneyInstance!.State; + if (state.HasPendingTrnRequest) + { + context.Result = Redirect(linkGenerator.RequestTrnSubmitted(JourneyInstance!.InstanceId)); + return; + } + + IsPlanningToTakeAnNpq ??= JourneyInstance!.State.IsPlanningToTakeAnNpq; + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/RequestTrnJourneyState.cs b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/RequestTrnJourneyState.cs index 699d85b5d8..83340c7b42 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/RequestTrnJourneyState.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/RequestTrn/RequestTrnJourneyState.cs @@ -9,6 +9,7 @@ public class RequestTrnJourneyState() public static JourneyDescriptor JourneyDescriptor { get; } = new JourneyDescriptor(JourneyName, typeof(RequestTrnJourneyState), requestDataKeys: [], appendUniqueKey: true); + public bool? IsPlanningToTakeAnNpq { get; set; } public string? Email { get; set; } public string? Name { get; set; } public bool? HasPreviousName { get; set; } diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.EndToEndTests/RequestTrnTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.EndToEndTests/RequestTrnTests.cs index 6db85f0598..45fdf471a8 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.EndToEndTests/RequestTrnTests.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.EndToEndTests/RequestTrnTests.cs @@ -5,88 +5,104 @@ namespace TeachingRecordSystem.AuthorizeAccess.EndToEndTests; public class RequestTrnTests(HostFixture hostFixture) : TestBase(hostFixture) { [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task RequestTrn(bool hasNationalInsuranceNumber) + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public async Task RequestTrn(bool isPlanningToTakeAnNpq, bool hasNationalInsuranceNumber) { await using var context = await HostFixture.CreateBrowserContext(); var page = await context.NewPageAsync(); await page.GotoAsync("/request-trn"); await page.ClickButton("Start now"); - await page.WaitForUrlPathAsync("/request-trn/email"); + await page.WaitForUrlPathAsync("/request-trn/npq-check"); - var email = Faker.Internet.Email(); - await page.FillAsync("input[name=Email]", email); - await page.ClickButton("Continue"); - - await page.WaitForUrlPathAsync("/request-trn/name"); + if (isPlanningToTakeAnNpq) + { + await page.CheckAsync("text=Yes"); + await page.ClickButton("Continue"); - var name = Faker.Name.FullName(); - var previousName = Faker.Name.FullName(); - await page.FillAsync("input[name=Name]", name); - await page.ClickButton("Continue"); + await page.WaitForUrlPathAsync("/request-trn/email"); - await page.WaitForUrlPathAsync("/request-trn/previous-name"); + var email = Faker.Internet.Email(); + await page.FillAsync("input[name=Email]", email); + await page.ClickButton("Continue"); - await page.CheckAsync("text=Yes"); - await page.FillAsync("input[name=PreviousName]", previousName); - await page.ClickButton("Continue"); + await page.WaitForUrlPathAsync("/request-trn/name"); - await page.WaitForUrlPathAsync("/request-trn/date-of-birth"); + var name = Faker.Name.FullName(); + var previousName = Faker.Name.FullName(); + await page.FillAsync("input[name=Name]", name); + await page.ClickButton("Continue"); - var dateOfBirth = new DateOnly(1980, 10, 12); - await page.FillDateInput(dateOfBirth); - await page.ClickButton("Continue"); + await page.WaitForUrlPathAsync("/request-trn/previous-name"); - await page.WaitForUrlPathAsync("/request-trn/identity"); + await page.CheckAsync("text=Yes"); + await page.FillAsync("input[name=PreviousName]", previousName); + await page.ClickButton("Continue"); - await page - .GetByLabel("Upload file") - .SetInputFilesAsync( - new FilePayload() - { - Name = "evidence.jpg", - MimeType = "image/jpeg", - Buffer = TestData.JpegImage - }); - await page.ClickButton("Continue"); + await page.WaitForUrlPathAsync("/request-trn/date-of-birth"); - await page.WaitForUrlPathAsync("/request-trn/national-insurance-number"); + var dateOfBirth = new DateOnly(1980, 10, 12); + await page.FillDateInput(dateOfBirth); + await page.ClickButton("Continue"); - var nationalInsuranceNumber = Faker.Identification.UkNationalInsuranceNumber(); - if (hasNationalInsuranceNumber) - { - await page.CheckAsync("text=Yes"); - await page.FillAsync("input[name=NationalInsuranceNumber]", nationalInsuranceNumber); + await page.WaitForUrlPathAsync("/request-trn/identity"); + + await page + .GetByLabel("Upload file") + .SetInputFilesAsync( + new FilePayload() + { + Name = "evidence.jpg", + MimeType = "image/jpeg", + Buffer = TestData.JpegImage + }); await page.ClickButton("Continue"); - await page.WaitForUrlPathAsync("/request-trn/check-answers"); + await page.WaitForUrlPathAsync("/request-trn/national-insurance-number"); + + var nationalInsuranceNumber = Faker.Identification.UkNationalInsuranceNumber(); + if (hasNationalInsuranceNumber) + { + await page.CheckAsync("text=Yes"); + await page.FillAsync("input[name=NationalInsuranceNumber]", nationalInsuranceNumber); + await page.ClickButton("Continue"); + + await page.WaitForUrlPathAsync("/request-trn/check-answers"); + } + else + { + await page.CheckAsync("text=No"); + await page.ClickButton("Continue"); + await page.WaitForUrlPathAsync("/request-trn/address"); + + var addressLine1 = Faker.Address.StreetAddress(); + var addressLine2 = Faker.Address.SecondaryAddress(); + var townOrCity = Faker.Address.City(); + var postalCode = Faker.Address.ZipCode(); + var country = Faker.Address.Country(); + + await page.FillAsync("input[name=AddressLine1]", addressLine1); + await page.FillAsync("input[name=AddressLine2]", addressLine2); + await page.FillAsync("input[name=TownOrCity]", townOrCity); + await page.FillAsync("input[name=PostalCode]", postalCode); + await page.FillAsync("input[name=Country]", country); + await page.ClickButton("Continue"); + + await page.WaitForUrlPathAsync("/request-trn/check-answers"); + } + + await page.ClickButton("Submit request"); + + await page.WaitForUrlPathAsync("/request-trn/submitted"); } else { await page.CheckAsync("text=No"); await page.ClickButton("Continue"); - await page.WaitForUrlPathAsync("/request-trn/address"); - - var addressLine1 = Faker.Address.StreetAddress(); - var addressLine2 = Faker.Address.SecondaryAddress(); - var townOrCity = Faker.Address.City(); - var postalCode = Faker.Address.ZipCode(); - var country = Faker.Address.Country(); - - await page.FillAsync("input[name=AddressLine1]", addressLine1); - await page.FillAsync("input[name=AddressLine2]", addressLine2); - await page.FillAsync("input[name=TownOrCity]", townOrCity); - await page.FillAsync("input[name=PostalCode]", postalCode); - await page.FillAsync("input[name=Country]", country); - await page.ClickButton("Continue"); - await page.WaitForUrlPathAsync("/request-trn/check-answers"); + await page.WaitForUrlPathAsync("/request-trn/not-eligible"); } - - await page.ClickButton("Submit request"); - - await page.WaitForUrlPathAsync("/request-trn/submitted"); } } diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.Tests/PageTests/RequestTrn/NotEligibleTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.Tests/PageTests/RequestTrn/NotEligibleTests.cs new file mode 100644 index 0000000000..ab8de5eff7 --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.Tests/PageTests/RequestTrn/NotEligibleTests.cs @@ -0,0 +1,91 @@ +namespace TeachingRecordSystem.AuthorizeAccess.Tests.PageTests.RequestTrn; + +public class NotEligibleTests(HostFixture hostFixture) : TestBase(hostFixture) +{ + [Fact] + public async Task Get_HasPendingTrnRequestSetTrue_RedirectsToSubmitted() + { + // Arrange + var state = CreateNewState(); + state.HasPendingTrnRequest = true; + var journeyInstance = await CreateJourneyInstance(state); + + var request = new HttpRequestMessage(HttpMethod.Get, $"/request-trn/not-eligible?{journeyInstance.GetUniqueIdQueryParameter()}"); + + // Act + var response = await HttpClient.SendAsync(request); + + // Assert + Assert.Equal(StatusCodes.Status302Found, (int)response.StatusCode); + Assert.Equal($"/request-trn/submitted?{journeyInstance.GetUniqueIdQueryParameter()}", response.Headers.Location?.OriginalString); + } + + [Fact] + public async Task Get_HasIsPlanningToTakeAnNpqMissingFromState_RedirectsToNpqCheck() + { + // Arrange + var state = CreateNewState(); + var journeyInstance = await CreateJourneyInstance(state); + + var request = new HttpRequestMessage(HttpMethod.Get, $"/request-trn/not-eligible?{journeyInstance.GetUniqueIdQueryParameter()}"); + + // Act + var response = await HttpClient.SendAsync(request); + + // Assert + Assert.Equal(StatusCodes.Status302Found, (int)response.StatusCode); + Assert.Equal($"/request-trn/npq-check?{journeyInstance.GetUniqueIdQueryParameter()}", response.Headers.Location?.OriginalString); + } + + [Fact] + public async Task Get_ValidRequest_RendersExpectedContent() + { + // Arrange + var state = CreateNewState(); + state.IsPlanningToTakeAnNpq = false; + var journeyInstance = await CreateJourneyInstance(state); + + var request = new HttpRequestMessage(HttpMethod.Get, $"/request-trn/not-eligible?{journeyInstance.GetUniqueIdQueryParameter()}"); + + // Act + var response = await HttpClient.SendAsync(request); + + // Assert + await AssertEx.HtmlResponse(response); + } + + [Fact] + public async Task Post_HasPendingTrnRequestSetTrue_RedirectsToSubmitted() + { + // Arrange + var state = CreateNewState(); + state.HasPendingTrnRequest = true; + var journeyInstance = await CreateJourneyInstance(state); + + var request = new HttpRequestMessage(HttpMethod.Post, $"/request-trn/not-eligible?{journeyInstance.GetUniqueIdQueryParameter()}"); + + // Act + var response = await HttpClient.SendAsync(request); + + // Assert + Assert.Equal(StatusCodes.Status302Found, (int)response.StatusCode); + Assert.Equal($"/request-trn/submitted?{journeyInstance.GetUniqueIdQueryParameter()}", response.Headers.Location?.OriginalString); + } + + [Fact] + public async Task Post_HasIsPlanningToTakeAnNpqMissingFromState_RedirectsToNpqCheck() + { + // Arrange + var state = CreateNewState(); + var journeyInstance = await CreateJourneyInstance(state); + + var request = new HttpRequestMessage(HttpMethod.Post, $"/request-trn/not-eligible?{journeyInstance.GetUniqueIdQueryParameter()}"); + + // Act + var response = await HttpClient.SendAsync(request); + + // Assert + Assert.Equal(StatusCodes.Status302Found, (int)response.StatusCode); + Assert.Equal($"/request-trn/npq-check?{journeyInstance.GetUniqueIdQueryParameter()}", response.Headers.Location?.OriginalString); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.Tests/PageTests/RequestTrn/NpqCheckTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.Tests/PageTests/RequestTrn/NpqCheckTests.cs new file mode 100644 index 0000000000..c6c1146679 --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.Tests/PageTests/RequestTrn/NpqCheckTests.cs @@ -0,0 +1,130 @@ +namespace TeachingRecordSystem.AuthorizeAccess.Tests.PageTests.RequestTrn; + +public class NpqCheckTests(HostFixture hostFixture) : TestBase(hostFixture) +{ + [Fact] + public async Task Get_HasPendingTrnRequestSetTrue_RedirectsToSubmitted() + { + // Arrange + var state = CreateNewState(); + state.HasPendingTrnRequest = true; + var journeyInstance = await CreateJourneyInstance(state); + + var request = new HttpRequestMessage(HttpMethod.Get, $"/request-trn/npq-check?{journeyInstance.GetUniqueIdQueryParameter()}"); + + // Act + var response = await HttpClient.SendAsync(request); + + // Assert + Assert.Equal(StatusCodes.Status302Found, (int)response.StatusCode); + Assert.Equal($"/request-trn/submitted?{journeyInstance.GetUniqueIdQueryParameter()}", response.Headers.Location?.OriginalString); + } + + [Fact] + public async Task Get_ValidRequest_RendersExpectedContent() + { + // Arrange + var state = CreateNewState(); + var journeyInstance = await CreateJourneyInstance(state); + + var request = new HttpRequestMessage(HttpMethod.Get, $"/request-trn/npq-check?{journeyInstance.GetUniqueIdQueryParameter()}"); + + // Act + var response = await HttpClient.SendAsync(request); + + // Assert + await AssertEx.HtmlResponse(response); + } + + [Fact] + public async Task Get_ValidRequestWithPopulatedDataInJourneyState_PopulatesModelFromJourneyState() + { + // Arrange + var state = CreateNewState(); + state.IsPlanningToTakeAnNpq = true; + var journeyInstance = await CreateJourneyInstance(state); + + var request = new HttpRequestMessage(HttpMethod.Get, $"/request-trn/npq-check?{journeyInstance.GetUniqueIdQueryParameter()}"); + + // Act + var response = await HttpClient.SendAsync(request); + + // Assert + var doc = await AssertEx.HtmlResponse(response); + var radioButtons = doc.GetElementsByName("IsPlanningToTakeAnNpq"); + var selectedRadioButton = radioButtons.Single(r => r.HasAttribute("checked")); + Assert.Equal("True", selectedRadioButton.GetAttribute("value")); + } + + [Fact] + public async Task Post_HasPendingTrnRequestSetTrue_RedirectsToSubmitted() + { + // Arrange + var state = CreateNewState(); + state.HasPendingTrnRequest = true; + var journeyInstance = await CreateJourneyInstance(state); + + var request = new HttpRequestMessage(HttpMethod.Post, $"/request-trn/npq-check?{journeyInstance.GetUniqueIdQueryParameter()}") + { + Content = new FormUrlEncodedContent(new Dictionary + { + ["IsPlanningToTakeAnNpq"] = "true" + }) + }; + + // Act + var response = await HttpClient.SendAsync(request); + + // Assert + Assert.Equal(StatusCodes.Status302Found, (int)response.StatusCode); + Assert.Equal($"/request-trn/submitted?{journeyInstance.GetUniqueIdQueryParameter()}", response.Headers.Location?.OriginalString); + } + + [Fact] + public async Task Post_WhenIsPlanningToTakeAnNpqHasNoSelection_ReturnsError() + { + // Arrange + var state = CreateNewState(); + var journeyInstance = await CreateJourneyInstance(state); + + var request = new HttpRequestMessage(HttpMethod.Post, $"/request-trn/npq-check?{journeyInstance.GetUniqueIdQueryParameter()}"); + + // Act + var response = await HttpClient.SendAsync(request); + + // Assert + await AssertEx.HtmlResponseHasError(response, "IsPlanningToTakeAnNpq", "Tell us whether you plan on taking a national professional qualification (NPQ)"); + } + + [Theory] + [InlineData("true")] + [InlineData("false")] + public async Task Post_ValidRequest_UpdatesJourneyStateAndRedirects(string isPlanningToTakeAnNpq) + { + // Arrange + var state = CreateNewState(); + var journeyInstance = await CreateJourneyInstance(state); + + var request = new HttpRequestMessage(HttpMethod.Post, $"/request-trn/npq-check?{journeyInstance.GetUniqueIdQueryParameter()}") + { + Content = new FormUrlEncodedContent(new Dictionary + { + ["IsPlanningToTakeAnNpq"] = isPlanningToTakeAnNpq + }) + }; + + // Act + var response = await HttpClient.SendAsync(request); + + // Assert + Assert.Equal(StatusCodes.Status302Found, (int)response.StatusCode); + if (isPlanningToTakeAnNpq == "true") + { + Assert.Equal($"/request-trn/email?{journeyInstance.GetUniqueIdQueryParameter()}", response.Headers.Location?.OriginalString); + } + else + { + Assert.Equal($"/request-trn/not-eligible?{journeyInstance.GetUniqueIdQueryParameter()}", response.Headers.Location?.OriginalString); + } + } +}