Skip to content

Commit

Permalink
EYQB-491: initial commit of the divider and hint text logic (#298)
Browse files Browse the repository at this point in the history
* EYQB-491: initial commit of the divider and hint text logic

* Added unit tests for the converter

* Updated to add in hint text rendering to other places radio buttons are used and updated the existing e2e tests to ensure hint and dividers are covered

* Removed commented code
  • Loading branch information
sam-c-dfe authored Aug 8, 2024
1 parent 66faf10 commit 74c65af
Show file tree
Hide file tree
Showing 20 changed files with 245 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Dfe.EarlyYearsQualification.Content.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Dfe.EarlyYearsQualification.Content.Converters;

public class OptionItemConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(IOptionItem);
}

public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
var jo = JObject.Load(reader);
var hasLabel = jo.ContainsKey("label") || jo.ContainsKey("Label");
IOptionItem model = hasLabel ? new Option() : new Divider();
serializer.Populate(jo.CreateReader(), model);
return model;
}

public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
6 changes: 6 additions & 0 deletions src/Dfe.EarlyYearsQualification.Content/Entities/Divider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Dfe.EarlyYearsQualification.Content.Entities;

public class Divider : IOptionItem
{
public string Text { get; init; } = string.Empty;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Dfe.EarlyYearsQualification.Content.Entities;

public interface IOptionItem;
4 changes: 3 additions & 1 deletion src/Dfe.EarlyYearsQualification.Content/Entities/Option.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
namespace Dfe.EarlyYearsQualification.Content.Entities;

public class Option
public class Option : IOptionItem
{
public string Label { get; init; } = string.Empty;

public string Value { get; init; } = string.Empty;

public string Hint { get; init; } = string.Empty;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public class RadioQuestionPage
{
public string Question { get; init; } = string.Empty;

public List<Option> Options { get; init; } = [];
public List<IOptionItem> Options { get; init; } = [];

public string CtaButtonText { get; init; } = string.Empty;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Contentful.Core.Models;
using Contentful.Core.Search;
using Dfe.EarlyYearsQualification.Content.Constants;
using Dfe.EarlyYearsQualification.Content.Converters;
using Dfe.EarlyYearsQualification.Content.Entities;
using Microsoft.Extensions.Logging;

Expand Down Expand Up @@ -135,6 +136,7 @@ public async Task<List<NavigationLink>> GetNavigationLinks()

public async Task<RadioQuestionPage?> GetRadioQuestionPage(string entryId)
{
contentfulClient.SerializerSettings.Converters.Add(new OptionItemConverter());
return await GetEntryById<RadioQuestionPage>(entryId);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -466,25 +466,29 @@ public Task<List<Qualification>> GetQualifications()

private static RadioQuestionPage CreateWhereWasTheQualificationAwardedPage()
{
var options = new List<Option>
var options = new List<IOptionItem>
{
new()
new Option
{
Label = "England", Value = "england"
},
new()
new Option
{
Label = "Scotland", Value = "scotland"
},
new()
new Option
{
Label = "Wales", Value = "wales"
},
new()
new Option
{
Label = "Northern Ireland", Value = "northern-ireland"
},
new()
new Divider
{
Text = "or"
},
new Option
{
Label = "Outside the United Kingdom",
Value = "outside-uk"
Expand All @@ -495,21 +499,21 @@ private static RadioQuestionPage CreateWhereWasTheQualificationAwardedPage()

private static RadioQuestionPage CreateWhatLevelIsTheQualificationPage()
{
var options = new List<Option>
var options = new List<IOptionItem>
{
new()
new Option
{
Label = "Level 2", Value = "2"
},
new()
new Option
{
Label = "Level 3", Value = "3"
},
new()
new Option
{
Label = "Level 6", Value = "6"
Label = "Level 6", Value = "6", Hint = "Some hint text"
},
new()
new Option
{
Label = "Level 7", Value = "7"
}
Expand All @@ -518,7 +522,7 @@ private static RadioQuestionPage CreateWhatLevelIsTheQualificationPage()
"/questions/when-was-the-qualification-started");
}

private static RadioQuestionPage CreateRadioQuestionPage(string question, List<Option> options,
private static RadioQuestionPage CreateRadioQuestionPage(string question, List<IOptionItem> options,
string backButtonUrl)
{
return new RadioQuestionPage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ private async Task<RadioQuestionModel> MapRadioModel(RadioQuestionModel model, R
string controllerName)
{
model.Question = question.Question;
model.Options = question.Options.Select(x => new OptionModel { Label = x.Label, Value = x.Value }).ToList();
model.OptionsItems = MapOptionItems(question.Options);
model.CtaButtonText = question.CtaButtonText;
model.ActionName = actionName;
model.ControllerName = controllerName;
Expand All @@ -256,6 +256,27 @@ private async Task<RadioQuestionModel> MapRadioModel(RadioQuestionModel model, R
return model;
}

private static List<IOptionItemModel> MapOptionItems(List<IOptionItem> questionOptions)
{
var results = new List<IOptionItemModel>();

foreach (var optionItem in questionOptions)
{
if (optionItem.GetType() == typeof(Option))
{
var option = (Option)optionItem;
results.Add(new OptionModel { Hint = option.Hint, Value = option.Value, Label = option.Label });
}
else if (optionItem.GetType() == typeof(Divider))
{
var divider = (Divider)optionItem;
results.Add(new DividerModel { Text = divider.Text });
}
}

return results;
}

private async Task<DateQuestionModel> MapDateModel(DateQuestionModel model, DateQuestionPage question,
string actionName,
string controllerName)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Dfe.EarlyYearsQualification.Web.Models.Content.QuestionModels;

public class DividerModel : IOptionItemModel
{
public string Text { get; set; } = string.Empty;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Dfe.EarlyYearsQualification.Web.Models.Content.QuestionModels;

public interface IOptionItemModel;
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
namespace Dfe.EarlyYearsQualification.Web.Models.Content.QuestionModels;

public class OptionModel
public class OptionModel : IOptionItemModel
{
public string Label { get; init; } = string.Empty;

public string Value { get; init; } = string.Empty;

public string Hint { get; init; } = string.Empty;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Dfe.EarlyYearsQualification.Web.Models.Content.QuestionModels;

public class RadioQuestionModel : BaseQuestionModel
{
public List<OptionModel> Options { get; set; } = [];
public List<IOptionItemModel> OptionsItems { get; set; } = [];

[Required] public string? Option { get; init; } = string.Empty;
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@
<label class="govuk-label govuk-radios__label" for="@id">
@option.Label
</label>
@if (!string.IsNullOrEmpty(option.Hint))
{
var hintId = $"{option.Value}_{qi}_{i}_hint";
<div id="@hintId" class="govuk-hint govuk-radios__hint">
@option.Hint
</div>
}
</div>
}
</fieldset>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@
<label class="govuk-label govuk-radios__label" for="@option.Value">
@option.Label
</label>
@if (!string.IsNullOrEmpty(option.Hint))
{
var hintId = $"{option.Value}_hint";
<div id="@hintId" class="govuk-hint govuk-radios__hint">
@option.Hint
</div>
}
</div>
}
</fieldset>
Expand Down
34 changes: 26 additions & 8 deletions src/Dfe.EarlyYearsQualification.Web/Views/Questions/Radio.cshtml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@using Dfe.EarlyYearsQualification.Web.Models.Content.QuestionModels
@model Dfe.EarlyYearsQualification.Web.Models.Content.QuestionModels.RadioQuestionModel

@{
Expand All @@ -14,11 +15,12 @@
<div class="govuk-grid-column-two-thirds">
@if (Model.HasErrors)
{
var elementLinkId = Model.OptionsItems.First(x => x.GetType() == typeof(OptionModel)) as OptionModel;
await Html.RenderPartialAsync("Partials/ErrorSummary", new ErrorSummaryModel
{
ErrorBannerHeading = Model.ErrorBannerHeading,
ErrorBannerLinkText = Model.ErrorBannerLinkText,
ElementLinkId = Model.Options[0].Value
ElementLinkId = elementLinkId != null ? elementLinkId.Value : ""
});
}
@using (Html.BeginForm(Model.ActionName, Model.ControllerName, FormMethod.Post))
Expand Down Expand Up @@ -48,14 +50,30 @@
</p>
}
<div class="govuk-radios" data-module="govuk-radios">
@foreach (var option in Model.Options)
@foreach (var option in Model.OptionsItems)
{
<div class="govuk-radios__item">
@Html.RadioButtonFor(x => x.Option, option.Value, new { @class = "govuk-radios__input", id = option.Value })
<label class="govuk-label govuk-radios__label" for="@option.Value">
@option.Label
</label>
</div>
if (option.GetType() == typeof(OptionModel))
{
var optionModel = option as OptionModel;
<div class="govuk-radios__item">
@Html.RadioButtonFor(x => x.Option, optionModel!.Value, new { @class = "govuk-radios__input", id = optionModel.Value })
<label class="govuk-label govuk-radios__label" for="@optionModel.Value">
@optionModel.Label
</label>
@if (!string.IsNullOrEmpty(optionModel.Hint))
{
var hintId = $"{optionModel.Value}_hint";
<div id="@hintId" class="govuk-hint govuk-radios__hint">
@optionModel.Hint
</div>
}
</div>
}
else if (option.GetType() == typeof(DividerModel))
{
var optionModel = option as DividerModel;
<div class="govuk-radios__divider">@optionModel!.Text</div>
}
}
</div>
</fieldset>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ describe("A spec that tests question pages", () => {

cy.get("#question").should("contain.text", "Where was the qualification awarded?");
cy.get("#england").should("exist");
cy.get("#scotland").should("exist");
cy.get("#wales").should("exist");
cy.get("#northern-ireland").should("exist");
cy.get(".govuk-radios__divider").should("contain.text", "or");
cy.get("#outside-uk").should("exist");
})

Expand Down Expand Up @@ -95,6 +99,10 @@ describe("A spec that tests question pages", () => {
cy.get("#question").should("contain.text", "What level is the qualification?");
cy.get("#2").should("exist");
cy.get("#3").should("exist");
cy.get("#6").should("exist");
cy.get("#6_hint").should("exist");
cy.get("#6_hint").should("contain.text", "Some hint text");
cy.get("#7").should("exist");
})

it("Checks additional information on the what-level-is-the-qualification page", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,11 @@ public async Task WhereWasTheQualificationAwarded_ContentServiceReturnsQuestionP

model!.Question.Should().Be(questionPage.Question);
model.CtaButtonText.Should().Be(questionPage.CtaButtonText);
model.Options.Count.Should().Be(1);
model.Options[0].Label.Should().Be(questionPage.Options[0].Label);
model.Options[0].Value.Should().Be(questionPage.Options[0].Value);
model.OptionsItems.Count.Should().Be(1);
model.OptionsItems.First().Should().BeAssignableTo<OptionModel>();
var modelOption = model.OptionsItems[0] as OptionModel;
modelOption!.Label.Should().Be((questionPage.Options[0] as Option)!.Label);
modelOption.Value.Should().Be((questionPage.Options[0] as Option)!.Value);
model.HasErrors.Should().BeFalse();
}

Expand Down Expand Up @@ -589,9 +591,11 @@ public async Task WhatLevelIsTheQualification_ContentServiceReturnsQuestionPage_

model!.Question.Should().Be(questionPage.Question);
model.CtaButtonText.Should().Be(questionPage.CtaButtonText);
model.Options.Count.Should().Be(1);
model.Options[0].Label.Should().Be(questionPage.Options[0].Label);
model.Options[0].Value.Should().Be(questionPage.Options[0].Value);
model.OptionsItems.Count.Should().Be(1);
model.OptionsItems.First().Should().BeAssignableTo<OptionModel>();
var modelOption = model.OptionsItems[0] as OptionModel;
modelOption!.Label.Should().Be((questionPage.Options[0] as Option)!.Label);
modelOption.Value.Should().Be((questionPage.Options[0] as Option)!.Value);
model.HasErrors.Should().BeFalse();
model.AdditionalInformationHeader.Should().Be(questionPage.AdditionalInformationHeader);
model.AdditionalInformationBody.Should().Be("Test html body");
Expand Down
Loading

0 comments on commit 74c65af

Please sign in to comment.