From 7bb2dc79810425999083a1704c62aab433191c02 Mon Sep 17 00:00:00 2001 From: Brett Kyle Date: Wed, 4 Oct 2023 16:00:00 +0100 Subject: [PATCH] Split section errors Actually ends up being a similar amount of code as before, but easier to parse. And separates the Things Wot Throw from the Things Wot We Ignore. Also noticed we'd popped our error tests within the i18n `describe`, so pulled them out into their own block. And finally, tried to edit all error messages so that they match what we're aiming for with our content review. --- .../govuk/components/accordion/accordion.mjs | 37 ++- .../accordion/accordion.puppeteer.test.js | 236 +++++++++--------- 2 files changed, 142 insertions(+), 131 deletions(-) diff --git a/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs b/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs index 8e1122f3a3..c8f1b3880e 100644 --- a/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs +++ b/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs @@ -122,7 +122,7 @@ export class Accordion extends GOVUKFrontendComponent { if (!($module instanceof HTMLElement)) { throw new ElementError($module, { componentName: 'Accordion', - identifier: '$module' + identifier: 'Root element (`[data-module=govuk-accordion]`)' }) } @@ -140,7 +140,7 @@ export class Accordion extends GOVUKFrontendComponent { if (!$sections.length) { throw new ElementError(null, { componentName: 'Accordion', - identifier: `.${this.sectionClass}` + identifier: `Element (\`.${this.sectionClass}\`)` }) } @@ -207,7 +207,7 @@ export class Accordion extends GOVUKFrontendComponent { if (!$header) { throw new ElementError(null, { componentName: 'Accordion', - identifier: `.${this.sectionHeaderClass}` + identifier: `Element (\`.${this.sectionHeaderClass}\`)` }) } @@ -239,14 +239,14 @@ export class Accordion extends GOVUKFrontendComponent { if (!$heading) { throw new ElementError(null, { componentName: 'Accordion', - identifier: `.${this.sectionHeadingClass}` + identifier: `Heading element (\`.${this.sectionHeadingClass}\`)` }) } if (!$span) { throw new ElementError(null, { componentName: 'Accordion', - identifier: `.${this.sectionButtonClass}` + identifier: `Span element (\`.${this.sectionButtonClass}\`)` }) } @@ -411,26 +411,25 @@ export class Accordion extends GOVUKFrontendComponent { const $button = $section.querySelector(`.${this.sectionButtonClass}`) const $content = $section.querySelector(`.${this.sectionContentClass}`) - // Return early for elements created during set up - if (!$showHideIcon || !$showHideText) { - return + if (!$button) { + throw new ElementError(null, { + componentName: 'Accordion', + identifier: `Span element (\`.${this.sectionButtonClass}\`)` + }) } - if (!$button || !$content) { - const [check] = /** @type {const} */ ([ - [$button, this.sectionButtonClass], - [$content, this.sectionContentClass] - ]) - // Filter the list by which checks failed - .filter(([$element]) => !($element instanceof HTMLElement)) - - throw new ElementError(check[0], { + if (!$content) { + throw new ElementError(null, { componentName: 'Accordion', - identifier: `.${check[1]}`, - expectedType: 'HTMLElement' + identifier: `Element (\`.${this.sectionContentClass}\`)` }) } + if (!$showHideIcon || !$showHideText) { + // Return early for elements we create + return + } + const newButtonText = expanded ? this.i18n.t('hideSection') : this.i18n.t('showSection') diff --git a/packages/govuk-frontend/src/govuk/components/accordion/accordion.puppeteer.test.js b/packages/govuk-frontend/src/govuk/components/accordion/accordion.puppeteer.test.js index 506806bd36..ebc841e957 100644 --- a/packages/govuk-frontend/src/govuk/components/accordion/accordion.puppeteer.test.js +++ b/packages/govuk-frontend/src/govuk/components/accordion/accordion.puppeteer.test.js @@ -712,148 +712,160 @@ describe('/components/accordion', () => { ) }) }) + }) - describe('errors at instantiation', () => { - let examples + describe('errors at instantiation', () => { + let examples - beforeAll(async () => { - examples = await getExamples('accordion') + beforeAll(async () => { + examples = await getExamples('accordion') + }) + + it('throws when GOV.UK Frontend is not supported', async () => { + await expect( + renderAndInitialise(page, 'accordion', { + params: examples.default, + beforeInitialisation() { + document.body.classList.remove('govuk-frontend-supported') + } + }) + ).rejects.toEqual({ + name: 'SupportError', + message: 'GOV.UK Frontend is not supported in this browser' }) + }) - it('throws when GOV.UK Frontend is not supported', async () => { - await expect( - renderAndInitialise(page, 'accordion', { - params: examples.default, - beforeInitialisation() { - document.body.classList.remove('govuk-frontend-supported') - } - }) - ).rejects.toEqual({ - name: 'SupportError', - message: 'GOV.UK Frontend is not supported in this browser' + it('throws when $module is not set', async () => { + await expect( + renderAndInitialise(page, 'accordion', { + params: examples.default, + beforeInitialisation($module) { + $module.remove() + } }) + ).rejects.toEqual({ + name: 'ElementError', + message: + 'Accordion: Root element (`[data-module=govuk-accordion]`) not found' }) + }) - it('throws when $module is not set', async () => { - await expect( - renderAndInitialise(page, 'accordion', { - params: examples.default, - beforeInitialisation($module) { - $module.remove() - } - }) - ).rejects.toEqual({ - name: 'ElementError', - message: 'Accordion: $module not found' + it('throws when receiving the wrong type for $module', async () => { + await expect( + renderAndInitialise(page, 'accordion', { + params: examples.default, + beforeInitialisation($module) { + // Replace with an `` element which is not an `HTMLElement` in the DOM (but an `SVGElement`) + $module.outerHTML = `` + } }) + ).rejects.toEqual({ + name: 'ElementError', + message: + 'Accordion: Root element (`[data-module=govuk-accordion]`) is not an instance of HTMLElement' }) + }) - it('throws when receiving the wrong type for $module', async () => { - await expect( - renderAndInitialise(page, 'accordion', { - params: examples.default, - beforeInitialisation($module) { - // Replace with an `` element which is not an `HTMLElement` in the DOM (but an `SVGElement`) - $module.outerHTML = `` - } - }) - ).rejects.toEqual({ - name: 'ElementError', - message: 'Accordion: $module is not an instance of HTMLElement' + it('throws when the accordion sections are missing', async () => { + await expect( + renderAndInitialise(page, 'accordion', { + params: examples.default, + beforeInitialisation($module) { + $module + .querySelectorAll('.govuk-accordion__section') + .forEach((item) => { + item.remove() + }) + } }) + ).rejects.toEqual({ + name: 'ElementError', + message: + 'Accordion: Element (`.govuk-accordion__section`) not found' }) + }) - it('throws when the accordion sections are missing', async () => { - await expect( - renderAndInitialise(page, 'accordion', { - params: examples.default, - beforeInitialisation($module) { - $module - .querySelectorAll('.govuk-accordion__section') - .forEach((item) => { - item.remove() - }) - } - }) - ).rejects.toEqual({ - name: 'ElementError', - message: 'Accordion: .govuk-accordion__section not found' + it('throws when any section header is missing', async () => { + await expect( + renderAndInitialise(page, 'accordion', { + params: examples.default, + beforeInitialisation($module) { + $module + .querySelector('.govuk-accordion__section-header') + .remove() + } }) + ).rejects.toEqual({ + name: 'ElementError', + message: + 'Accordion: Element (`.govuk-accordion__section-header`) not found' }) + }) - it('throws when any section header is missing', async () => { - await expect( - renderAndInitialise(page, 'accordion', { - params: examples.default, - beforeInitialisation($module) { - $module - .querySelector('.govuk-accordion__section-header') - .remove() - } - }) - ).rejects.toEqual({ - name: 'ElementError', - message: 'Accordion: .govuk-accordion__section-header not found' + it('throws when any section button span is missing', async () => { + await expect( + renderAndInitialise(page, 'accordion', { + params: examples.default, + beforeInitialisation($module) { + $module + .querySelector('.govuk-accordion__section-button') + .remove() + } }) + ).rejects.toEqual({ + name: 'ElementError', + message: + 'Accordion: Span element (`.govuk-accordion__section-button`) not found' }) + }) - it('throws when any section button span is missing', async () => { - await expect( - renderAndInitialise(page, 'accordion', { - params: examples.default, - beforeInitialisation($module) { - $module - .querySelector('.govuk-accordion__section-button') - .remove() - } - }) - ).rejects.toEqual({ - name: 'ElementError', - message: 'Accordion: .govuk-accordion__section-button not found' + it('throws when any section heading is missing', async () => { + await expect( + renderAndInitialise(page, 'accordion', { + params: examples.default, + beforeInitialisation($module) { + $module + .querySelector('.govuk-accordion__section-heading') + .remove() + } }) + ).rejects.toEqual({ + name: 'ElementError', + message: + 'Accordion: Heading element (`.govuk-accordion__section-heading`) not found' }) + }) - it('throws when any section heading is missing', async () => { + const sectionElements = [ + { + elementName: 'Span element', + selector: '.govuk-accordion__section-button' + }, + { + elementName: 'Element', + selector: '.govuk-accordion__section-content' + } + ] + + it.each(sectionElements)( + 'throws when any section button or section content element is missing', + async ({ elementName, selector }) => { await expect( renderAndInitialise(page, 'accordion', { params: examples.default, - beforeInitialisation($module) { - $module - .querySelector('.govuk-accordion__section-heading') - .remove() + beforeInitialisation($module, { selector }) { + $module.querySelector(selector).remove() + }, + beforeInitialisationOptions: { + selector } }) ).rejects.toEqual({ name: 'ElementError', - message: 'Accordion: .govuk-accordion__section-heading not found' + message: `Accordion: ${elementName} (\`${selector}\`) not found` }) - }) - - const toggleButtonElements = [ - '.govuk-accordion__section-button', - '.govuk-accordion__section-content' - ] - - it.each(toggleButtonElements)( - 'throws when any section toggle button-related element is missing', - async (selector) => { - await expect( - renderAndInitialise(page, 'accordion', { - params: examples.default, - beforeInitialisation($module, { selector }) { - $module.querySelector(selector).remove() - }, - beforeInitialisationOptions: { - selector - } - }) - ).rejects.toEqual({ - name: 'ElementError', - message: `Accordion: ${selector} not found` - }) - } - ) - }) + } + ) }) }) })