diff --git a/Childrens-Social-Care-CPD-Tests/Contentful/EntityResolverTests.cs b/Childrens-Social-Care-CPD-Tests/Contentful/EntityResolverTests.cs index 0eeb9e61..d5e2b8ee 100644 --- a/Childrens-Social-Care-CPD-Tests/Contentful/EntityResolverTests.cs +++ b/Childrens-Social-Care-CPD-Tests/Contentful/EntityResolverTests.cs @@ -10,6 +10,8 @@ namespace Childrens_Social_Care_CPD_Tests.Contentful; public class EntityResolverTests { [Test] + [TestCase("areaOfPractice", typeof(AreaOfPractice))] + [TestCase("areaOfPracticeList", typeof(AreaOfPracticeList))] [TestCase("applicationFeature", typeof(ApplicationFeature))] [TestCase("applicationFeatures", typeof(ApplicationFeatures))] [TestCase("columnLayout", typeof(ColumnLayout))] diff --git a/Childrens-Social-Care-CPD-Tests/Contentful/PartialsFactoryTests.cs b/Childrens-Social-Care-CPD-Tests/Contentful/PartialsFactoryTests.cs index 6fa5b18f..de4a5411 100644 --- a/Childrens-Social-Care-CPD-Tests/Contentful/PartialsFactoryTests.cs +++ b/Childrens-Social-Care-CPD-Tests/Contentful/PartialsFactoryTests.cs @@ -11,6 +11,8 @@ public partial class PartialsFactoryTests { public static object[] Successful_Resolves = { + new object[] { new AreaOfPractice(), "_AreaOfPractice" }, + new object[] { new AreaOfPracticeList(), "_AreaOfPracticeList" }, new object[] { new ColumnLayout(), "_ColumnLayout" }, new object[] { new Content(), "_Content" }, new object[] { new ContentLink(), "_ContentLink" }, diff --git a/Childrens-Social-Care-CPD-Tests/Contentful/Renderers/InlineAreaOfPracticeListRendererTests.cs b/Childrens-Social-Care-CPD-Tests/Contentful/Renderers/InlineAreaOfPracticeListRendererTests.cs new file mode 100644 index 00000000..c0a65064 --- /dev/null +++ b/Childrens-Social-Care-CPD-Tests/Contentful/Renderers/InlineAreaOfPracticeListRendererTests.cs @@ -0,0 +1,152 @@ +using Childrens_Social_Care_CPD.Contentful.Models; +using Childrens_Social_Care_CPD.Contentful.Renderers; +using Contentful.Core.Models; +using FluentAssertions; +using Microsoft.AspNetCore.Html; +using Microsoft.Extensions.WebEncoders.Testing; +using NSubstitute; +using NUnit.Framework; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; + +namespace Childrens_Social_Care_CPD_Tests.Contentful.Renderers; + +public class InlineAreaOfPracticeListRendererTests +{ + private IRenderer _contentLinkRenderer; + private InlineAreaOfPracticeListRenderer _sut; + + [SetUp] + public void Setup() + { + _contentLinkRenderer = Substitute.For>(); + _sut = new InlineAreaOfPracticeListRenderer(_contentLinkRenderer); + } + + [Test] + public void AreaOfPractice_Renders_When_No_AreasOfPractice() + { + // arrange + var stringWriter = new StringWriter(); + var areaOfPracticeList = new AreaOfPracticeList() + { + Title = "A Title", + Areas = new List() + }; + _contentLinkRenderer.Render(Arg.Any()).Returns(new HtmlString("AAA")); + + // act + var htmlContent = _sut.Render(areaOfPracticeList); + htmlContent.WriteTo(stringWriter, new HtmlTestEncoder()); + var actual = stringWriter.ToString(); + + // assert + actual.Should().Be("HtmlEncode[[No Areas Of practice Available]]"); + } + + [Test] + public void AreaOfPracticeList_Renders_Empty_When_AreaOfPractice_Is_Null() + { + // arrange + var stringWriter = new StringWriter(); + var areaOfPracticeList = new AreaOfPracticeList() + { + Title = "A Title", + Areas = new List + { + new Content + { + Id = "id", + Title = "title", + Items = new List() + } + } + }; + + _contentLinkRenderer.Render(Arg.Any()).Returns(new HtmlString("AAA")); + + // act + var htmlContent = _sut.Render(areaOfPracticeList); + htmlContent.WriteTo(stringWriter, new HtmlTestEncoder()); + var actual = stringWriter.ToString(); + + // assert + actual.Should().Be(string.Empty); + } + + [Test] + public void AreaOfPracticeList_Renders_Title() + { + // arrange + var stringWriter = new StringWriter(); + var areaOfPracticeList = new AreaOfPracticeList + { + Title = "A Title", + Areas = new List + { + new Content + { + Id = "id", + Items = new List() + { + new AreaOfPractice() + { + Title = "title" + } + } + } + } + }; + + _contentLinkRenderer.Render(Arg.Any()).Returns(new HtmlString("AAA")); + var expected = $"^{Regex.Escape("

AAA

")}.*"; + + // act + var htmlContent = _sut.Render(areaOfPracticeList); + htmlContent.WriteTo(stringWriter, new HtmlTestEncoder()); + var actual = stringWriter.ToString(); + + // assert + actual.Should().MatchRegex(expected); + } + + [Test] + public void AreaOfPracticeList_Renders_Summary() + { + // arrange + var stringWriter = new StringWriter(); + var areaOfPractice = new AreaOfPractice() + { + Title = "title", + AreaOfPracticeListSummary = "summary" + }; + var areaOfPracticeList = new AreaOfPracticeList() + { + Title = "A Title", + Areas = new List + { + new Content + { + Id = "id", + Items = new List() + { + areaOfPractice + } + } + } + }; + + _contentLinkRenderer.Render(Arg.Any()).Returns(new HtmlString("AAA")); + var expected = $".*?{Regex.Escape("

HtmlEncode[[summary]]

")}.*"; + + // act + var htmlContent = _sut.Render(areaOfPracticeList); + htmlContent.WriteTo(stringWriter, new HtmlTestEncoder()); + var actual = stringWriter.ToString(); + + // assert + actual.Should().MatchRegex(expected); + } +} diff --git a/Childrens-Social-Care-CPD-Tests/Contentful/Renderers/ParagraphRendererTests.cs b/Childrens-Social-Care-CPD-Tests/Contentful/Renderers/ParagraphRendererTests.cs index 3d91ef51..6bbbadf0 100644 --- a/Childrens-Social-Care-CPD-Tests/Contentful/Renderers/ParagraphRendererTests.cs +++ b/Childrens-Social-Care-CPD-Tests/Contentful/Renderers/ParagraphRendererTests.cs @@ -18,7 +18,8 @@ public class ParagraphRendererTests private IRenderer _roleListRenderer; private IRenderer _hyperlinkRenderer; private IRenderer _contentLinkRenderer; - + private IRenderer _areaOfPracticeListRenderer; + private ParagraphRenderer _sut; [SetUp] @@ -28,8 +29,8 @@ public void Setup() _roleListRenderer = Substitute.For>(); _hyperlinkRenderer = Substitute.For>(); _contentLinkRenderer = Substitute.For>(); - - _sut = new ParagraphRenderer(_textRenderer, _roleListRenderer, _hyperlinkRenderer, _contentLinkRenderer); + _areaOfPracticeListRenderer = Substitute.For>(); + _sut = new ParagraphRenderer(_textRenderer, _roleListRenderer, _hyperlinkRenderer, _contentLinkRenderer, _areaOfPracticeListRenderer); } [Test] @@ -82,6 +83,7 @@ public void Paragraph_Renders_With_RoleList() _roleListRenderer.Render(Arg.Any()).Returns(new HtmlString("BBB")); _hyperlinkRenderer.Render(Arg.Any()).Returns(new HtmlString("CCC")); _contentLinkRenderer.Render(Arg.Any()).Returns(new HtmlString("DDD")); + _areaOfPracticeListRenderer.Render(Arg.Any()).Returns(new HtmlString("EEE")); // act var htmlContent = _sut.Render(paragraph); @@ -109,6 +111,7 @@ public void Paragraph_Renders_With_Hyperlink() _roleListRenderer.Render(Arg.Any()).Returns(new HtmlString("BBB")); _hyperlinkRenderer.Render(Arg.Any()).Returns(new HtmlString("CCC")); _contentLinkRenderer.Render(Arg.Any()).Returns(new HtmlString("DDD")); + _areaOfPracticeListRenderer.Render(Arg.Any()).Returns(new HtmlString("EEE")); // act var htmlContent = _sut.Render(paragraph); @@ -142,6 +145,7 @@ public void Paragraph_Renders_With_ContentLink() _roleListRenderer.Render(Arg.Any()).Returns(new HtmlString("BBB")); _hyperlinkRenderer.Render(Arg.Any()).Returns(new HtmlString("CCC")); _contentLinkRenderer.Render(Arg.Any()).Returns(new HtmlString("DDD")); + _areaOfPracticeListRenderer.Render(Arg.Any()).Returns(new HtmlString("EEE")); // act var htmlContent = _sut.Render(paragraph); @@ -151,4 +155,38 @@ public void Paragraph_Renders_With_ContentLink() // assert actual.Should().Be($"

DDD

"); } + + [Test] + public void Paragraph_Renders_With_AreaOfPracticeList() + { + // arrange + var stringWriter = new StringWriter(); + var paragraph = new Paragraph() + { + Content = new List + { + new EntryStructure + { + Data = new EntryStructureData + { + Target = new AreaOfPracticeList() + } + } + } + }; + + _textRenderer.Render(Arg.Any()).Returns(new HtmlString("AAA")); + _roleListRenderer.Render(Arg.Any()).Returns(new HtmlString("BBB")); + _hyperlinkRenderer.Render(Arg.Any()).Returns(new HtmlString("CCC")); + _contentLinkRenderer.Render(Arg.Any()).Returns(new HtmlString("DDD")); + _areaOfPracticeListRenderer.Render(Arg.Any()).Returns(new HtmlString("EEE")); + + // act + var htmlContent = _sut.Render(paragraph); + htmlContent.WriteTo(stringWriter, new HtmlTestEncoder()); + var actual = stringWriter.ToString(); + + // assert + actual.Should().Be($"

EEE

"); + } } diff --git a/Childrens-Social-Care-CPD/Contentful/EntityResolver.cs b/Childrens-Social-Care-CPD/Contentful/EntityResolver.cs index 8150a872..6948043f 100644 --- a/Childrens-Social-Care-CPD/Contentful/EntityResolver.cs +++ b/Childrens-Social-Care-CPD/Contentful/EntityResolver.cs @@ -13,6 +13,8 @@ public Type Resolve(string contentTypeId) { return contentTypeId switch { + "areaOfPractice" => typeof(AreaOfPractice), + "areaOfPracticeList" => typeof(AreaOfPracticeList), "applicationFeature" => typeof(ApplicationFeature), "applicationFeatures" => typeof(ApplicationFeatures), "columnLayout" => typeof(ColumnLayout), diff --git a/Childrens-Social-Care-CPD/Contentful/Models/AreaOfPractice.cs b/Childrens-Social-Care-CPD/Contentful/Models/AreaOfPractice.cs new file mode 100644 index 00000000..c9575fa2 --- /dev/null +++ b/Childrens-Social-Care-CPD/Contentful/Models/AreaOfPractice.cs @@ -0,0 +1,16 @@ +using Contentful.Core.Models; + +namespace Childrens_Social_Care_CPD.Contentful.Models; + +public class AreaOfPractice : IContent +{ + public string Title { get; set; } + public string Summary { get; set; } + public string AreaOfPracticeListSummary { get; set; } + public string OtherNames { get; set; } + public Document WhatYoullDo { get; set; } + public Document SkillsAndKnowledge { get; set; } + public Document WhoYouWillWorkWith { get; set; } + public Document HowYouWillWork { get; set; } + public Document CurrentOpportunities { get; set; } +} diff --git a/Childrens-Social-Care-CPD/Contentful/Models/AreaOfPracticeList.cs b/Childrens-Social-Care-CPD/Contentful/Models/AreaOfPracticeList.cs new file mode 100644 index 00000000..8a1668a0 --- /dev/null +++ b/Childrens-Social-Care-CPD/Contentful/Models/AreaOfPracticeList.cs @@ -0,0 +1,9 @@ +using Contentful.Core.Models; + +namespace Childrens_Social_Care_CPD.Contentful.Models; + +public class AreaOfPracticeList : IContent +{ + public string Title { get; set; } + public List Areas { get; set; } +} diff --git a/Childrens-Social-Care-CPD/Contentful/PartialsFactory.cs b/Childrens-Social-Care-CPD/Contentful/PartialsFactory.cs index 0bca6754..794961e8 100644 --- a/Childrens-Social-Care-CPD/Contentful/PartialsFactory.cs +++ b/Childrens-Social-Care-CPD/Contentful/PartialsFactory.cs @@ -14,6 +14,8 @@ public static string GetPartialFor(IContent item) { switch (item) { + case (AreaOfPractice): return "_AreaOfPractice"; + case (AreaOfPracticeList): return "_AreaOfPracticeList"; case (ColumnLayout): return "_ColumnLayout"; case (Content): return "_Content"; case (ContentLink): return "_ContentLink"; @@ -27,6 +29,7 @@ public static string GetPartialFor(IContent item) case (RoleList): return "_RoleList"; case (SideMenu): return "_SideMenu"; case (TextBlock): return "_TextBlock"; + default: return "_UnknownContentWarning"; } } diff --git a/Childrens-Social-Care-CPD/Contentful/Renderers/InlineAreaOfPracticeListRenderer.cs b/Childrens-Social-Care-CPD/Contentful/Renderers/InlineAreaOfPracticeListRenderer.cs new file mode 100644 index 00000000..6ce28c91 --- /dev/null +++ b/Childrens-Social-Care-CPD/Contentful/Renderers/InlineAreaOfPracticeListRenderer.cs @@ -0,0 +1,71 @@ +using Childrens_Social_Care_CPD.Contentful.Models; +using Microsoft.AspNetCore.Html; +using Microsoft.AspNetCore.Mvc.Rendering; + +namespace Childrens_Social_Care_CPD.Contentful.Renderers; + +internal class InlineAreaOfPracticeListRenderer : IRenderer +{ + private readonly IRenderer _contentLinkRenderer; + + public InlineAreaOfPracticeListRenderer(IRenderer contentLinkRenderer) + { + _contentLinkRenderer = contentLinkRenderer; + } + + public IHtmlContent Render(AreaOfPracticeList item) + { + if (item.Areas.Count == 0) + { + return NoAreasOfpractice(); + } + + var htmlContentBuilder = new HtmlContentBuilder(); + + foreach (var contentItem in item.Areas) + { + var areaOfpractice = contentItem.Items.OfType().FirstOrDefault(); + if (areaOfpractice == null) continue; + + htmlContentBuilder.AppendHtml(AreaOfPracticeTitle(contentItem.Id, areaOfpractice)); + htmlContentBuilder.AppendHtml(AreaOfPracticeSummary(areaOfpractice)); + } + + return htmlContentBuilder; + } + + private static IHtmlContent NoAreasOfpractice() + { + var span = new TagBuilder("span"); + span.InnerHtml.Append("No Areas Of practice Available"); + return span; + } + + private IHtmlContent AreaOfPracticeTitle(string id, AreaOfPractice areaOfPractice) + { + var div = new TagBuilder("div"); + div.AddCssClass("govuk-heading-s govuk-!-margin-bottom-1"); + var heading2 = new TagBuilder("h2"); + + var contentLink = new ContentLink() + { + Name = areaOfPractice.Title, + Uri = id + }; + + heading2.InnerHtml.AppendHtml(_contentLinkRenderer.Render(contentLink)); + + div.InnerHtml.AppendHtml(heading2); + return div; + } + + private static IHtmlContent AreaOfPracticeSummary(AreaOfPractice areaOfPractice) + { + var htmlContentBuilder = new HtmlContentBuilder(); + var p = new TagBuilder("p"); + p.AddCssClass("govuk-body"); + p.InnerHtml.Append(areaOfPractice.AreaOfPracticeListSummary); + htmlContentBuilder.AppendHtml(p); + return htmlContentBuilder; + } +} diff --git a/Childrens-Social-Care-CPD/Contentful/Renderers/ParagraphRenderer.cs b/Childrens-Social-Care-CPD/Contentful/Renderers/ParagraphRenderer.cs index acb25059..e3d9666d 100644 --- a/Childrens-Social-Care-CPD/Contentful/Renderers/ParagraphRenderer.cs +++ b/Childrens-Social-Care-CPD/Contentful/Renderers/ParagraphRenderer.cs @@ -11,14 +11,16 @@ internal class ParagraphRenderer : IRenderer private readonly IRenderer _roleListRenderer; private readonly IRenderer _hyperlinkRenderer; private readonly IRenderer _contentLinkRenderer; - + private readonly IRenderer _areaOfPracticeList; - public ParagraphRenderer(IRenderer textRenderer, IRenderer roleListRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) + + public ParagraphRenderer(IRenderer textRenderer, IRenderer roleListRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer, IRenderer areaOfPracticeList) { _textRenderer = textRenderer; _roleListRenderer = roleListRenderer; _hyperlinkRenderer = hyperlinkRenderer; _contentLinkRenderer = contentLinkRenderer; + _areaOfPracticeList = areaOfPracticeList; } public IHtmlContent Render(Paragraph item) @@ -37,6 +39,7 @@ public IHtmlContent Render(Paragraph item) { case ContentLink contentLink: p.InnerHtml.AppendHtml(_contentLinkRenderer.Render(contentLink)); break; case RoleList roleList: p.InnerHtml.AppendHtml(_roleListRenderer.Render(roleList)); break; + case AreaOfPracticeList areaOfPracticeList: p.InnerHtml.AppendHtml(_areaOfPracticeList.Render(areaOfPracticeList)); break; } break; } diff --git a/Childrens-Social-Care-CPD/Views/Shared/_AreaOfPractice.cshtml b/Childrens-Social-Care-CPD/Views/Shared/_AreaOfPractice.cshtml new file mode 100644 index 00000000..6f37c065 --- /dev/null +++ b/Childrens-Social-Care-CPD/Views/Shared/_AreaOfPractice.cshtml @@ -0,0 +1,88 @@ +@using Childrens_Social_Care_CPD.Contentful; +@using Childrens_Social_Care_CPD.Contentful.Models; +@using Contentful.Core.Models; + +@model AreaOfPractice + +@functions { + + public async Task RenderAccordianSection(string title, Document model, int id) + { +
+
+

+ + @title + +

+
+
+ @{ + await Html.RenderPartialAsync("_RichText", model); + } +
+
+ } +} + +
+
+ Areas of practice +

@Model.Title

+
+
+ +
+
+
+
+
+ Summary +
+
+ @Model.Summary +
+
+ + @if (!string.IsNullOrEmpty(Model.OtherNames)) + { +
+
+ Other names +
+
+ @Model.OtherNames +
+
+ } +
+ +
+ + @if (Model.WhatYoullDo != null) + { + await RenderAccordianSection("What you'll do", Model.WhatYoullDo, 1); + } + + @if (Model.SkillsAndKnowledge != null) + { + await RenderAccordianSection("Skills and knowledge", Model.SkillsAndKnowledge, 2); + } + + @if (Model.WhoYouWillWorkWith != null) + { + await RenderAccordianSection("Who you'll work with", Model.WhoYouWillWorkWith, 3); + } + + @if (Model.HowYouWillWork != null) + { + await RenderAccordianSection("How you'll work", Model.HowYouWillWork, 4); + } + + @if (Model.CurrentOpportunities != null) + { + await RenderAccordianSection("Current opportunities", Model.CurrentOpportunities, 5); + } +
+
+
\ No newline at end of file diff --git a/Childrens-Social-Care-CPD/Views/Shared/_AreaOfPracticeList.cshtml b/Childrens-Social-Care-CPD/Views/Shared/_AreaOfPracticeList.cshtml new file mode 100644 index 00000000..938270df --- /dev/null +++ b/Childrens-Social-Care-CPD/Views/Shared/_AreaOfPracticeList.cshtml @@ -0,0 +1,12 @@ +@using Childrens_Social_Care_CPD.Contentful.Models; +@using Childrens_Social_Care_CPD.Contentful; +@using Childrens_Social_Care_CPD.Contentful.Renderers; + +@model AreaOfPracticeList +@inject IRenderer _inlineAreaOfPracticeListRenderer + +
+
+ @_inlineAreaOfPracticeListRenderer.Render(Model) +
+
diff --git a/browser-tests/content-regression-tests/tests/explore-area-of-practice/child-protection-and-family-safeguarding.spec.ts b/browser-tests/content-regression-tests/tests/explore-area-of-practice/child-protection-and-family-safeguarding.spec.ts new file mode 100644 index 00000000..cdb7485e --- /dev/null +++ b/browser-tests/content-regression-tests/tests/explore-area-of-practice/child-protection-and-family-safeguarding.spec.ts @@ -0,0 +1,71 @@ +import { test, expect } from '@playwright/test' + +test.describe('Child Protection & Family Safeguarding', () => { + test('User journey via Explore menu @journey', async ({ page }) => { + await page.goto('/') + await page.getByLabel('Menu').getByRole('link', { name: 'Explore roles', exact: true }).click() + await page.getByRole('link', { name: 'Explore areas of practice', exact: true }).click() + await page.getByRole('link', { name: 'Child Protection & Family Safeguarding', exact: true }).click() + + await expect(page.locator('h1', { hasText: /^Child Protection & Family Safeguarding$/ })).toBeVisible() + await expect(page).toHaveURL(/.*\/explore-areas-of-practice\/child-protection-and-safegaurding/) + await expect(page.locator('#mmi-exploreRoles')).toHaveClass(/dfe-header__navigation-item--current/) + }) + + test.describe('Accordian @accordian', () => { + test('All sections are collapsed when you arrive on page' , async ({ page }) => { + await page.goto('/explore-areas-of-practice/child-protection-and-safegaurding') + await expect(page.getByLabel('What you\'ll do , Show this section')).toHaveAttribute('aria-expanded', 'false') + await expect(page.getByLabel('Skills and knowledge , Show this section')).toHaveAttribute('aria-expanded', 'false') + await expect(page.getByLabel('Who you\'ll work with , Show this section')).toHaveAttribute('aria-expanded', 'false') + await expect(page.getByLabel('How you\'ll work , Show this section')).toHaveAttribute('aria-expanded', 'false') + await expect(page.getByLabel('Current opportunities , Show this section')).toHaveAttribute('aria-expanded', 'false') + }) + + test('Clicking show all sections expand all sections' , async ({ page }) => { + await page.goto('/explore-areas-of-practice/child-protection-and-safegaurding') + await page.getByRole('button', { name: 'Show all sections' }).click() + + await expect(page.getByLabel('What you\'ll do , Hide this section')).toHaveAttribute('aria-expanded', 'true') + await expect(page.getByLabel('Skills and knowledge , Hide this section')).toHaveAttribute('aria-expanded', 'true') + await expect(page.getByLabel('Who you\'ll work with , Hide this section')).toHaveAttribute('aria-expanded', 'true') + await expect(page.getByLabel('How you\'ll work , Hide this section')).toHaveAttribute('aria-expanded', 'true') + await expect(page.getByLabel('Current opportunities , Hide this section')).toHaveAttribute('aria-expanded', 'true') + }) + + test('Clicking show all sections, then hide all sections collapses all sections' , async ({ page }) => { + await page.goto('/explore-areas-of-practice/child-protection-and-safegaurding') + await page.getByRole('button', { name: 'Show all sections' }).click() + await page.getByRole('button', { name: 'Hide all sections' }).click() + + await expect(page.getByLabel('What you\'ll do , Show this section')).toHaveAttribute('aria-expanded', 'false') + await expect(page.getByLabel('Skills and knowledge , Show this section')).toHaveAttribute('aria-expanded', 'false') + await expect(page.getByLabel('Who you\'ll work with , Show this section')).toHaveAttribute('aria-expanded', 'false') + await expect(page.getByLabel('How you\'ll work , Show this section')).toHaveAttribute('aria-expanded', 'false') + await expect(page.getByLabel('Current opportunities , Show this section')).toHaveAttribute('aria-expanded', 'false') + }) + + test.describe('Sections', () => { + const links = [ + ['What you\'ll do , Show this section', 'What you\'ll do , Hide this section'], + ['Skills and knowledge , Show this section', 'Skills and knowledge , Hide this section'], + ['Who you\'ll work with , Show this section', 'Who you\'ll work with , Hide this section'], + ['How you\'ll work , Show this section', 'How you\'ll work , Hide this section'], + ['Current opportunities , Show this section', 'Current opportunities , Hide this section'], + ] + + for (const link of links) { + test(`Expanding/Collapsing the '${link[0]}'`, async ({ page }) => { + await page.goto('/explore-areas-of-practice/child-protection-and-safegaurding') + await page.getByLabel(link[0]).click() + + await expect(page.getByLabel(link[1])).toHaveAttribute('aria-expanded', 'true') + + await page.getByLabel(link[1]).click() + + await expect(page.getByLabel(link[0])).toHaveAttribute('aria-expanded', 'false') + }) + } + }) + }) +}) \ No newline at end of file