Skip to content

Commit

Permalink
Refactor validation of GOV.UK Frontend support in a base class
Browse files Browse the repository at this point in the history
It's the same code for all components and the architecture we're looking to implement
so we may as well start introducing it, keeping it internal
  • Loading branch information
romaricpascal committed Aug 11, 2023
1 parent a64c0f5 commit 98eaeca
Show file tree
Hide file tree
Showing 14 changed files with 74 additions and 57 deletions.
14 changes: 14 additions & 0 deletions packages/govuk-frontend/src/govuk/common/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,17 @@ export function extractConfigByNamespace(configObject, namespace) {
}
return newObject
}

/**
* Checks if GOV.UK Frontend is supported on this page
*
* Some browsers will load and run our JavaScript but GOV.UK Frontend
* won't be supported.
*
* @internal
* @param {HTMLElement} [$scope] - The `<body>` element of the document to check for support
* @returns {boolean} Whether GOV.UK Frontend is supported on this page
*/
export function isSupported($scope = document.body) {
return $scope.classList.contains('govuk-frontend-supported')
}
24 changes: 23 additions & 1 deletion packages/govuk-frontend/src/govuk/common/index.unit.test.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { mergeConfigs, extractConfigByNamespace } from './index.mjs'
import {
mergeConfigs,
extractConfigByNamespace,
isSupported
} from './index.mjs'

