From 07f4ee112e4da3b022bd6f9c13652d5456a3dc80 Mon Sep 17 00:00:00 2001 From: rmccar <42928680+rmccar@users.noreply.github.com> Date: Mon, 9 Sep 2024 16:35:07 +0100 Subject: [PATCH] Update Puppeteer to v22 (#3266) --- .github/workflows/macro-and-script-tests.yml | 2 + .nvmrc | 2 +- README.md | 4 +- package.json | 5 +- .../address-input/autosuggest.address.spec.js | 29 +- .../autosuggest/autosuggest.spec.js | 12 +- .../back-to-top/back-to-top.spec.js | 6 +- .../cookies-banner/cookies-banner.spec.js | 2 +- .../mutually-exclusive.checkboxes.spec.js | 12 +- .../mutually-exclusive.date.spec.js | 18 +- .../mutually-exclusive.duration.spec.js | 18 +- .../mutually-exclusive.email.spec.js | 10 +- ...lusive.multiple-options.checkboxes.spec.js | 12 +- .../mutually-exclusive.number.spec.js | 10 +- .../mutually-exclusive.textarea.spec.js | 10 +- src/components/navigation/navigation.spec.js | 14 +- src/components/table-of-contents/toc.spec.js | 6 +- src/components/table/table.spec.js | 2 +- .../timeout-modal/timeout-modal.spec.js | 77 ++--- .../timeout-panel/timeout-panel.spec.js | 6 +- src/components/video/video.spec.js | 194 ++++++----- src/js/cookies-settings.spec.js | 2 +- src/tests/helpers/puppeteer.js | 2 +- yarn.lock | 303 ++++++++++++++---- 24 files changed, 493 insertions(+), 265 deletions(-) diff --git a/.github/workflows/macro-and-script-tests.yml b/.github/workflows/macro-and-script-tests.yml index e34598dfd5..668862b922 100644 --- a/.github/workflows/macro-and-script-tests.yml +++ b/.github/workflows/macro-and-script-tests.yml @@ -18,5 +18,7 @@ jobs: node-version-file: '.nvmrc' - name: Install dependencies run: yarn install + - name: Clear jest cache + run: yarn test:clear-cache - name: Run macro and script tests run: yarn test diff --git a/.nvmrc b/.nvmrc index 790e1105f2..80a9956e1e 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v20.10.0 +v20.16.0 diff --git a/README.md b/README.md index 32adbb73f2..00a71a3f54 100644 --- a/README.md +++ b/README.md @@ -106,13 +106,13 @@ _Note_: This command is of limited use since JavaScript and SCSS files will only It is sometimes useful to adjust the following settings when writing tests or diagnosing issues: -- `headless` in 'jest-puppeteer.config.js' - when set to `false` will show web browser whilst running tests. Many browser windows open since jest runs tests in parallel so it is useful to also adjust the `test` script inside 'package.json' such that it targets a specific test file. `await page.waitForTimeout(100000)` can be temporarily added to a test to allow yourself time to inspect the browser that appears. +- `headless` in 'jest-puppeteer.config.js' - when set to `false` will show web browser whilst running tests. Many browser windows open since jest runs tests in parallel so it is useful to also adjust the `test` script inside 'package.json' such that it targets a specific test file. `await new Promise(r => setTimeout(r, 100000));` can be temporarily added to a test to allow yourself time to inspect the browser that appears. - `testTimeout` in 'jest.config.js' - set to a high value such as `1000000` to prevent tests from timing out when doing the above. ## Testing - Visual regression tests -This project uses [Backstop JS](https://github.com/garris/BackstopJS) for visual regression testing. The tests run in Chrome headless using pupeteer inside docker and run in three viewports; 1920 (desktop), 768 (tablet) and 375 (mobile). Reference images are stored in Git LFS and any approved changes will automatically be stored in Git LFS when pushed to the repository. +This project uses [Backstop JS](https://github.com/garris/BackstopJS) for visual regression testing. The tests run in Chrome headless using Pupeteer inside docker and run in three viewports; 1920 (desktop), 768 (tablet) and 375 (mobile). Reference images are stored in Git LFS and any approved changes will automatically be stored in Git LFS when pushed to the repository. The visual tests will run automatically on pull requests and the result will be available in the Github Action logs. If the tests fail, the process for viewing the failures and approving changes will need to be handled locally using the following workflow and commands. diff --git a/package.json b/package.json index 024b795f99..ca466fed19 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "start": "gulp start", "watch": "gulp watch", "test": "gulp build-assets && TEST_PORT=3020 TEST_WITH_PUPPETEER=1 jest '.*\\.spec\\.js'", + "test:clear-cache": "jest --clearCache", "test:no-build": "TEST_PORT=3020 TEST_WITH_PUPPETEER=1 jest '.*\\.spec\\.js'", "test:with-log": "yarn test --no-color 2>test.log", "test:start-server": "TEST_PORT=3020 gulp start-dev-server", @@ -98,7 +99,7 @@ "jest": "^29.6.1", "jest-axe": "^8.0.0", "jest-environment-jsdom": "^29.6.1", - "jest-puppeteer": "^9.0.0", + "jest-puppeteer": "^10.0.0", "lighthouse": "^11.0.0", "lint-staged": "^15.2.0", "lodash": "^4.17.21", @@ -111,7 +112,7 @@ "prepend-file": "^2.0.1", "prettier": "^3.2.5", "prettier-plugin-jinja-template": "^1.4.0", - "puppeteer": "^21.0.2", + "puppeteer": "^22.0.0", "remark-cli": "^12.0.0", "remark-lint": "^9.1.2", "remark-preset-lint-recommended": "^6.1.3", diff --git a/src/components/address-input/autosuggest.address.spec.js b/src/components/address-input/autosuggest.address.spec.js index 065f3f273f..a124dd26ef 100644 --- a/src/components/address-input/autosuggest.address.spec.js +++ b/src/components/address-input/autosuggest.address.spec.js @@ -62,6 +62,8 @@ const EXAMPLE_ADDRESS_INPUT_WITH_API = { externalInitialiser: true, }; +const { setTimeout } = require('node:timers/promises'); + describe('script: address-input', () => { const apiFaker = new PuppeteerEndpointFaker(EXAMPLE_ADDRESS_INPUT_WITH_API.APIDomain); @@ -184,7 +186,7 @@ describe('script: address-input', () => { describe('When the component initializes', () => { it('checks api status by trying a request', async () => { await setTestPage('/test', renderComponent('address-input', EXAMPLE_ADDRESS_INPUT_WITH_API)); - await page.waitForTimeout(50); + await setTimeout(50); expect(apiFaker.getRequestCount('/addresses/eq?input=cf142&limit=10')).toBe(1); }); @@ -192,7 +194,7 @@ describe('script: address-input', () => { describe('when api status is okay', () => { beforeEach(async () => { await setTestPage('/test', renderComponent('address-input', EXAMPLE_ADDRESS_INPUT_WITH_API)); - await page.waitForTimeout(50); + await setTimeout(50); }); it('does not switch to manual input', async () => { @@ -216,7 +218,7 @@ describe('script: address-input', () => { }); await setTestPage('/test', renderComponent('address-input', EXAMPLE_ADDRESS_INPUT_WITH_API)); - await page.waitForTimeout(50); + await setTimeout(50); }); it('switches to manual input', async () => { @@ -271,6 +273,7 @@ describe('script: address-input', () => { }); it('has expected suggestion entries', async () => { + await setTimeout(100); const suggestions = await page.$$eval('.ons-autosuggest__option', (nodes) => nodes.map((node) => node.textContent.trim())); expect(suggestions).toEqual(['196 College Road, Birmingham, B44 8HF', '196 College Road, Whitchurch, Cardiff, CF14 2NZ']); }); @@ -305,7 +308,7 @@ describe('script: address-input', () => { await page.$eval('.ons-js-autosuggest-input', (node) => (node.value = 'Penlline Road, Whitchurch, Cardiff, CF14 2N')); await page.type('.ons-js-autosuggest-input', 'Z'); - await page.waitForTimeout(100); + await setTimeout(100); }); it('provides expected parameters to the address API', async () => { @@ -328,7 +331,7 @@ describe('script: address-input', () => { beforeEach(async () => { await page.keyboard.press('ArrowDown'); await page.keyboard.press('Enter'); - await page.waitForTimeout(100); + await setTimeout(100); }); it('makes expected request when a suggestion is selected', async () => { @@ -352,7 +355,7 @@ describe('script: address-input', () => { await page.$eval('.ons-js-autosuggest-input', (node) => (node.value = 'CF14 ')); await page.type('.ons-js-autosuggest-input', '2'); - await page.waitForTimeout(200); + await setTimeout(200); }); it('provides expected parameters to the address API', async () => { @@ -371,7 +374,7 @@ describe('script: address-input', () => { beforeEach(async () => { await page.keyboard.press('ArrowDown'); await page.keyboard.press('Enter'); - await page.waitForTimeout(200); + await setTimeout(200); }); it('makes expected request', async () => { @@ -393,7 +396,7 @@ describe('script: address-input', () => { beforeEach(async () => { await page.keyboard.press('ArrowDown'); await page.keyboard.press('Enter'); - await page.waitForTimeout(200); + await setTimeout(200); }); it('populates manual input fields with address from selection', async () => { @@ -437,7 +440,7 @@ describe('script: address-input', () => { await page.type('.ons-js-autosuggest-input', '2', { delay: 20 }); await page.keyboard.press('ArrowDown'); await page.keyboard.press('Enter'); - await page.waitForTimeout(100); + await setTimeout(100); const isManualElementHidden = await page.$eval('.ons-js-address-input__manual', (node) => node.classList.contains('ons-u-db-no-js_enabled'), @@ -480,7 +483,7 @@ describe('script: address-input', () => { await page.type('.ons-js-autosuggest-input', 'T', { delay: 20 }); await page.keyboard.press('ArrowDown'); await page.keyboard.press('Enter'); - await page.waitForTimeout(100); + await setTimeout(100); const urpnValueBefore = await page.$eval('.ons-js-hidden-uprn', (node) => node.value); expect(urpnValueBefore).toBe('100070332099'); @@ -619,7 +622,7 @@ describe('script: address-input', () => { await page.keyboard.press('ArrowDown'); await page.keyboard.press('Enter'); - await page.waitForTimeout(50); + await setTimeout(50); }); it('then the retrieveAddress function will be called', async () => { @@ -730,6 +733,8 @@ describe('script: address-input', () => { await page.$eval('.ons-js-autosuggest-input', (node) => (node.value = '196 coll')); await page.type('.ons-js-autosuggest-input', 'e'); + await setTimeout(50); + expect(apiFaker.getRequestCount(searchEndpoint)).toBe(1); }); @@ -739,7 +744,7 @@ describe('script: address-input', () => { await page.keyboard.press('ArrowDown'); await page.keyboard.press('Enter'); - await page.waitForTimeout(50); + await setTimeout(50); expect(apiFaker.getRequestCount(uprnEndpoint)).toBe(1); }); diff --git a/src/components/autosuggest/autosuggest.spec.js b/src/components/autosuggest/autosuggest.spec.js index ff502c29e0..f79058abec 100644 --- a/src/components/autosuggest/autosuggest.spec.js +++ b/src/components/autosuggest/autosuggest.spec.js @@ -53,6 +53,8 @@ const EXAMPLE_AUTOSUGGEST_WITH_LANGUAGE = { language: 'en-gb', }; +const { setTimeout } = require('node:timers/promises'); + describe('script: autosuggest', () => { const apiFaker = new PuppeteerEndpointFaker('/test/fake/api'); @@ -298,11 +300,11 @@ describe('script: autosuggest', () => { const suggestionCountSample1 = await page.$$eval('.ons-autosuggest__option', (nodes) => nodes.length); expect(suggestionCountSample1).toBe(2); - await page.waitForTimeout(200); + await setTimeout(200); const suggestionCountSample2 = await page.$$eval('.ons-autosuggest__option', (nodes) => nodes.length); expect(suggestionCountSample2).toBe(2); - await page.waitForTimeout(320); + await setTimeout(320); const suggestionCountSample3 = await page.$$eval('.ons-autosuggest__option', (nodes) => nodes.length); expect(suggestionCountSample3).toBe(0); }); @@ -312,7 +314,7 @@ describe('script: autosuggest', () => { await page.type('.ons-js-autosuggest-input', 'Unite', { delay: 20 }); await page.keyboard.press('Tab'); - await page.waitForTimeout(320); + await setTimeout(320); const listboxInnerHTML = await page.$eval('.ons-js-autosuggest-listbox', (node) => node.innerHTML); expect(listboxInnerHTML).toBe(''); @@ -323,7 +325,7 @@ describe('script: autosuggest', () => { await page.type('.ons-js-autosuggest-input', 'Unite', { delay: 20 }); await page.keyboard.press('Tab'); - await page.waitForTimeout(320); + await setTimeout(320); const hasClass = await page.$eval('.ons-autosuggest', (node) => node.classList.contains('ons-autosuggest--has-results')); expect(hasClass).toBe(false); @@ -334,7 +336,7 @@ describe('script: autosuggest', () => { await page.type('.ons-js-autosuggest-input', 'Unite', { delay: 20 }); await page.keyboard.press('Tab'); - await page.waitForTimeout(320); + await setTimeout(320); const attributes = await getNodeAttributes(page, '.ons-js-autosuggest-input'); expect(attributes['aria-activedescendant']).toBeUndefined(); diff --git a/src/components/back-to-top/back-to-top.spec.js b/src/components/back-to-top/back-to-top.spec.js index b0033b340b..157db0e293 100644 --- a/src/components/back-to-top/back-to-top.spec.js +++ b/src/components/back-to-top/back-to-top.spec.js @@ -1,5 +1,7 @@ import { renderComponent, setTestPage } from '../../tests/helpers/rendering'; +const { setTimeout } = require('node:timers/promises'); + describe('script: back-to-top', () => { beforeEach(async () => { await setTestPage( @@ -98,7 +100,7 @@ describe('script: back-to-top', () => { await page.evaluate(() => { window.scrollTo(0, window.innerHeight * 2); }); - await new Promise((r) => setTimeout(r, 250)); + await setTimeout(250); const previousWidth = await page.evaluate(() => { const node = document.querySelector('.ons-back-to-top > .ons-back-to-top__link').children[0]; return window.getComputedStyle(node).marginLeft; @@ -107,7 +109,7 @@ describe('script: back-to-top', () => { await page.evaluate(() => { window.scrollTo(0, window.innerHeight * 2); }); - await new Promise((r) => setTimeout(r, 250)); + await setTimeout(250); const newWidth = await page.evaluate(() => { const node = document.querySelector('.ons-back-to-top > .ons-back-to-top__link').children[0]; return window.getComputedStyle(node).marginLeft; diff --git a/src/components/cookies-banner/cookies-banner.spec.js b/src/components/cookies-banner/cookies-banner.spec.js index 7fdd4e262e..7263016b16 100644 --- a/src/components/cookies-banner/cookies-banner.spec.js +++ b/src/components/cookies-banner/cookies-banner.spec.js @@ -4,7 +4,7 @@ const EXAMPLE_COOKIES_BANNER_PAGE = renderComponent('cookies-banner', {}); describe('script: cookies-banner', () => { beforeEach(async () => { - const client = await page.target().createCDPSession(); + const client = await page.createCDPSession(); await client.send('Network.clearBrowserCookies'); }); diff --git a/src/components/mutually-exclusive/mutually-exclusive.checkboxes.spec.js b/src/components/mutually-exclusive/mutually-exclusive.checkboxes.spec.js index 091ad1cb12..6432d3b9ae 100644 --- a/src/components/mutually-exclusive/mutually-exclusive.checkboxes.spec.js +++ b/src/components/mutually-exclusive/mutually-exclusive.checkboxes.spec.js @@ -60,6 +60,8 @@ const EXAMPLE_MUTUALLY_EXCLUSIVE_CHECKBOXES_PARAMS = { }, }; +const { setTimeout } = require('node:timers/promises'); + describe('script: mutually-exclusive', () => { describe('checkboxes', () => { beforeEach(async () => { @@ -93,7 +95,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria-live message should reflect the removed non exclusive options', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('Gas deselected. Electric deselected. Other deselected. Please specify deselected.'); @@ -125,7 +127,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria-live message should reflect the removed exclusive option', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('No central heating deselected.'); @@ -137,7 +139,7 @@ describe('script: mutually-exclusive', () => { }); it('the aria-live message should not be updated', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('No central heating deselected.'); @@ -166,7 +168,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria-live message should say nothing', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); @@ -192,7 +194,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria-live message should say nothing', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); diff --git a/src/components/mutually-exclusive/mutually-exclusive.date.spec.js b/src/components/mutually-exclusive/mutually-exclusive.date.spec.js index 6a44ede9fc..2e55b845b6 100644 --- a/src/components/mutually-exclusive/mutually-exclusive.date.spec.js +++ b/src/components/mutually-exclusive/mutually-exclusive.date.spec.js @@ -70,6 +70,8 @@ const EXAMPLE_MUTUALLY_EXCLUSIVE_DATE_SINGLE_PARAMS = { }, }; +const { setTimeout } = require('node:timers/promises'); + describe('script: mutually-exclusive', () => { describe('date', () => { beforeEach(async () => { @@ -103,7 +105,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert should tell the user that the date input has been cleared', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('Day cleared. Month cleared. Year cleared.'); @@ -129,7 +131,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('I have never had a paid job deselected.'); @@ -146,7 +148,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert shouldnt say anything', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); @@ -159,7 +161,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert shouldnt say anything', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); @@ -193,7 +195,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert should tell the user that the date input has been cleared', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('What year was your last MOT? cleared.'); @@ -217,7 +219,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('I have never had a paid job deselected.'); @@ -232,7 +234,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert shouldnt say anything', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); @@ -245,7 +247,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert shouldnt say anything', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); diff --git a/src/components/mutually-exclusive/mutually-exclusive.duration.spec.js b/src/components/mutually-exclusive/mutually-exclusive.duration.spec.js index d8161383b3..3704e22389 100644 --- a/src/components/mutually-exclusive/mutually-exclusive.duration.spec.js +++ b/src/components/mutually-exclusive/mutually-exclusive.duration.spec.js @@ -70,6 +70,8 @@ const EXAMPLE_MUTUALLY_EXCLUSIVE_DURATION_SINGLE_PARAMS = { }, }; +const { setTimeout } = require('node:timers/promises'); + describe('script: mutually-exclusive', () => { describe('duration', () => { beforeEach(async () => { @@ -100,7 +102,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert should tell the user that the inputs have been cleared', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('Years cleared. Months cleared.'); @@ -125,7 +127,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('I have not moved in to this address yet deselected.'); @@ -141,7 +143,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert shouldnt say anything', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); @@ -154,7 +156,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert shouldnt say anything', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); @@ -189,7 +191,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert should tell the user that the inputs have been cleared', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('How long have you lived at this address? cleared.'); @@ -213,7 +215,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('I have not moved in to this address yet deselected.'); @@ -228,7 +230,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert shouldnt say anything', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); @@ -241,7 +243,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert shouldnt say anything', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); diff --git a/src/components/mutually-exclusive/mutually-exclusive.email.spec.js b/src/components/mutually-exclusive/mutually-exclusive.email.spec.js index 24794ac21d..1c289e1163 100644 --- a/src/components/mutually-exclusive/mutually-exclusive.email.spec.js +++ b/src/components/mutually-exclusive/mutually-exclusive.email.spec.js @@ -27,6 +27,8 @@ const EXAMPLE_MUTUALLY_EXCLUSIVE_EMAIL_INPUT_PARAMS = { }, }; +const { setTimeout } = require('node:timers/promises'); + describe('script: mutually-exclusive', () => { describe('email input', () => { beforeEach(async () => { @@ -54,7 +56,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert should tell the user that the email input has been cleared', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('Enter an email cleared.'); @@ -78,7 +80,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('I dont want to receive a confirmation email deselected.'); @@ -93,7 +95,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert shouldnt say anything', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); @@ -106,7 +108,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert shouldnt say anything', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); diff --git a/src/components/mutually-exclusive/mutually-exclusive.multiple-options.checkboxes.spec.js b/src/components/mutually-exclusive/mutually-exclusive.multiple-options.checkboxes.spec.js index 2a7b6f79f3..396ecdd21a 100644 --- a/src/components/mutually-exclusive/mutually-exclusive.multiple-options.checkboxes.spec.js +++ b/src/components/mutually-exclusive/mutually-exclusive.multiple-options.checkboxes.spec.js @@ -67,6 +67,8 @@ const EXAMPLE_MUTUALLY_EXCLUSIVE_CHECKBOXES_PARAMS = { }, }; +const { setTimeout } = require('node:timers/promises'); + describe('script: mutually-exclusive', () => { describe('checkboxes', () => { beforeEach(async () => { @@ -100,7 +102,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria-live message should reflect the removed non exclusive options', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('Gas deselected. Electric deselected. Other deselected. Please specify deselected.'); @@ -133,7 +135,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria-live message should reflect the removed exclusive option', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('Dont know deselected.'); @@ -145,7 +147,7 @@ describe('script: mutually-exclusive', () => { }); it('the aria-live message should not be updated', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('Dont know deselected.'); @@ -175,7 +177,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria-live message should say nothing', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); @@ -202,7 +204,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria-live message should say nothing', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); diff --git a/src/components/mutually-exclusive/mutually-exclusive.number.spec.js b/src/components/mutually-exclusive/mutually-exclusive.number.spec.js index d2dd0cbe16..3fb34423a3 100644 --- a/src/components/mutually-exclusive/mutually-exclusive.number.spec.js +++ b/src/components/mutually-exclusive/mutually-exclusive.number.spec.js @@ -33,6 +33,8 @@ const EXAMPLE_MUTUALLY_EXCLUSIVE_NUMBER_INPUT_PARAMS = { }, }; +const { setTimeout } = require('node:timers/promises'); + describe('script: mutually-exclusive', () => { describe('number input', () => { beforeEach(async () => { @@ -60,7 +62,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert should tell the user that the number input has been cleared', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('Gross annual income cleared.'); @@ -84,7 +86,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('I prefer not to say deselected.'); @@ -99,7 +101,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert shouldnt say anything', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); @@ -112,7 +114,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert shouldnt say anything', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); diff --git a/src/components/mutually-exclusive/mutually-exclusive.textarea.spec.js b/src/components/mutually-exclusive/mutually-exclusive.textarea.spec.js index d7fea99544..7449837e34 100644 --- a/src/components/mutually-exclusive/mutually-exclusive.textarea.spec.js +++ b/src/components/mutually-exclusive/mutually-exclusive.textarea.spec.js @@ -34,6 +34,8 @@ const EXAMPLE_MUTUALLY_EXCLUSIVE_TEXTAREA_PARAMS = { }, }; +const { setTimeout } = require('node:timers/promises'); + const FAKE_TEXTAREA_INPUT = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; describe('script: mutually-exclusive', () => { @@ -68,7 +70,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert should tell the user that the textarea has been cleared', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('Enter your feedback cleared.'); @@ -92,7 +94,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe('I dont want to provide feedback deselected.'); @@ -107,7 +109,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert shouldnt say anything', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); @@ -120,7 +122,7 @@ describe('script: mutually-exclusive', () => { }); it('then the aria alert shouldnt say anything', async () => { - await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY); + await setTimeout(SCREEN_READER_TIMEOUT_DELAY); const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent); expect(alertText).toBe(''); diff --git a/src/components/navigation/navigation.spec.js b/src/components/navigation/navigation.spec.js index 39709977ab..f6b485f070 100644 --- a/src/components/navigation/navigation.spec.js +++ b/src/components/navigation/navigation.spec.js @@ -230,12 +230,14 @@ describe('script: navigation', () => { }); describe('when the toggle button is clicked to close the navigation list', () => { + const { setTimeout } = require('node:timers/promises'); + beforeEach(async () => { await page.focus(buttonEl); await page.keyboard.press('Enter'); - await page.waitForTimeout(100); + await setTimeout(100); await page.keyboard.press('Enter'); - await page.waitForTimeout(100); + await setTimeout(100); }); it('has aria-hidden set as `true` on the navigation list', async () => { @@ -270,14 +272,14 @@ describe('script: navigation', () => { it('has the aria-hidden attribute removed from the navigation list', async () => { const nav = await page.$(navEl); - const hasAriaAttribute = await nav.evaluate((node) => node.getAttribute('aria-hidden') !== null); - expect(hasAriaAttribute).toBe(false); + const hasAriaAttribute = await nav.evaluate((node) => node.getAttribute('aria-hidden') === null); + expect(hasAriaAttribute).toBe(true); }); it('has aria-expanded removed from the navigation toggle button', async () => { const button = await page.$(buttonEl); - const hasAriaExpanded = await button.evaluate((node) => node.getAttribute('aria-expanded') !== null); - expect(hasAriaExpanded).toBe(false); + const hasAriaExpanded = await button.evaluate((node) => node.getAttribute('aria-expanded') === null); + expect(hasAriaExpanded).toBe(true); }); it('has the hide class removed from the navigation list', async () => { diff --git a/src/components/table-of-contents/toc.spec.js b/src/components/table-of-contents/toc.spec.js index 9b040392a9..dd994c002b 100644 --- a/src/components/table-of-contents/toc.spec.js +++ b/src/components/table-of-contents/toc.spec.js @@ -1,5 +1,7 @@ import { renderComponent, setTestPage } from '../../tests/helpers/rendering'; +const { setTimeout } = require('node:timers/promises'); + describe('script: table-of-contents', () => { beforeEach(async () => { await setTestPage( @@ -55,7 +57,7 @@ describe('script: table-of-contents', () => { ['section3', 'Third section'], ])('marks "%s" as the current section', async (sectionId, sectionTitle) => { await page.$eval(`#${sectionId}`, (node) => node.scrollIntoView()); - await page.waitForTimeout(250); + await setTimeout(250); const activeSection = await page.$eval('.ons-toc__link-active', (node) => node.innerText.trim()); expect(activeSection).toBe(sectionTitle); @@ -154,7 +156,7 @@ describe('script: table-of-contents-fixed-position', () => { window.scrollTo(0, 1000); }); - await page.waitForTimeout(250); + await setTimeout(250); const leftColumn = await page.$('#sticky-container'); const boundingBox = await leftColumn.boundingBox(); diff --git a/src/components/table/table.spec.js b/src/components/table/table.spec.js index bfadc29c6b..aa25819294 100644 --- a/src/components/table/table.spec.js +++ b/src/components/table/table.spec.js @@ -31,7 +31,7 @@ describe('script: table', () => { }); it('should show both shadow elements', async () => { - await page.waitForTimeout(200); + await new Promise((r) => setTimeout(r, 200)); const leftShadowVisibleCount = await page.$$eval('.ons-table__left-shadow.ons-visible', (nodes) => nodes.length); expect(leftShadowVisibleCount).not.toBe(0); diff --git a/src/components/timeout-modal/timeout-modal.spec.js b/src/components/timeout-modal/timeout-modal.spec.js index 8ed4c6e28d..fa2538ff96 100644 --- a/src/components/timeout-modal/timeout-modal.spec.js +++ b/src/components/timeout-modal/timeout-modal.spec.js @@ -14,20 +14,22 @@ const EXAMPLE_TIMEOUT_MODAL_BASIC = { endWithFullStop: true, }; +const { setTimeout } = require('node:timers/promises'); + describe('script: timeout modal', () => { describe('when the page loads', () => { beforeEach(async () => { const component = renderComponent('timeout-modal', { ...EXAMPLE_TIMEOUT_MODAL_BASIC, showModalTimeInSeconds: 58 }); const template = ` -
- ${component} -
- `; +
+ ${component} +
+ `; await setTestPage('/test', template); }); it('displays the modal after the correct number of seconds', async () => { - await page.waitForTimeout(2000); + await setTimeout(2000); const modalIsVisible = await page.$eval('.ons-modal', (node) => node.classList.contains('ons-u-db')); expect(modalIsVisible).toBe(true); }); @@ -42,17 +44,17 @@ describe('script: timeout modal', () => { }); const template = ` -
- ${component} -
- `; +
+ ${component} +
+ `; await setTestPage('/test', template); }); it('shows the time counting down', async () => { const timeAtStart = await page.$eval('.ons-js-timeout-timer span', (element) => element.innerHTML); - await page.waitForTimeout(1000); + await setTimeout(1000); const timeAfterOneSecond = await page.$eval('.ons-js-timeout-timer span', (element) => element.innerHTML); expect(timeAfterOneSecond).not.toEqual(timeAtStart); }); @@ -70,10 +72,10 @@ describe('script: timeout modal', () => { }); const template = ` -
- ${component} -
- `; +
+ ${component} +
+ `; await setTestPage('/test', template); }); @@ -95,10 +97,10 @@ describe('script: timeout modal', () => { }); const template = ` -
- ${component} -
- `; +
+ ${component} +
+ `; await setTestPage('/test', template); }); @@ -120,10 +122,10 @@ describe('script: timeout modal', () => { }); const template = ` -
- ${component} -
- `; +
+ ${component} +
+ `; await setTestPage('/test', template); }); @@ -145,10 +147,10 @@ describe('script: timeout modal', () => { }); const template = ` -
- ${component} -
- `; +
+ ${component} +
+ `; await setTestPage('/test', template); }); @@ -170,10 +172,10 @@ describe('script: timeout modal', () => { }); const template = ` -
- ${component} -
- `; +
+ ${component} +
+ `; await setTestPage('/test', template); }); @@ -183,7 +185,7 @@ describe('script: timeout modal', () => { }); it('then redirects to the provided `redirectUrl`', async () => { - await page.waitForTimeout(2000); + await setTimeout(2000); expect(page.url()).toContain('#!'); }); }); @@ -197,10 +199,10 @@ describe('script: timeout modal', () => { }); const template = ` -
- ${component} -
- `; +
+ ${component} +
+ `; await setTestPage('/test', template); }); @@ -213,11 +215,14 @@ describe('script: timeout modal', () => { it('closes the modal', async () => { const modalIsVisible = await page.$eval('.ons-modal', (node) => node.classList.contains('ons-u-db')); + + await setTimeout(50); + expect(modalIsVisible).toBe(false); }); it('restarts the timer and displays the modal after the correct number of seconds', async () => { - await page.waitForTimeout(2000); + await setTimeout(2000); const modalIsVisible = await page.$eval('.ons-modal', (node) => node.classList.contains('ons-u-db')); expect(modalIsVisible).toBe(true); }); diff --git a/src/components/timeout-panel/timeout-panel.spec.js b/src/components/timeout-panel/timeout-panel.spec.js index c2b8b5541d..db8392c930 100644 --- a/src/components/timeout-panel/timeout-panel.spec.js +++ b/src/components/timeout-panel/timeout-panel.spec.js @@ -13,6 +13,8 @@ const EXAMPLE_TIMEOUT_PANEL_BASIC = { endWithFullStop: true, }; +const { setTimeout } = require('node:timers/promises'); + describe('script: timeout panel', () => { describe('when the page loads', () => { beforeEach(async () => { @@ -29,7 +31,7 @@ describe('script: timeout panel', () => { it('shows the time counting down', async () => { const timeAtStart = await page.$eval('.ons-js-timeout-timer', (element) => element.innerHTML); - await page.waitForTimeout(1000); + await setTimeout(1000); const timeAfterOneSecond = await page.$eval('.ons-js-timeout-timer', (element) => element.innerHTML); expect(timeAfterOneSecond).not.toEqual(timeAtStart); }); @@ -130,7 +132,7 @@ describe('script: timeout panel', () => { }); it('then redirects to the provided `redirectUrl`', async () => { - await page.waitForTimeout(2000); + await setTimeout(2000); expect(page.url()).toContain('#!'); }); }); diff --git a/src/components/video/video.spec.js b/src/components/video/video.spec.js index 5a632e8f03..15f45a7b01 100644 --- a/src/components/video/video.spec.js +++ b/src/components/video/video.spec.js @@ -1,10 +1,13 @@ import { renderComponent, setTestPage } from '../../tests/helpers/rendering'; +const { setTimeout } = require('node:timers/promises'); + const EXAMPLE_VIDEO_YOUTUBE = { videoEmbedUrl: 'https://www.youtube.com/embed/_EGJlvkgbPo', title: 'Census 2021 promotional TV advert', linkText: 'Example link text', }; + const EXAMPLE_VIDEO_VIMEO = { videoEmbedUrl: 'https://player.vimeo.com/video/838454524?h=24551a3754', title: 'Vimeo Video', @@ -14,112 +17,133 @@ const EXAMPLE_VIDEO_VIMEO = { const EXAMPLE_APPROVED_COOKIE = JSON.stringify({ campaigns: true }).replace(/"/g, "'"); describe('script: video', () => { - beforeEach(async () => { - const client = await page.target().createCDPSession(); - await client.send('Network.clearBrowserCookies'); - }); - - it('should show the placeholder content', async () => { - await setTestPage('/test', renderComponent('video', EXAMPLE_VIDEO_YOUTUBE)); - - const displayStyle = await page.$eval('.ons-js-video-placeholder', (node) => - window.getComputedStyle(node).getPropertyValue('display'), - ); - expect(displayStyle).toBe('block'); - }); - - it('should not show the iframe', async () => { - await setTestPage('/test', renderComponent('video', EXAMPLE_VIDEO_YOUTUBE)); - - const displayStyle = await page.$eval('.ons-js-video-iframe', (node) => window.getComputedStyle(node).getPropertyValue('display')); - expect(displayStyle).toBe('none'); - }); - - describe('when cookies are accepted on page load', () => { + describe('YouTube videos', () => { beforeEach(async () => { - await page.setCookie({ - name: 'ons_cookie_policy', - value: EXAMPLE_APPROVED_COOKIE, - }); + const client = await page.createCDPSession(); + await client.send('Network.clearBrowserCookies'); + }); + it('should show the placeholder content', async () => { await setTestPage('/test', renderComponent('video', EXAMPLE_VIDEO_YOUTUBE)); - }); - it('should hide the placeholder content', async () => { const displayStyle = await page.$eval('.ons-js-video-placeholder', (node) => window.getComputedStyle(node).getPropertyValue('display'), ); - expect(displayStyle).toBe('none'); - }, 10000); + expect(displayStyle).toBe('block'); + }); + + it('should not show the iframe', async () => { + await setTestPage('/test', renderComponent('video', EXAMPLE_VIDEO_YOUTUBE)); - it('should show the iframe', async () => { const displayStyle = await page.$eval('.ons-js-video-iframe', (node) => window.getComputedStyle(node).getPropertyValue('display'), ); - expect(displayStyle).toBe('block'); - }, 10000); + expect(displayStyle).toBe('none'); + }); - it('should add the correct modifier class', async () => { - const hasClass = await page.$eval('.ons-js-video', (node) => node.classList.contains('ons-video--hasIframe')); - expect(hasClass).toBe(true); - }, 10000); + describe('when cookies are accepted on page load', () => { + beforeEach(async () => { + await page.setCookie({ + name: 'ons_cookie_policy', + value: EXAMPLE_APPROVED_COOKIE, + }); - it('should not add dnt to YouTube videos', async () => { - const src = await page.$eval('.ons-js-video-iframe', (node) => node.getAttribute('src')); - expect(src.includes('?dnt=1')).toBe(false); - }, 10000); + await setTestPage('/test', renderComponent('video', EXAMPLE_VIDEO_YOUTUBE)); + }); - it('should add dnt to Vimeo videos', async () => { - await setTestPage('/test', renderComponent('video', EXAMPLE_VIDEO_VIMEO)); + it('should hide the placeholder content', async () => { + const displayStyle = await page.$eval('.ons-js-video-placeholder', (node) => + window.getComputedStyle(node).getPropertyValue('display'), + ); + expect(displayStyle).toBe('none'); + }, 10000); + + it('should show the iframe', async () => { + const displayStyle = await page.$eval('.ons-js-video-iframe', (node) => + window.getComputedStyle(node).getPropertyValue('display'), + ); + expect(displayStyle).toBe('block'); + }, 10000); + + it('should add the correct modifier class', async () => { + const hasClass = await page.$eval('.ons-js-video', (node) => node.classList.contains('ons-video--hasIframe')); + expect(hasClass).toBe(true); + }, 10000); + + it('should not add dnt', async () => { + const src = await page.$eval('.ons-js-video-iframe', (node) => node.getAttribute('src')); + expect(src.includes('?dnt=1')).toBe(false); + }, 10000); + }); - const src = await page.$eval('.ons-js-video-iframe', (node) => node.getAttribute('src')); - expect(src.includes('?dnt=1')).toBe(true); - }, 10000); - }); + describe('when cookies are accepted via banner', () => { + beforeEach(async () => { + await setTestPage( + '/test', + `${renderComponent('video', EXAMPLE_VIDEO_YOUTUBE)} +
`, + ); + await page.click('.ons-js-accept-cookies'); + }); - describe('when cookies are accepted via banner', () => { - beforeEach(async () => { - await setTestPage( - '/test', - `${renderComponent('video', EXAMPLE_VIDEO_YOUTUBE)} -
`, - ); - await page.click('.ons-js-accept-cookies'); - }); + it('should hide the placeholder content', async () => { + const displayStyle = await page.$eval('.ons-js-video-placeholder', (node) => + window.getComputedStyle(node).getPropertyValue('display'), + ); + expect(displayStyle).toBe('none'); + }); - it('should hide the placeholder content', async () => { - const displayStyle = await page.$eval('.ons-js-video-placeholder', (node) => - window.getComputedStyle(node).getPropertyValue('display'), - ); - expect(displayStyle).toBe('none'); + it('should show the iframe', async () => { + const displayStyle = await page.$eval('.ons-js-video-iframe', (node) => + window.getComputedStyle(node).getPropertyValue('display'), + ); + expect(displayStyle).toBe('block'); + }); + + it('should add the correct modifier class', async () => { + const hasClass = await page.$eval('.ons-js-video', (node) => node.classList.contains('ons-video--hasIframe')); + expect(hasClass).toBe(true); + }, 10000); + + it('should not add dnt', async () => { + const src = await page.$eval('.ons-js-video-iframe', (node) => node.getAttribute('src')); + expect(src.includes('?dnt=1')).toBe(false); + }, 10000); }); + }); - it('should show the iframe', async () => { - const displayStyle = await page.$eval('.ons-js-video-iframe', (node) => - window.getComputedStyle(node).getPropertyValue('display'), - ); - expect(displayStyle).toBe('block'); + describe('Vimeo videos', () => { + describe('when cookies are accepted on page load', () => { + it('should add dnt', async () => { + await page.setCookie({ + name: 'ons_cookie_policy', + value: EXAMPLE_APPROVED_COOKIE, + }); + await setTestPage('/test', renderComponent('video', EXAMPLE_VIDEO_VIMEO)); + + const src = await page.$eval('.ons-js-video-iframe', (node) => node.getAttribute('src')); + + await setTimeout(100); + + expect(src.includes('?dnt=1')).toBe(true); + }, 10000); }); - it('should add the correct modifier class', async () => { - const hasClass = await page.$eval('.ons-js-video', (node) => node.classList.contains('ons-video--hasIframe')); - expect(hasClass).toBe(true); - }, 10000); - it('should not add dnt to YouTube videos', async () => { - const src = await page.$eval('.ons-js-video-iframe', (node) => node.getAttribute('src')); - expect(src.includes('?dnt=1')).toBe(false); - }, 10000); - - it('should add dnt to Vimeo videos', async () => { - await setTestPage( - '/test', - `${renderComponent('video', EXAMPLE_VIDEO_VIMEO)} -
`, - ); - await page.click('.ons-js-accept-cookies'); + describe('when cookies are accepted on page load', () => { + it('when cookies are accepted via banner, should add dnt', async () => { + await setTestPage( + '/test', + `${renderComponent('video', EXAMPLE_VIDEO_VIMEO)} +
`, + ); + await page.click('.ons-js-accept-cookies'); - const src = await page.$eval('.ons-js-video-iframe', (node) => node.getAttribute('src')); - expect(src.includes('?dnt=1')).toBe(true); - }, 10000); + const src = await page.$eval('.ons-js-video-iframe', (node) => node.getAttribute('src')); + + await setTimeout(100); + + expect(src.includes('?dnt=1')).toBe(true); + }, 10000); + }); }); }); diff --git a/src/js/cookies-settings.spec.js b/src/js/cookies-settings.spec.js index d95f267f94..7d27596ae0 100644 --- a/src/js/cookies-settings.spec.js +++ b/src/js/cookies-settings.spec.js @@ -38,7 +38,7 @@ const EXAMPLE_PART_COOKIES_SETTINGS_PAGE = ` describe('script: cookies-settings', () => { beforeEach(async () => { - const client = await page.target().createCDPSession(); + const client = await page.createCDPSession(); await client.send('Network.clearBrowserCookies'); }); diff --git a/src/tests/helpers/puppeteer.js b/src/tests/helpers/puppeteer.js index b06fbb97fe..b69556038a 100644 --- a/src/tests/helpers/puppeteer.js +++ b/src/tests/helpers/puppeteer.js @@ -16,7 +16,7 @@ export async function getNodeAttributes(page, selector) { export async function setViewport(page, viewport) { await page.setViewport(viewport); - await page.waitForTimeout(100); + await page.evaluate(() => new Promise((r) => setTimeout(r, 100))); } function sanitizeHref(href) { diff --git a/yarn.lock b/yarn.lock index d01063ad71..c467968be2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1132,12 +1132,12 @@ normalize-path "^2.0.1" through2 "^2.0.3" -"@hapi/hoek@^9.0.0": +"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== -"@hapi/topo@^5.0.0": +"@hapi/topo@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== @@ -1532,6 +1532,20 @@ unbzip2-stream "1.4.3" yargs "17.7.1" +"@puppeteer/browsers@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.3.0.tgz#791ea7d80450fea24eb19fb1d70c367ad4e08cae" + integrity sha512-ioXoq9gPxkss4MYhD+SFaU9p1IHFUX0ILAWFPyjGaBdjLsYAlZw6j1iLA0N/m12uVHLFDfSYNF7EQccjinIMDA== + dependencies: + debug "^4.3.5" + extract-zip "^2.0.1" + progress "^2.0.3" + proxy-agent "^6.4.0" + semver "^7.6.3" + tar-fs "^3.0.6" + unbzip2-stream "^1.4.3" + yargs "^17.7.2" + "@sentry/core@6.19.7": version "6.19.7" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.19.7.tgz#156aaa56dd7fad8c89c145be6ad7a4f7209f9785" @@ -1588,10 +1602,10 @@ "@sentry/types" "6.19.7" tslib "^1.9.3" -"@sideway/address@^4.1.3": - version "4.1.4" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" - integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== +"@sideway/address@^4.1.5": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" + integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== dependencies: "@hapi/hoek" "^9.0.0" @@ -2331,13 +2345,14 @@ axios@0.21.4: dependencies: follow-redirects "^1.14.0" -axios@^0.27.2: - version "0.27.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" - integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== +axios@^1.6.1: + version "1.7.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" + integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== dependencies: - follow-redirects "^1.14.9" + follow-redirects "^1.15.6" form-data "^4.0.0" + proxy-from-env "^1.1.0" b4a@^1.6.4: version "1.6.4" @@ -2487,6 +2502,39 @@ balanced-match@^2.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-2.0.0.tgz#dc70f920d78db8b858535795867bf48f820633d9" integrity sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA== +bare-events@^2.0.0, bare-events@^2.2.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.4.2.tgz#3140cca7a0e11d49b3edc5041ab560659fd8e1f8" + integrity sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q== + +bare-fs@^2.1.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-2.3.1.tgz#cdbd63dac7a552dfb2b87d18c822298d1efd213d" + integrity sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA== + dependencies: + bare-events "^2.0.0" + bare-path "^2.0.0" + bare-stream "^2.0.0" + +bare-os@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/bare-os/-/bare-os-2.4.0.tgz#5de5e3ba7704f459c9656629edca7cc736e06608" + integrity sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg== + +bare-path@^2.0.0, bare-path@^2.1.0: + version "2.1.3" + resolved "https://registry.yarnpkg.com/bare-path/-/bare-path-2.1.3.tgz#594104c829ef660e43b5589ec8daef7df6cedb3e" + integrity sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA== + dependencies: + bare-os "^2.1.0" + +bare-stream@^2.0.0: + version "2.1.3" + resolved "https://registry.yarnpkg.com/bare-stream/-/bare-stream-2.1.3.tgz#070b69919963a437cc9e20554ede079ce0a129b2" + integrity sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ== + dependencies: + streamx "^2.18.0" + base64-js@^1.0.2, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -3090,6 +3138,15 @@ chromium-bidi@0.4.7: dependencies: mitt "3.0.0" +chromium-bidi@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.6.3.tgz#363fe1ca6b9c6122b9f1b2a47f9449ecf712f755" + integrity sha512-qXlsCmpCZJAnoTYI83Iu6EdYQpMYdVkCfq08KDh2pmlVqK5t5IA9mGs4/LwCwp4fqisSOMXZxP3HIh8w8aRn0A== + dependencies: + mitt "3.0.1" + urlpattern-polyfill "10.0.0" + zod "3.23.8" + ci-info@^3.2.0, ci-info@^3.8.0: version "3.9.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" @@ -3489,7 +3546,7 @@ cosmiconfig@8.1.3: parse-json "^5.0.0" path-type "^4.0.0" -cosmiconfig@8.3.6, cosmiconfig@^8.3.6: +cosmiconfig@^8.3.6: version "8.3.6" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== @@ -3745,6 +3802,20 @@ debug@4.3.2: dependencies: ms "2.1.2" +debug@^4.3.5: + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + dependencies: + ms "2.1.2" + +debug@^4.3.6: + version "4.3.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" + integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== + dependencies: + ms "2.1.2" + decamelize@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -3975,6 +4046,11 @@ devtools-protocol@0.0.1200039: resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1200039.tgz#5a546df3edff52e6226abfc26f559e05647c956b" integrity sha512-ZQCB/hbFmu23fLrR3OX3FEJ56dBHXBO+OrnXBtutZzJmIRWycDb7Yz4aO7BiFF9moUgBS+Xo7+EAWZhZraOUfg== +devtools-protocol@0.0.1312386: + version "0.0.1312386" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz#5ab824d6f1669ec6c6eb0fba047e73601d969052" + integrity sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA== + dialog-polyfill@^0.5.6: version "0.5.6" resolved "https://registry.yarnpkg.com/dialog-polyfill/-/dialog-polyfill-0.5.6.tgz#7507b4c745a82fcee0fa07ce64d835979719599a" @@ -4653,10 +4729,10 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" -expect-puppeteer@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/expect-puppeteer/-/expect-puppeteer-9.0.1.tgz#2c2efa55984939f0d2bd8dd1443a2d3c3c26d5d0" - integrity sha512-LqGzoyW4XgZbfJadjllSMCwZflX9gVBqjFUg8qde+etXr/SEFWLBgn98nRAmO3hUjMRNyh5gIFcaSi4DzHAWLw== +expect-puppeteer@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/expect-puppeteer/-/expect-puppeteer-10.0.0.tgz#4b00c7a0636ecb776365d90396949ebf4710d804" + integrity sha512-E7sE6nVdEbrnpDOBMmcLgyqLJKt876AlBg1A+gsu5R8cWx+SLafreOgJAgzXg5Qko7Tk0cW5oZdRbHQLU738dg== expect@^29.7.0: version "29.7.0" @@ -4747,7 +4823,7 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-zip@2.0.1: +extract-zip@2.0.1, extract-zip@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== @@ -4778,7 +4854,7 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== -fast-fifo@^1.1.0, fast-fifo@^1.2.0: +fast-fifo@^1.1.0, fast-fifo@^1.2.0, fast-fifo@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== @@ -5050,7 +5126,7 @@ flush-write-stream@^1.0.2: inherits "^2.0.3" readable-stream "^2.3.6" -follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.9: +follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.15.6: version "1.15.6" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== @@ -5823,6 +5899,14 @@ http-proxy-agent@^7.0.0: agent-base "^7.1.0" debug "^4.3.4" +http-proxy-agent@^7.0.1: + version "7.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + http-proxy@^1.18.1: version "1.18.1" resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" @@ -5872,6 +5956,14 @@ https-proxy-agent@^7.0.2: agent-base "^7.0.2" debug "4" +https-proxy-agent@^7.0.3: + version "7.0.5" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2" + integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw== + dependencies: + agent-base "^7.0.2" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -6658,18 +6750,18 @@ jest-config@^29.7.0: slash "^3.0.0" strip-json-comments "^3.1.1" -jest-dev-server@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/jest-dev-server/-/jest-dev-server-9.0.1.tgz#75d50b946c94e278401158bcc9a29da23d21204d" - integrity sha512-eqpJKSvVl4M0ojHZUPNbka8yEzLNbIMiINXDsuMF3lYfIdRO2iPqy+ASR4wBQ6nUyR3OT24oKPWhpsfLhgAVyg== +jest-dev-server@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/jest-dev-server/-/jest-dev-server-10.0.0.tgz#a2f3ccd0b9c9e8a493ab73908bc082bedc6b86eb" + integrity sha512-FtyBBDxrAIfTX3hyKSOwj5KU6Z7fFLew5pQYOFpwyf+qpPpULL8aYxtsFkbkAwcs+Mb7qhcNbVLeiWsLOd7CKw== dependencies: chalk "^4.1.2" cwd "^0.10.0" find-process "^1.4.7" prompts "^2.4.2" - spawnd "^9.0.1" + spawnd "^10.0.0" tree-kill "^1.2.2" - wait-on "^7.0.1" + wait-on "^7.2.0" jest-diff@^29.2.1, jest-diff@^29.7.0: version "29.7.0" @@ -6725,15 +6817,15 @@ jest-environment-node@^29.7.0: jest-mock "^29.7.0" jest-util "^29.7.0" -jest-environment-puppeteer@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/jest-environment-puppeteer/-/jest-environment-puppeteer-9.0.1.tgz#1b87f07410652c5a5782ed6693bb04bed593d086" - integrity sha512-5WC3w2+gUNMNVNdeRwyc5xpd9lbTGTVEanESaW3bCW7SIKJKIPMDLgfXhYswW2V6VeHIisuxIDx+hx5qczt4Rw== +jest-environment-puppeteer@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/jest-environment-puppeteer/-/jest-environment-puppeteer-10.0.1.tgz#f69a62606b51beee2d6f21494218bea2ad6643a5" + integrity sha512-FxMzVRyqieQqSy5CPWiwdK5t9dkRHid5eoRTVa8RtYeXLlpW6lU0dAmxEfPkdnDVCiPUhC2APeKOXq0J72bgag== dependencies: chalk "^4.1.2" cosmiconfig "^8.3.6" deepmerge "^4.3.1" - jest-dev-server "^9.0.1" + jest-dev-server "^10.0.0" jest-environment-node "^29.7.0" jest-get-type@^29.2.0, jest-get-type@^29.6.3: @@ -6817,13 +6909,13 @@ jest-pnp-resolver@^1.2.2: resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== -jest-puppeteer@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/jest-puppeteer/-/jest-puppeteer-9.0.1.tgz#a267f0f0abb67806fdede5e20ad8c968743c3781" - integrity sha512-lNWoUCn1zKO6vlD0uvHLBJHvgBmZ7+DKy+Kd6TkQJO4mJ5aDRqeG4XOuy43yYlS2EYVuzqEru2BgbXSpA8V8Vw== +jest-puppeteer@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/jest-puppeteer/-/jest-puppeteer-10.0.1.tgz#c9537ed42b98f6764dc91fa33819e0b20aaaf83b" + integrity sha512-FzC35XbqeuQEt1smXh1EOqhJaRkWqJkyWDMfGkcZ8C59QHXeJ7F/iOmiNqYi6l/OsycUuOPCk+IkjfGfS9YbrQ== dependencies: - expect-puppeteer "^9.0.1" - jest-environment-puppeteer "^9.0.1" + expect-puppeteer "^10.0.0" + jest-environment-puppeteer "^10.0.1" jest-regex-util@^29.6.3: version "29.6.3" @@ -6992,14 +7084,14 @@ jest@^29.6.1: import-local "^3.0.2" jest-cli "^29.7.0" -joi@^17.7.0: - version "17.11.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.11.0.tgz#aa9da753578ec7720e6f0ca2c7046996ed04fc1a" - integrity sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ== +joi@^17.11.0: + version "17.13.3" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec" + integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA== dependencies: - "@hapi/hoek" "^9.0.0" - "@hapi/topo" "^5.0.0" - "@sideway/address" "^4.1.3" + "@hapi/hoek" "^9.3.0" + "@hapi/topo" "^5.1.0" + "@sideway/address" "^4.1.5" "@sideway/formula" "^3.0.1" "@sideway/pinpoint" "^2.0.0" @@ -8267,7 +8359,7 @@ minimatch@~3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@^1.0.0, minimist@^1.1.0, minimist@^1.2.6, minimist@^1.2.7: +minimist@^1.0.0, minimist@^1.1.0, minimist@^1.2.6, minimist@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -9315,7 +9407,7 @@ process@^0.11.1, process@~0.11.0: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -progress@2.0.3: +progress@2.0.3, progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -9350,6 +9442,20 @@ proxy-agent@6.3.1: proxy-from-env "^1.1.0" socks-proxy-agent "^8.0.2" +proxy-agent@^6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.4.0.tgz#b4e2dd51dee2b377748aef8d45604c2d7608652d" + integrity sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ== + dependencies: + agent-base "^7.0.2" + debug "^4.3.4" + http-proxy-agent "^7.0.1" + https-proxy-agent "^7.0.3" + lru-cache "^7.14.1" + pac-proxy-agent "^7.0.1" + proxy-from-env "^1.1.0" + socks-proxy-agent "^8.0.2" + proxy-from-env@1.1.0, proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -9429,7 +9535,18 @@ puppeteer-core@19.11.1: unbzip2-stream "1.4.3" ws "8.13.0" -puppeteer-core@21.3.8, puppeteer-core@^21.3.6: +puppeteer-core@22.15.0: + version "22.15.0" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-22.15.0.tgz#c76926cce5dbc177572797a9dacc325c313fa91a" + integrity sha512-cHArnywCiAAVXa3t4GGL2vttNxh7GqXtIYGym99egkNJ3oG//wL9LkvO4WE8W1TJe95t1F1ocu9X4xWaGsOKOA== + dependencies: + "@puppeteer/browsers" "2.3.0" + chromium-bidi "0.6.3" + debug "^4.3.6" + devtools-protocol "0.0.1312386" + ws "^8.18.0" + +puppeteer-core@^21.3.6: version "21.3.8" resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-21.3.8.tgz#7ac4879c9f73e8426431d8ca4c58680e517a4b08" integrity sha512-yv12E/+zZ7Lei5tJB4sUkSrsuqKibuYpYxLGbmtLUjjYIqGE5HKz9OUI2I/RFHEvF+pHi2bTbv5bWydeCGJ6Mw== @@ -9453,14 +9570,15 @@ puppeteer@^19.7.0: proxy-from-env "1.1.0" puppeteer-core "19.11.1" -puppeteer@^21.0.2: - version "21.3.8" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-21.3.8.tgz#986f95fef0a0f74381053fade8cb7a3595144fbf" - integrity sha512-4OrInVIAtDgcznENUV4Du4gYSZhRmbCkckvOoPstXrUH4JsQ3atSegY+9f/tOKCDB2qh7sXaszDcFEn+RymY0g== +puppeteer@^22.0.0: + version "22.15.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-22.15.0.tgz#4f842087090f1d9017ce947512e7baff55a10e75" + integrity sha512-XjCY1SiSEi1T7iSYuxS82ft85kwDJUS7wj1Z0eGVXKdtr5g4xnVcbjwxhq5xBnpK/E7x1VZZoJDxpjAOasHT4Q== dependencies: - "@puppeteer/browsers" "1.7.1" - cosmiconfig "8.3.6" - puppeteer-core "21.3.8" + "@puppeteer/browsers" "2.3.0" + cosmiconfig "^9.0.0" + devtools-protocol "0.0.1312386" + puppeteer-core "22.15.0" pure-rand@^6.0.0: version "6.0.4" @@ -10126,7 +10244,7 @@ rx@4.1.0: resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" integrity sha512-CiaiuN6gapkdl+cZUr67W6I8jquN4lkak3vtIsIWCl4XIPP8ffsoyN6/+PuGXnQy8Cu8W2y9Xxh31Rq4M6wUug== -rxjs@^7.8.0: +rxjs@^7.8.1: version "7.8.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== @@ -10226,6 +10344,11 @@ semver@^7.3.5, semver@^7.5.3, semver@^7.5.4: dependencies: lru-cache "^6.0.0" +semver@^7.6.3: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" @@ -10584,10 +10707,10 @@ sparkles@^1.0.0: resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== -spawnd@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/spawnd/-/spawnd-9.0.1.tgz#43b39b4bf5bdf6b5e38fbb7fabb2fbd0385b23b9" - integrity sha512-vaMk8E9CpbjTYToBxLXowDeArGf1+yI7A6PU6Nr57b2g8BVY8nRi5vTBj3bMF8UkCrMdTMyf/Lh+lrcrW2z7pw== +spawnd@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/spawnd/-/spawnd-10.0.0.tgz#cf1b222831272f4bef7e2abc9f98cd31c380a4dc" + integrity sha512-6GKcakMTryb5b1SWCvdubCDHEsR2k+5VZUD5G19umZRarkvj1RyCGyizcqhjewI7cqZo8fTVD8HpnDZbVOLMtg== dependencies: signal-exit "^4.1.0" tree-kill "^1.2.2" @@ -10746,6 +10869,17 @@ streamx@^2.15.0: fast-fifo "^1.1.0" queue-tick "^1.0.1" +streamx@^2.18.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.18.0.tgz#5bc1a51eb412a667ebfdcd4e6cf6a6fc65721ac7" + integrity sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ== + dependencies: + fast-fifo "^1.3.2" + queue-tick "^1.0.1" + text-decoder "^1.1.0" + optionalDependencies: + bare-events "^2.2.0" + string-argv@0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" @@ -11135,6 +11269,17 @@ tar-fs@3.0.4: pump "^3.0.0" tar-stream "^3.1.5" +tar-fs@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.6.tgz#eaccd3a67d5672f09ca8e8f9c3d2b89fa173f217" + integrity sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w== + dependencies: + pump "^3.0.0" + tar-stream "^3.1.5" + optionalDependencies: + bare-fs "^2.1.1" + bare-path "^2.1.0" + tar-stream@^2.1.4: version "2.2.0" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" @@ -11219,6 +11364,13 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +text-decoder@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.1.1.tgz#5df9c224cebac4a7977720b9f083f9efa1aefde8" + integrity sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA== + dependencies: + b4a "^1.6.4" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -11520,7 +11672,7 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -unbzip2-stream@1.4.3: +unbzip2-stream@1.4.3, unbzip2-stream@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== @@ -11899,6 +12051,11 @@ urlgrey@1.0.0: dependencies: fast-url-parser "^1.1.3" +urlpattern-polyfill@10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz#f0a03a97bfb03cdf33553e5e79a2aadd22cac8ec" + integrity sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg== + urlpattern-polyfill@9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-9.0.0.tgz#bc7e386bb12fd7898b58d1509df21d3c29ab3460" @@ -12152,16 +12309,16 @@ w3c-xmlserializer@^4.0.0: dependencies: xml-name-validator "^4.0.0" -wait-on@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-7.0.1.tgz#5cff9f8427e94f4deacbc2762e6b0a489b19eae9" - integrity sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog== +wait-on@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-7.2.0.tgz#d76b20ed3fc1e2bebc051fae5c1ff93be7892928" + integrity sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ== dependencies: - axios "^0.27.2" - joi "^17.7.0" + axios "^1.6.1" + joi "^17.11.0" lodash "^4.17.21" - minimist "^1.2.7" - rxjs "^7.8.0" + minimist "^1.2.8" + rxjs "^7.8.1" walk-up-path@^3.0.1: version "3.0.1" @@ -12354,6 +12511,11 @@ ws@^8.11.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== +ws@^8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== + ws@~8.11.0: version "8.11.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" @@ -12475,7 +12637,7 @@ yargs@17.7.1: y18n "^5.0.5" yargs-parser "^21.1.1" -yargs@^17.3.1: +yargs@^17.3.1, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== @@ -12520,6 +12682,11 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +zod@3.23.8: + version "3.23.8" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" + integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g== + zwitch@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7"