Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Induction edit start date #1779

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@
<govuk-back-link data-testid="back-link" href="@Model.BackLink">Back</govuk-back-link>
}

<h1 data-testid="page-title" class="govuk-heading-l">@ViewBag.Title</h1>

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds-from-desktop">
<form data-testid="submit-form" action="@LinkGenerator.InductionEditStartDate(Model.PersonId, Model.JourneyInstance!.InstanceId)" method="post">
<span class="govuk-caption-l">Induction - @Model.PersonName</span>

<govuk-date-input asp-for="StartDate">
<govuk-date-input-fieldset>
<govuk-date-input-fieldset-legend is-page-heading="true" class="govuk-fieldset__legend--l">
When did they start induction?
</govuk-date-input-fieldset-legend>
</govuk-date-input-fieldset>
</govuk-date-input>

<div class="govuk-button-group">
<govuk-button type="submit" data-testid="continue-button">Continue</govuk-button>
<govuk-button data-testid="cancel-button" formaction="@LinkGenerator.InductionEditStartDateCancel(Model.PersonId, Model.JourneyInstance!.InstanceId)" class="govuk-button--secondary" type="submit">Cancel and return to record</govuk-button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using TeachingRecordSystem.Core.DataStore.Postgres;

namespace TeachingRecordSystem.SupportUi.Pages.Persons.PersonDetail.EditInduction;

