-
Notifications
You must be signed in to change notification settings - Fork 324
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
Set skip link linked element in init and put event listener behind flag #2467
Conversation
I think I've managed to get to the bottom of this… We're bailing out of the govuk-frontend/src/govuk/components/skip-link/skip-link.js Lines 39 to 42 in 91f6254
If you try to get the BUT – why would the skip link be initialised on an element that doesn't have an It looks like the error is actually coming from the test immediately before it: govuk-frontend/src/govuk/all.test.js Lines 61 to 76 in 429af61
There are a few unusual things going on in that test:
You can make the error surface in the correct test by changing lines 69 to 75 so that we // Check that all the components on the GOV.UK Frontend global can be initialised
- components.forEach(component => {
- page.evaluate(component => {
+ await page.evaluate((components) => {
+ components.forEach(component => {
const Component = window.GOVUKFrontend[component]
const $module = document.documentElement
new Component($module).init()
- }, component)
- })
+ })
+ }, components)
}) However, I am still not sure what we should do with the test… it's not testing what we think it does, and at the minute seems to offer little value. From talking to @lfdebrux, the suggestions so far are to either delete it, or to alter it so that it only checks that there is an |
The test currently passes `document.documentElement` (the root `<html>` element) as the `$module` when initialising each component. This is also incorrect – every component expects `$module` to be the element with the corresponding data-module attribute. If we did want to initialise with the correct HTML for each component, we'd need to make substantial changes to the test. At the minute it runs in the context of the 'home page' of the review app, which doesn't include the majority of the components that have JavaScript. Given these constraints, replace the test with one that does not try to instantiate or initialise the components, but only check that they all have an `init` function. We were also not waiting for the Promises returned by `page.evaluate` to by fulfilled, so any errors thrown by the JS could cause unrelated tests that run later to fail. We were seeing this occur in #2467 when adding tests for the new skip link JavaScript. Fix this by moving the bulk of the test logic into a single `page.evaluate` call and using `await` to pause execution until the returned Promise is fulfilled.
The test currently passes `document.documentElement` (the root `<html>` element) as the `$module` when initialising each component. This is also incorrect – every component expects `$module` to be the element with the corresponding data-module attribute. If we did want to initialise with the correct HTML for each component, we'd need to make substantial changes to the test. At the minute it runs in the context of the 'home page' of the review app, which doesn't include the majority of the components that have JavaScript. Given these constraints, replace the test with one that does not try to instantiate or initialise the components, but only check that they all have an `init` function. We were also not waiting for the Promises returned by `page.evaluate` to by fulfilled, so any errors thrown by the JS could cause unrelated tests that run later to fail. We were seeing this occur in #2467 when adding tests for the new skip link JavaScript. Fix this by moving the bulk of the test logic into a single `page.evaluate` call and using `await` to pause execution until the returned Promise is fulfilled. (It would likely make more sense to run these tests against the classes directly, rather than using Puppeteer to assert things about the `window.GOVUKFrontend` global object in a browser. However, we don't currently have a good way to test the component JavaScript directly. When we do, we should revisit this test.)
I've raised a PR to update the test (#2470) |
The test currently passes `document.documentElement` (the root `<html>` element) as the `$module` when initialising each component. This is also incorrect – every component expects `$module` to be the element with the corresponding data-module attribute. If we did want to initialise with the correct HTML for each component, we'd need to make substantial changes to the test. At the minute it runs in the context of the 'home page' of the review app, which doesn't include the majority of the components that have JavaScript. Given these constraints, replace the test with one that does not try to instantiate or initialise the components, but only check that they all have an `init` function. We were also not waiting for the Promises returned by `page.evaluate` to by fulfilled, so any errors thrown by the JS could cause unrelated tests that run later to fail. We were seeing this occur in #2467 when adding tests for the new skip link JavaScript. Fix this by moving the bulk of the test logic into a single `page.evaluate` call and using `await` to pause execution until the returned Promise is fulfilled. (It would likely make more sense to run these tests against the classes directly, rather than using Puppeteer to assert things about the `window.GOVUKFrontend` global object in a browser. However, we don't currently have a good way to test the component JavaScript directly. When we do, we should revisit this test.)
The test currently passes `document.documentElement` (the root `<html>` element) as the `$module` when initialising each component. This is not what the component expects – `$module` should be the element with the corresponding `data-module` attribute, for example `<div data-module="govuk-button">`. If we did want to initialise with the correct HTML for each component, we'd need to make substantial changes to the test. At the minute it runs in the context of the 'home page' of the review app, which doesn't include the majority of the components that have JavaScript. Given these constraints, replace the test with one that does not try to instantiate or initialise the components, but only check that they all have an `init` function. We were also not waiting for the Promises returned by `page.evaluate` to by fulfilled, so any errors thrown by the JS could cause unrelated tests that run later to fail. We were seeing this occur in #2467 when adding tests for the new skip link JavaScript. Fix this by moving the bulk of the test logic into a single `page.evaluate` call and using `await` to pause execution until the returned Promise is fulfilled. (It would likely make more sense to run these tests against the classes directly, rather than using Puppeteer to assert things about the `window.GOVUKFrontend` global object in a browser. However, we don't currently have a good way to test the component JavaScript directly. When we do, we should revisit this test.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this approach makes sense – nice work 👍🏻 I pushed a commit to fix the issue in my previous comment, hope that's OK.
There's a couple of other things that I think we might need to look at, and a couple of suggestions.
Improve the readability and performance of the skip link script by: - checking for the linked element early as part of the initialisation - moving the event listener for the main content behind a flag so it's only set once - simplifying init() and getFragmentFromUrl() - removing redundant clickEventHandler()
3a9e1e3
to
cf7e9ad
Compare
This PR solves the issue mentioned in #2450 (review).
Improve the readability and performance of the skip link script by:
init()
andgetFragmentFromUrl()
clickEventHandler()
This also doesn’t seem to play nice with theSolved in #2470exported Components can be initialised
test we have inall.test.js
, I don’t fully understand right now whether it’s picked up on an issue or if the test is not working correctly. Was going to do some test debugging tomorrow anyway so could look at this then.Tested in