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` - }) - } - ) - }) + } + ) }) }) })