From d55b7fb8ae17e9664bc4c65c3b1c8784368633fd Mon Sep 17 00:00:00 2001 From: Sam C <156680559+sam-c-dfe@users.noreply.github.com> Date: Thu, 1 Aug 2024 09:52:56 +0100 Subject: [PATCH] Updated the content models to add additional information section (#281) * Updated the content models so that questions have the optional additional information section * Changed set to init --- .../Entities/DateQuestionPage.cs | 6 +++ .../Entities/DropdownQuestionPage.cs | 6 +++ .../Content/MockContentfulService.cs | 12 +++-- .../Controllers/QuestionsController.cs | 16 ++++--- .../Models/AdditionalInformationModel.cs | 8 ++++ .../QuestionModels/BaseQuestionModel.cs | 4 ++ .../QuestionModels/RadioQuestionModel.cs | 4 -- .../Views/Questions/Date.cshtml | 8 ++++ .../Views/Questions/Dropdown.cshtml | 8 ++++ .../Views/Questions/Radio.cshtml | 16 +++---- .../Partials/AdditionalInformation.cshtml | 12 +++++ .../cypress/e2e/pages/question-spec.cy.js | 44 +++++++++++++++++++ .../Mocks/MockContentfulServiceTests.cs | 9 ++++ 13 files changed, 130 insertions(+), 23 deletions(-) create mode 100644 src/Dfe.EarlyYearsQualification.Web/Models/AdditionalInformationModel.cs create mode 100644 src/Dfe.EarlyYearsQualification.Web/Views/Shared/Partials/AdditionalInformation.cshtml diff --git a/src/Dfe.EarlyYearsQualification.Content/Entities/DateQuestionPage.cs b/src/Dfe.EarlyYearsQualification.Content/Entities/DateQuestionPage.cs index f564b5f9..f8d09910 100644 --- a/src/Dfe.EarlyYearsQualification.Content/Entities/DateQuestionPage.cs +++ b/src/Dfe.EarlyYearsQualification.Content/Entities/DateQuestionPage.cs @@ -1,3 +1,5 @@ +using Contentful.Core.Models; + namespace Dfe.EarlyYearsQualification.Content.Entities; public class DateQuestionPage @@ -19,4 +21,8 @@ public class DateQuestionPage public string ErrorBannerHeading { get; init; } = string.Empty; public string ErrorBannerLinkText { get; init; } = string.Empty; + + public string AdditionalInformationHeader { get; init; } = string.Empty; + + public Document? AdditionalInformationBody { get; init; } } \ No newline at end of file diff --git a/src/Dfe.EarlyYearsQualification.Content/Entities/DropdownQuestionPage.cs b/src/Dfe.EarlyYearsQualification.Content/Entities/DropdownQuestionPage.cs index 7e607549..58259bb9 100644 --- a/src/Dfe.EarlyYearsQualification.Content/Entities/DropdownQuestionPage.cs +++ b/src/Dfe.EarlyYearsQualification.Content/Entities/DropdownQuestionPage.cs @@ -1,3 +1,5 @@ +using Contentful.Core.Models; + namespace Dfe.EarlyYearsQualification.Content.Entities; public class DropdownQuestionPage @@ -19,4 +21,8 @@ public class DropdownQuestionPage public string ErrorBannerHeading { get; init; } = string.Empty; public string ErrorBannerLinkText { get; init; } = string.Empty; + + public string AdditionalInformationHeader { get; init; } = string.Empty; + + public Document? AdditionalInformationBody { get; init; } } \ No newline at end of file diff --git a/src/Dfe.EarlyYearsQualification.Mock/Content/MockContentfulService.cs b/src/Dfe.EarlyYearsQualification.Mock/Content/MockContentfulService.cs index cc86c661..1eed7f98 100644 --- a/src/Dfe.EarlyYearsQualification.Mock/Content/MockContentfulService.cs +++ b/src/Dfe.EarlyYearsQualification.Mock/Content/MockContentfulService.cs @@ -477,7 +477,9 @@ private static RadioQuestionPage CreateRadioQuestionPage(string question, List WhenWasTheQualificationStarted() return RedirectToAction("Index", "Error"); } - var model = MapDateModel(new DateQuestionModel(), questionPage, nameof(this.WhenWasTheQualificationStarted), + var model = await MapDateModel(new DateQuestionModel(), questionPage, nameof(this.WhenWasTheQualificationStarted), Questions); return View("Date", model); } @@ -94,7 +94,7 @@ public async Task WhenWasTheQualificationStarted(DateQuestionMode // ReSharper disable once InvertIf if (questionPage is not null) { - model = MapDateModel(model, questionPage, nameof(this.WhenWasTheQualificationStarted), Questions); + model = await MapDateModel(model, questionPage, nameof(this.WhenWasTheQualificationStarted), Questions); model.HasErrors = true; } @@ -153,7 +153,7 @@ public async Task WhatIsTheAwardingOrganisation() var qualifications = await GetFilteredQualifications(); - var model = MapDropdownModel(new DropdownQuestionModel(), questionPage, qualifications, + var model = await MapDropdownModel(new DropdownQuestionModel(), questionPage, qualifications, nameof(this.WhatIsTheAwardingOrganisation), Questions); @@ -173,7 +173,7 @@ public async Task WhatIsTheAwardingOrganisation(DropdownQuestionM { var qualifications = await GetFilteredQualifications(); - model = MapDropdownModel(model, questionPage, qualifications, + model = await MapDropdownModel(model, questionPage, qualifications, nameof(this.WhatIsTheAwardingOrganisation), Questions); model.HasErrors = true; @@ -239,7 +239,7 @@ private async Task MapRadioModel(RadioQuestionModel model, R return model; } - private static DateQuestionModel MapDateModel(DateQuestionModel model, DateQuestionPage question, string actionName, + private async Task MapDateModel(DateQuestionModel model, DateQuestionPage question, string actionName, string controllerName) { model.Question = question.Question; @@ -253,10 +253,12 @@ private static DateQuestionModel MapDateModel(DateQuestionModel model, DateQuest model.BackButton = question.BackButton; model.ErrorBannerHeading = question.ErrorBannerHeading; model.ErrorBannerLinkText = question.ErrorBannerLinkText; + model.AdditionalInformationHeader = question.AdditionalInformationHeader; + model.AdditionalInformationBody = await renderer.ToHtml(question.AdditionalInformationBody); return model; } - private static DropdownQuestionModel MapDropdownModel(DropdownQuestionModel model, DropdownQuestionPage question, + private async Task MapDropdownModel(DropdownQuestionModel model, DropdownQuestionPage question, List qualifications, string actionName, string controllerName) { @@ -295,6 +297,8 @@ var uniqueAwardingOrganisations model.ErrorBannerHeading = question.ErrorBannerHeading; model.ErrorBannerLinkText = question.ErrorBannerLinkText; + model.AdditionalInformationHeader = question.AdditionalInformationHeader; + model.AdditionalInformationBody = await renderer.ToHtml(question.AdditionalInformationBody); return model; } } \ No newline at end of file diff --git a/src/Dfe.EarlyYearsQualification.Web/Models/AdditionalInformationModel.cs b/src/Dfe.EarlyYearsQualification.Web/Models/AdditionalInformationModel.cs new file mode 100644 index 00000000..0926bc11 --- /dev/null +++ b/src/Dfe.EarlyYearsQualification.Web/Models/AdditionalInformationModel.cs @@ -0,0 +1,8 @@ +namespace Dfe.EarlyYearsQualification.Web.Models; + +public class AdditionalInformationModel +{ + public string AdditionalInformationHeader { get; init; } = string.Empty; + + public string AdditionalInformationBody { get; init; } = string.Empty; +} \ No newline at end of file diff --git a/src/Dfe.EarlyYearsQualification.Web/Models/Content/QuestionModels/BaseQuestionModel.cs b/src/Dfe.EarlyYearsQualification.Web/Models/Content/QuestionModels/BaseQuestionModel.cs index 97b5e041..710b3273 100644 --- a/src/Dfe.EarlyYearsQualification.Web/Models/Content/QuestionModels/BaseQuestionModel.cs +++ b/src/Dfe.EarlyYearsQualification.Web/Models/Content/QuestionModels/BaseQuestionModel.cs @@ -21,4 +21,8 @@ public abstract class BaseQuestionModel public string ErrorBannerHeading { get; set; } = string.Empty; public string ErrorBannerLinkText { get; set; } = string.Empty; + + public string AdditionalInformationHeader { get; set; } = string.Empty; + + public string AdditionalInformationBody { get; set; } = string.Empty; } \ No newline at end of file diff --git a/src/Dfe.EarlyYearsQualification.Web/Models/Content/QuestionModels/RadioQuestionModel.cs b/src/Dfe.EarlyYearsQualification.Web/Models/Content/QuestionModels/RadioQuestionModel.cs index 072793b5..448cf2d6 100644 --- a/src/Dfe.EarlyYearsQualification.Web/Models/Content/QuestionModels/RadioQuestionModel.cs +++ b/src/Dfe.EarlyYearsQualification.Web/Models/Content/QuestionModels/RadioQuestionModel.cs @@ -7,8 +7,4 @@ public class RadioQuestionModel : BaseQuestionModel public List Options { get; set; } = []; [Required] public string? Option { get; init; } = string.Empty; - - public string AdditionalInformationHeader { get; set; } = string.Empty; - - public string AdditionalInformationBody { get; set; } = string.Empty; } \ No newline at end of file diff --git a/src/Dfe.EarlyYearsQualification.Web/Views/Questions/Date.cshtml b/src/Dfe.EarlyYearsQualification.Web/Views/Questions/Date.cshtml index 92febd2b..393b8101 100644 --- a/src/Dfe.EarlyYearsQualification.Web/Views/Questions/Date.cshtml +++ b/src/Dfe.EarlyYearsQualification.Web/Views/Questions/Date.cshtml @@ -31,6 +31,14 @@ + @if (!string.IsNullOrEmpty(Model.AdditionalInformationHeader) && !string.IsNullOrEmpty(Model.AdditionalInformationBody)) + { + await Html.RenderPartialAsync("Partials/AdditionalInformation", new AdditionalInformationModel + { + AdditionalInformationHeader = Model.AdditionalInformationHeader, + AdditionalInformationBody = Model.AdditionalInformationBody + }); + }
@Model.QuestionHint
diff --git a/src/Dfe.EarlyYearsQualification.Web/Views/Questions/Dropdown.cshtml b/src/Dfe.EarlyYearsQualification.Web/Views/Questions/Dropdown.cshtml index 80352299..1e88d566 100644 --- a/src/Dfe.EarlyYearsQualification.Web/Views/Questions/Dropdown.cshtml +++ b/src/Dfe.EarlyYearsQualification.Web/Views/Questions/Dropdown.cshtml @@ -42,6 +42,14 @@ + @if (!string.IsNullOrEmpty(Model.AdditionalInformationHeader) && !string.IsNullOrEmpty(Model.AdditionalInformationBody)) + { + await Html.RenderPartialAsync("Partials/AdditionalInformation", new AdditionalInformationModel + { + AdditionalInformationHeader = Model.AdditionalInformationHeader, + AdditionalInformationBody = Model.AdditionalInformationBody + }); + }

@Html.Label(Model.DropdownId, Model.DropdownHeading, new { @class = "govuk-label govuk-fieldset__legend--m" }) diff --git a/src/Dfe.EarlyYearsQualification.Web/Views/Questions/Radio.cshtml b/src/Dfe.EarlyYearsQualification.Web/Views/Questions/Radio.cshtml index 36d17239..31f95c4c 100644 --- a/src/Dfe.EarlyYearsQualification.Web/Views/Questions/Radio.cshtml +++ b/src/Dfe.EarlyYearsQualification.Web/Views/Questions/Radio.cshtml @@ -34,17 +34,13 @@ @if (!string.IsNullOrEmpty(Model.AdditionalInformationHeader) && !string.IsNullOrEmpty(Model.AdditionalInformationBody)) { -
- - - @Model.AdditionalInformationHeader - - -
- @Html.Raw(Model.AdditionalInformationBody) -
-
+ await Html.RenderPartialAsync("Partials/AdditionalInformation", new AdditionalInformationModel + { + AdditionalInformationHeader = Model.AdditionalInformationHeader, + AdditionalInformationBody = Model.AdditionalInformationBody + }); } + @if (Model.HasErrors) {

diff --git a/src/Dfe.EarlyYearsQualification.Web/Views/Shared/Partials/AdditionalInformation.cshtml b/src/Dfe.EarlyYearsQualification.Web/Views/Shared/Partials/AdditionalInformation.cshtml new file mode 100644 index 00000000..ce0b8764 --- /dev/null +++ b/src/Dfe.EarlyYearsQualification.Web/Views/Shared/Partials/AdditionalInformation.cshtml @@ -0,0 +1,12 @@ +@model Dfe.EarlyYearsQualification.Web.Models.AdditionalInformationModel + +

+ + + @Model.AdditionalInformationHeader + + +
+ @Html.Raw(Model.AdditionalInformationBody) +
+
\ No newline at end of file diff --git a/tests/Dfe.EarlyYearsQualification.E2ETests/cypress/e2e/pages/question-spec.cy.js b/tests/Dfe.EarlyYearsQualification.E2ETests/cypress/e2e/pages/question-spec.cy.js index e40e7ffb..8d4fc69c 100644 --- a/tests/Dfe.EarlyYearsQualification.E2ETests/cypress/e2e/pages/question-spec.cy.js +++ b/tests/Dfe.EarlyYearsQualification.E2ETests/cypress/e2e/pages/question-spec.cy.js @@ -14,6 +14,17 @@ describe("A spec that tests question pages", () => { cy.get("#outside-uk").should("exist"); }) + it("Checks additional information on the where-was-the-qualification-awarded page", () => { + cy.visit("/questions/where-was-the-qualification-awarded"); + + cy.get(".govuk-details").should("not.have.attr", "open"); + cy.get(".govuk-details__summary-text").should("contain.text", "This is the additional information header"); + cy.get(".govuk-details__text").should("contain.text", "This is the additional information body"); + + cy.get(".govuk-details__summary-text").click(); + cy.get(".govuk-details").should("have.attr", "open"); + }) + it("shows an error message when a user doesnt select an option on the where-was-the-qualification-awarded page", () => { cy.visit("/questions/where-was-the-qualification-awarded"); @@ -45,6 +56,17 @@ describe("A spec that tests question pages", () => { cy.get("#date-started-year").should("exist"); }) + it("Checks additional information on the when-was-the-qualification-started page", () => { + cy.visit("/questions/when-was-the-qualification-started"); + + cy.get(".govuk-details").should("not.have.attr", "open"); + cy.get(".govuk-details__summary-text").should("contain.text", "This is the additional information header"); + cy.get(".govuk-details__text").should("contain.text", "This is the additional information body"); + + cy.get(".govuk-details__summary-text").click(); + cy.get(".govuk-details").should("have.attr", "open"); + }) + it("shows an error message when a user doesnt type a date on the when-was-the-qualification-started page", () => { cy.visit("/questions/when-was-the-qualification-started"); @@ -75,6 +97,17 @@ describe("A spec that tests question pages", () => { cy.get("#3").should("exist"); }) + it("Checks additional information on the what-level-is-the-qualification page", () => { + cy.visit("/questions/what-level-is-the-qualification"); + + cy.get(".govuk-details").should("not.have.attr", "open"); + cy.get(".govuk-details__summary-text").should("contain.text", "This is the additional information header"); + cy.get(".govuk-details__text").should("contain.text", "This is the additional information body"); + + cy.get(".govuk-details__summary-text").click(); + cy.get(".govuk-details").should("have.attr", "open"); + }) + it("shows an error message when a user doesnt select an option on the what-level-is-the-qualification page", () => { cy.visit("/questions/what-level-is-the-qualification"); @@ -106,6 +139,17 @@ describe("A spec that tests question pages", () => { cy.get('button[id="question-submit"]').should("exist"); }) + it("Checks additional information on the what-is-the-awarding-organisation page", () => { + cy.visit("/questions/what-is-the-awarding-organisation"); + + cy.get(".govuk-details").should("not.have.attr", "open"); + cy.get(".govuk-details__summary-text").should("contain.text", "This is the additional information header"); + cy.get(".govuk-details__text").should("contain.text", "This is the additional information body"); + + cy.get(".govuk-details__summary-text").click(); + cy.get(".govuk-details").should("have.attr", "open"); + }) + it("shows an error message when a user doesnt select an option from the dropdown list" + "and also does not check 'not in the list' on the what-is-the-awarding-organisation", () => { cy.visit("/questions/what-is-the-awarding-organisation"); diff --git a/tests/Dfe.EarlyYearsQualification.UnitTests/Mocks/MockContentfulServiceTests.cs b/tests/Dfe.EarlyYearsQualification.UnitTests/Mocks/MockContentfulServiceTests.cs index 9a7c3d91..c3a5b9db 100644 --- a/tests/Dfe.EarlyYearsQualification.UnitTests/Mocks/MockContentfulServiceTests.cs +++ b/tests/Dfe.EarlyYearsQualification.UnitTests/Mocks/MockContentfulServiceTests.cs @@ -275,6 +275,9 @@ public async Task GetRadioQuestionPage_PassInWhatLevelIsTheQualification_Returns result.ErrorMessage.Should().NotBeNullOrEmpty(); result.ErrorBannerHeading.Should().NotBeNull(); result.ErrorBannerLinkText.Should().NotBeNull(); + result.AdditionalInformationHeader.Should().Be("This is the additional information header"); + result.AdditionalInformationBody!.Content[0].Should().BeAssignableTo() + .Which.Content.Should().ContainSingle(x => ((Text)x).Value == "This is the additional information body"); result.Options.Should().NotBeNullOrEmpty(); result.Options.Count.Should().Be(2); result.Options[0].Label.Should().Be("Level 2"); @@ -306,6 +309,9 @@ public async Task GetDateQuestionPage_PassWhenWasQualificationStartedId_ReturnsE result.ErrorMessage.Should().Be("Test Error Message"); result.ErrorBannerHeading.Should().Be("There is a problem"); result.ErrorBannerLinkText.Should().Be("Test error banner link text"); + result.AdditionalInformationHeader.Should().Be("This is the additional information header"); + result.AdditionalInformationBody!.Content[0].Should().BeAssignableTo() + .Which.Content.Should().ContainSingle(x => ((Text)x).Value == "This is the additional information body"); result.MonthLabel.Should().Be("Test Month Label"); result.YearLabel.Should().Be("Test Year Label"); result.QuestionHint.Should().Be("Test Question Hint"); @@ -334,6 +340,9 @@ public async Task GetDropdownQuestionPage_PassWhenWasQualificationStartedId_Retu result.ErrorMessage.Should().Be("Test Error Message"); result.ErrorBannerHeading.Should().Be("There is a problem"); result.ErrorBannerLinkText.Should().Be("Test error banner link text"); + result.AdditionalInformationHeader.Should().Be("This is the additional information header"); + result.AdditionalInformationBody!.Content[0].Should().BeAssignableTo() + .Which.Content.Should().ContainSingle(x => ((Text)x).Value == "This is the additional information body"); result.Question.Should().Be("Test Dropdown Question"); result.DefaultText.Should().Be("Test Default Dropdown Text"); result.DropdownHeading.Should().Be("Test Dropdown Heading");