[Journey(JourneyNames.EditInduction), ActivatesJourney, RequireJourneyInstance]
public class StartDateModel : CommonJourneyPage
{
protected TrsDbContext _dbContext;
protected IClock _clock;

public InductionStatus InductionStatus => JourneyInstance!.State.InductionStatus;
public string? PersonName { get; set; }

[BindProperty]
[Required(ErrorMessage = "Enter an induction start date")]
[Display(Name = "Start date")] // https://github.com/gunndabad/govuk-frontend-aspnetcore/issues/282
public DateOnly? StartDate { get; set; }

public InductionJourneyPage NextPage
{
Expand All @@ -23,19 +35,36 @@ public string BackLink
get => PageLink(InductionJourneyPage.Status);
}

public StartDateModel(TrsLinkGenerator linkGenerator) : base(linkGenerator)
public StartDateModel(TrsLinkGenerator linkGenerator, TrsDbContext dbContext, IClock clock) : base(linkGenerator)
{
_dbContext = dbContext;
_clock = clock;
}

public void OnGet()
{
StartDate = JourneyInstance!.State.StartDate;
}

public async Task<IActionResult> OnPostAsync()
{
if (StartDate > _clock.Today)
{
ModelState.AddModelError(nameof(StartDate), "The induction start date cannot be in the future");
}
if (StartDate < new DateOnly(1999, 5, 7)) // CML TODO - business logic - move
{
ModelState.AddModelError(nameof(StartDate), "The induction start date cannot be before 7th May 1999");
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation logic to be added to person ? Not sure I can add it to the ValidateInductionData method because that's being used for updating the cpd induction data which I guess might have dates prior to 7th may 1999?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could put a staticDateOnly EarliestInductionStartDate on Person; we don't have a great way of sharing validation logic with Razor Pages currently.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done - I might get in trouble for this though because that error string is supposed to say 7th May not 7 May. I propose to deal with that if it's mentioned and not before

The method ValidateInductionData - is that intended to be only for the API? I know this FE is updating the DB directly but I expect I'll call a validate method before I update the record from the last page of the wizard.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have UiDefaults.DateOnlyDisplayFormat to use for date formatting.

method ValidateInductionData - is that intended to be only for the API?
Yes, we don't have a way of easily sharing validation logic across the API and the front-end currently.


if (!ModelState.IsValid)
{
return this.PageWithErrors();
}

await JourneyInstance!.UpdateStateAsync(state =>
{
// TODO - store the start date
state.StartDate = StartDate!.Value;
if (state.JourneyStartPage == null)
{
state.JourneyStartPage = InductionJourneyPage.StartDate;
Expand All @@ -44,4 +73,14 @@ public async Task<IActionResult> OnPostAsync()

return Redirect(PageLink(NextPage));
}

public override async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
await JourneyInstance!.State.EnsureInitializedAsync(_dbContext, PersonId, InductionJourneyPage.Status);

var personInfo = context.HttpContext.GetCurrentPersonFeature();
PersonId = personInfo.PersonId;
PersonName = personInfo.Name;
await next();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class StatusModel : CommonJourneyPage
protected bool InductionStatusManagedByCpd;

[BindProperty]
[Display(Name = "Select a status")]
[Display(Name = "What is their induction status?")]
[NotEqual(InductionStatus.None, ErrorMessage = "Select a status")]
public InductionStatus InductionStatus { get; set; }
public InductionStatus CurrentInductionStatus { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<govuk-summary-list-row-key>Induction status</govuk-summary-list-row-key>
<govuk-summary-list-row-value>@Model.Status.GetTitle()</govuk-summary-list-row-value>
<govuk-summary-list-row-actions>
<govuk-summary-list-row-action href="@LinkGenerator.InductionEditStatus(person.PersonId, journeyInstanceId: null)" visually-hidden-text="change status">Change</govuk-summary-list-row-action>
<govuk-summary-list-row-action data-testid="change-induction-status" href="@LinkGenerator.InductionEditStatus(person.PersonId, journeyInstanceId: null)" visually-hidden-text="change status">Change</govuk-summary-list-row-action>
</govuk-summary-list-row-actions>
</govuk-summary-list-row>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using Microsoft.Playwright;

namespace TeachingRecordSystem.SupportUi.EndToEndTests;

public static class EditInductionPageExtensions
{
public static Task GoToPersonInductionPageAsync(this IPage page, Guid personId)
{
return page.GotoAsync($"/persons/{personId}/induction");
}

public static Task ClickEditInductionStatusPageAsync(this IPage page)
{
return page.GetByTestId($"change-induction-status").ClickAsync();
}

public static Task AssertOnEditInductionStatusPageAsync(this IPage page, Guid personId)
{
return page.WaitForUrlPathAsync($"/persons/{personId}/edit-induction/status");
}

public static Task AssertOnEditInductionStartDatePageAsync(this IPage page, Guid personId)
{
return page.WaitForUrlPathAsync($"/persons/{personId}/edit-induction/start-date");
}

public static Task AssertOnEditInductionCompletedDatePageAsync(this IPage page, Guid personId)
{
return page.WaitForUrlPathAsync($"/persons/{personId}/edit-induction/date-completed");
}

public static Task AssertOnEditInductionChangeReasonPageAsync(this IPage page, Guid personId)
{
return page.WaitForUrlPathAsync($"/persons/{personId}/edit-induction/change-reason");
}

public static Task AssertOnEditInductionCheckYourAnswersPageAsync(this IPage page, Guid personId)
{
return page.WaitForUrlPathAsync($"/persons/{personId}/edit-induction/check-answers");
}

public static Task AssertInductionStatusSelected(this IPage page, InductionStatus status)
{
var radioButton = page.Locator($"input[type='radio'][value='{status.ToString()}']");
return radioButton.Locator("xpath=following-sibling::label").IsCheckedAsync();
}

public static Task SelectStatusAsync(this IPage page, InductionStatus status)
{
var radioButton = page.Locator($"input[type='radio'][value='{status.ToString()}']");
return radioButton.Locator("xpath=following-sibling::label").ClickAsync();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using TeachingRecordSystem.SupportUi.Pages.Alerts.EditAlert.StartDate;
using TeachingRecordSystem.SupportUi.Pages.Alerts.ReopenAlert;

namespace TeachingRecordSystem.SupportUi.EndToEndTests;
namespace TeachingRecordSystem.SupportUi.EndToEndTests.JourneyTests;

public class AlertTests(HostFixture hostFixture) : TestBase(hostFixture)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Security.Cryptography;

namespace TeachingRecordSystem.SupportUi.EndToEndTests;
namespace TeachingRecordSystem.SupportUi.EndToEndTests.JourneyTests;

public class ApplicationUserTests(HostFixture hostFixture) : TestBase(hostFixture)
{
Expand Down Expand Up @@ -47,7 +47,7 @@ public async Task EditApplicationUser()
var newPostLogoutRedirectUris = "https://localhost/logout-callback";
var newAuthenticationSchemeName = Guid.NewGuid().ToString();
var newOneLoginClientId = Guid.NewGuid().ToString();
var newOneLoginPrivateKeyPem = TestCommon.TestData.GeneratePrivateKeyPem();
var newOneLoginPrivateKeyPem = TestData.GeneratePrivateKeyPem();
var newOneLoginRedirectUri = $"/_onelogin/{newAuthenticationSchemeName}/callback";
var newOneLoginPostLogoutRedirectUri = $"/_onelogin/{newAuthenticationSchemeName}/logout-callback";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeachingRecordSystem.SupportUi.EndToEndTests;
namespace TeachingRecordSystem.SupportUi.EndToEndTests.JourneyTests;

public class ChangeRequestTests : TestBase
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeachingRecordSystem.SupportUi.EndToEndTests;
namespace TeachingRecordSystem.SupportUi.EndToEndTests.JourneyTests;

public class IndexTests : TestBase
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
namespace TeachingRecordSystem.SupportUi.EndToEndTests.JourneyTests;

public class InductionTests : TestBase
{
public InductionTests(HostFixture hostFixture)
: base(hostFixture)
{
}

[Fact]
public async Task EditInduction()
{
var setStartDate = new DateOnly(2021, 1, 1);
var person = await TestData.CreatePersonAsync(
personBuilder => personBuilder
.WithQts()
.WithInductionStatus(inductionBuilder => inductionBuilder
.WithStatus(InductionStatus.RequiredToComplete)
));
var personId = person.ContactId;

await using var context = await HostFixture.CreateBrowserContext();
var page = await context.NewPageAsync();

await page.GoToPersonInductionPageAsync(personId);
await page.ClickEditInductionStatusPageAsync();

await page.AssertOnEditInductionStatusPageAsync(person.PersonId);

await page.SelectStatusAsync(InductionStatus.Failed);
await page.ClickContinueButtonAsync();

await page.AssertOnEditInductionStartDatePageAsync(person.PersonId);
await page.FillDateInputAsync(setStartDate);
await page.ClickContinueButtonAsync();

await page.AssertOnEditInductionCompletedDatePageAsync(person.PersonId);
await page.ClickContinueButtonAsync();

await page.AssertOnEditInductionChangeReasonPageAsync(person.PersonId);
await page.ClickContinueButtonAsync();

await page.AssertOnEditInductionCheckYourAnswersPageAsync(person.PersonId);
}

[Fact]
public async Task EditInduction_NavigateBack()
{
var inductionStatusToSelect = InductionStatus.Failed;
var setStartDate = new DateOnly(2021, 1, 1);
var person = await TestData.CreatePersonAsync(
personBuilder => personBuilder
.WithQts()
.WithInductionStatus(inductionBuilder => inductionBuilder
.WithStatus(InductionStatus.RequiredToComplete)
));
var personId = person.ContactId;

await using var context = await HostFixture.CreateBrowserContext();
var page = await context.NewPageAsync();

await page.GoToPersonInductionPageAsync(personId);
await page.ClickEditInductionStatusPageAsync();

await page.AssertOnEditInductionStatusPageAsync(person.PersonId);

await page.SelectStatusAsync(inductionStatusToSelect);
await page.ClickContinueButtonAsync();

await page.AssertOnEditInductionStartDatePageAsync(person.PersonId);
await page.FillDateInputAsync(setStartDate);
await page.ClickContinueButtonAsync();

await page.AssertOnEditInductionCompletedDatePageAsync(person.PersonId);
await page.ClickContinueButtonAsync();

await page.AssertOnEditInductionChangeReasonPageAsync(person.PersonId);
await page.ClickContinueButtonAsync();

await page.AssertOnEditInductionCheckYourAnswersPageAsync(person.PersonId);
await page.ClickBackLink();

await page.AssertOnEditInductionChangeReasonPageAsync(person.PersonId);
await page.ClickBackLink();

await page.AssertOnEditInductionCompletedDatePageAsync(person.PersonId);
await page.ClickBackLink();

await page.AssertOnEditInductionStartDatePageAsync(person.PersonId);
await page.ClickBackLink();

await page.AssertOnEditInductionStatusPageAsync(person.PersonId);
await page.AssertInductionStatusSelected(inductionStatusToSelect);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using TeachingRecordSystem.SupportUi.Pages.Mqs.EditMq.StartDate;
using TeachingRecordSystem.SupportUi.Pages.Mqs.EditMq.Status;

namespace TeachingRecordSystem.SupportUi.EndToEndTests;
namespace TeachingRecordSystem.SupportUi.EndToEndTests.JourneyTests;

public class MqTests(HostFixture hostFixture) : TestBase(hostFixture)
{
Expand Down Expand Up @@ -107,7 +107,7 @@ await page.SetInputFilesAsync(
{
Name = "evidence.jpg",
MimeType = "image/jpeg",
Buffer = TestCommon.TestData.JpegImage
Buffer = TestData.JpegImage
});

await page.ClickContinueButtonAsync();
Expand Down Expand Up @@ -163,7 +163,7 @@ await page.SetInputFilesAsync(
{
Name = "evidence.jpg",
MimeType = "image/jpeg",
Buffer = TestCommon.TestData.JpegImage
Buffer = TestData.JpegImage
});

await page.ClickContinueButtonAsync();
Expand Down Expand Up @@ -217,7 +217,7 @@ await page.SetInputFilesAsync(
{
Name = "evidence.jpg",
MimeType = "image/jpeg",
Buffer = TestCommon.TestData.JpegImage
Buffer = TestData.JpegImage
});

await page.ClickContinueButtonAsync();
Expand Down Expand Up @@ -317,7 +317,7 @@ await page.SetInputFilesAsync(
{
Name = "evidence.jpg",
MimeType = "image/jpeg",
Buffer = TestCommon.TestData.JpegImage
Buffer = TestData.JpegImage
});

await page.ClickContinueButtonAsync();
Expand Down Expand Up @@ -363,7 +363,7 @@ await page.SetInputFilesAsync(
{
Name = "evidence.jpg",
MimeType = "image/jpeg",
Buffer = TestCommon.TestData.JpegImage
Buffer = TestData.JpegImage
});

await page.ClickContinueButtonAsync();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeachingRecordSystem.SupportUi.EndToEndTests;
namespace TeachingRecordSystem.SupportUi.EndToEndTests.JourneyTests;

public class PersonTests : TestBase
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeachingRecordSystem.SupportUi.EndToEndTests;
namespace TeachingRecordSystem.SupportUi.EndToEndTests.JourneyTests;

public class UserTests : TestBase
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -516,4 +516,7 @@ public static Task ClickReactivateButtonAsync(this IPage page)

public static Task ClickButtonAsync(this IPage page, string text) =>
page.ClickAsync($".govuk-button:text-is('{text}')");

public static Task ClickBackLink(this IPage page) =>
page.ClickAsync($".govuk-back-link");
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ public EditInductionStateBuilder WithUpdatedState(InductionStatus inductionStatu
return this;
}

public EditInductionStateBuilder WithStartDate(DateOnly startDate)
{
StartDate = startDate;
return this;
}

public EditInductionState Create()
{
return new EditInductionState()
Expand Down
Loading
Loading