Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HTML validation rules for missing elements #4417

Merged
merged 5 commits into from
Nov 20, 2023

Conversation

colinrotherham
Copy link
Contributor

@colinrotherham colinrotherham commented Nov 1, 2023

This PR enables extra HTML validation rules:

  1. input-missing-label – Require input to have a label
  2. no-missing-references – Require all form field and ARIA references to exist

But also adds the HTML validation preset html-validate:document for testing govuk/template.njk

The good news is we’re fully valid already, but we’d be extra safe 😅

Missing elements

To resolve missing elements, we could use render() renderPreview() to render the entire page

But instead I've taken the id="content" wrapper like we did for Skip link accessibility tests in #4346 and updated it with @36degrees's idea to use a dummy element instead:

  const html = outdent`
    ${render(componentName, {
      context: fixture.options,
      fixture
    })}
+
+   <!--
+     Target for references in examples (e.g. aria-controls)
+     https://html-validate.org/rules/no-missing-references.html
+   -->
+   <div id="test-target-element"></div>
  `

This passes validation for examples that add aria-describedby etc such as in fieldset.yaml

  - name: with describedBy
    hidden: true
    options:
-     describedBy: content
+     describedBy: test-target-element
      legend:
        text: Which option?

@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4417 November 1, 2023 18:57 Inactive
Copy link

github-actions bot commented Nov 1, 2023

📋 Stats

File sizes

File Size
dist/govuk-frontend-5.0.0-beta.1.min.css 114 KiB
dist/govuk-frontend-5.0.0-beta.1.min.js 37.93 KiB
packages/govuk-frontend/dist/govuk/all.bundle.js 77.02 KiB
packages/govuk-frontend/dist/govuk/all.bundle.mjs 72.35 KiB
packages/govuk-frontend/dist/govuk/all.mjs 3.8 KiB
packages/govuk-frontend/dist/govuk/govuk-frontend-component.mjs 359 B
packages/govuk-frontend/dist/govuk/govuk-frontend.min.css 113.53 KiB
packages/govuk-frontend/dist/govuk/govuk-frontend.min.js 37.94 KiB
packages/govuk-frontend/dist/govuk/i18n.mjs 5.3 KiB

Modules

File Size
all.mjs 68.67 KiB
components/accordion/accordion.mjs 21.37 KiB
components/button/button.mjs 4.48 KiB
components/character-count/character-count.mjs 20.78 KiB
components/checkboxes/checkboxes.mjs 5.61 KiB
components/error-summary/error-summary.mjs 5.79 KiB
components/exit-this-page/exit-this-page.mjs 15.79 KiB
components/header/header.mjs 3.68 KiB
components/notification-banner/notification-banner.mjs 4.32 KiB
components/radios/radios.mjs 4.6 KiB
components/skip-link/skip-link.mjs 3.6 KiB
components/tabs/tabs.mjs 9.33 KiB

View stats and visualisations on the review app


Action run for f4f16a0

@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4417 November 1, 2023 20:28 Inactive
@colinrotherham colinrotherham changed the title [SPIKE] Add HTML validation presets for accessibility, documents [SPIKE] Add HTML validation rules for missing elements Nov 2, 2023
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4417 November 2, 2023 10:45 Inactive
Base automatically changed from puppeteer-accessibility to main November 2, 2023 12:23
@colinrotherham colinrotherham changed the title [SPIKE] Add HTML validation rules for missing elements Add HTML validation rules for missing elements Nov 2, 2023
@colinrotherham colinrotherham requested a review from a team as a code owner November 2, 2023 13:14
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4417 November 2, 2023 13:14 Inactive
@colinrotherham colinrotherham changed the base branch from main to puppeteer-render-all November 2, 2023 13:14
@colinrotherham colinrotherham force-pushed the puppeteer-render-all branch 3 times, most recently from 022350c to 5529af2 Compare November 2, 2023 15:39
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4417 November 2, 2023 15:48 Inactive
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4417 November 2, 2023 16:03 Inactive
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4417 November 2, 2023 16:54 Inactive
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4417 November 2, 2023 17:59 Inactive
Base automatically changed from puppeteer-render-all to main November 6, 2023 10:02
Comment on lines 69 to 80
const html = outdent`
<div id="content" class="govuk-width-container">
${render(componentName, {
context: fixture.options,
fixture
})}
</div>
`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could be slightly misleading because this looks very much like one of our main wrapper elements, which I don't think is something you'd ever associate with a component using aria-describedby.

Can we make it clearer what this is for by:

  • adding the extra element after the rendered component
  • changing the ID to something like test-target-element (and in the corresponding examples)
  • adding a comment to explain what it's for
Suggested change
const html = outdent`
<div id="content" class="govuk-width-container">
${render(componentName, {
context: fixture.options,
fixture
})}
</div>
`
const html = outdent`
${render(componentName, {
context: fixture.options,
fixture
})}
<div id="test-target-element">
<!-- Target for references in examples (e.g. aria-describedby) so no-missing-references can pass -->
</div>
`

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@36degrees Mind if I tag @romaricpascal in?

I thought the same as you but we agreed it was acceptable for the Skip link accessibility tests

I'd like to make your suggestion there too

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I follow, sorry – how is the skip link involved here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I'll explain, it was covered in dev catch-up after your holiday

E.g. Skip link failed Accessibility tests (JavaScript error) without a target element

So we decided that a dummy element ID was acceptable for now, but due to hard-coded defaults like default("#content", true) we added id="content" to the component preview wrapper just like in this PR

I like your suggestion so perhaps we can annotate the test ID in both wrappers?

Copy link
Contributor Author

@colinrotherham colinrotherham Nov 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the existing component preview wrapper with id="content" added in 3ed9d1f

<div id="content" class="govuk-width-container">
${render(componentName, options)}
</div>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, that's helpful context 👍🏻

I think annotating the test ID in both wrappers sounds like a good solution.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Morning 👋

I've swapped all the #content references in 3ed9d1f to test-target-element

Whilst the HTML validation tests lack the <div id="content"> wrapper, it's still needed by:

npx jest --selectProjects "Accessibility tests"
npx jest --selectProjects "JavaScript component tests"

But that's only because it's hard coded in href="{{ params.href | default("#content", true) }}"

Without it we'll see JavaScript warnings for every Skip link example:

  console.warn
    Initialising `new SkipLink()` with example 'no href' threw:
     ElementError: Skip link: Target content (`id="content"`) not found

Think we're looking good now, ready for review again 👍

We previously enabled the rule `no-missing-references` but lots of examples target `id="test-target-element"` on the preview container which isn’t available when only the component is rendered

For example from fieldset.yaml

```
  - name: with describedBy
    hidden: true
    options:
      describedBy: test-target-element
      legend:
        text: Which option?
```
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4417 November 10, 2023 08:19 Inactive
Copy link
Contributor

@36degrees 36degrees left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks for making that change 👍🏻 Think it's a lot clearer what's going on now.

@colinrotherham
Copy link
Contributor Author

Looks great, thanks for making that change 👍🏻 Think it's a lot clearer what's going on now.

Totally agree. Thanks for pushing for it

@colinrotherham colinrotherham merged commit 46cf96d into main Nov 20, 2023
45 checks passed
@colinrotherham colinrotherham deleted the html-validate-rules branch November 20, 2023 15:40
owenatgov pushed a commit that referenced this pull request Jan 11, 2024
owenatgov pushed a commit that referenced this pull request Jan 11, 2024
Add HTML validation rules for missing elements
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

3 participants