From eabdc8441dfee06712ef0107c5afdef6d5a13c84 Mon Sep 17 00:00:00 2001 From: Romaric Pascal Date: Fri, 18 Aug 2023 13:14:51 +0100 Subject: [PATCH] Implement check for type of `$module` Simply replaces `return this` with explicit `throw` as trying to factor further leads to extra complexity figuring out inheritance and typing, which we can do after v5 is shipped. request-checks: true --- .../govuk/components/accordion/accordion.mjs | 7 +++- .../components/accordion/accordion.test.js | 16 ++++++++ .../src/govuk/components/button/button.mjs | 7 +++- .../govuk/components/button/button.test.js | 37 ++++++++---------- .../character-count/character-count.mjs | 7 +++- .../character-count/character-count.test.js | 16 ++++++++ .../components/checkboxes/checkboxes.mjs | 7 +++- .../components/checkboxes/checkboxes.test.js | 16 ++++++++ .../error-summary/error-summary.mjs | 7 +++- .../error-summary/error-summary.test.js | 39 ++++++++----------- .../exit-this-page/exit-this-page.mjs | 7 +++- .../exit-this-page/exit-this-page.test.js | 16 ++++++++ .../src/govuk/components/header/header.mjs | 7 +++- .../govuk/components/header/header.test.js | 16 ++++++++ .../notification-banner.mjs | 7 +++- .../notification-banner.test.js | 16 ++++++++ .../src/govuk/components/radios/radios.mjs | 7 +++- .../govuk/components/radios/radios.test.js | 16 ++++++++ .../govuk/components/skip-link/skip-link.mjs | 11 +++--- .../components/skip-link/skip-link.test.js | 16 ++++++++ .../src/govuk/components/tabs/tabs.mjs | 7 +++- .../src/govuk/components/tabs/tabs.test.js | 16 ++++++++ .../src/govuk/govuk-frontend-component.mjs | 6 --- 23 files changed, 242 insertions(+), 65 deletions(-) diff --git a/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs b/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs index f4b5ea0f3b..7a012eff1d 100644 --- a/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs +++ b/packages/govuk-frontend/src/govuk/components/accordion/accordion.mjs @@ -18,6 +18,9 @@ import { I18n } from '../../i18n.mjs' * @preserve */ export class Accordion extends GOVUKFrontendComponent { + /** @private */ + $module + /** * @private * @type {AccordionConfig} @@ -116,7 +119,9 @@ export class Accordion extends GOVUKFrontendComponent { super() if (!($module instanceof HTMLElement)) { - return this + throw new TypeError( + 'Expected `$module` to be an instance of `HTMLElement`' + ) } this.$module = $module diff --git a/packages/govuk-frontend/src/govuk/components/accordion/accordion.test.js b/packages/govuk-frontend/src/govuk/components/accordion/accordion.test.js index 99edf6c5d6..65a25f5e49 100644 --- a/packages/govuk-frontend/src/govuk/components/accordion/accordion.test.js +++ b/packages/govuk-frontend/src/govuk/components/accordion/accordion.test.js @@ -733,6 +733,22 @@ describe('/components/accordion', () => { message: 'GOV.UK Frontend is not supported in this browser' }) }) + + it('throws when receiving the wrong type for $module', async () => { + await expect( + renderAndInitialise(page, 'accordion', { + params: examples.default, + beforeInitialisation() { + // Remove the root of the components as a way + // for the constructor to receive the wrong type for `$module` + document.querySelector('[data-module]').remove() + } + }) + ).rejects.toEqual({ + name: 'TypeError', + message: 'Expected `$module` to be an instance of `HTMLElement`' + }) + }) }) }) }) diff --git a/packages/govuk-frontend/src/govuk/components/button/button.mjs b/packages/govuk-frontend/src/govuk/components/button/button.mjs index cfe35eab62..61bb51bd6e 100644 --- a/packages/govuk-frontend/src/govuk/components/button/button.mjs +++ b/packages/govuk-frontend/src/govuk/components/button/button.mjs @@ -11,6 +11,9 @@ const DEBOUNCE_TIMEOUT_IN_SECONDS = 1 * @preserve */ export class Button extends GOVUKFrontendComponent { + /** @private */ + $module + /** * @private * @type {ButtonConfig} @@ -31,7 +34,9 @@ export class Button extends GOVUKFrontendComponent { super() if (!($module instanceof HTMLElement)) { - return this + throw new TypeError( + 'Expected `$module` to be an instance of `HTMLElement`' + ) } this.$module = $module diff --git a/packages/govuk-frontend/src/govuk/components/button/button.test.js b/packages/govuk-frontend/src/govuk/components/button/button.test.js index 5f51025d22..ea7a461492 100644 --- a/packages/govuk-frontend/src/govuk/components/button/button.test.js +++ b/packages/govuk-frontend/src/govuk/components/button/button.test.js @@ -1,5 +1,4 @@ const { - goTo, goToComponent, renderAndInitialise } = require('@govuk-frontend/helpers/puppeteer') @@ -18,26 +17,6 @@ describe('/components/button', () => { examples = await getExamples('button') }) - describe('mis-instantiation', () => { - it('does not prevent further JavaScript from running', async () => { - await goTo(page, '/tests/boilerplate') - - const result = await page.evaluate(async (exportName) => { - const namespace = await import('govuk-frontend') - - // `undefined` simulates the element being missing, - // from an unchecked `document.querySelector` for example - /* eslint-disable-next-line no-new */ - new namespace[exportName](undefined) - - // If our component initialisation breaks, this won't run - return true - }, 'Button') - - expect(result).toBe(true) - }) - }) - describe('/components/button/link', () => { beforeAll(async () => { await goToComponent(page, 'button', { @@ -359,6 +338,22 @@ describe('/components/button', () => { message: 'GOV.UK Frontend is not supported in this browser' }) }) + + it('throws when receiving the wrong type for $module', async () => { + await expect( + renderAndInitialise(page, 'button', { + params: examples.default, + beforeInitialisation() { + // Remove the root of the components as a way + // for the constructor to receive the wrong type for `$module` + document.querySelector('[data-module]').remove() + } + }) + ).rejects.toEqual({ + name: 'TypeError', + message: 'Expected `$module` to be an instance of `HTMLElement`' + }) + }) }) }) }) 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 067cf59291..66f713357c 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 @@ -17,6 +17,9 @@ import { I18n } from '../../i18n.mjs' * @preserve */ export class CharacterCount extends GOVUKFrontendComponent { + /** @private */ + $module + /** @private */ $textarea @@ -67,7 +70,9 @@ export class CharacterCount extends GOVUKFrontendComponent { super() if (!($module instanceof HTMLElement)) { - return this + throw new TypeError( + 'Expected `$module` to be an instance of `HTMLElement`' + ) } const $textarea = $module.querySelector('.govuk-js-character-count') diff --git a/packages/govuk-frontend/src/govuk/components/character-count/character-count.test.js b/packages/govuk-frontend/src/govuk/components/character-count/character-count.test.js index 927ae7dfe4..81ae57ba23 100644 --- a/packages/govuk-frontend/src/govuk/components/character-count/character-count.test.js +++ b/packages/govuk-frontend/src/govuk/components/character-count/character-count.test.js @@ -784,6 +784,22 @@ describe('Character count', () => { message: 'GOV.UK Frontend is not supported in this browser' }) }) + + it('throws when receiving the wrong type for $module', async () => { + await expect( + renderAndInitialise(page, 'character-count', { + params: examples.default, + beforeInitialisation() { + // Remove the root of the components as a way + // for the constructor to receive the wrong type for `$module` + document.querySelector('[data-module]').remove() + } + }) + ).rejects.toEqual({ + name: 'TypeError', + message: 'Expected `$module` to be an instance of `HTMLElement`' + }) + }) }) }) diff --git a/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.mjs b/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.mjs index 8d9d93fffc..f61f079868 100644 --- a/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.mjs +++ b/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.mjs @@ -6,6 +6,9 @@ import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs' * @preserve */ export class Checkboxes extends GOVUKFrontendComponent { + /** @private */ + $module + /** @private */ $inputs @@ -27,7 +30,9 @@ export class Checkboxes extends GOVUKFrontendComponent { super() if (!($module instanceof HTMLElement)) { - return this + throw new TypeError( + 'Expected `$module` to be an instance of `HTMLElement`' + ) } /** @satisfies {NodeListOf} */ diff --git a/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.test.js b/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.test.js index 6876358cd8..c03f6a5468 100644 --- a/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.test.js +++ b/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.test.js @@ -339,6 +339,22 @@ describe('Checkboxes with multiple groups and a "None" checkbox and conditional message: 'GOV.UK Frontend is not supported in this browser' }) }) + + it('throws when receiving the wrong type for $module', async () => { + await expect( + renderAndInitialise(page, 'checkboxes', { + params: examples.default, + beforeInitialisation() { + // Remove the root of the components as a way + // for the constructor to receive the wrong type for `$module` + document.querySelector('[data-module]').remove() + } + }) + ).rejects.toEqual({ + name: 'TypeError', + message: 'Expected `$module` to be an instance of `HTMLElement`' + }) + }) }) }) }) 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 a180bedc20..d6b2d0dd37 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 @@ -10,6 +10,9 @@ import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs' * @preserve */ export class ErrorSummary extends GOVUKFrontendComponent { + /** @private */ + $module + /** * @private * @type {ErrorSummaryConfig} @@ -24,7 +27,9 @@ export class ErrorSummary extends GOVUKFrontendComponent { super() if (!($module instanceof HTMLElement)) { - return this + throw new TypeError( + 'Expected `$module` to be an instance of `HTMLElement`' + ) } this.$module = $module diff --git a/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.test.js b/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.test.js index 96fde8d9ae..05eab1e6a9 100644 --- a/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.test.js +++ b/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.test.js @@ -1,8 +1,7 @@ const { goToComponent, goToExample, - renderAndInitialise, - goTo + renderAndInitialise } = require('@govuk-frontend/helpers/puppeteer') const { getExamples } = require('@govuk-frontend/lib/components') @@ -94,26 +93,6 @@ describe('Error Summary', () => { }) }) - describe('using JavaScript configuration, with no elements on the page', () => { - it('does not prevent further JavaScript from running', async () => { - await goTo(page, '/tests/boilerplate') - - const result = await page.evaluate(async (exportName) => { - const namespace = await import('govuk-frontend') - - // `undefined` simulates the element being missing, - // from an unchecked `document.querySelector` for example - /* eslint-disable-next-line no-new */ - new namespace[exportName](undefined) - - // If our component initialisation breaks, this won't run - return true - }, 'ErrorSummary') - - expect(result).toBe(true) - }) - }) - describe('using JavaScript configuration, but enabled via data-attributes', () => { beforeAll(async () => { await renderAndInitialise(page, 'error-summary', { @@ -251,5 +230,21 @@ describe('Error Summary', () => { message: 'GOV.UK Frontend is not supported in this browser' }) }) + + it('throws when receiving the wrong type for $module', async () => { + await expect( + renderAndInitialise(page, 'error-summary', { + params: examples.default, + beforeInitialisation() { + // Remove the root of the components as a way + // for the constructor to receive the wrong type for `$module` + document.querySelector('[data-module]').remove() + } + }) + ).rejects.toEqual({ + name: 'TypeError', + message: 'Expected `$module` to be an instance of `HTMLElement`' + }) + }) }) }) 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 2ab98f6fe0..a8fa9ef096 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 @@ -9,6 +9,9 @@ import { I18n } from '../../i18n.mjs' * @preserve */ export class ExitThisPage extends GOVUKFrontendComponent { + /** @private */ + $module + /** * @private * @type {ExitThisPageConfig} @@ -78,7 +81,9 @@ export class ExitThisPage extends GOVUKFrontendComponent { super() if (!($module instanceof HTMLElement)) { - return this + throw new TypeError( + 'Expected `$module` to be an instance of `HTMLElement`' + ) } const $button = $module.querySelector('.govuk-exit-this-page__button') diff --git a/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.test.js b/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.test.js index e903b7f237..9a26a7b674 100644 --- a/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.test.js +++ b/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.test.js @@ -208,6 +208,22 @@ describe('/components/exit-this-page', () => { message: 'GOV.UK Frontend is not supported in this browser' }) }) + + it('throws when receiving the wrong type for $module', async () => { + await expect( + renderAndInitialise(page, 'exit-this-page', { + params: examples.default, + beforeInitialisation() { + // Remove the root of the components as a way + // for the constructor to receive the wrong type for `$module` + document.querySelector('[data-module]').remove() + } + }) + ).rejects.toEqual({ + name: 'TypeError', + message: 'Expected `$module` to be an instance of `HTMLElement`' + }) + }) }) }) }) diff --git a/packages/govuk-frontend/src/govuk/components/header/header.mjs b/packages/govuk-frontend/src/govuk/components/header/header.mjs index 1cc9582b67..67b69d825d 100644 --- a/packages/govuk-frontend/src/govuk/components/header/header.mjs +++ b/packages/govuk-frontend/src/govuk/components/header/header.mjs @@ -6,6 +6,9 @@ import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs' * @preserve */ export class Header extends GOVUKFrontendComponent { + /** @private */ + $module + /** @private */ $menuButton @@ -41,7 +44,9 @@ export class Header extends GOVUKFrontendComponent { super() if (!($module instanceof HTMLElement)) { - return this + throw new TypeError( + 'Expected `$module` to be an instance of `HTMLElement`' + ) } this.$module = $module diff --git a/packages/govuk-frontend/src/govuk/components/header/header.test.js b/packages/govuk-frontend/src/govuk/components/header/header.test.js index a5252e6d21..8a98ef1acc 100644 --- a/packages/govuk-frontend/src/govuk/components/header/header.test.js +++ b/packages/govuk-frontend/src/govuk/components/header/header.test.js @@ -188,6 +188,22 @@ describe('Header navigation', () => { message: 'GOV.UK Frontend is not supported in this browser' }) }) + + it('throws when receiving the wrong type for $module', async () => { + await expect( + renderAndInitialise(page, 'header', { + params: examples.default, + beforeInitialisation() { + // Remove the root of the components as a way + // for the constructor to receive the wrong type for `$module` + document.querySelector('[data-module]').remove() + } + }) + ).rejects.toEqual({ + name: 'TypeError', + message: 'Expected `$module` to be an instance of `HTMLElement`' + }) + }) }) }) }) 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 64eb37b4b4..c0ca117278 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 @@ -8,6 +8,9 @@ import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs' * @preserve */ export class NotificationBanner extends GOVUKFrontendComponent { + /** @private */ + $module + /** * @private * @type {NotificationBannerConfig} @@ -22,7 +25,9 @@ export class NotificationBanner extends GOVUKFrontendComponent { super() if (!($module instanceof HTMLElement)) { - return this + throw new TypeError( + 'Expected `$module` to be an instance of `HTMLElement`' + ) } this.$module = $module diff --git a/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.test.js b/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.test.js index cd5e04a578..ee7a0a6c8b 100644 --- a/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.test.js +++ b/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.test.js @@ -218,5 +218,21 @@ describe('Notification banner', () => { message: 'GOV.UK Frontend is not supported in this browser' }) }) + + it('throws when receiving the wrong type for $module', async () => { + await expect( + renderAndInitialise(page, 'notification-banner', { + params: examples.default, + beforeInitialisation() { + // Remove the root of the components as a way + // for the constructor to receive the wrong type for `$module` + document.querySelector('[data-module]').remove() + } + }) + ).rejects.toEqual({ + name: 'TypeError', + message: 'Expected `$module` to be an instance of `HTMLElement`' + }) + }) }) }) diff --git a/packages/govuk-frontend/src/govuk/components/radios/radios.mjs b/packages/govuk-frontend/src/govuk/components/radios/radios.mjs index ca77106b81..ec7594edec 100644 --- a/packages/govuk-frontend/src/govuk/components/radios/radios.mjs +++ b/packages/govuk-frontend/src/govuk/components/radios/radios.mjs @@ -6,6 +6,9 @@ import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs' * @preserve */ export class Radios extends GOVUKFrontendComponent { + /** @private */ + $module + /** @private */ $inputs @@ -27,7 +30,9 @@ export class Radios extends GOVUKFrontendComponent { super() if (!($module instanceof HTMLElement)) { - return this + throw new TypeError( + 'Expected `$module` to be an instance of `HTMLElement`' + ) } /** @satisfies {NodeListOf} */ diff --git a/packages/govuk-frontend/src/govuk/components/radios/radios.test.js b/packages/govuk-frontend/src/govuk/components/radios/radios.test.js index 6b29740cd3..daf3ca8766 100644 --- a/packages/govuk-frontend/src/govuk/components/radios/radios.test.js +++ b/packages/govuk-frontend/src/govuk/components/radios/radios.test.js @@ -290,5 +290,21 @@ describe('Radios', () => { message: 'GOV.UK Frontend is not supported in this browser' }) }) + + it('throws when receiving the wrong type for $module', async () => { + await expect( + renderAndInitialise(page, 'radios', { + params: examples.default, + beforeInitialisation() { + // Remove the root of the components as a way + // for the constructor to receive the wrong type for `$module` + document.querySelector('[data-module]').remove() + } + }) + ).rejects.toEqual({ + name: 'TypeError', + message: 'Expected `$module` to be an instance of `HTMLElement`' + }) + }) }) }) 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 1aff30f340..48b4b26960 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 @@ -6,11 +6,8 @@ import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs' * @preserve */ export class SkipLink extends GOVUKFrontendComponent { - /** - * @protected - * @type {HTMLAnchorElement} - */ - $module = this.$module + /** @private */ + $module /** * @private @@ -28,7 +25,9 @@ export class SkipLink extends GOVUKFrontendComponent { super() if (!($module instanceof HTMLAnchorElement)) { - return this + throw new TypeError( + 'Expected `$module` to be an instance of `HTMLAnchorElement`' + ) } this.$module = $module diff --git a/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.test.js b/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.test.js index ad065b1a65..021c09a9a7 100644 --- a/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.test.js +++ b/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.test.js @@ -81,5 +81,21 @@ describe('Skip Link', () => { message: 'GOV.UK Frontend is not supported in this browser' }) }) + + it('throws when receiving the wrong type for $module', async () => { + await expect( + renderAndInitialise(page, 'skip-link', { + params: examples.default, + beforeInitialisation() { + // Remove the root of the components as a way + // for the constructor to receive the wrong type for `$module` + document.querySelector('[data-module]').remove() + } + }) + ).rejects.toEqual({ + name: 'TypeError', + message: 'Expected `$module` to be an instance of `HTMLAnchorElement`' + }) + }) }) }) diff --git a/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs b/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs index a44284a654..c419addb59 100644 --- a/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs +++ b/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs @@ -6,6 +6,9 @@ import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs' * @preserve */ export class Tabs extends GOVUKFrontendComponent { + /** @private */ + $module + /** @private */ $tabs @@ -40,7 +43,9 @@ export class Tabs extends GOVUKFrontendComponent { super() if (!($module instanceof HTMLElement)) { - return this + throw new TypeError( + 'Expected `$module` to be an instance of `HTMLElement`' + ) } /** @satisfies {NodeListOf} */ diff --git a/packages/govuk-frontend/src/govuk/components/tabs/tabs.test.js b/packages/govuk-frontend/src/govuk/components/tabs/tabs.test.js index bd96371f7c..9a78695972 100644 --- a/packages/govuk-frontend/src/govuk/components/tabs/tabs.test.js +++ b/packages/govuk-frontend/src/govuk/components/tabs/tabs.test.js @@ -268,6 +268,22 @@ describe('/components/tabs', () => { message: 'GOV.UK Frontend is not supported in this browser' }) }) + + it('throws when receiving the wrong type for $module', async () => { + await expect( + renderAndInitialise(page, 'tabs', { + params: examples.default, + beforeInitialisation() { + // Remove the root of the components as a way + // for the constructor to receive the wrong type for `$module` + document.querySelector('[data-module]').remove() + } + }) + ).rejects.toEqual({ + name: 'TypeError', + message: 'Expected `$module` to be an instance of `HTMLElement`' + }) + }) }) }) }) diff --git a/packages/govuk-frontend/src/govuk/govuk-frontend-component.mjs b/packages/govuk-frontend/src/govuk/govuk-frontend-component.mjs index 0f55c069a3..bd537c2ac5 100644 --- a/packages/govuk-frontend/src/govuk/govuk-frontend-component.mjs +++ b/packages/govuk-frontend/src/govuk/govuk-frontend-component.mjs @@ -10,12 +10,6 @@ import { SupportError } from './errors/index.mjs' * @abstract */ export class GOVUKFrontendComponent { - /** - * @protected - * @type {HTMLElement} - */ - $module - /** * Constructs a new component, validating that GOV.UK Frontend is supported *