diff --git a/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs b/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs index 25f815d688..5cc95984d0 100644 --- a/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs +++ b/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs @@ -139,7 +139,10 @@ export class Accordion extends GOVUKFrontendComponent { const $sections = this.$module.querySelectorAll(`.${this.sectionClass}`) if (!$sections.length) { - return this + throw new ElementError({ + componentName: 'Accordion', + identifier: `Sections (\`
\`)` + }) } this.$sections = $sections @@ -203,7 +206,10 @@ export class Accordion extends GOVUKFrontendComponent { this.$sections.forEach(($section, i) => { const $header = $section.querySelector(`.${this.sectionHeaderClass}`) if (!$header) { - return + throw new ElementError({ + componentName: 'Accordion', + identifier: `Section headers (\`
\`)` + }) } // Set header attributes @@ -231,8 +237,18 @@ export class Accordion extends GOVUKFrontendComponent { const $heading = $header.querySelector(`.${this.sectionHeadingClass}`) const $summary = $header.querySelector(`.${this.sectionSummaryClass}`) - if (!$span || !$heading) { - return + if (!$heading) { + throw new ElementError({ + componentName: 'Accordion', + identifier: `Section heading (\`.${this.sectionHeadingClass}\`)` + }) + } + + if (!$span) { + throw new ElementError({ + componentName: 'Accordion', + identifier: `Section button placeholder (\`\`)` + }) } // Create a button element that will replace the @@ -395,7 +411,15 @@ export class Accordion extends GOVUKFrontendComponent { const $button = $section.querySelector(`.${this.sectionButtonClass}`) const $content = $section.querySelector(`.${this.sectionContentClass}`) - if (!$showHideIcon || !$showHideText || !$button || !$content) { + if (!$content) { + throw new ElementError({ + componentName: 'Accordion', + identifier: `Section content (\`
\`)` + }) + } + + if (!$showHideIcon || !$showHideText || !$button) { + // Return early for elements we create return } 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 1a1eff4ca1..1624365d3b 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 @@ -711,59 +711,158 @@ 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( + render(page, 'accordion', examples.default, { + beforeInitialisation() { + document.body.classList.remove('govuk-frontend-supported') + } + }) + ).rejects.toMatchObject({ + cause: { + name: 'SupportError', + message: 'GOV.UK Frontend is not supported in this browser' + } }) + }) - it('throws when GOV.UK Frontend is not supported', async () => { - await expect( - render(page, 'accordion', examples.default, { - beforeInitialisation() { - document.body.classList.remove('govuk-frontend-supported') - } - }) - ).rejects.toMatchObject({ - cause: { - name: 'SupportError', - message: 'GOV.UK Frontend is not supported in this browser' + it('throws when $module is not set', async () => { + await expect( + render(page, 'accordion', examples.default, { + beforeInitialisation($module) { + $module.remove() } }) + ).rejects.toMatchObject({ + cause: { + name: 'ElementError', + message: 'Accordion: Root element (`$module`) not found' + } }) + }) - it('throws when $module is not set', async () => { - await expect( - render(page, 'accordion', examples.default, { - beforeInitialisation($module) { - $module.remove() - } - }) - ).rejects.toMatchObject({ - cause: { - name: 'ElementError', - message: 'Accordion: Root element (`$module`) not found' + it('throws when receiving the wrong type for $module', async () => { + await expect( + render(page, 'accordion', examples.default, { + beforeInitialisation($module) { + // Replace with an `` element which is not an `HTMLElement` in the DOM (but an `SVGElement`) + $module.outerHTML = `` } }) + ).rejects.toMatchObject({ + cause: { + name: 'ElementError', + message: + 'Accordion: Root element (`$module`) is not of type HTMLElement' + } }) + }) - it('throws when receiving the wrong type for $module', async () => { - await expect( - render(page, 'accordion', examples.default, { - beforeInitialisation($module) { - // Replace with an `` element which is not an `HTMLElement` in the DOM (but an `SVGElement`) - $module.outerHTML = `` - } - }) - ).rejects.toMatchObject({ - cause: { - name: 'ElementError', - message: - 'Accordion: Root element (`$module`) is not of type HTMLElement' + it('throws when the accordion sections are missing', async () => { + await expect( + render(page, 'accordion', examples.default, { + beforeInitialisation($module, { selector }) { + $module + .querySelectorAll(selector) + .forEach((item) => item.remove()) + }, + context: { + selector: '.govuk-accordion__section' + } + }) + ).rejects.toMatchObject({ + cause: { + name: 'ElementError', + message: + 'Accordion: Sections (`
`) not found' + } + }) + }) + + it('throws when section header is missing', async () => { + await expect( + render(page, 'accordion', examples.default, { + beforeInitialisation($module, { selector }) { + $module + .querySelectorAll(selector) + .forEach((item) => item.remove()) + }, + context: { + selector: '.govuk-accordion__section-header' + } + }) + ).rejects.toMatchObject({ + cause: { + name: 'ElementError', + message: + 'Accordion: Section headers (`
`) not found' + } + }) + }) + + it('throws when any section heading is missing', async () => { + await expect( + render(page, 'accordion', examples.default, { + beforeInitialisation($module, { selector }) { + $module.querySelector(selector).remove() + }, + context: { + selector: '.govuk-accordion__section-heading' + } + }) + ).rejects.toMatchObject({ + cause: { + name: 'ElementError', + message: + 'Accordion: Section heading (`.govuk-accordion__section-heading`) not found' + } + }) + }) + + it('throws when any section button placeholder span is missing', async () => { + await expect( + render(page, 'accordion', examples.default, { + beforeInitialisation($module, { selector }) { + $module.querySelector(selector).remove() + }, + context: { + selector: '.govuk-accordion__section-button' + } + }) + ).rejects.toMatchObject({ + cause: { + name: 'ElementError', + message: + 'Accordion: Section button placeholder (``) not found' + } + }) + }) + + it('throws when any section content is missing', async () => { + await expect( + render(page, 'accordion', examples.default, { + beforeInitialisation($module, { selector }) { + $module.querySelector(selector).remove() + }, + context: { + selector: '.govuk-accordion__section-content' } }) + ).rejects.toMatchObject({ + cause: { + name: 'ElementError', + message: + 'Accordion: Section content (`
`) not found' + } }) }) })