Skip to content

Commit

Permalink
edit start date page functionality and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
CathLass committed Dec 31, 2024
1 parent 82cd675 commit 52554f2
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 10 deletions.
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");
}

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 @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public async Task Get_InductionNotManagedByCpd_ExpectedRadioButtonsExistOnPage(I
var doc = await AssertEx.HtmlResponseAsync(response);
var statusChoices = doc.QuerySelectorAll<IHtmlInputElement>("[type=radio]").Select(r => r.Value);
var statusChoicesLegend = doc.GetElementByTestId("status-choices-legend");
Assert.Equal("Select a status", statusChoicesLegend!.TextContent);
Assert.Equal("What is their induction status?", statusChoicesLegend!.TextContent);
Assert.Equal(expectedChoices, statusChoices);
}

Expand Down Expand Up @@ -137,7 +137,7 @@ await WithDbContext(async dbContext =>
var doc = await AssertEx.HtmlResponseAsync(response);
var statusChoices = doc.QuerySelectorAll<IHtmlInputElement>("[type=radio]").Select(r => r.Value);
var statusChoicesLegend = doc.GetElementByTestId("status-choices-legend");
Assert.Equal("Select a status", statusChoicesLegend!.TextContent);
Assert.Equal("What is their induction status?", statusChoicesLegend!.TextContent);
Assert.Equal(expectedChoices, statusChoices);
}

Expand All @@ -148,7 +148,7 @@ await WithDbContext(async dbContext =>
[InlineData(InductionStatus.Passed, InductionStatus.InProgress)]
[InlineData(InductionStatus.Failed, InductionStatus.FailedInWales)]
[InlineData(InductionStatus.FailedInWales, InductionStatus.Failed)]
public async Task Get_InductionstatusHasBeenSet_ShowsSelectedRadioButton(InductionStatus currentInductionStatus, InductionStatus selectedInductionStatus)
public async Task Get_InductionStatusHasBeenSet_ShowsSelectedRadioButton(InductionStatus currentInductionStatus, InductionStatus selectedInductionStatus)
{
// Arrange
var person = await TestData.CreatePersonAsync(p => p.WithQts());
Expand Down Expand Up @@ -234,7 +234,6 @@ public async Task Post_NoSelectedStatus_ShowsPageError(InductionStatus currentIn
var doc = await response.GetDocumentAsync();
var statusChoices = doc.QuerySelectorAll<IHtmlInputElement>("[type=radio]").Select(r => r.Value);
var statusChoicesLegend = doc.GetElementByTestId("status-choices-legend");
Assert.Equal("Select a status", statusChoicesLegend!.TextContent);
Assert.Equal(expectedStatusChoices.Select(c => c.ToString()), statusChoices);
}

Expand Down Expand Up @@ -281,7 +280,6 @@ await WithDbContext(async dbContext =>
var doc = await response.GetDocumentAsync();
var statusChoices = doc.QuerySelectorAll<IHtmlInputElement>("[type=radio]").Select(r => r.Value);
var statusChoicesLegend = doc.GetElementByTestId("status-choices-legend");
Assert.Equal("Select a status", statusChoicesLegend!.TextContent);
Assert.Equal(expectedChoices.Select(c => c.ToString()), statusChoices);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
using AngleSharp.Dom;
using AngleSharp.Html.Dom;
using TeachingRecordSystem.SupportUi.Pages.Persons.PersonDetail.EditInduction;

namespace TeachingRecordSystem.SupportUi.Tests.PageTests.Persons.PersonDetail.EditInduction;

public class EditStartDateTests(HostFixture hostFixture) : TestBase(hostFixture)
{
[Fact]
public async Task Get_WithStartDate_ShowsDate()
{
// Arrange
var dateValid = Clock.Today;
var inductionStatus = InductionStatus.InProgress;
var person = await TestData.CreatePersonAsync(p => p.WithQts());
var journeyInstance = await CreateJourneyInstanceAsync(
person.PersonId,
new EditInductionStateBuilder()
.WithInitialisedState(inductionStatus, InductionJourneyPage.Status)
.WithStartDate(dateValid)
.Create());

var request = new HttpRequestMessage(HttpMethod.Get, $"/persons/{person.PersonId}/edit-induction/start-date?{journeyInstance.GetUniqueIdQueryParameter()}");

// Act
var response = await HttpClient.SendAsync(request);

// Assert
var doc = await AssertEx.HtmlResponseAsync(response);
var startDate = doc.QuerySelectorAll<IHtmlInputElement>("[type=text]");
Assert.Equal(dateValid.Day.ToString(), startDate.ElementAt(0).Value);
Assert.Equal(dateValid.Month.ToString(), startDate.ElementAt(1).Value);
Assert.Equal(dateValid.Year.ToString(), startDate.ElementAt(2).Value);
}

[Fact]
public async Task Post_SetValidStartDate_PersistsStartDate()
{
// Arrange
var dateValid = Clock.Today;
var inductionStatus = InductionStatus.InProgress;
var person = await TestData.CreatePersonAsync(p => p.WithQts());

var journeyInstance = await CreateJourneyInstanceAsync(
person.PersonId,
new EditInductionStateBuilder()
.WithInitialisedState(inductionStatus, InductionJourneyPage.Status)
.Create());

var postRequest = new HttpRequestMessage(HttpMethod.Post, $"/persons/{person.PersonId}/edit-induction/start-date?{journeyInstance.GetUniqueIdQueryParameter()}")
{
Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
["StartDate.Day"] = dateValid.Day.ToString(),
["StartDate.Month"] = dateValid.Month.ToString(),
["StartDate.Year"] = dateValid.Year.ToString()
})
};

// Act
var response = await HttpClient.SendAsync(postRequest);

// Assert
journeyInstance = await ReloadJourneyInstance(journeyInstance);
Assert.Equal(dateValid, journeyInstance.State.StartDate);
}

[Fact]
public async Task Post_NoStartDateIsEntered_ReturnsError()
{
// Arrange
var inductionStatus = InductionStatus.InProgress;
var person = await TestData.CreatePersonAsync(p => p.WithQts());
var journeyInstance = await CreateJourneyInstanceAsync(
person.PersonId,
new EditInductionStateBuilder()
.WithInitialisedState(inductionStatus, InductionJourneyPage.Status)
.Create());

var postRequest = new HttpRequestMessage(HttpMethod.Post, $"/persons/{person.PersonId}/edit-induction/start-date?{journeyInstance.GetUniqueIdQueryParameter()}");

// Act
var response = await HttpClient.SendAsync(postRequest);

// Assert
await AssertEx.HtmlResponseHasErrorAsync(response, "StartDate", "Enter an induction start date");
}

[Fact]
public async Task Post_StartDateIsInTheFuture_ReturnsError()
{
// Arrange
var dateTomorrow = Clock.Today.AddDays(1);
var inductionStatus = InductionStatus.InProgress;
var person = await TestData.CreatePersonAsync(p => p.WithQts());
var journeyInstance = await CreateJourneyInstanceAsync(
person.PersonId,
new EditInductionStateBuilder()
.WithInitialisedState(inductionStatus, InductionJourneyPage.Status)
.Create());

var postRequest = new HttpRequestMessage(HttpMethod.Post, $"/persons/{person.PersonId}/edit-induction/start-date?{journeyInstance.GetUniqueIdQueryParameter()}")
{
Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
["StartDate.Day"] = dateTomorrow.Day.ToString(),
["StartDate.Month"] = dateTomorrow.Month.ToString(),
["StartDate.Year"] = dateTomorrow.Year.ToString()
})
};

// Act
var response = await HttpClient.SendAsync(postRequest);

// Assert
await AssertEx.HtmlResponseHasErrorAsync(response, "StartDate", "The induction start date cannot be in the future");
}

