1
0
mirror of https://github.com/svg/svgo.git synced 2026-01-25 18:41:39 +03:00

refactor: improve regression testing (#1898)

This commit is contained in:
Seth Falco
2023-12-23 06:56:46 +00:00
committed by GitHub
parent 16c6977215
commit 2c408ce56f
6 changed files with 118 additions and 293 deletions

View File

@@ -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

View File

@@ -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",

View File

@@ -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 = `<svg xmlns="http://www.w3.org/2000/svg">
@@ -33,14 +33,14 @@ globalThis.result = result.data;
</script>
`;
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();
});

View File

@@ -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 <g> 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'),

View File

@@ -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<boolean>}
*/
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 <g> 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) {

238
yarn.lock
View File

@@ -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<compat/fsevents>, fsevents@patch:fsevents@~2.3.2#~builtin<compat/fsevents>":
"fsevents@patch:fsevents@2.3.2#~builtin<compat/fsevents>, fsevents@patch:fsevents@^2.3.2#~builtin<compat/fsevents>, fsevents@patch:fsevents@~2.3.2#~builtin<compat/fsevents>":
version: 2.3.2
resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin<compat/fsevents>::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"