diff --git a/packages/govuk-frontend/src/govuk/govuk-frontend-component.mjs b/packages/govuk-frontend/src/govuk/govuk-frontend-component.mjs index 7f0cd7ffdd..49f48dc7dd 100644 --- a/packages/govuk-frontend/src/govuk/govuk-frontend-component.mjs +++ b/packages/govuk-frontend/src/govuk/govuk-frontend-component.mjs @@ -17,7 +17,15 @@ export class GOVUKFrontendComponent { * @param {Element | null} [$module] - HTML element to use for component */ constructor($module) { + // const checkSupport = /** @type {ChildClassConstructor} */ (this.constructor) + // .checkSupport + + // if (typeof checkSupport === 'function') { + // checkSupport() + // } else { this.checkSupport() + // } + this.checkInitialised($module) const moduleName = /** @type {ChildClassConstructor} */ (this.constructor) @@ -49,7 +57,8 @@ export class GOVUKFrontendComponent { /** * Validates whether components are supported * - * @private + * @protected + * @static * @throws {SupportError} when the components are not supported */ checkSupport() { @@ -72,6 +81,7 @@ export class GOVUKFrontendComponent { /** * @typedef ChildClass * @property {string} [moduleName] - The module name that'll be looked for in the DOM when initialising the component + * @property {() => void} [checkSupport] - The module name that'll be looked for in the DOM when initialising the component */ /** diff --git a/packages/govuk-frontend/src/govuk/init.jsdom.test.mjs b/packages/govuk-frontend/src/govuk/init.jsdom.test.mjs index 58462f9458..00645a7f11 100644 --- a/packages/govuk-frontend/src/govuk/init.jsdom.test.mjs +++ b/packages/govuk-frontend/src/govuk/init.jsdom.test.mjs @@ -4,6 +4,7 @@ import { } from '@govuk-frontend/lib/names' import * as GOVUKFrontend from './all.mjs' +import { GOVUKFrontendComponent } from './govuk-frontend-component.mjs' import { initAll, createAll } from './init.mjs' // Annoyingly these don't get hoisted if done in a loop @@ -226,8 +227,9 @@ describe('createAll', () => { document.body.outerHTML = '' }) - class MockComponent { + class MockComponent extends GOVUKFrontendComponent { constructor(...args) { + super(...args) this.args = args } @@ -292,6 +294,49 @@ describe('createAll', () => { ) }) + it('executes overloaded checkSupport of component', () => { + const componentRoot = document.createElement('div') + componentRoot.setAttribute('data-module', 'mock-component') + document.body.appendChild(componentRoot) + + const checkSupportMock = jest.fn(() => {}) + + class MockComponentWithCheckSupport extends MockComponent { + checkSupport() { + checkSupportMock() + } + } + + const result = createAll(MockComponentWithCheckSupport) + + expect(checkSupportMock).toHaveBeenCalled() + expect(result).toStrictEqual([expect.any(MockComponent)]) + }) + + it('returns empty array if overloaded checkSupport of component throws error', () => { + const componentRoot = document.createElement('div') + componentRoot.setAttribute('data-module', 'mock-component') + document.body.appendChild(componentRoot) + + // Silence warnings in test output, and allow us to 'expect' them + jest.spyOn(global.console, 'log').mockImplementation() + + const checkSupportMock = jest.fn(() => { + throw Error('Mock error') + }) + + class MockComponentWithCheckSupport extends MockComponent { + checkSupport() { + checkSupportMock() + } + } + + const result = createAll(MockComponentWithCheckSupport) + expect(checkSupportMock).toHaveBeenCalled() + expect(result).toStrictEqual([]) + expect(global.console.log).toHaveBeenCalledWith(expect.any(Error)) + }) + it('returns an empty array if no matching components exist on the page', () => { const componentRoot = document.createElement('div') componentRoot.setAttribute(