[Fact]
public async Task Post_StartDateIsTooEarly_ReturnsError()
{
// Arrange
var dateTooEarly = new DateOnly(1999,5,6);
var inductionStatus = InductionStatus.InProgress;
var person = await TestData.CreatePersonAsync(p => p.WithQts());
var journeyInstance = await CreateJourneyInstanceAsync(
person.PersonId,
new EditInductionStateBuilder()
.WithInitialisedState(inductionStatus, InductionJourneyPage.Status)
.Create());

var postRequest = new HttpRequestMessage(HttpMethod.Post, $"/persons/{person.PersonId}/edit-induction/start-date?{journeyInstance.GetUniqueIdQueryParameter()}")
{
Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
["StartDate.Day"] = dateTooEarly.Day.ToString(),
["StartDate.Month"] = dateTooEarly.Month.ToString(),
["StartDate.Year"] = dateTooEarly.Year.ToString()
})
};

// Act
var response = await HttpClient.SendAsync(postRequest);

// Assert
await AssertEx.HtmlResponseHasErrorAsync(response, "StartDate", "The induction start date cannot be before 7th May 1999");
}

private Task<JourneyInstance<EditInductionState>> CreateJourneyInstanceAsync(Guid personId, EditInductionState? state = null) =>
CreateJourneyInstance(
JourneyNames.EditInduction,
state ?? new EditInductionState(),
new KeyValuePair<string, object>("personId", personId));
}

0 comments on commit 52554f2

Please sign in to comment.