diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ea21e137f..42af4a390 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -36,6 +36,7 @@ jobs: node-version: ${{ env.NODE }} cache: yarn - run: yarn install + - run: yarn playwright install --with-deps chromium - run: yarn test-regression test: name: ${{ matrix.os }} Node.js ${{ matrix.node-version }} @@ -58,5 +59,6 @@ jobs: node-version: ${{ matrix.node-version }} cache: yarn - run: yarn install + - run: yarn playwright install --with-deps chromium - run: yarn test - run: yarn test-browser diff --git a/package.json b/package.json index a0d699835..e0b4873c4 100644 --- a/package.json +++ b/package.json @@ -96,9 +96,9 @@ "eslint": "^8.55.0", "jest": "^29.5.5", "node-fetch": "^2.7.0", - "pixelmatch": "^5.2.1", - "playwright": "^1.14.1", - "pngjs": "^6.0.0", + "pixelmatch": "^5.3.0", + "playwright": "^1.40.1", + "pngjs": "^7.0.0", "prettier": "^3.1.1", "rollup": "^2.79.1", "rollup-plugin-terser": "^7.0.2", diff --git a/test/browser.js b/test/browser.js index 2d654521f..ac120674b 100644 --- a/test/browser.js +++ b/test/browser.js @@ -1,6 +1,6 @@ -const fs = require('fs'); -const http = require('http'); const assert = require('assert'); +const fs = require('node:fs/promises'); +const http = require('http'); const { chromium } = require('playwright'); const fixture = ` @@ -33,14 +33,14 @@ globalThis.result = result.data; `; -const server = http.createServer((req, res) => { +const server = http.createServer(async (req, res) => { if (req.url === '/') { res.setHeader('Content-Type', 'text/html'); res.end(content); } if (req.url === '/svgo.browser.js') { res.setHeader('Content-Type', 'application/javascript'); - res.end(fs.readFileSync('./dist/svgo.browser.js')); + res.end(await fs.readFile('./dist/svgo.browser.js')); } res.end(); }); diff --git a/test/regression-extract.js b/test/regression-extract.js index 38fb0d00c..2c0e6232f 100644 --- a/test/regression-extract.js +++ b/test/regression-extract.js @@ -2,14 +2,33 @@ const fs = require('fs'); const path = require('path'); +const stream = require('stream'); const util = require('util'); const zlib = require('zlib'); -const stream = require('stream'); const { default: fetch } = require('node-fetch'); const tarStream = require('tar-stream'); const pipeline = util.promisify(stream.pipeline); +const exclude = [ + // animated + 'svg/filters-light-04-f.svg', + 'svg/filters-composite-05-f.svg', + // messed gradients + 'svg/pservers-grad-18-b.svg', + // removing wrapping breaks :first-child pseudo-class + 'svg/styling-pres-04-f.svg', + // rect is converted to path which matches wrong styles + 'svg/styling-css-08-f.svg', + // complex selectors are messed because of converting shapes to paths + 'svg/struct-use-10-f.svg', + 'svg/struct-use-11-f.svg', + 'svg/styling-css-01-b.svg', + 'svg/styling-css-04-f.svg', + // strange artifact breaks inconsistently breaks regression tests + 'svg/filters-conv-05-f.svg', +]; + /** * @param {string} url * @param {string} baseDir @@ -18,15 +37,21 @@ const pipeline = util.promisify(stream.pipeline); const extractTarGz = async (url, baseDir, include) => { const extract = tarStream.extract(); extract.on('entry', async (header, stream, next) => { + const name = header.name; + try { - if (include == null || include.test(header.name)) { - if (header.name.endsWith('.svg')) { - const file = path.join(baseDir, header.name); + if (include == null || include.test(name)) { + if ( + name.endsWith('.svg') && + !exclude.includes(name) && + !name.startsWith('svg/animate-') + ) { + const file = path.join(baseDir, name); await fs.promises.mkdir(path.dirname(file), { recursive: true }); await pipeline(stream, fs.createWriteStream(file)); - } else if (header.name.endsWith('.svgz')) { + } else if (name.endsWith('.svgz')) { // .svgz -> .svg - const file = path.join(baseDir, header.name.slice(0, -1)); + const file = path.join(baseDir, name.slice(0, -1)); await fs.promises.mkdir(path.dirname(file), { recursive: true }); await pipeline( stream, @@ -48,7 +73,7 @@ const extractTarGz = async (url, baseDir, include) => { (async () => { try { - console.info('Download W3C SVG 1.1 Test Suite and extract svg files'); + console.info('Download W3C SVG 1.1 Test Suite and extract SVG files'); await extractTarGz( 'https://www.w3.org/Graphics/SVG/Test/20110816/archives/W3C_SVG_11_TestSuite.tar.gz', path.join(__dirname, 'regression-fixtures', 'w3c-svg-11-test-suite'), diff --git a/test/regression.js b/test/regression.js index e89dfd3f3..c76e3edd2 100644 --- a/test/regression.js +++ b/test/regression.js @@ -1,57 +1,49 @@ 'use strict'; -const fs = require('fs'); -const path = require('path'); +/** + * @typedef {import('playwright').Page} Page + * @typedef {import('playwright').PageScreenshotOptions} PageScreenshotOptions + */ + +const fs = require('node:fs/promises'); const http = require('http'); const os = require('os'); +const path = require('path'); +const pixelmatch = require('pixelmatch'); const { chromium } = require('playwright'); const { PNG } = require('pngjs'); -const pixelmatch = require('pixelmatch'); const { optimize } = require('../lib/svgo.js'); -const runTests = async ({ list }) => { - let skipped = 0; +const width = 960; +const height = 720; + +/** @type {PageScreenshotOptions} */ +const screenshotOptions = { + omitBackground: true, + clip: { x: 0, y: 0, width, height }, + animations: 'disabled', +}; + +/** + * @param {string[]} list + * @returns {Promise} + */ +const runTests = async (list) => { let mismatched = 0; let passed = 0; - list.reverse(); - console.info('Start browser...'); + console.info('Start browser…'); + /** + * @param {Page} page + * @param {string} name + */ const processFile = async (page, name) => { - if ( - // animated - name.startsWith('w3c-svg-11-test-suite/svg/animate-') || - name === 'w3c-svg-11-test-suite/svg/filters-light-04-f.svg' || - name === 'w3c-svg-11-test-suite/svg/filters-composite-05-f.svg' || - // messed gradients - name === 'w3c-svg-11-test-suite/svg/pservers-grad-18-b.svg' || - // removing wrapping breaks :first-child pseudo-class - name === 'w3c-svg-11-test-suite/svg/styling-pres-04-f.svg' || - // rect is converted to path which matches wrong styles - name === 'w3c-svg-11-test-suite/svg/styling-css-08-f.svg' || - // complex selectors are messed because of converting shapes to paths - name === 'w3c-svg-11-test-suite/svg/struct-use-10-f.svg' || - name === 'w3c-svg-11-test-suite/svg/struct-use-11-f.svg' || - name === 'w3c-svg-11-test-suite/svg/styling-css-01-b.svg' || - name === 'w3c-svg-11-test-suite/svg/styling-css-04-f.svg' || - // strange artifact breaks inconsistently breaks regression tests - name === 'w3c-svg-11-test-suite/svg/filters-conv-05-f.svg' - ) { - console.info(`${name} is skipped`); - skipped += 1; - return; - } await page.goto(`http://localhost:5000/original/${name}`); - await page.setViewportSize({ width, height }); - const originalBuffer = await page.screenshot({ - omitBackground: true, - clip: { x: 0, y: 0, width, height }, - }); + const originalBuffer = await page.screenshot(screenshotOptions); await page.goto(`http://localhost:5000/optimized/${name}`); - const optimizedBuffer = await page.screenshot({ - omitBackground: true, - clip: { x: 0, y: 0, width, height }, - }); + const optimizedBufferPromise = page.screenshot(screenshotOptions); + const originalPng = PNG.sync.read(originalBuffer); - const optimizedPng = PNG.sync.read(optimizedBuffer); + const optimizedPng = PNG.sync.read(await optimizedBufferPromise); const diff = new PNG({ width, height }); const matched = pixelmatch( originalPng.data, @@ -63,9 +55,9 @@ const runTests = async ({ list }) => { // ignore small aliasing issues if (matched <= 4) { console.info(`${name} is passed`); - passed += 1; + passed++; } else { - mismatched += 1; + mismatched++; console.error(`${name} is mismatched`); if (process.env.NO_DIFF == null) { const file = path.join( @@ -73,14 +65,15 @@ const runTests = async ({ list }) => { 'regression-diffs', `${name}.diff.png`, ); - await fs.promises.mkdir(path.dirname(file), { recursive: true }); - await fs.promises.writeFile(file, PNG.sync.write(diff)); + await fs.mkdir(path.dirname(file), { recursive: true }); + await fs.writeFile(file, PNG.sync.write(diff)); } } }; const worker = async () => { let item; const page = await context.newPage(); + await page.setViewportSize({ width, height }); while ((item = list.pop())) { await processFile(page, item); } @@ -93,44 +86,21 @@ const runTests = async ({ list }) => { Array.from(new Array(os.cpus().length * 2), () => worker()), ); await browser.close(); - console.info(`Skipped: ${skipped}`); console.info(`Mismatched: ${mismatched}`); console.info(`Passed: ${passed}`); return mismatched === 0; }; -const readdirRecursive = async (absolute, relative = '') => { - let result = []; - const list = await fs.promises.readdir(absolute, { withFileTypes: true }); - for (const item of list) { - const itemAbsolute = path.join(absolute, item.name); - const itemRelative = path.join(relative, item.name); - if (item.isDirectory()) { - const itemList = await readdirRecursive(itemAbsolute, itemRelative); - result = [...result, ...itemList]; - } else if (item.name.endsWith('.svg')) { - result = [...result, itemRelative]; - } - } - return result; -}; - -const width = 960; -const height = 720; (async () => { try { const start = process.hrtime.bigint(); const fixturesDir = path.join(__dirname, 'regression-fixtures'); - const list = await readdirRecursive(fixturesDir); - // setup server + const filesPromise = fs.readdir(fixturesDir, { recursive: true }); const server = http.createServer(async (req, res) => { const name = req.url.slice(req.url.indexOf('/', 1)); let file; try { - file = await fs.promises.readFile( - path.join(fixturesDir, name), - 'utf-8', - ); + file = await fs.readFile(path.join(fixturesDir, name), 'utf-8'); } catch (error) { res.statusCode = 404; res.end(); @@ -144,14 +114,8 @@ const height = 720; } if (req.url.startsWith('/optimized/')) { const optimized = optimize(file, { - path: name, floatPrecision: 4, }); - if (optimized.error) { - throw new Error(`Failed to optimize ${name}`, { - cause: optimized.error, - }); - } res.setHeader('Content-Type', 'image/svg+xml'); res.end(optimized.data); return; @@ -161,9 +125,9 @@ const height = 720; await new Promise((resolve) => { server.listen(5000, resolve); }); - const passed = await runTests({ list }); + const list = (await filesPromise).filter((name) => name.endsWith('.svg')); + const passed = await runTests(list); server.close(); - // compute time const end = process.hrtime.bigint(); const diff = (end - start) / BigInt(1e6); if (passed) { diff --git a/yarn.lock b/yarn.lock index 092db56e8..49e179584 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1082,15 +1082,6 @@ __metadata: languageName: node linkType: hard -"@types/yauzl@npm:^2.9.1": - version: 2.9.2 - resolution: "@types/yauzl@npm:2.9.2" - dependencies: - "@types/node": "*" - checksum: dfb49abe82605615712fc694eaa4f7068fe30aa03f38c085e2c2e74408beaad30471d36da9654a811482ece2ea4405575fd99b19c0aa327ed2a9736b554bbf43 - languageName: node - linkType: hard - "@ungap/structured-clone@npm:^1.2.0": version: 1.2.0 resolution: "@ungap/structured-clone@npm:1.2.0" @@ -1409,13 +1400,6 @@ __metadata: languageName: node linkType: hard -"buffer-crc32@npm:~0.2.3": - version: 0.2.13 - resolution: "buffer-crc32@npm:0.2.13" - checksum: 06252347ae6daca3453b94e4b2f1d3754a3b146a111d81c68924c22d91889a40623264e95e67955b1cb4a68cbedf317abeabb5140a9766ed248973096db5ce1c - languageName: node - linkType: hard - "buffer-from@npm:^1.0.0": version: 1.1.2 resolution: "buffer-from@npm:1.1.2" @@ -1611,13 +1595,6 @@ __metadata: languageName: node linkType: hard -"commander@npm:^6.1.0": - version: 6.2.1 - resolution: "commander@npm:6.2.1" - checksum: d7090410c0de6bc5c67d3ca41c41760d6d268f3c799e530aafb73b7437d1826bbf0d2a3edac33f8b57cc9887b4a986dce307fa5557e109be40eadb7c43b21742 - languageName: node - linkType: hard - "commander@npm:^7.2.0": version: 7.2.0 resolution: "commander@npm:7.2.0" @@ -1904,15 +1881,6 @@ __metadata: languageName: node linkType: hard -"end-of-stream@npm:^1.1.0": - version: 1.4.4 - resolution: "end-of-stream@npm:1.4.4" - dependencies: - once: ^1.4.0 - checksum: 530a5a5a1e517e962854a31693dbb5c0b2fc40b46dad2a56a2deec656ca040631124f4795823acc68238147805f8b021abbe221f4afed5ef3c8e8efc2024908b - languageName: node - linkType: hard - "entities@npm:^4.2.0": version: 4.4.0 resolution: "entities@npm:4.4.0" @@ -2140,23 +2108,6 @@ __metadata: languageName: node linkType: hard -"extract-zip@npm:^2.0.1": - version: 2.0.1 - resolution: "extract-zip@npm:2.0.1" - dependencies: - "@types/yauzl": ^2.9.1 - debug: ^4.1.1 - get-stream: ^5.1.0 - yauzl: ^2.10.0 - dependenciesMeta: - "@types/yauzl": - optional: true - bin: - extract-zip: cli.js - checksum: 8cbda9debdd6d6980819cc69734d874ddd71051c9fe5bde1ef307ebcedfe949ba57b004894b585f758b7c9eeeea0e3d87f2dda89b7d25320459c2c9643ebb635 - languageName: node - linkType: hard - "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -2216,15 +2167,6 @@ __metadata: languageName: node linkType: hard -"fd-slicer@npm:~1.1.0": - version: 1.1.0 - resolution: "fd-slicer@npm:1.1.0" - dependencies: - pend: ~1.2.0 - checksum: c8585fd5713f4476eb8261150900d2cb7f6ff2d87f8feb306ccc8a1122efd152f1783bdb2b8dc891395744583436bfd8081d8e63ece0ec8687eeefea394d4ff2 - languageName: node - linkType: hard - "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -2296,7 +2238,7 @@ __metadata: languageName: node linkType: hard -"fsevents@^2.3.2, fsevents@~2.3.2": +"fsevents@^2.3.2, fsevents@npm:2.3.2, fsevents@~2.3.2": version: 2.3.2 resolution: "fsevents@npm:2.3.2" dependencies: @@ -2306,7 +2248,7 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@^2.3.2#~builtin, fsevents@patch:fsevents@~2.3.2#~builtin": +"fsevents@patch:fsevents@2.3.2#~builtin, fsevents@patch:fsevents@^2.3.2#~builtin, fsevents@patch:fsevents@~2.3.2#~builtin": version: 2.3.2 resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=18f3a7" dependencies: @@ -2359,15 +2301,6 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^5.1.0": - version: 5.2.0 - resolution: "get-stream@npm:5.2.0" - dependencies: - pump: ^3.0.0 - checksum: 8bc1a23174a06b2b4ce600df38d6c98d2ef6d84e020c1ddad632ad75bac4e092eeb40e4c09e0761c35fc2dbc5e7fff5dab5e763a383582c4a167dd69a905bd12 - languageName: node - linkType: hard - "get-stream@npm:^6.0.0": version: 6.0.1 resolution: "get-stream@npm:6.0.1" @@ -3266,13 +3199,6 @@ __metadata: languageName: node linkType: hard -"jpeg-js@npm:^0.4.2": - version: 0.4.4 - resolution: "jpeg-js@npm:0.4.4" - checksum: bd7cb61aa8df40a9ee2c2106839c3df6054891e56cfc22c0ac581402e06c6295f962a4754b0b2ac50a401789131b1c6dc9df8d24400f1352168be1894833c590 - languageName: node - linkType: hard - "js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -3488,15 +3414,6 @@ __metadata: languageName: node linkType: hard -"mime@npm:^2.4.6": - version: 2.5.2 - resolution: "mime@npm:2.5.2" - bin: - mime: cli.js - checksum: dd3c93d433d41a09f6a1cfa969b653b769899f3bd573e7bfcea33bdc8b0cc4eba57daa2f95937369c2bd2b6d39d62389b11a4309fe40d1d3a1b736afdedad0ff - languageName: node - linkType: hard - "mimic-fn@npm:^2.1.0": version: 2.1.0 resolution: "mimic-fn@npm:2.1.0" @@ -3723,7 +3640,7 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": +"once@npm:^1.3.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -3863,13 +3780,6 @@ __metadata: languageName: node linkType: hard -"pend@npm:~1.2.0": - version: 1.2.0 - resolution: "pend@npm:1.2.0" - checksum: 6c72f5243303d9c60bd98e6446ba7d30ae29e3d56fdb6fae8767e8ba6386f33ee284c97efe3230a0d0217e2b1723b8ab490b1bbf34fcbb2180dbc8a9de47850d - languageName: node - linkType: hard - "picocolors@npm:^1.0.0": version: 1.0.0 resolution: "picocolors@npm:1.0.0" @@ -3891,14 +3801,14 @@ __metadata: languageName: node linkType: hard -"pixelmatch@npm:^5.2.1": - version: 5.2.1 - resolution: "pixelmatch@npm:5.2.1" +"pixelmatch@npm:^5.3.0": + version: 5.3.0 + resolution: "pixelmatch@npm:5.3.0" dependencies: - pngjs: ^4.0.1 + pngjs: ^6.0.0 bin: pixelmatch: bin/pixelmatch - checksum: 0ec7a87168e51b80812d1c39fe1a278e2266dc1e9c426418c2a9d7f0c6465de3c03c51dbf7e6b97c5ba72a043ec3fb576571cdde1f88b12ef0851bf9bfd16da0 + checksum: f542713d89536551181ad9ddb666a1792ba00a8632d831093232a075cb3ccac05856e7a453ed7d0a41aaef64dcb5962e8ae5cbe646dd2761790d8ee51b0a0743 languageName: node linkType: hard @@ -3911,41 +3821,27 @@ __metadata: languageName: node linkType: hard -"playwright@npm:^1.14.1": - version: 1.14.1 - resolution: "playwright@npm:1.14.1" - dependencies: - commander: ^6.1.0 - debug: ^4.1.1 - extract-zip: ^2.0.1 - https-proxy-agent: ^5.0.0 - jpeg-js: ^0.4.2 - mime: ^2.4.6 - pngjs: ^5.0.0 - progress: ^2.0.3 - proper-lockfile: ^4.1.1 - proxy-from-env: ^1.1.0 - rimraf: ^3.0.2 - stack-utils: ^2.0.3 - ws: ^7.4.6 - yazl: ^2.5.1 +"playwright-core@npm:1.40.1": + version: 1.40.1 + resolution: "playwright-core@npm:1.40.1" bin: - playwright: lib/cli/cli.js - checksum: fbf0cd58f3d9eed01c2b5332bf388c89474494bff9027191baf27be2d0dba74af0c506b666ddab356e2f697c3df9ce158969d0b335be352a41710ce07db88b20 + playwright-core: cli.js + checksum: 84d92fb9b86e3c225b16b6886bf858eb5059b4e60fa1205ff23336e56a06dcb2eac62650992dede72f406c8e70a7b6a5303e511f9b4bc0b85022ede356a01ee0 languageName: node linkType: hard -"pngjs@npm:^4.0.1": - version: 4.0.1 - resolution: "pngjs@npm:4.0.1" - checksum: 9497e08a6c2d850630ba7c8d3738fd36c9db1af7ee8b8c2d4b664e450807a280936dfa1489deb60e6943b968bedd58c9aa93def25a765579d745ea44467fc47f - languageName: node - linkType: hard - -"pngjs@npm:^5.0.0": - version: 5.0.0 - resolution: "pngjs@npm:5.0.0" - checksum: 04e912cc45fb9601564e2284efaf0c5d20d131d9b596244f8a6789fc6cdb6b18d2975a6bbf7a001858d7e159d5c5c5dd7b11592e97629b7137f7f5cef05904c8 +"playwright@npm:^1.40.1": + version: 1.40.1 + resolution: "playwright@npm:1.40.1" + dependencies: + fsevents: 2.3.2 + playwright-core: 1.40.1 + dependenciesMeta: + fsevents: + optional: true + bin: + playwright: cli.js + checksum: 9e36791c1b4a649c104aa365fdd9d049924eeb518c5967c0e921aa38b9b00994aa6ee54784d6c2af194b3b494b6f69772673081ef53c6c4a4b2065af9955c4ba languageName: node linkType: hard @@ -3956,6 +3852,13 @@ __metadata: languageName: node linkType: hard +"pngjs@npm:^7.0.0": + version: 7.0.0 + resolution: "pngjs@npm:7.0.0" + checksum: b19a018930d27de26229c1b3ff250b3a25d09caa22cbb0b0459987d91eb0a560a18ab5d67da45a38ed7514140f26d1db58de83c31159ec101f2bb270a3c707f1 + languageName: node + linkType: hard + "prelude-ls@npm:^1.2.1": version: 1.2.1 resolution: "prelude-ls@npm:1.2.1" @@ -3990,13 +3893,6 @@ __metadata: languageName: node linkType: hard -"progress@npm:^2.0.3": - version: 2.0.3 - resolution: "progress@npm:2.0.3" - checksum: f67403fe7b34912148d9252cb7481266a354bd99ce82c835f79070643bb3c6583d10dbcfda4d41e04bbc1d8437e9af0fb1e1f2135727878f5308682a579429b7 - languageName: node - linkType: hard - "promise-inflight@npm:^1.0.1": version: 1.0.1 resolution: "promise-inflight@npm:1.0.1" @@ -4024,34 +3920,6 @@ __metadata: languageName: node linkType: hard -"proper-lockfile@npm:^4.1.1": - version: 4.1.2 - resolution: "proper-lockfile@npm:4.1.2" - dependencies: - graceful-fs: ^4.2.4 - retry: ^0.12.0 - signal-exit: ^3.0.2 - checksum: 00078ee6a61c216a56a6140c7d2a98c6c733b3678503002dc073ab8beca5d50ca271de4c85fca13b9b8ee2ff546c36674d1850509b84a04a5d0363bcb8638939 - languageName: node - linkType: hard - -"proxy-from-env@npm:^1.1.0": - version: 1.1.0 - resolution: "proxy-from-env@npm:1.1.0" - checksum: ed7fcc2ba0a33404958e34d95d18638249a68c430e30fcb6c478497d72739ba64ce9810a24f53a7d921d0c065e5b78e3822759800698167256b04659366ca4d4 - languageName: node - linkType: hard - -"pump@npm:^3.0.0": - version: 3.0.0 - resolution: "pump@npm:3.0.0" - dependencies: - end-of-stream: ^1.1.0 - once: ^1.3.1 - checksum: e42e9229fba14732593a718b04cb5e1cfef8254544870997e0ecd9732b189a48e1256e4e5478148ecb47c8511dca2b09eae56b4d0aad8009e6fac8072923cfc9 - languageName: node - linkType: hard - "punycode@npm:^2.1.0": version: 2.1.1 resolution: "punycode@npm:2.1.1" @@ -4303,7 +4171,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": +"signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 @@ -4574,9 +4442,9 @@ __metadata: jest: ^29.5.5 node-fetch: ^2.7.0 picocolors: ^1.0.0 - pixelmatch: ^5.2.1 - playwright: ^1.14.1 - pngjs: ^6.0.0 + pixelmatch: ^5.3.0 + playwright: ^1.40.1 + pngjs: ^7.0.0 prettier: ^3.1.1 rollup: ^2.79.1 rollup-plugin-terser: ^7.0.2 @@ -4857,21 +4725,6 @@ __metadata: languageName: node linkType: hard -"ws@npm:^7.4.6": - version: 7.5.5 - resolution: "ws@npm:7.5.5" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: bd2b437256012af526c69c03d6670a132e7ab0fe5853f3b7092826acea4203fad4ee2a8d0d9bd44834b2b968e747bf34f753ab535f4a3edf40d262da4b1d0805 - languageName: node - linkType: hard - "y18n@npm:^5.0.5": version: 5.0.8 resolution: "y18n@npm:5.0.8" @@ -4908,25 +4761,6 @@ __metadata: languageName: node linkType: hard -"yauzl@npm:^2.10.0": - version: 2.10.0 - resolution: "yauzl@npm:2.10.0" - dependencies: - buffer-crc32: ~0.2.3 - fd-slicer: ~1.1.0 - checksum: 7f21fe0bbad6e2cb130044a5d1d0d5a0e5bf3d8d4f8c4e6ee12163ce798fee3de7388d22a7a0907f563ac5f9d40f8699a223d3d5c1718da90b0156da6904022b - languageName: node - linkType: hard - -"yazl@npm:^2.5.1": - version: 2.5.1 - resolution: "yazl@npm:2.5.1" - dependencies: - buffer-crc32: ~0.2.3 - checksum: daec5154b5485d8621bfea359e905ddca0b2f068430a4aa0a802bf5d67391157a383e0c2767acccbf5964264851da643bc740155a9458e2d8dce55b94c1cc2ed - languageName: node - linkType: hard - "yocto-queue@npm:^0.1.0": version: 0.1.0 resolution: "yocto-queue@npm:0.1.0"