describe('Common JS utilities', () => {
describe('mergeConfigs', () => {
Expand Down Expand Up @@ -112,4 +116,22 @@ describe('Common JS utilities', () => {
expect(() => extractConfigByNamespace(flattenedConfig)).toThrow()
})
})

describe.only('isSupported', () => {
beforeEach(() => {
// Jest does not tidy the JSDOM document between tests
// so we need to take care of that ourselves
document.documentElement.innerHTML = ''
})

it('returns true if the govuk-frontend-supported class is set', () => {
document.body.classList.add('govuk-frontend-supported')

expect(isSupported(document.body)).toBe(true)
})

it('returns false if the govuk-frontend-supported class is not set', () => {
expect(isSupported(document.body)).toBe(false)
})
})
})
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { mergeConfigs, extractConfigByNamespace } from '../../common/index.mjs'
import { normaliseDataset } from '../../common/normalise-dataset.mjs'
import { GOVUKFrontendSupportError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'
import { I18n } from '../../i18n.mjs'

/**
Expand All @@ -15,7 +15,7 @@ import { I18n } from '../../i18n.mjs'
* The state of each section is saved to the DOM via the `aria-expanded`
* attribute, which also provides accessibility.
*/
export class Accordion {
export class Accordion extends GOVUKFrontendComponent {
/** @private */
$module

Expand Down Expand Up @@ -114,9 +114,7 @@ export class Accordion {
* @param {AccordionConfig} [config] - Accordion config
*/
constructor($module, config) {
if (!document.body.classList.contains('govuk-frontend-supported')) {
throw new GOVUKFrontendSupportError()
}
super()

if (!($module instanceof HTMLElement)) {
return this
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { mergeConfigs } from '../../common/index.mjs'
import { normaliseDataset } from '../../common/normalise-dataset.mjs'
import { GOVUKFrontendSupportError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

const KEY_SPACE = 32
const DEBOUNCE_TIMEOUT_IN_SECONDS = 1

/**
* JavaScript enhancements for the Button component
*/
export class Button {
export class Button extends GOVUKFrontendComponent {
/** @private */
$module

Expand All @@ -30,9 +30,7 @@ export class Button {
* @param {ButtonConfig} [config] - Button config
*/
constructor($module, config) {
if (!document.body.classList.contains('govuk-frontend-supported')) {
throw new GOVUKFrontendSupportError()
}
super()

if (!($module instanceof HTMLElement)) {
return this
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { closestAttributeValue } from '../../common/closest-attribute-value.mjs'
import { extractConfigByNamespace, mergeConfigs } from '../../common/index.mjs'
import { normaliseDataset } from '../../common/normalise-dataset.mjs'
import { GOVUKFrontendSupportError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'
import { I18n } from '../../i18n.mjs'

/**
Expand All @@ -14,7 +14,7 @@ import { I18n } from '../../i18n.mjs'
* You can configure the message to only appear after a certain percentage
* of the available characters/words has been entered.
*/
export class CharacterCount {
export class CharacterCount extends GOVUKFrontendComponent {
/** @private */
$module

Expand Down Expand Up @@ -65,9 +65,7 @@ export class CharacterCount {
* @param {CharacterCountConfig} [config] - Character count config
*/
constructor($module, config) {
if (!document.body.classList.contains('govuk-frontend-supported')) {
throw new GOVUKFrontendSupportError()
}
super()

if (!($module instanceof HTMLElement)) {
return this
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { GOVUKFrontendSupportError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

/**
* Checkboxes component
*/
export class Checkboxes {
export class Checkboxes extends GOVUKFrontendComponent {
/** @private */
$module

Expand All @@ -25,9 +25,7 @@ export class Checkboxes {
* @param {Element} $module - HTML element to use for checkboxes
*/
constructor($module) {
if (!document.body.classList.contains('govuk-frontend-supported')) {
throw new GOVUKFrontendSupportError()
}
super()

if (!($module instanceof HTMLElement)) {
return this
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { mergeConfigs } from '../../common/index.mjs'
import { normaliseDataset } from '../../common/normalise-dataset.mjs'
import { GOVUKFrontendSupportError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

/**
* Error summary component
*
* Takes focus on initialisation for accessible announcement, unless disabled in configuration.
*/
export class ErrorSummary {
export class ErrorSummary extends GOVUKFrontendComponent {
/** @private */
$module

Expand All @@ -23,9 +23,7 @@ export class ErrorSummary {
* @param {ErrorSummaryConfig} [config] - Error summary config
*/
constructor($module, config) {
if (!document.body.classList.contains('govuk-frontend-supported')) {
throw new GOVUKFrontendSupportError()
}
super()

if (!($module instanceof HTMLElement)) {
return this
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { mergeConfigs, extractConfigByNamespace } from '../../common/index.mjs'
import { normaliseDataset } from '../../common/normalise-dataset.mjs'
import { GOVUKFrontendSupportError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'
import { I18n } from '../../i18n.mjs'

/**
* Exit This Page component
*/
export class ExitThisPage {
export class ExitThisPage extends GOVUKFrontendComponent {
/** @private */
$module

Expand Down Expand Up @@ -76,9 +76,7 @@ export class ExitThisPage {
* @param {ExitThisPageConfig} [config] - Exit This Page config
*/
constructor($module, config) {
if (!document.body.classList.contains('govuk-frontend-supported')) {
throw new GOVUKFrontendSupportError()
}
super()

if (!($module instanceof HTMLElement)) {
return this
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { GOVUKFrontendSupportError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

/**
* Header component
*/
export class Header {
export class Header extends GOVUKFrontendComponent {
/** @private */
$module

Expand Down Expand Up @@ -39,9 +39,7 @@ export class Header {
* @param {Element} $module - HTML element to use for header
*/
constructor($module) {
if (!document.body.classList.contains('govuk-frontend-supported')) {
throw new GOVUKFrontendSupportError()
}
super()

if (!($module instanceof HTMLElement)) {
return this
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { mergeConfigs } from '../../common/index.mjs'
import { normaliseDataset } from '../../common/normalise-dataset.mjs'
import { GOVUKFrontendSupportError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

/**
* Notification Banner component
*/
export class NotificationBanner {
export class NotificationBanner extends GOVUKFrontendComponent {
/** @private */
$module

Expand All @@ -20,9 +20,7 @@ export class NotificationBanner {
* @param {NotificationBannerConfig} [config] - Notification banner config
*/
constructor($module, config) {
if (!document.body.classList.contains('govuk-frontend-supported')) {
throw new GOVUKFrontendSupportError()
}
super()

if (!($module instanceof HTMLElement)) {
return this
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { GOVUKFrontendSupportError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

/**
* Radios component
*/
export class Radios {
export class Radios extends GOVUKFrontendComponent {
/** @private */
$module

Expand All @@ -25,9 +25,7 @@ export class Radios {
* @param {Element} $module - HTML element to use for radios
*/
constructor($module) {
if (!document.body.classList.contains('govuk-frontend-supported')) {
throw new GOVUKFrontendSupportError()
}
super()

if (!($module instanceof HTMLElement)) {
return this
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { GOVUKFrontendSupportError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

/**
* Skip link component
*/
export class SkipLink {
export class SkipLink extends GOVUKFrontendComponent {
/** @private */
$module

Expand All @@ -21,9 +21,7 @@ export class SkipLink {
* @param {Element} $module - HTML element to use for skip link
*/
constructor($module) {
if (!document.body.classList.contains('govuk-frontend-supported')) {
throw new GOVUKFrontendSupportError()
}
super()

if (!($module instanceof HTMLAnchorElement)) {
return this
Expand Down
8 changes: 3 additions & 5 deletions packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { GOVUKFrontendSupportError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

/**
* Tabs component
*/
export class Tabs {
export class Tabs extends GOVUKFrontendComponent {
/** @private */
$module

Expand Down Expand Up @@ -38,9 +38,7 @@ export class Tabs {
* @param {Element} $module - HTML element to use for tabs
*/
constructor($module) {
if (!document.body.classList.contains('govuk-frontend-supported')) {
throw new GOVUKFrontendSupportError()
}
super()

if (!($module instanceof HTMLElement)) {
return this
Expand Down
5 changes: 4 additions & 1 deletion packages/govuk-frontend/tasks/build/package.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,10 @@ describe('packages/govuk-frontend/dist/', () => {
for (const componentName of componentNamesWithJavaScript) {
const componentClassName = componentNameToClassName(componentName)

expect(contents).toContain(`class ${componentClassName} {`)
expect(contents).toContain(
// Trailing space is important to not match `class ${componentClassName}Something`
`class ${componentClassName} `
)
expect(contents).toContain(
`exports.${componentClassName} = ${componentClassName};`
)
Expand Down

0 comments on commit 98eaeca

Please sign in to comment.