From d2b7cb294cda92a4ecb09e930fdb7bbc5f4b42e7 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Tue, 12 Dec 2023 15:43:33 +0000 Subject: [PATCH 1/3] Add `InitError` to throw for components already initialised --- .../src/govuk/errors/index.jsdom.test.mjs | 40 ++++++++++++++++++- .../govuk-frontend/src/govuk/errors/index.mjs | 22 ++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/packages/govuk-frontend/src/govuk/errors/index.jsdom.test.mjs b/packages/govuk-frontend/src/govuk/errors/index.jsdom.test.mjs index 516bf1af91..401d8bde66 100644 --- a/packages/govuk-frontend/src/govuk/errors/index.jsdom.test.mjs +++ b/packages/govuk-frontend/src/govuk/errors/index.jsdom.test.mjs @@ -1,4 +1,9 @@ -import { ElementError, GOVUKFrontendError, SupportError } from './index.mjs' +import { + ElementError, + GOVUKFrontendError, + InitError, + SupportError +} from './index.mjs' describe('errors', () => { describe('GOVUKFrontendError', () => { @@ -47,6 +52,39 @@ describe('errors', () => { }) }) + describe('InitError', () => { + let $element + let $moduleName + + beforeAll(() => { + $element = document.createElement('div') + $element.setAttribute('data-module', 'govuk-accordion') + $moduleName = 'govuk-accordion' + }) + + it('is an instance of GOVUKFrontendError', () => { + expect(new InitError($moduleName)).toBeInstanceOf(GOVUKFrontendError) + }) + + it('has its own name set', () => { + expect(new InitError($moduleName).name).toBe('InitError') + }) + + it('provides feedback for modules already initialised', () => { + expect(new InitError($moduleName).message).toBe( + 'Root element (`$module`) already initialised (`govuk-accordion`)' + ) + }) + + it('provides feedback for modules already initialised', () => { + $moduleName = undefined + + expect(new InitError($moduleName, 'Accordion').message).toBe( + 'moduleName not defined in component (`Accordion`)' + ) + }) + }) + describe('ElementError', () => { it('is an instance of GOVUKFrontendError', () => { expect( diff --git a/packages/govuk-frontend/src/govuk/errors/index.mjs b/packages/govuk-frontend/src/govuk/errors/index.mjs index 6e079d23b4..aa599ba836 100644 --- a/packages/govuk-frontend/src/govuk/errors/index.mjs +++ b/packages/govuk-frontend/src/govuk/errors/index.mjs @@ -97,6 +97,28 @@ export class ElementError extends GOVUKFrontendError { } } +/** + * Indicates that a component is already initialised + */ +export class InitError extends GOVUKFrontendError { + name = 'InitError' + + /** + * @internal + * @param {string|undefined} moduleName - name of the component module + * @param {string} [className] - name of the component module + */ + constructor(moduleName, className) { + let errorText = `moduleName not defined in component (\`${className}\`)` + + if (typeof moduleName === 'string') { + errorText = `Root element (\`$module\`) already initialised (\`${moduleName}\`)` + } + + super(errorText) + } +} + /** * Element error options * From 89eca3c9b0d39b132687563e0ea583e2eeaada8a Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Mon, 8 Jan 2024 17:46:06 +0000 Subject: [PATCH 2/3] Throw `InitError` when components are already initialised --- .../govuk-frontend/src/govuk/common/index.mjs | 15 +++++++ .../govuk/components/accordion/accordion.mjs | 2 +- .../src/govuk/components/button/button.mjs | 2 +- .../character-count/character-count.mjs | 2 +- .../components/checkboxes/checkboxes.mjs | 2 +- .../error-summary/error-summary.mjs | 2 +- .../exit-this-page/exit-this-page.mjs | 2 +- .../src/govuk/components/header/header.mjs | 2 +- .../notification-banner.mjs | 2 +- .../src/govuk/components/radios/radios.mjs | 2 +- .../govuk/components/skip-link/skip-link.mjs | 2 +- .../src/govuk/components/tabs/tabs.mjs | 2 +- .../src/govuk/govuk-frontend-component.mjs | 42 +++++++++++++++++-- 13 files changed, 65 insertions(+), 14 deletions(-) diff --git a/packages/govuk-frontend/src/govuk/common/index.mjs b/packages/govuk-frontend/src/govuk/common/index.mjs index 60699f4088..68b2f9b2c7 100644 --- a/packages/govuk-frontend/src/govuk/common/index.mjs +++ b/packages/govuk-frontend/src/govuk/common/index.mjs @@ -188,6 +188,21 @@ export function setFocus($element, options = {}) { $element.focus() } +/** + * Checks if component is already initialised + * + * @internal + * @param {Element} $module - HTML element to be checked + * @param {string} moduleName - name of component module + * @returns {boolean} Whether component is already initialised + */ +export function isInitialised($module, moduleName) { + return ( + $module instanceof HTMLElement && + $module.hasAttribute(`data-${moduleName}-init`) + ) +} + /** * Checks if GOV.UK Frontend is supported on this page * diff --git a/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs b/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs index d18d179f24..01bef59de7 100644 --- a/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs +++ b/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs @@ -114,7 +114,7 @@ export class Accordion extends GOVUKFrontendComponent { * @param {AccordionConfig} [config] - Accordion config */ constructor($module, config = {}) { - super() + super($module) if (!($module instanceof HTMLElement)) { throw new ElementError({ diff --git a/packages/govuk-frontend/src/govuk/components/button/button.mjs b/packages/govuk-frontend/src/govuk/components/button/button.mjs index 7dde40b11e..a0b5fee192 100644 --- a/packages/govuk-frontend/src/govuk/components/button/button.mjs +++ b/packages/govuk-frontend/src/govuk/components/button/button.mjs @@ -31,7 +31,7 @@ export class Button extends GOVUKFrontendComponent { * @param {ButtonConfig} [config] - Button config */ constructor($module, config = {}) { - super() + super($module) if (!($module instanceof HTMLElement)) { throw new ElementError({ diff --git a/packages/govuk-frontend/src/govuk/components/character-count/character-count.mjs b/packages/govuk-frontend/src/govuk/components/character-count/character-count.mjs index 6c434b4dcf..cbd8e9351b 100644 --- a/packages/govuk-frontend/src/govuk/components/character-count/character-count.mjs +++ b/packages/govuk-frontend/src/govuk/components/character-count/character-count.mjs @@ -62,7 +62,7 @@ export class CharacterCount extends GOVUKFrontendComponent { * @param {CharacterCountConfig} [config] - Character count config */ constructor($module, config = {}) { - super() + super($module) if (!($module instanceof HTMLElement)) { throw new ElementError({ diff --git a/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.mjs b/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.mjs index 1cb074c58e..8314ae217d 100644 --- a/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.mjs +++ b/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.mjs @@ -28,7 +28,7 @@ export class Checkboxes extends GOVUKFrontendComponent { * @param {Element | null} $module - HTML element to use for checkboxes */ constructor($module) { - super() + super($module) if (!($module instanceof HTMLElement)) { throw new ElementError({ diff --git a/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.mjs b/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.mjs index 51a8b4144f..9707a53af4 100644 --- a/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.mjs +++ b/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.mjs @@ -30,7 +30,7 @@ export class ErrorSummary extends GOVUKFrontendComponent { * @param {ErrorSummaryConfig} [config] - Error summary config */ constructor($module, config = {}) { - super() + super($module) if (!($module instanceof HTMLElement)) { throw new ElementError({ diff --git a/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.mjs b/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.mjs index a9983bf60a..d7a9c1cc2c 100644 --- a/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.mjs +++ b/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.mjs @@ -79,7 +79,7 @@ export class ExitThisPage extends GOVUKFrontendComponent { * @param {ExitThisPageConfig} [config] - Exit This Page config */ constructor($module, config = {}) { - super() + super($module) if (!($module instanceof HTMLElement)) { throw new ElementError({ diff --git a/packages/govuk-frontend/src/govuk/components/header/header.mjs b/packages/govuk-frontend/src/govuk/components/header/header.mjs index 0e03a309b4..1fee86c8a1 100644 --- a/packages/govuk-frontend/src/govuk/components/header/header.mjs +++ b/packages/govuk-frontend/src/govuk/components/header/header.mjs @@ -43,7 +43,7 @@ export class Header extends GOVUKFrontendComponent { * @param {Element | null} $module - HTML element to use for header */ constructor($module) { - super() + super($module) if (!$module) { throw new ElementError({ diff --git a/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.mjs b/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.mjs index 089fd0438b..133031332f 100644 --- a/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.mjs +++ b/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.mjs @@ -23,7 +23,7 @@ export class NotificationBanner extends GOVUKFrontendComponent { * @param {NotificationBannerConfig} [config] - Notification banner config */ constructor($module, config = {}) { - super() + super($module) if (!($module instanceof HTMLElement)) { throw new ElementError({ diff --git a/packages/govuk-frontend/src/govuk/components/radios/radios.mjs b/packages/govuk-frontend/src/govuk/components/radios/radios.mjs index 675d555754..336430f168 100644 --- a/packages/govuk-frontend/src/govuk/components/radios/radios.mjs +++ b/packages/govuk-frontend/src/govuk/components/radios/radios.mjs @@ -28,7 +28,7 @@ export class Radios extends GOVUKFrontendComponent { * @param {Element | null} $module - HTML element to use for radios */ constructor($module) { - super() + super($module) if (!($module instanceof HTMLElement)) { throw new ElementError({ diff --git a/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.mjs b/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.mjs index ea34d387be..2b6d276f57 100644 --- a/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.mjs +++ b/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.mjs @@ -18,7 +18,7 @@ export class SkipLink extends GOVUKFrontendComponent { * @throws {ElementError} when the linked element is missing or the wrong type */ constructor($module) { - super() + super($module) if (!($module instanceof HTMLAnchorElement)) { throw new ElementError({ diff --git a/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs b/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs index d5af038949..4effe5b769 100644 --- a/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs +++ b/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs @@ -45,7 +45,7 @@ export class Tabs extends GOVUKFrontendComponent { * @param {Element | null} $module - HTML element to use for tabs */ constructor($module) { - super() + super($module) if (!$module) { throw new ElementError({ diff --git a/packages/govuk-frontend/src/govuk/govuk-frontend-component.mjs b/packages/govuk-frontend/src/govuk/govuk-frontend-component.mjs index df99479f31..273d00dbf3 100644 --- a/packages/govuk-frontend/src/govuk/govuk-frontend-component.mjs +++ b/packages/govuk-frontend/src/govuk/govuk-frontend-component.mjs @@ -1,5 +1,5 @@ -import { isSupported } from './common/index.mjs' -import { SupportError } from './errors/index.mjs' +import { isInitialised, isSupported } from './common/index.mjs' +import { InitError, SupportError } from './errors/index.mjs' /** * Base Component class @@ -14,9 +14,36 @@ export class GOVUKFrontendComponent { * Constructs a new component, validating that GOV.UK Frontend is supported * * @internal + * @param {Element | null} [$module] - HTML element to use for component */ - constructor() { + constructor($module) { this.checkSupport() + this.checkInitialised($module) + + const moduleName = /** @type {ChildClassConstructor} */ (this.constructor) + .moduleName + + if (typeof moduleName === 'string') { + moduleName && $module?.setAttribute(`data-${moduleName}-init`, '') + } else { + throw new InitError(moduleName) + } + } + + /** + * Validates whether component is already initialised + * + * @private + * @param {Element | null} [$module] - HTML element to be checked + * @throws {InitError} when component is already initialised + */ + checkInitialised($module) { + const moduleName = /** @type {ChildClassConstructor} */ (this.constructor) + .moduleName + + if ($module && moduleName && isInitialised($module, moduleName)) { + throw new InitError(moduleName) + } } /** @@ -31,3 +58,12 @@ export class GOVUKFrontendComponent { } } } + +/** + * @typedef ChildClass + * @property {string} [moduleName] - The module name that'll be looked for in the DOM when initialising the component + */ + +/** + * @typedef {typeof GOVUKFrontendComponent & ChildClass} ChildClassConstructor + */ From 49f01851a490a079d6a93cf5cc88e57f4caec4d4 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Tue, 12 Dec 2023 15:47:35 +0000 Subject: [PATCH 3/3] Add tests for initialising components twice --- .../accordion/accordion.puppeteer.test.js | 17 +++++++++++++++++ .../components/button/button.puppeteer.test.js | 17 +++++++++++++++++ .../character-count.puppeteer.test.js | 17 +++++++++++++++++ .../checkboxes/checkboxes.puppeteer.test.js | 17 +++++++++++++++++ .../error-summary.puppeteer.test.js | 17 +++++++++++++++++ .../exit-this-page.puppeteer.test.js | 17 +++++++++++++++++ .../components/header/header.puppeteer.test.js | 17 +++++++++++++++++ .../notification-banner.puppeteer.test.js | 17 +++++++++++++++++ .../components/radios/radios.puppeteer.test.js | 16 ++++++++++++++++ .../skip-link/skip-link.puppeteer.test.js | 17 +++++++++++++++++ .../components/tabs/tabs.puppeteer.test.js | 16 ++++++++++++++++ 11 files changed, 185 insertions(+) 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 d823c5dc09..0a866e2016 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 @@ -1,3 +1,5 @@ +/* eslint-disable no-new */ + const { goToExample, render, @@ -712,6 +714,21 @@ describe('/components/accordion', () => { }) }) + it('throws when initialised twice', async () => { + await expect( + render(page, 'accordion', examples.default, { + async afterInitialisation($module) { + const { Accordion } = await import('govuk-frontend') + new Accordion($module) + } + }) + ).rejects.toMatchObject({ + name: 'InitError', + message: + 'Root element (`$module`) already initialised (`govuk-accordion`)' + }) + }) + it('throws when $module is not set', async () => { await expect( render(page, 'accordion', examples.default, { diff --git a/packages/govuk-frontend/src/govuk/components/button/button.puppeteer.test.js b/packages/govuk-frontend/src/govuk/components/button/button.puppeteer.test.js index e6b3bf6590..dda57595a9 100644 --- a/packages/govuk-frontend/src/govuk/components/button/button.puppeteer.test.js +++ b/packages/govuk-frontend/src/govuk/components/button/button.puppeteer.test.js @@ -1,3 +1,5 @@ +/* eslint-disable no-new */ + const { render } = require('@govuk-frontend/helpers/puppeteer') const { getExamples } = require('@govuk-frontend/lib/components') @@ -329,6 +331,21 @@ describe('/components/button', () => { }) }) + it('throws when initialised twice', async () => { + await expect( + render(page, 'button', examples.default, { + async afterInitialisation($module) { + const { Button } = await import('govuk-frontend') + new Button($module) + } + }) + ).rejects.toMatchObject({ + name: 'InitError', + message: + 'Root element (`$module`) already initialised (`govuk-button`)' + }) + }) + it('throws when $module is not set', async () => { await expect( render(page, 'button', examples.default, { diff --git a/packages/govuk-frontend/src/govuk/components/character-count/character-count.puppeteer.test.js b/packages/govuk-frontend/src/govuk/components/character-count/character-count.puppeteer.test.js index f6d2c95102..4f6d7fe76a 100644 --- a/packages/govuk-frontend/src/govuk/components/character-count/character-count.puppeteer.test.js +++ b/packages/govuk-frontend/src/govuk/components/character-count/character-count.puppeteer.test.js @@ -1,3 +1,5 @@ +/* eslint-disable no-new */ + const { setTimeout } = require('timers/promises') const { render } = require('@govuk-frontend/helpers/puppeteer') @@ -812,6 +814,21 @@ describe('Character count', () => { }) }) + it('throws when initialised twice', async () => { + await expect( + render(page, 'character-count', examples.default, { + async afterInitialisation($module) { + const { CharacterCount } = await import('govuk-frontend') + new CharacterCount($module) + } + }) + ).rejects.toMatchObject({ + name: 'InitError', + message: + 'Root element (`$module`) already initialised (`govuk-character-count`)' + }) + }) + it('throws when $module is not set', async () => { await expect( render(page, 'character-count', examples.default, { diff --git a/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.puppeteer.test.js b/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.puppeteer.test.js index fa913c9acf..fedadb067c 100644 --- a/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.puppeteer.test.js +++ b/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.puppeteer.test.js @@ -1,3 +1,5 @@ +/* eslint-disable no-new */ + const { goToExample, getAttribute, @@ -367,6 +369,21 @@ describe('Checkboxes', () => { }) }) + it('throws when initialised twice', async () => { + await expect( + render(page, 'checkboxes', examples.default, { + async afterInitialisation($module) { + const { Checkboxes } = await import('govuk-frontend') + new Checkboxes($module) + } + }) + ).rejects.toMatchObject({ + name: 'InitError', + message: + 'Root element (`$module`) already initialised (`govuk-checkboxes`)' + }) + }) + it('throws when $module is not set', async () => { await expect( render(page, 'checkboxes', examples.default, { diff --git a/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.puppeteer.test.js b/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.puppeteer.test.js index e77a1c1b27..169d992756 100644 --- a/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.puppeteer.test.js +++ b/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.puppeteer.test.js @@ -1,3 +1,5 @@ +/* eslint-disable no-new */ + const { goToExample, render } = require('@govuk-frontend/helpers/puppeteer') const { getExamples } = require('@govuk-frontend/lib/components') @@ -236,6 +238,21 @@ describe('Error Summary', () => { }) }) + it('throws when initialised twice', async () => { + await expect( + render(page, 'error-summary', examples.default, { + async afterInitialisation($module) { + const { ErrorSummary } = await import('govuk-frontend') + new ErrorSummary($module) + } + }) + ).rejects.toMatchObject({ + name: 'InitError', + message: + 'Root element (`$module`) already initialised (`govuk-error-summary`)' + }) + }) + it('throws when $module is not set', async () => { await expect( render(page, 'error-summary', examples.default, { diff --git a/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.puppeteer.test.js b/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.puppeteer.test.js index cdd37cf7c8..452b206428 100644 --- a/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.puppeteer.test.js +++ b/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.puppeteer.test.js @@ -1,3 +1,5 @@ +/* eslint-disable no-new */ + const { setTimeout } = require('timers/promises') const { goToExample, render } = require('@govuk-frontend/helpers/puppeteer') @@ -231,6 +233,21 @@ describe('/components/exit-this-page', () => { }) }) + it('throws when initialised twice', async () => { + await expect( + render(page, 'exit-this-page', examples.default, { + async afterInitialisation($module) { + const { ExitThisPage } = await import('govuk-frontend') + new ExitThisPage($module) + } + }) + ).rejects.toMatchObject({ + name: 'InitError', + message: + 'Root element (`$module`) already initialised (`govuk-exit-this-page`)' + }) + }) + it('throws when $module is not set', async () => { await expect( render(page, 'exit-this-page', examples.default, { diff --git a/packages/govuk-frontend/src/govuk/components/header/header.puppeteer.test.js b/packages/govuk-frontend/src/govuk/components/header/header.puppeteer.test.js index fe7c0e3d55..cab35c7285 100644 --- a/packages/govuk-frontend/src/govuk/components/header/header.puppeteer.test.js +++ b/packages/govuk-frontend/src/govuk/components/header/header.puppeteer.test.js @@ -1,3 +1,5 @@ +/* eslint-disable no-new */ + const { render } = require('@govuk-frontend/helpers/puppeteer') const { getExamples } = require('@govuk-frontend/lib/components') const { KnownDevices } = require('puppeteer') @@ -181,6 +183,21 @@ describe('Header navigation', () => { }) }) + it('throws when initialised twice', async () => { + await expect( + render(page, 'header', examples.default, { + async afterInitialisation($module) { + const { Header } = await import('govuk-frontend') + new Header($module) + } + }) + ).rejects.toMatchObject({ + name: 'InitError', + message: + 'Root element (`$module`) already initialised (`govuk-header`)' + }) + }) + it('throws when $module is not set', async () => { await expect( render(page, 'header', examples.default, { diff --git a/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.puppeteer.test.js b/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.puppeteer.test.js index 344d70ecc1..fd14b1d6bc 100644 --- a/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.puppeteer.test.js +++ b/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.puppeteer.test.js @@ -1,3 +1,5 @@ +/* eslint-disable no-new */ + const { render } = require('@govuk-frontend/helpers/puppeteer') const { getExamples } = require('@govuk-frontend/lib/components') @@ -236,6 +238,21 @@ describe('Notification banner', () => { }) }) + it('throws when initialised twice', async () => { + await expect( + render(page, 'notification-banner', examples.default, { + async afterInitialisation($module) { + const { NotificationBanner } = await import('govuk-frontend') + new NotificationBanner($module) + } + }) + ).rejects.toMatchObject({ + name: 'InitError', + message: + 'Root element (`$module`) already initialised (`govuk-notification-banner`)' + }) + }) + it('throws when $module is not set', async () => { await expect( render(page, 'notification-banner', examples.default, { diff --git a/packages/govuk-frontend/src/govuk/components/radios/radios.puppeteer.test.js b/packages/govuk-frontend/src/govuk/components/radios/radios.puppeteer.test.js index 6a21385981..19894f62c2 100644 --- a/packages/govuk-frontend/src/govuk/components/radios/radios.puppeteer.test.js +++ b/packages/govuk-frontend/src/govuk/components/radios/radios.puppeteer.test.js @@ -1,3 +1,5 @@ +/* eslint-disable no-new */ + const { goToExample, getProperty, @@ -320,6 +322,20 @@ describe('Radios', () => { }) }) + it('throws when initialised twice', async () => { + await expect( + render(page, 'radios', examples.default, { + async afterInitialisation($module) { + const { Radios } = await import('govuk-frontend') + new Radios($module) + } + }) + ).rejects.toMatchObject({ + name: 'InitError', + message: 'Root element (`$module`) already initialised (`govuk-radios`)' + }) + }) + it('throws when $module is not set', async () => { await expect( render(page, 'radios', examples.default, { diff --git a/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.puppeteer.test.js b/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.puppeteer.test.js index 26c30818b7..2f7764025a 100644 --- a/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.puppeteer.test.js +++ b/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.puppeteer.test.js @@ -1,3 +1,5 @@ +/* eslint-disable no-new */ + const { render } = require('@govuk-frontend/helpers/puppeteer') const { getExamples } = require('@govuk-frontend/lib/components') @@ -127,6 +129,21 @@ describe('Skip Link', () => { }) }) + it('throws when initialised twice', async () => { + await expect( + render(page, 'skip-link', examples.default, { + async afterInitialisation($module) { + const { SkipLink } = await import('govuk-frontend') + new SkipLink($module) + } + }) + ).rejects.toMatchObject({ + name: 'InitError', + message: + 'Root element (`$module`) already initialised (`govuk-skip-link`)' + }) + }) + it('throws when $module is not set', async () => { return expect( render(page, 'skip-link', examples.default, { diff --git a/packages/govuk-frontend/src/govuk/components/tabs/tabs.puppeteer.test.js b/packages/govuk-frontend/src/govuk/components/tabs/tabs.puppeteer.test.js index a24982d4a6..6bef0229b5 100644 --- a/packages/govuk-frontend/src/govuk/components/tabs/tabs.puppeteer.test.js +++ b/packages/govuk-frontend/src/govuk/components/tabs/tabs.puppeteer.test.js @@ -1,3 +1,5 @@ +/* eslint-disable no-new */ + const { render } = require('@govuk-frontend/helpers/puppeteer') const { getExamples } = require('@govuk-frontend/lib/components') const { KnownDevices } = require('puppeteer') @@ -269,6 +271,20 @@ describe('/components/tabs', () => { }) }) + it('throws when initialised twice', async () => { + await expect( + render(page, 'tabs', examples.default, { + async afterInitialisation($module) { + const { Tabs } = await import('govuk-frontend') + new Tabs($module) + } + }) + ).rejects.toMatchObject({ + name: 'InitError', + message: 'Root element (`$module`) already initialised (`govuk-tabs`)' + }) + }) + it('throws when $module is not set', async () => { await expect( render(page, 'tabs', examples.default, {