mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
# Backport This will backport the following commits from `main` to `9.0`: - [[Space time] extending Scout with perfTracker fixture (#212397)](https://github.com/elastic/kibana/pull/212397) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Dzmitry Lemechko","email":"dzmitry.lemechko@elastic.co"},"sourceCommit":{"committedDate":"2025-03-14T17:35:31Z","message":"[Space time] extending Scout with perfTracker fixture (#212397)\n\n## Summary\n\nOn-Week project \"Client-side performance insights with Playwright &\nLighthouse\"\n\nrevisiting old PR #66224\n\nThis PR extends Scout with `perfTracker` fixture designed to analyze\nJavaScript bundle performance and page-level performance metrics in\nKibana by leveraging Chrome DevTools Protocol (CDP).\n\nIt intercepts network requests, filters static bundles, and computes\nbundle size statistics per page load. Additionally, it collects CDP\nPerformance Domain Metrics, allowing in-depth analysis of rendering and\nscript execution times.\n\n\n[README](c013c39b7e/src/platform/packages/shared/kbn-scout/src/playwright/fixtures/test/performance/README.md
)\nfile with more details and examples was added\n\nOutput example for `/app/discover` (shorten, just to share the idea):\n\n```\n{\n \"url\": \"http://localhost:5620/app/discover#/\",\n \"bundleCount\": 87,\n \"totalSize\": 3133420,\n \"pluginCount\": 9,\n \"plugins\": [\n {\n \"name\": \"aiops\",\n \"bundlesCount\": 2,\n \"totalSize\": 5982,\n \"bundles\": [\n {\n \"name\": \"aiops.chunk.1.js\",\n \"transferredSize\": 2013\n },\n ...\n ]\n },\n {\n \"name\": \"discover\",\n \"bundlesCount\": 17,\n \"totalSize\": 631605,\n \"bundles\": [\n {\n \"name\": \"discover.chunk.1.js\",\n \"transferredSize\": 41915\n },\n ...\n ]\n },\n {\n \"name\": \"eventAnnotation\",\n \"bundlesCount\": 1,\n \"totalSize\": 8652,\n \"bundles\": [\n {\n \"name\": \"eventAnnotation.chunk.1.js\",\n \"transferredSize\": 8652\n }\n ]\n },\n {\n \"name\": \"expressionXY\",\n \"bundlesCount\": 5,\n \"totalSize\": 203127,\n \"bundles\": [\n {\n \"name\": \"expressionXY.chunk.2.js\",\n \"transferredSize\": 5328\n },\n ...\n ]\n },\n ]\n}\n```\n\nYou can create a Scout UI test and start bundle tracker whenever you\nwant to compute collected stats when all loading is done. Designed as\ntest, it allows you to have individual validations for plugins, total\nbundle size, individual plugin size, etc.\n\n```\n // Ensure all JS bundles are loaded\n await perfTracker.waitForJsLoad(cdp);\n\n // Collect and validate stats\n const stats = perfTracker.collectJsBundleStats(currentUrl);\n expect(\n stats.totalSize,\n `Total bundles size loaded on page should not exceed 3.0 MB`\n ).toBeLessThan(3 * 1024 * 1024);\n expect(stats.bundleCount, {\n message: `Total bundle chunks count loaded on page should not exceed 100`,\n }).toBeLessThan(100);\n expect(\n stats.plugins.map((p) => p.name),\n { message: 'Unexpected plugins were loaded on page' }\n ).toStrictEqual([\n 'aiops',\n 'discover',\n 'eventAnnotation',\n 'expressionXY',\n 'kbn-ui-shared-deps-npm',\n 'lens',\n 'maps',\n 'unifiedHistogram',\n 'unifiedSearch',\n ]);\n // Validate individual plugin bundle sizes\n expect(stats.plugins.find((p) => p.name === 'discover')?.totalSize, {\n message: `Total 'discover' bundles size should not exceed 625 KB`,\n }).toBeLessThan(625 * 1024);\n```\n\nFull test example:\n7b18e85541/x-pack/platform/plugins/private/discover_enhanced/ui_tests/tests/discover_cdp_perf.spec.ts
\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"b5f158bc42285c37911abca17c371f4459106fa7","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","wg:performance","backport:version","test:scout","v9.1.0","v8.19.0"],"title":"[Space time] extending Scout with perfTracker fixture","number":212397,"url":"https://github.com/elastic/kibana/pull/212397","mergeCommit":{"message":"[Space time] extending Scout with perfTracker fixture (#212397)\n\n## Summary\n\nOn-Week project \"Client-side performance insights with Playwright &\nLighthouse\"\n\nrevisiting old PR #66224\n\nThis PR extends Scout with `perfTracker` fixture designed to analyze\nJavaScript bundle performance and page-level performance metrics in\nKibana by leveraging Chrome DevTools Protocol (CDP).\n\nIt intercepts network requests, filters static bundles, and computes\nbundle size statistics per page load. Additionally, it collects CDP\nPerformance Domain Metrics, allowing in-depth analysis of rendering and\nscript execution times.\n\n\n[README](c013c39b7e/src/platform/packages/shared/kbn-scout/src/playwright/fixtures/test/performance/README.md
)\nfile with more details and examples was added\n\nOutput example for `/app/discover` (shorten, just to share the idea):\n\n```\n{\n \"url\": \"http://localhost:5620/app/discover#/\",\n \"bundleCount\": 87,\n \"totalSize\": 3133420,\n \"pluginCount\": 9,\n \"plugins\": [\n {\n \"name\": \"aiops\",\n \"bundlesCount\": 2,\n \"totalSize\": 5982,\n \"bundles\": [\n {\n \"name\": \"aiops.chunk.1.js\",\n \"transferredSize\": 2013\n },\n ...\n ]\n },\n {\n \"name\": \"discover\",\n \"bundlesCount\": 17,\n \"totalSize\": 631605,\n \"bundles\": [\n {\n \"name\": \"discover.chunk.1.js\",\n \"transferredSize\": 41915\n },\n ...\n ]\n },\n {\n \"name\": \"eventAnnotation\",\n \"bundlesCount\": 1,\n \"totalSize\": 8652,\n \"bundles\": [\n {\n \"name\": \"eventAnnotation.chunk.1.js\",\n \"transferredSize\": 8652\n }\n ]\n },\n {\n \"name\": \"expressionXY\",\n \"bundlesCount\": 5,\n \"totalSize\": 203127,\n \"bundles\": [\n {\n \"name\": \"expressionXY.chunk.2.js\",\n \"transferredSize\": 5328\n },\n ...\n ]\n },\n ]\n}\n```\n\nYou can create a Scout UI test and start bundle tracker whenever you\nwant to compute collected stats when all loading is done. Designed as\ntest, it allows you to have individual validations for plugins, total\nbundle size, individual plugin size, etc.\n\n```\n // Ensure all JS bundles are loaded\n await perfTracker.waitForJsLoad(cdp);\n\n // Collect and validate stats\n const stats = perfTracker.collectJsBundleStats(currentUrl);\n expect(\n stats.totalSize,\n `Total bundles size loaded on page should not exceed 3.0 MB`\n ).toBeLessThan(3 * 1024 * 1024);\n expect(stats.bundleCount, {\n message: `Total bundle chunks count loaded on page should not exceed 100`,\n }).toBeLessThan(100);\n expect(\n stats.plugins.map((p) => p.name),\n { message: 'Unexpected plugins were loaded on page' }\n ).toStrictEqual([\n 'aiops',\n 'discover',\n 'eventAnnotation',\n 'expressionXY',\n 'kbn-ui-shared-deps-npm',\n 'lens',\n 'maps',\n 'unifiedHistogram',\n 'unifiedSearch',\n ]);\n // Validate individual plugin bundle sizes\n expect(stats.plugins.find((p) => p.name === 'discover')?.totalSize, {\n message: `Total 'discover' bundles size should not exceed 625 KB`,\n }).toBeLessThan(625 * 1024);\n```\n\nFull test example:\n7b18e85541/x-pack/platform/plugins/private/discover_enhanced/ui_tests/tests/discover_cdp_perf.spec.ts
\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"b5f158bc42285c37911abca17c371f4459106fa7"}},"sourceBranch":"main","suggestedTargetBranches":["9.0","8.x"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/212397","number":212397,"mergeCommit":{"message":"[Space time] extending Scout with perfTracker fixture (#212397)\n\n## Summary\n\nOn-Week project \"Client-side performance insights with Playwright &\nLighthouse\"\n\nrevisiting old PR #66224\n\nThis PR extends Scout with `perfTracker` fixture designed to analyze\nJavaScript bundle performance and page-level performance metrics in\nKibana by leveraging Chrome DevTools Protocol (CDP).\n\nIt intercepts network requests, filters static bundles, and computes\nbundle size statistics per page load. Additionally, it collects CDP\nPerformance Domain Metrics, allowing in-depth analysis of rendering and\nscript execution times.\n\n\n[README](c013c39b7e/src/platform/packages/shared/kbn-scout/src/playwright/fixtures/test/performance/README.md
)\nfile with more details and examples was added\n\nOutput example for `/app/discover` (shorten, just to share the idea):\n\n```\n{\n \"url\": \"http://localhost:5620/app/discover#/\",\n \"bundleCount\": 87,\n \"totalSize\": 3133420,\n \"pluginCount\": 9,\n \"plugins\": [\n {\n \"name\": \"aiops\",\n \"bundlesCount\": 2,\n \"totalSize\": 5982,\n \"bundles\": [\n {\n \"name\": \"aiops.chunk.1.js\",\n \"transferredSize\": 2013\n },\n ...\n ]\n },\n {\n \"name\": \"discover\",\n \"bundlesCount\": 17,\n \"totalSize\": 631605,\n \"bundles\": [\n {\n \"name\": \"discover.chunk.1.js\",\n \"transferredSize\": 41915\n },\n ...\n ]\n },\n {\n \"name\": \"eventAnnotation\",\n \"bundlesCount\": 1,\n \"totalSize\": 8652,\n \"bundles\": [\n {\n \"name\": \"eventAnnotation.chunk.1.js\",\n \"transferredSize\": 8652\n }\n ]\n },\n {\n \"name\": \"expressionXY\",\n \"bundlesCount\": 5,\n \"totalSize\": 203127,\n \"bundles\": [\n {\n \"name\": \"expressionXY.chunk.2.js\",\n \"transferredSize\": 5328\n },\n ...\n ]\n },\n ]\n}\n```\n\nYou can create a Scout UI test and start bundle tracker whenever you\nwant to compute collected stats when all loading is done. Designed as\ntest, it allows you to have individual validations for plugins, total\nbundle size, individual plugin size, etc.\n\n```\n // Ensure all JS bundles are loaded\n await perfTracker.waitForJsLoad(cdp);\n\n // Collect and validate stats\n const stats = perfTracker.collectJsBundleStats(currentUrl);\n expect(\n stats.totalSize,\n `Total bundles size loaded on page should not exceed 3.0 MB`\n ).toBeLessThan(3 * 1024 * 1024);\n expect(stats.bundleCount, {\n message: `Total bundle chunks count loaded on page should not exceed 100`,\n }).toBeLessThan(100);\n expect(\n stats.plugins.map((p) => p.name),\n { message: 'Unexpected plugins were loaded on page' }\n ).toStrictEqual([\n 'aiops',\n 'discover',\n 'eventAnnotation',\n 'expressionXY',\n 'kbn-ui-shared-deps-npm',\n 'lens',\n 'maps',\n 'unifiedHistogram',\n 'unifiedSearch',\n ]);\n // Validate individual plugin bundle sizes\n expect(stats.plugins.find((p) => p.name === 'discover')?.totalSize, {\n message: `Total 'discover' bundles size should not exceed 625 KB`,\n }).toBeLessThan(625 * 1024);\n```\n\nFull test example:\n7b18e85541/x-pack/platform/plugins/private/discover_enhanced/ui_tests/tests/discover_cdp_perf.spec.ts
\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"b5f158bc42285c37911abca17c371f4459106fa7"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT-->
This commit is contained in:
parent
c04009575a
commit
270867bac6
28 changed files with 1287 additions and 85 deletions
|
@ -1788,6 +1788,7 @@
|
|||
"json5": "^2.2.3",
|
||||
"jsondiffpatch": "0.4.1",
|
||||
"license-checker": "^25.0.1",
|
||||
"lighthouse": "^12.4.0",
|
||||
"listr2": "^8.2.5",
|
||||
"lmdb": "^2.9.2",
|
||||
"marge": "^1.0.1",
|
||||
|
|
|
@ -158,6 +158,7 @@
|
|||
"@types/supertest",
|
||||
"@types/react-test-renderer",
|
||||
"babel-plugin-istanbul",
|
||||
"lighthouse",
|
||||
"nyc",
|
||||
"oboe",
|
||||
"pixelmatch",
|
||||
|
|
|
@ -12,6 +12,7 @@ export {
|
|||
expect,
|
||||
test,
|
||||
spaceTest,
|
||||
lighthouseTest,
|
||||
globalSetupHook,
|
||||
tags,
|
||||
createPlaywrightConfig,
|
||||
|
@ -38,6 +39,6 @@ export type {
|
|||
} from './src/types';
|
||||
|
||||
// re-export from Playwright
|
||||
export type { Locator } from 'playwright/test';
|
||||
export type { Locator, CDPSession } from 'playwright/test';
|
||||
|
||||
export { measurePerformance, measurePerformanceAsync } from './src/common';
|
||||
|
|
|
@ -11,6 +11,7 @@ import path from 'path';
|
|||
import Fs from 'fs';
|
||||
import { ToolingLog } from '@kbn/tooling-log';
|
||||
import { saveScoutTestConfigOnDisk } from './save_scout_test_config';
|
||||
import { ServerlessProjectType } from '@kbn/es';
|
||||
|
||||
const MOCKED_SCOUT_SERVERS_ROOT = '/mock/repo/root/scout/servers';
|
||||
|
||||
|
@ -34,6 +35,7 @@ const testServersConfig = {
|
|||
password: 'changeme',
|
||||
},
|
||||
serverless: true,
|
||||
projectType: 'oblt' as ServerlessProjectType,
|
||||
isCloud: true,
|
||||
license: 'trial',
|
||||
cloudUsersFilePath: '/path/to/users',
|
||||
|
|
|
@ -49,6 +49,8 @@ describe('createPlaywrightConfig', () => {
|
|||
expect(config.use).toEqual({
|
||||
serversConfigDir: SCOUT_SERVERS_ROOT,
|
||||
[VALID_CONFIG_MARKER]: true,
|
||||
actionTimeout: 10000,
|
||||
navigationTimeout: 20000,
|
||||
screenshot: 'only-on-failure',
|
||||
testIdAttribute: 'data-test-subj',
|
||||
trace: 'on-first-retry',
|
||||
|
|
|
@ -72,6 +72,8 @@ export function createPlaywrightConfig(options: ScoutPlaywrightOptions): Playwri
|
|||
],
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
use: {
|
||||
actionTimeout: 10000, // Shorten timeout for actions like `click()`
|
||||
navigationTimeout: 20000, // Shorter timeout for page navigations
|
||||
// 'configName' is not defined by default to enforce using '--project' flag when running the tests
|
||||
testIdAttribute: 'data-test-subj',
|
||||
serversConfigDir: SCOUT_SERVERS_ROOT,
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
esArchiverFixture,
|
||||
uiSettingsFixture,
|
||||
synthtraceFixture,
|
||||
lighthouseFixture,
|
||||
} from './worker';
|
||||
import type {
|
||||
EsArchiverFixture,
|
||||
|
@ -31,9 +32,12 @@ import {
|
|||
browserAuthFixture,
|
||||
pageObjectsFixture,
|
||||
validateTagsFixture,
|
||||
persistentContext,
|
||||
perfTrackerFixture,
|
||||
} from './test';
|
||||
import type { BrowserAuthFixture, ScoutPage, PageObjects } from './test';
|
||||
import type { BrowserAuthFixture, ScoutPage, PageObjects, PerfTrackerFixture } from './test';
|
||||
export type { ScoutPage, PageObjects } from './test';
|
||||
export type { LighthouseAuditOptions } from './worker';
|
||||
|
||||
export const scoutFixtures = mergeTests(
|
||||
// worker scope fixtures
|
||||
|
@ -47,13 +51,16 @@ export const scoutFixtures = mergeTests(
|
|||
browserAuthFixture,
|
||||
scoutPageFixture,
|
||||
pageObjectsFixture,
|
||||
validateTagsFixture
|
||||
validateTagsFixture,
|
||||
// performance fixtures
|
||||
perfTrackerFixture
|
||||
);
|
||||
|
||||
export interface ScoutTestFixtures {
|
||||
browserAuth: BrowserAuthFixture;
|
||||
page: ScoutPage;
|
||||
pageObjects: PageObjects;
|
||||
perfTracker: PerfTrackerFixture;
|
||||
}
|
||||
|
||||
export interface ScoutWorkerFixtures extends ApiFixtures {
|
||||
|
@ -68,3 +75,5 @@ export interface ScoutWorkerFixtures extends ApiFixtures {
|
|||
infraSynthtraceEsClient: SynthtraceFixture['infraSynthtraceEsClient'];
|
||||
otelSynthtraceEsClient: SynthtraceFixture['otelSynthtraceEsClient'];
|
||||
}
|
||||
|
||||
export const lighthouseFixtures = mergeTests(scoutFixtures, persistentContext, lighthouseFixture);
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import * as os from 'os';
|
||||
import getPort from 'get-port';
|
||||
import { BrowserContext, chromium } from 'playwright/test';
|
||||
import { coreWorkerFixtures } from '../../worker';
|
||||
|
||||
/**
|
||||
* Launches browser with persistent context across multiple tests / browser windows in the same test.
|
||||
* E.g. Lighthouse launches a new browser window and the authentication state
|
||||
* is not persisted between windows by default, so we can't do page audit without persistent context.
|
||||
*/
|
||||
export const persistentContext = coreWorkerFixtures.extend<
|
||||
{
|
||||
context: BrowserContext;
|
||||
},
|
||||
{ debuggingPort: number }
|
||||
>({
|
||||
debuggingPort: [
|
||||
async ({ log }, use) => {
|
||||
const port = await getPort({ port: [9222, 9223, 9224] });
|
||||
log.serviceLoaded(`remote debugging port [${port}]`);
|
||||
use(port);
|
||||
},
|
||||
{ scope: 'worker' },
|
||||
],
|
||||
context: [
|
||||
async ({ log, debuggingPort }, use) => {
|
||||
const userDataDir = os.tmpdir();
|
||||
const context = await chromium.launchPersistentContext(userDataDir, {
|
||||
args: [`--remote-debugging-port=${debuggingPort}`],
|
||||
});
|
||||
log.serviceLoaded(`persistentContext on port [${debuggingPort}]`);
|
||||
await use(context);
|
||||
await context.close();
|
||||
},
|
||||
{ scope: 'test' },
|
||||
],
|
||||
});
|
|
@ -14,3 +14,6 @@ export type { ScoutPage } from './scout_page';
|
|||
export { validateTagsFixture } from './validate_tags';
|
||||
export { pageObjectsFixture, pageObjectsParallelFixture } from './page_objects';
|
||||
export type { PageObjects } from './page_objects';
|
||||
export { persistentContext } from './context';
|
||||
export { perfTrackerFixture } from './performance';
|
||||
export type { PerfTrackerFixture } from './performance';
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
import { PageObjects, createCorePageObjects } from '../../../page_objects';
|
||||
import { ScoutSpaceParallelFixture } from '../../worker';
|
||||
import { ScoutSpaceParallelFixture, ScoutTestConfig } from '../../worker';
|
||||
import { scoutPageParallelFixture } from '../scout_page';
|
||||
|
||||
/**
|
||||
|
@ -23,10 +23,10 @@ export const pageObjectsParallelFixture = scoutPageParallelFixture.extend<
|
|||
{
|
||||
pageObjects: PageObjects;
|
||||
},
|
||||
{ scoutSpace: ScoutSpaceParallelFixture }
|
||||
{ scoutSpace: ScoutSpaceParallelFixture; config: ScoutTestConfig }
|
||||
>({
|
||||
pageObjects: async ({ page, log }, use) => {
|
||||
const corePageObjects = createCorePageObjects(page);
|
||||
pageObjects: async ({ page, config, log }, use) => {
|
||||
const corePageObjects = createCorePageObjects({ page, config, log });
|
||||
log.serviceLoaded(`pageObjects`);
|
||||
await use(corePageObjects);
|
||||
},
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
import { PageObjects, createCorePageObjects } from '../../../page_objects';
|
||||
import { ScoutTestConfig } from '../../worker';
|
||||
import { scoutPageFixture } from '../scout_page';
|
||||
|
||||
/**
|
||||
|
@ -18,11 +19,14 @@ import { scoutPageFixture } from '../scout_page';
|
|||
*
|
||||
* Note: Page Objects are lazily instantiated on first access.
|
||||
*/
|
||||
export const pageObjectsFixture = scoutPageFixture.extend<{
|
||||
pageObjects: PageObjects;
|
||||
}>({
|
||||
pageObjects: async ({ page, log }, use) => {
|
||||
const corePageObjects = createCorePageObjects(page);
|
||||
export const pageObjectsFixture = scoutPageFixture.extend<
|
||||
{
|
||||
pageObjects: PageObjects;
|
||||
},
|
||||
{ config: ScoutTestConfig }
|
||||
>({
|
||||
pageObjects: async ({ page, log, config }, use) => {
|
||||
const corePageObjects = createCorePageObjects({ page, config, log });
|
||||
log.serviceLoaded('pageObjects');
|
||||
await use(corePageObjects);
|
||||
},
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
## Performance Tracker Fixture
|
||||
|
||||
### Overview
|
||||
|
||||
`perfTrackerFixture` is a Playwright fixture designed to analyze JavaScript bundle performance and page-level performance metrics in Kibana by leveraging Chrome DevTools Protocol (CDP). It intercepts network requests, filters static bundles, and computes bundle size statistics per page load. Additionally, it collects CDP Performance Domain Metrics, allowing in-depth analysis of rendering and script execution times.
|
||||
|
||||
### Key Features
|
||||
|
||||
- Uses CDP session to monitor network requests in Playwright tests.
|
||||
- Exposes `waitForJsLoad` to ensure all incoming bundle requests are fully resolved before proceeding.
|
||||
- Exposes `captureBundleResponses` to start tracking network requests and collect JavaScript bundle responses.
|
||||
- Exposes `collectJsBundleStats` to aggregate all captured responses by plugin, making validation easier in tests.
|
||||
- Automatically attaches collected JS bundle stats as a JSON artifact in test reports, making them available in the `Playwright HTML report`.
|
||||
- Captures `CDP Performance Domain Metrics`, including:
|
||||
- JavaScript Heap Usage (jsHeapUsedSize, jsHeapTotalSize)
|
||||
- CPU Execution Time (cpuTime)
|
||||
- Script Execution Time (scriptTime)
|
||||
- Layout & Rendering Performance (layoutTime, layoutCount, styleRecalcCount)
|
||||
- Frames Per Second (FPS) (fps)
|
||||
- DOM Complexity Metrics (nodesCount, documentsCount)
|
||||
|
||||
|
||||
### Usage: capturing JS bundles on page
|
||||
|
||||
```ts
|
||||
test.describe(
|
||||
'Discover App - Performance Metrics & Bundle Analysis',
|
||||
{ tag: [...tags.DEPLOYMENT_AGNOSTIC, ...tags.PERFORMANCE] },
|
||||
() => {
|
||||
let cdp: CDPSession;
|
||||
|
||||
test.beforeEach(async ({ browserAuth, page, context, perfTracker }) => {
|
||||
await browserAuth.loginAsAdmin();
|
||||
cdp = await context.newCDPSession(page);
|
||||
await cdp.send('Network.enable');
|
||||
// load the starting page, e.g. '/app/home'
|
||||
await perfTracker.waitForJsLoad(cdp); // Ensure JS bundles are fully loaded
|
||||
});
|
||||
|
||||
test('collects and validates JS Bundles loaded on page', async ({
|
||||
page,
|
||||
pageObjects,
|
||||
perfTracker,
|
||||
}) => {
|
||||
perfTracker.captureBundleResponses(cdp); // Start tracking
|
||||
|
||||
// Navigate to Discover app
|
||||
await pageObjects.collapsibleNav.clickItem('Discover');
|
||||
const currentUrl = page.url();
|
||||
expect(currentUrl).toContain('app/discover#/');
|
||||
|
||||
// Ensure all JS bundles are loaded
|
||||
await perfTracker.waitForJsLoad(cdp);
|
||||
|
||||
// Collect and validate stats
|
||||
const stats = perfTracker.collectJsBundleStats(currentUrl);
|
||||
expect(
|
||||
stats.totalSize,
|
||||
`Total bundles size loaded on page should not exceed 3.0 MB`
|
||||
).toBeLessThan(3 * 1024 * 1024);
|
||||
expect(stats.bundleCount, {
|
||||
message: `Total bundle chunks count loaded on page should not exceed 100`,
|
||||
}).toBeLessThan(100);
|
||||
expect(
|
||||
stats.plugins.map((p) => p.name),
|
||||
{ message: 'Unexpected plugins were loaded on page' }
|
||||
).toStrictEqual([
|
||||
'aiops',
|
||||
'discover',
|
||||
'eventAnnotation',
|
||||
'expressionXY',
|
||||
'kbn-ui-shared-deps-npm',
|
||||
'lens',
|
||||
'maps',
|
||||
'unifiedHistogram',
|
||||
'unifiedSearch',
|
||||
]);
|
||||
// Validate individual plugin bundle sizes
|
||||
expect(stats.plugins.find((p) => p.name === 'discover')?.totalSize, {
|
||||
message: `Total 'discover' bundles size should not exceed 625 KB`,
|
||||
}).toBeLessThan(625 * 1024);
|
||||
});
|
||||
```
|
||||
|
||||
### Uage: collecting CDP Performance metrics
|
||||
|
||||
```ts
|
||||
test.describe(
|
||||
'Discover App - Performance Metrics & Bundle Analysis',
|
||||
{ tag: [...tags.DEPLOYMENT_AGNOSTIC, ...tags.PERFORMANCE] },
|
||||
() => {
|
||||
let cdp: CDPSession;
|
||||
|
||||
test.beforeEach(async ({ browserAuth, page, context, perfTracker }) => {
|
||||
await browserAuth.loginAsAdmin();
|
||||
cdp = await context.newCDPSession(page);
|
||||
// load the starting page, e.g. '/app/home' and wait for loading to finish
|
||||
});
|
||||
|
||||
test('measures Performance Metrics before and after Discover load', async ({
|
||||
page,
|
||||
pageObjects,
|
||||
perfTracker,
|
||||
}) => {
|
||||
const beforeMetrics = await perfTracker.capturePagePerformanceMetrics(cdp);
|
||||
|
||||
// Navigate to Discover app
|
||||
await pageObjects.collapsibleNav.clickItem('Discover');
|
||||
await page.waitForLoadingIndicatorHidden();
|
||||
const currentUrl = page.url();
|
||||
expect(currentUrl).toContain('app/discover#/');
|
||||
|
||||
await pageObjects.discover.waitForHistogramRendered();
|
||||
|
||||
const afterMetrics = await perfTracker.capturePagePerformanceMetrics(cdp);
|
||||
const perfStats = perfTracker.collectPagePerformanceStats(
|
||||
currentUrl,
|
||||
beforeMetrics,
|
||||
afterMetrics
|
||||
);
|
||||
|
||||
expect(perfStats.cpuTime.diff).toBeLessThan(1.5); // CPU time (seconds) usage during page navigation
|
||||
expect(perfStats.scriptTime.diff).toBeLessThan(0.4); // Additional time (seconds) spent executing JS scripts
|
||||
expect(perfStats.layoutTime.diff).toBeLessThan(0.06); // Total layout computation time (seconds)
|
||||
});
|
||||
```
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { coreWorkerFixtures } from '../../worker';
|
||||
import { PerformanceTracker } from './performance_tracker';
|
||||
|
||||
export const perfTrackerFixture = coreWorkerFixtures.extend<{ perfTracker: PerformanceTracker }>({
|
||||
perfTracker: [
|
||||
async ({ log }, use, testInfo) => {
|
||||
log.serviceLoaded('perfTracker');
|
||||
|
||||
const tracker = new PerformanceTracker(testInfo);
|
||||
await use(tracker);
|
||||
},
|
||||
{ scope: 'test' },
|
||||
],
|
||||
});
|
||||
|
||||
export type PerfTrackerFixture = ReturnType<typeof perfTrackerFixture>;
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { CDPSession, TestInfo } from '@playwright/test';
|
||||
import { BundleInfo, PageInfo, PerformanceMetrics, PluginInfo } from './types';
|
||||
|
||||
export class PerformanceTracker {
|
||||
private bundleResponses = new Map<string, BundleInfo>();
|
||||
|
||||
constructor(private testInfo: TestInfo) {}
|
||||
|
||||
private getRequestData(requestId: string): BundleInfo {
|
||||
if (!this.bundleResponses.has(requestId)) {
|
||||
this.bundleResponses.set(requestId, {
|
||||
url: '',
|
||||
name: '',
|
||||
plugin: '',
|
||||
transferredSize: 0,
|
||||
headersSize: 0,
|
||||
});
|
||||
}
|
||||
return this.bundleResponses.get(requestId)!;
|
||||
}
|
||||
|
||||
captureBundleResponses(cdp: CDPSession) {
|
||||
cdp.on('Network.responseReceived', (event) => {
|
||||
if (event.response.url.endsWith('.js') && event.response.url.includes('bundles')) {
|
||||
const requestData = this.getRequestData(event.requestId);
|
||||
requestData.url = event.response.url;
|
||||
requestData.name = event.response.url.split('/').pop()!;
|
||||
requestData.plugin = requestData.name.split('.')[0];
|
||||
requestData.headersSize = event.response.headersText?.length ?? 0;
|
||||
}
|
||||
});
|
||||
|
||||
cdp.on('Network.loadingFinished', (event) => {
|
||||
if (this.bundleResponses.has(event.requestId)) {
|
||||
this.bundleResponses.get(event.requestId)!.transferredSize = event.encodedDataLength;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async waitForJsLoad(cdp: CDPSession, timeout: number = 2000): Promise<void> {
|
||||
return new Promise<void>((resolve) => {
|
||||
let lastRequestTime = Date.now();
|
||||
let activeRequests = 0;
|
||||
|
||||
// Track new JS requests
|
||||
cdp.on('Network.requestWillBeSent', (event) => {
|
||||
if (event.request.url.endsWith('.js') && event.request.url.includes('bundles')) {
|
||||
activeRequests++;
|
||||
lastRequestTime = Date.now();
|
||||
}
|
||||
});
|
||||
|
||||
// Track when JS requests are completed
|
||||
cdp.on('Network.loadingFinished', () => {
|
||||
activeRequests = Math.max(0, activeRequests - 1);
|
||||
});
|
||||
|
||||
// Check every 500ms if no new requests arrived
|
||||
const interval = setInterval(() => {
|
||||
if (Date.now() - lastRequestTime > timeout && activeRequests === 0) {
|
||||
clearInterval(interval);
|
||||
resolve();
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
|
||||
computeBundleStats(bundleResponses: Map<string, BundleInfo>): PageInfo {
|
||||
const bundles = Array.from(bundleResponses.values());
|
||||
const pluginAggregates = new Map<string, PluginInfo>();
|
||||
|
||||
let totalSize = 0;
|
||||
|
||||
for (const { plugin, transferredSize, name } of bundles) {
|
||||
totalSize += transferredSize;
|
||||
|
||||
if (!pluginAggregates.has(plugin)) {
|
||||
pluginAggregates.set(plugin, { count: 0, totalSize: 0, bundles: [] });
|
||||
}
|
||||
|
||||
const pluginInfo = pluginAggregates.get(plugin)!;
|
||||
pluginInfo.count += 1;
|
||||
pluginInfo.totalSize += transferredSize;
|
||||
pluginInfo.bundles.push({ name, transferredSize });
|
||||
}
|
||||
|
||||
// Sort plugins alphabetically and bundle names inside them
|
||||
const plugins = Array.from(pluginAggregates.entries())
|
||||
.map(([pluginName, pluginInfo]) => ({
|
||||
name: pluginName,
|
||||
bundlesCount: pluginInfo.count,
|
||||
totalSize: pluginInfo.totalSize,
|
||||
bundles: pluginInfo.bundles.sort((a, b) => a.name.localeCompare(b.name)),
|
||||
}))
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
return {
|
||||
bundleCount: bundles.length,
|
||||
totalSize,
|
||||
pluginCount: pluginAggregates.size,
|
||||
plugins,
|
||||
};
|
||||
}
|
||||
|
||||
collectJsBundleStats(url: string) {
|
||||
const stats = this.computeBundleStats(this.bundleResponses);
|
||||
|
||||
this.testInfo.attach('page-bundles-report', {
|
||||
body: JSON.stringify({ url, ...stats }, null, 2),
|
||||
contentType: 'application/json',
|
||||
});
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
// CDP Performance Domain Metrics
|
||||
|
||||
async capturePagePerformanceMetrics(cdp: CDPSession) {
|
||||
await cdp.send('Performance.enable');
|
||||
const { metrics } = await cdp.send('Performance.getMetrics');
|
||||
|
||||
return {
|
||||
jsHeapUsedSize: metrics.find((m) => m.name === 'JSHeapUsedSize')?.value,
|
||||
jsHeapTotalSize: metrics.find((m) => m.name === 'JSHeapTotalSize')?.value,
|
||||
cpuTime: metrics.find((m) => m.name === 'TaskDuration')?.value,
|
||||
scriptTime: metrics.find((m) => m.name === 'ScriptDuration')?.value,
|
||||
layoutTime: metrics.find((m) => m.name === 'LayoutDuration')?.value,
|
||||
fps: metrics.find((m) => m.name === 'FramesPerSecond')?.value,
|
||||
nodesCount: metrics.find((m) => m.name === 'Nodes')?.value,
|
||||
documentsCount: metrics.find((m) => m.name === 'Documents')?.value,
|
||||
layoutCount: metrics.find((m) => m.name === 'LayoutCount')?.value,
|
||||
styleRecalcCount: metrics.find((m) => m.name === 'RecalcStyleCount')?.value,
|
||||
};
|
||||
}
|
||||
|
||||
private comparePerformanceMetrics(before: PerformanceMetrics, after: PerformanceMetrics) {
|
||||
const metrics: Record<
|
||||
string,
|
||||
{ before: number; after: number; diff: number; percentage: string }
|
||||
> = {};
|
||||
|
||||
for (const key of Object.keys(after)) {
|
||||
const metricKey = key as keyof PerformanceMetrics;
|
||||
if (after[metricKey] !== undefined && before[metricKey] !== undefined) {
|
||||
const diff = after[metricKey]! - before[metricKey]!;
|
||||
const percentage =
|
||||
before[metricKey] !== 0 ? ((diff / before[metricKey]!) * 100).toFixed(2) + '%' : 'N/A';
|
||||
|
||||
metrics[metricKey] = {
|
||||
before: before[metricKey]!,
|
||||
after: after[metricKey]!,
|
||||
diff,
|
||||
percentage,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return metrics;
|
||||
}
|
||||
|
||||
collectPagePerformanceStats = (
|
||||
url: string,
|
||||
before: PerformanceMetrics,
|
||||
after: PerformanceMetrics
|
||||
) => {
|
||||
const stats = this.comparePerformanceMetrics(before, after);
|
||||
|
||||
this.testInfo.attach('perf-metrics-report', {
|
||||
body: JSON.stringify({ url, stats }, null, 2),
|
||||
contentType: 'application/json',
|
||||
});
|
||||
|
||||
return stats;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
export interface BundleInfo {
|
||||
url: string;
|
||||
name: string;
|
||||
plugin: string;
|
||||
transferredSize: number;
|
||||
headersSize: number;
|
||||
}
|
||||
|
||||
export interface PluginInfo {
|
||||
count: number;
|
||||
totalSize: number;
|
||||
bundles: Array<{ name: string; transferredSize: number }>;
|
||||
}
|
||||
|
||||
export interface PageInfo {
|
||||
bundleCount: number;
|
||||
totalSize: number;
|
||||
pluginCount: number;
|
||||
plugins: Array<{
|
||||
name: string;
|
||||
bundlesCount: number;
|
||||
totalSize: number;
|
||||
bundles: Array<{ name: string; transferredSize: number }>;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface PerformanceMetrics {
|
||||
jsHeapUsedSize?: number;
|
||||
jsHeapTotalSize?: number;
|
||||
cpuTime?: number;
|
||||
scriptTime?: number;
|
||||
layoutTime?: number;
|
||||
fps?: number;
|
||||
nodesCount?: number;
|
||||
documentsCount?: number;
|
||||
layoutCount?: number;
|
||||
styleRecalcCount?: number;
|
||||
}
|
|
@ -7,10 +7,10 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { Page } from '@playwright/test';
|
||||
import { Page, test as base } from '@playwright/test';
|
||||
import { subj } from '@kbn/test-subj-selector';
|
||||
import { PathOptions } from '../../../../common/services/kibana_url';
|
||||
import { KibanaUrl, ScoutLogger, coreWorkerFixtures } from '../../worker';
|
||||
import { KibanaUrl, ScoutLogger } from '../../worker';
|
||||
import { ScoutPage } from '.';
|
||||
|
||||
/**
|
||||
|
@ -120,7 +120,7 @@ export function extendPlaywrightPage({
|
|||
* await page.gotoApp('discover);
|
||||
* ```
|
||||
*/
|
||||
export const scoutPageFixture = coreWorkerFixtures.extend<
|
||||
export const scoutPageFixture = base.extend<
|
||||
{ page: ScoutPage; log: ScoutLogger },
|
||||
{ kbnUrl: KibanaUrl }
|
||||
>({
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
import { test as base } from '@playwright/test';
|
||||
import { tags } from '../../../tags';
|
||||
|
||||
const supportedTags = tags.DEPLOYMENT_AGNOSTIC;
|
||||
const supportedTags = [...tags.DEPLOYMENT_AGNOSTIC, ...tags.PERFORMANCE];
|
||||
|
||||
export const validateTagsFixture = base.extend<{ validateTags: void }>({
|
||||
validateTags: [
|
||||
|
|
|
@ -31,3 +31,6 @@ export type { ApiFixtures, ApiParallelWorkerFixtures } from './apis';
|
|||
|
||||
export { synthtraceFixture } from './synthtrace';
|
||||
export type { SynthtraceFixture } from './synthtrace';
|
||||
|
||||
export { lighthouseFixture } from './lighthouse';
|
||||
export type { LighthouseFixture, LighthouseAuditOptions } from './lighthouse';
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
## Lighthouse Fixture
|
||||
|
||||
### Overview
|
||||
|
||||
`lighthouseFixture` integrates Lighthouse with Playwright, allowing automated performance and accessibility audits for Kibana and other web applications. It leverages persistent browser sessions to ensure authenticated audits and automatically attaches reports as artifacts in Playwright test reports.
|
||||
|
||||
### How it works
|
||||
|
||||
- Dynamically imports Lighthouse (ES module)
|
||||
- Uses `persistentContext` fixture to launch a new browser context on the specified debugging port, preserving authentication state across sessions.
|
||||
- Loads the provided Kibana URL inside this persistent context and runs the Lighthouse audit, using the same debug port and ensuring the session remains active (otherwise Lighthouse will be redirected to login page)
|
||||
- Automatically attaches Lighthouse report as html artifact in test reports, making them available in the `Playwright HTML report`.
|
||||
|
||||
### Usage: running report on Kibana page
|
||||
|
||||
```ts
|
||||
import { lighthouseTest, tags } from '@kbn/scout';
|
||||
|
||||
lighthouseTest.describe(
|
||||
'Discover App - Lighthouse Performance Audit',
|
||||
{ tag: [...tags.DEPLOYMENT_AGNOSTIC, ...tags.PERFORMANCE] },
|
||||
() => {
|
||||
lighthouseTest.beforeAll(async ({ esArchiver, kbnClient, uiSettings }) => {
|
||||
// loading the data
|
||||
});
|
||||
|
||||
lighthouseTest.afterAll(async ({ kbnClient, uiSettings }) => {
|
||||
// unloading the data
|
||||
});
|
||||
|
||||
lighthouseTest(
|
||||
'runs audit on Discover Page',
|
||||
async ({ browserAuth, lighthouse, page, pageObjects }) => {
|
||||
await browserAuth.loginAsAdmin();
|
||||
await pageObjects.discover.goto();
|
||||
await pageObjects.discover.waitForHistogramRendered();
|
||||
const currentUrl = page.url();
|
||||
|
||||
// Run the Lighthouse audit on the current page and attach the report
|
||||
await lighthouse.runAudit(currentUrl);
|
||||
}
|
||||
);
|
||||
}
|
||||
```
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { RunnerResult } from 'lighthouse';
|
||||
import { coreWorkerFixtures } from '../core_fixtures';
|
||||
|
||||
type OutputMode = 'html' | 'json' | 'csv';
|
||||
export interface LighthouseAuditOptions {
|
||||
maxWaitForLoad?: number;
|
||||
screenEmulation?: {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface LighthouseFixture {
|
||||
runAudit: (url: string, options?: LighthouseAuditOptions) => Promise<RunnerResult>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lighthouse fixture https://developer.chrome.com/docs/lighthouse/overview/
|
||||
* It allows to run Lighthouse audits on a given URL
|
||||
*/
|
||||
export const lighthouseFixture = coreWorkerFixtures.extend<
|
||||
{ lighthouse: LighthouseFixture },
|
||||
{ debuggingPort: number }
|
||||
>({
|
||||
lighthouse: [
|
||||
async ({ log, debuggingPort }, use, testInfo) => {
|
||||
// Import Lighthouse dynamically (ES module)
|
||||
const lighthouse = (await import('lighthouse')).default;
|
||||
|
||||
if (!debuggingPort) {
|
||||
throw new Error(
|
||||
`Remote debugging port is not set: Check 'use.launchOptions.args' in Playwright configuration`
|
||||
);
|
||||
}
|
||||
|
||||
const DEFAULT_AUDIT_OPTIONS: Partial<import('lighthouse').Flags> = {
|
||||
maxWaitForLoad: 30000,
|
||||
output: ['html'],
|
||||
formFactor: 'desktop',
|
||||
screenEmulation: {
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
mobile: false,
|
||||
deviceScaleFactor: 1,
|
||||
disabled: false,
|
||||
},
|
||||
};
|
||||
|
||||
const runAudit = async (url: string, auditOptions?: LighthouseAuditOptions) => {
|
||||
const options: import('lighthouse').Flags = {
|
||||
port: debuggingPort,
|
||||
maxWaitForLoad: auditOptions?.maxWaitForLoad ?? DEFAULT_AUDIT_OPTIONS.maxWaitForLoad,
|
||||
output: DEFAULT_AUDIT_OPTIONS.output as OutputMode[],
|
||||
formFactor: DEFAULT_AUDIT_OPTIONS.formFactor as 'desktop' | 'mobile',
|
||||
screenEmulation: {
|
||||
width:
|
||||
auditOptions?.screenEmulation?.width ?? DEFAULT_AUDIT_OPTIONS.screenEmulation!.width,
|
||||
height:
|
||||
auditOptions?.screenEmulation?.height ??
|
||||
DEFAULT_AUDIT_OPTIONS.screenEmulation!.height,
|
||||
mobile: DEFAULT_AUDIT_OPTIONS.screenEmulation!.mobile,
|
||||
deviceScaleFactor: DEFAULT_AUDIT_OPTIONS.screenEmulation!.deviceScaleFactor,
|
||||
disabled: DEFAULT_AUDIT_OPTIONS.screenEmulation!.disabled,
|
||||
},
|
||||
};
|
||||
|
||||
const auditResult = await lighthouse(url, options);
|
||||
|
||||
if (!auditResult?.lhr?.categories?.performance?.score) {
|
||||
throw new Error('Lighthouse audit failed: No performance score found');
|
||||
}
|
||||
|
||||
const perfScore = auditResult.lhr.categories.performance.score;
|
||||
log.info(`✅ Lighthouse audit completed with performance score: ${perfScore}`);
|
||||
|
||||
testInfo.attach('lighthouse-report', {
|
||||
body: auditResult.report?.[0] ?? 'No report generated',
|
||||
contentType: 'text/html',
|
||||
});
|
||||
|
||||
return auditResult;
|
||||
};
|
||||
|
||||
use({ runAudit });
|
||||
},
|
||||
{ scope: 'test' },
|
||||
],
|
||||
});
|
|
@ -7,11 +7,13 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { scoutFixtures, scoutParallelFixtures, globalSetup } from './fixtures';
|
||||
import { scoutFixtures, scoutParallelFixtures, lighthouseFixtures, globalSetup } from './fixtures';
|
||||
|
||||
// Scout core fixtures: worker & test scope
|
||||
export const test = scoutFixtures;
|
||||
|
||||
export const lighthouseTest = lighthouseFixtures;
|
||||
|
||||
// Scout core 'space aware' fixtures: worker & test scope
|
||||
export const spaceTest = scoutParallelFixtures;
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { Locator } from 'playwright/test';
|
||||
import { ScoutPage } from '..';
|
||||
import { ScoutTestConfig } from '../../types';
|
||||
|
||||
export class CollapsibleNav {
|
||||
private toggleNavButton: Locator;
|
||||
|
||||
constructor(private readonly page: ScoutPage, private readonly config: ScoutTestConfig) {
|
||||
this.toggleNavButton = this.page.testSubj.locator(
|
||||
this.config.serverless ? 'euiCollapsibleNavButton' : 'toggleNavButton'
|
||||
);
|
||||
}
|
||||
|
||||
async expandNav() {
|
||||
if (await this.toggleNavButton.isVisible()) {
|
||||
const isExpanded = await this.toggleNavButton.getAttribute('aria-expanded');
|
||||
if (isExpanded === 'false') {
|
||||
await this.toggleNavButton.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async clickItem(itemName: 'Discover' | 'Dashboards' | 'Maps' | 'Machine Learning') {
|
||||
await this.expandNav();
|
||||
return this.config.serverless
|
||||
? this.page.testSubj.click(`*nav-item-id-${itemName.toLocaleLowerCase()}`)
|
||||
: this.page.click(`[title="${itemName}"]`);
|
||||
}
|
||||
}
|
|
@ -25,6 +25,10 @@ export class DashboardApp {
|
|||
await this.page.gotoApp('dashboards');
|
||||
}
|
||||
|
||||
async waitForListingTableToLoad() {
|
||||
return this.page.testSubj.waitForSelector('table-is-ready', { state: 'visible' });
|
||||
}
|
||||
|
||||
async openNewDashboard() {
|
||||
await this.page.testSubj.click('newItemButton');
|
||||
await this.page.testSubj.waitForSelector('emptyDashboardWidget', { state: 'visible' });
|
||||
|
@ -92,4 +96,24 @@ export class DashboardApp {
|
|||
state: 'hidden',
|
||||
});
|
||||
}
|
||||
|
||||
async waitForPanelsToLoad(
|
||||
expectedCount: number,
|
||||
options: { timeout: number; selector: string } = {
|
||||
timeout: 20000,
|
||||
selector: '[data-test-subj="embeddablePanel"][data-render-complete="true"]',
|
||||
}
|
||||
) {
|
||||
const startTime = Date.now();
|
||||
|
||||
while (Date.now() - startTime < options.timeout) {
|
||||
const count = await this.page.locator(options.selector).count();
|
||||
if (count === expectedCount) return;
|
||||
// Short polling interval
|
||||
// eslint-disable-next-line playwright/no-wait-for-timeout
|
||||
await this.page.waitForTimeout(100);
|
||||
}
|
||||
|
||||
throw new Error(`Timeout waiting for ${expectedCount} elements matching ${options.selector}`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
*/
|
||||
|
||||
import { ScoutPage } from '..';
|
||||
import { ScoutLogger } from '../../common';
|
||||
import { ScoutTestConfig } from '../../types';
|
||||
import { CollapsibleNav } from './collapsible_nav';
|
||||
import { DashboardApp } from './dashboard_app';
|
||||
import { DatePicker } from './date_picker';
|
||||
import { DiscoverApp } from './discover_app';
|
||||
|
@ -16,6 +19,12 @@ import { MapsPage } from './maps_page';
|
|||
import { RenderablePage } from './renderable_page';
|
||||
import { createLazyPageObject } from './utils';
|
||||
|
||||
export interface PageObjectsFixtures {
|
||||
page: ScoutPage;
|
||||
config: ScoutTestConfig;
|
||||
log: ScoutLogger;
|
||||
}
|
||||
|
||||
export interface PageObjects {
|
||||
datePicker: DatePicker;
|
||||
discover: DiscoverApp;
|
||||
|
@ -23,6 +32,7 @@ export interface PageObjects {
|
|||
filterBar: FilterBar;
|
||||
maps: MapsPage;
|
||||
renderable: RenderablePage;
|
||||
collapsibleNav: CollapsibleNav;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,14 +41,15 @@ export interface PageObjects {
|
|||
* @param page - `ScoutPage` instance used for initializing page objects.
|
||||
* @returns An object containing lazy-loaded core page objects.
|
||||
*/
|
||||
export function createCorePageObjects(page: ScoutPage): PageObjects {
|
||||
export function createCorePageObjects(fixtures: PageObjectsFixtures): PageObjects {
|
||||
return {
|
||||
datePicker: createLazyPageObject(DatePicker, page),
|
||||
dashboard: createLazyPageObject(DashboardApp, page),
|
||||
discover: createLazyPageObject(DiscoverApp, page),
|
||||
filterBar: createLazyPageObject(FilterBar, page),
|
||||
maps: createLazyPageObject(MapsPage, page),
|
||||
renderable: createLazyPageObject(RenderablePage, page),
|
||||
datePicker: createLazyPageObject(DatePicker, fixtures.page),
|
||||
dashboard: createLazyPageObject(DashboardApp, fixtures.page),
|
||||
discover: createLazyPageObject(DiscoverApp, fixtures.page),
|
||||
filterBar: createLazyPageObject(FilterBar, fixtures.page),
|
||||
maps: createLazyPageObject(MapsPage, fixtures.page),
|
||||
renderable: createLazyPageObject(RenderablePage, fixtures.page),
|
||||
collapsibleNav: createLazyPageObject(CollapsibleNav, fixtures.page, fixtures.config),
|
||||
// Add new page objects here
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,11 +10,13 @@
|
|||
const SERVERLESS_ONLY = ['@svlSecurity', '@svlOblt', '@svlSearch'];
|
||||
const ESS_ONLY = ['@ess'];
|
||||
const DEPLOYMENT_AGNOSTIC = SERVERLESS_ONLY.concat(ESS_ONLY);
|
||||
const PERFORMANCE = ['@perf'];
|
||||
|
||||
export const tags = {
|
||||
ESS_ONLY,
|
||||
SERVERLESS_ONLY,
|
||||
DEPLOYMENT_AGNOSTIC,
|
||||
PERFORMANCE,
|
||||
};
|
||||
|
||||
export const tagsByMode = {
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { test, tags, expect, CDPSession } from '@kbn/scout';
|
||||
import { testData } from '../fixtures';
|
||||
|
||||
test.describe(
|
||||
'Discover App - Performance Metrics & Bundle Analysis',
|
||||
{ tag: [...tags.DEPLOYMENT_AGNOSTIC, ...tags.PERFORMANCE] },
|
||||
() => {
|
||||
let cdp: CDPSession;
|
||||
|
||||
test.beforeAll(async ({ esArchiver, kbnClient, uiSettings }) => {
|
||||
await esArchiver.loadIfNeeded(testData.ES_ARCHIVES.LOGSTASH);
|
||||
await kbnClient.importExport.load(testData.KBN_ARCHIVES.DASHBOARD_DRILLDOWNS);
|
||||
await uiSettings.set({
|
||||
defaultIndex: testData.DATA_VIEW_ID.LOGSTASH,
|
||||
'timepicker:timeDefaults': `{ "from": "${testData.LOGSTASH_DEFAULT_START_TIME}", "to": "${testData.LOGSTASH_DEFAULT_END_TIME}"}`,
|
||||
});
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ browserAuth, page, context, perfTracker }) => {
|
||||
await browserAuth.loginAsAdmin();
|
||||
cdp = await context.newCDPSession(page);
|
||||
await cdp.send('Network.enable');
|
||||
await page.gotoApp('home');
|
||||
await page.waitForLoadingIndicatorHidden();
|
||||
await perfTracker.waitForJsLoad(cdp); // Ensure JS bundles are fully loaded
|
||||
});
|
||||
|
||||
test.afterAll(async ({ kbnClient, uiSettings }) => {
|
||||
await uiSettings.unset('defaultIndex', 'timepicker:timeDefaults');
|
||||
await kbnClient.savedObjects.cleanStandardList();
|
||||
});
|
||||
|
||||
test('collects and validates JS Bundles loaded on page', async ({
|
||||
page,
|
||||
pageObjects,
|
||||
perfTracker,
|
||||
}) => {
|
||||
perfTracker.captureBundleResponses(cdp); // Start tracking
|
||||
|
||||
// Navigate to Discover app
|
||||
await pageObjects.collapsibleNav.clickItem('Discover');
|
||||
const currentUrl = page.url();
|
||||
expect(currentUrl).toContain('app/discover#/');
|
||||
|
||||
// Ensure all JS bundles are loaded
|
||||
await perfTracker.waitForJsLoad(cdp);
|
||||
|
||||
// Collect and validate stats
|
||||
const stats = perfTracker.collectJsBundleStats(currentUrl);
|
||||
expect(
|
||||
stats.totalSize,
|
||||
`Total bundles size loaded on page should not exceed 3.1 MB`
|
||||
).toBeLessThan(3.1 * 1024 * 1024);
|
||||
expect(
|
||||
stats.bundleCount,
|
||||
`Total bundle chunks count loaded on page should not exceed 100`
|
||||
).toBeLessThan(100);
|
||||
expect(
|
||||
stats.plugins.map((p) => p.name),
|
||||
'Unexpected plugins were loaded on page'
|
||||
).toStrictEqual([
|
||||
'aiops',
|
||||
'discover',
|
||||
'eventAnnotation',
|
||||
'expressionXY',
|
||||
'kbn-ui-shared-deps-npm',
|
||||
'lens',
|
||||
'maps',
|
||||
'unifiedHistogram',
|
||||
'unifiedSearch',
|
||||
]);
|
||||
// Validate individual plugin bundle sizes
|
||||
expect(
|
||||
stats.plugins.find((p) => p.name === 'discover')?.totalSize,
|
||||
`Total 'discover' bundles size should not exceed 650 KB`
|
||||
).toBeLessThan(650 * 1024);
|
||||
expect(
|
||||
stats.plugins.find((p) => p.name === 'unifiedHistogram')?.totalSize,
|
||||
`Total 'unifiedHistogram' bundles size should not exceed 150 KB`
|
||||
).toBeLessThan(150 * 1024);
|
||||
expect(
|
||||
stats.plugins.find((p) => p.name === 'unifiedSearch')?.totalSize,
|
||||
`Total 'unifiedSearch' bundles size should not exceed 450 KB`
|
||||
).toBeLessThan(450 * 1024);
|
||||
});
|
||||
|
||||
test('measures Performance Metrics before and after Discover load', async ({
|
||||
page,
|
||||
pageObjects,
|
||||
perfTracker,
|
||||
}) => {
|
||||
const beforeMetrics = await perfTracker.capturePagePerformanceMetrics(cdp);
|
||||
|
||||
// Navigate to Discover app
|
||||
await pageObjects.collapsibleNav.clickItem('Discover');
|
||||
await page.waitForLoadingIndicatorHidden();
|
||||
const currentUrl = page.url();
|
||||
expect(currentUrl).toContain('app/discover#/');
|
||||
|
||||
await pageObjects.discover.waitForHistogramRendered();
|
||||
|
||||
const afterMetrics = await perfTracker.capturePagePerformanceMetrics(cdp);
|
||||
const perfStats = perfTracker.collectPagePerformanceStats(
|
||||
currentUrl,
|
||||
beforeMetrics,
|
||||
afterMetrics
|
||||
);
|
||||
|
||||
expect(
|
||||
perfStats.cpuTime.diff,
|
||||
'CPU time (seconds) usage during page navigation should not exceed 1.5 seconds'
|
||||
).toBeLessThan(1.5);
|
||||
expect(
|
||||
perfStats.scriptTime.diff,
|
||||
'Additional time spent executing JS scripts should not exceed 0.5 second'
|
||||
).toBeLessThan(0.5);
|
||||
expect(
|
||||
perfStats.layoutTime.diff,
|
||||
'Total layout computation time should not exceed 0.1 second'
|
||||
).toBeLessThan(0.06);
|
||||
});
|
||||
}
|
||||
);
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { lighthouseTest, tags } from '@kbn/scout';
|
||||
import { testData } from '../fixtures';
|
||||
|
||||
lighthouseTest.describe(
|
||||
'Discover App - Lighthouse Performance Audit',
|
||||
{ tag: [...tags.DEPLOYMENT_AGNOSTIC, ...tags.PERFORMANCE] },
|
||||
() => {
|
||||
lighthouseTest.beforeAll(async ({ esArchiver, kbnClient, uiSettings }) => {
|
||||
await esArchiver.loadIfNeeded(testData.ES_ARCHIVES.LOGSTASH);
|
||||
await kbnClient.importExport.load(testData.KBN_ARCHIVES.DASHBOARD_DRILLDOWNS);
|
||||
await uiSettings.set({
|
||||
defaultIndex: testData.DATA_VIEW_ID.LOGSTASH,
|
||||
'timepicker:timeDefaults': `{ "from": "${testData.LOGSTASH_DEFAULT_START_TIME}", "to": "${testData.LOGSTASH_DEFAULT_END_TIME}"}`,
|
||||
});
|
||||
});
|
||||
|
||||
lighthouseTest.afterAll(async ({ kbnClient, uiSettings }) => {
|
||||
await uiSettings.unset('defaultIndex', 'timepicker:timeDefaults');
|
||||
await kbnClient.savedObjects.cleanStandardList();
|
||||
});
|
||||
|
||||
lighthouseTest(
|
||||
'runs audit on Discover Page',
|
||||
async ({ browserAuth, lighthouse, page, pageObjects }) => {
|
||||
await browserAuth.loginAsAdmin();
|
||||
await pageObjects.discover.goto();
|
||||
await pageObjects.discover.waitForHistogramRendered();
|
||||
const currentUrl = page.url();
|
||||
|
||||
// Run the Lighthouse audit on the current page and attach the report
|
||||
await lighthouse.runAudit(currentUrl);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
478
yarn.lock
478
yarn.lock
|
@ -71,7 +71,7 @@
|
|||
"@jridgewell/gen-mapping" "^0.1.0"
|
||||
"@jridgewell/trace-mapping" "^0.3.9"
|
||||
|
||||
"@apidevtools/json-schema-ref-parser@11.7.2", "@apidevtools/json-schema-ref-parser@^11.5.5":
|
||||
"@apidevtools/json-schema-ref-parser@11.7.2":
|
||||
version "11.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz#cdf3e0aded21492364a70e193b45b7cf4177f031"
|
||||
integrity sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==
|
||||
|
@ -80,6 +80,15 @@
|
|||
"@types/json-schema" "^7.0.15"
|
||||
js-yaml "^4.1.0"
|
||||
|
||||
"@apidevtools/json-schema-ref-parser@^11.5.5":
|
||||
version "11.9.3"
|
||||
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.9.3.tgz#0e0c9061fc41cf03737d499a4e6a8299fdd2bfa7"
|
||||
integrity sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==
|
||||
dependencies:
|
||||
"@jsdevtools/ono" "^7.1.3"
|
||||
"@types/json-schema" "^7.0.15"
|
||||
js-yaml "^4.1.0"
|
||||
|
||||
"@apidevtools/json-schema-ref-parser@^9.0.6":
|
||||
version "9.0.9"
|
||||
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b"
|
||||
|
@ -2938,6 +2947,16 @@
|
|||
"@formatjs/intl-localematcher" "0.5.4"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@formatjs/ecma402-abstract@2.3.3":
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.3.tgz#fbc7555c9e4fdd104cd5e23129fa3735be3ad0ba"
|
||||
integrity sha512-pJT1OkhplSmvvr6i3CWTPvC/FGC06MbN5TNBfRO6Ox62AEz90eMq+dVvtX9Bl3jxCEkS0tATzDarRZuOLw7oFg==
|
||||
dependencies:
|
||||
"@formatjs/fast-memoize" "2.2.6"
|
||||
"@formatjs/intl-localematcher" "0.6.0"
|
||||
decimal.js "10"
|
||||
tslib "2"
|
||||
|
||||
"@formatjs/fast-memoize@2.2.0":
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-2.2.0.tgz#33bd616d2e486c3e8ef4e68c99648c196887802b"
|
||||
|
@ -2945,6 +2964,22 @@
|
|||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@formatjs/fast-memoize@2.2.6":
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-2.2.6.tgz#fac0a84207a1396be1f1aa4ee2805b179e9343d1"
|
||||
integrity sha512-luIXeE2LJbQnnzotY1f2U2m7xuQNj2DA8Vq4ce1BY9ebRZaoPB1+8eZ6nXpLzsxuW5spQxr7LdCg+CApZwkqkw==
|
||||
dependencies:
|
||||
tslib "2"
|
||||
|
||||
"@formatjs/icu-messageformat-parser@2.11.1", "@formatjs/icu-messageformat-parser@^2.7.6":
|
||||
version "2.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.1.tgz#59d69124b9cf3186800a576c0228947d10594347"
|
||||
integrity sha512-o0AhSNaOfKoic0Sn1GkFCK4MxdRsw7mPJ5/rBpIqdvcC7MIuyUSW8WChUEvrK78HhNpYOgqCQbINxCTumJLzZA==
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract" "2.3.3"
|
||||
"@formatjs/icu-skeleton-parser" "1.8.13"
|
||||
tslib "2"
|
||||
|
||||
"@formatjs/icu-messageformat-parser@2.7.6":
|
||||
version "2.7.6"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.7.6.tgz#3d69806de056d2919d53dad895a5ff4851e4e9ff"
|
||||
|
@ -2954,7 +2989,7 @@
|
|||
"@formatjs/icu-skeleton-parser" "1.8.0"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@formatjs/icu-messageformat-parser@2.7.8", "@formatjs/icu-messageformat-parser@^2.7.6":
|
||||
"@formatjs/icu-messageformat-parser@2.7.8":
|
||||
version "2.7.8"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.7.8.tgz#f6d7643001e9bb5930d812f1f9a9856f30fa0343"
|
||||
integrity sha512-nBZJYmhpcSX0WeJ5SDYUkZ42AgR3xiyhNCsQweFx3cz/ULJjym8bHAzWKvG5e2+1XO98dBYC0fWeeAECAVSwLA==
|
||||
|
@ -2971,6 +3006,14 @@
|
|||
"@formatjs/ecma402-abstract" "1.18.2"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@formatjs/icu-skeleton-parser@1.8.13":
|
||||
version "1.8.13"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.13.tgz#5e8b1e1bb467c937735fecb4cb4b345932151a44"
|
||||
integrity sha512-N/LIdTvVc1TpJmMt2jVg0Fr1F7Q1qJPdZSCs19unMskCmVQ/sa0H9L8PWt13vq+gLdLg1+pPsvBLydL1Apahjg==
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract" "2.3.3"
|
||||
tslib "2"
|
||||
|
||||
"@formatjs/icu-skeleton-parser@1.8.2":
|
||||
version "1.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.2.tgz#2252c949ae84ee66930e726130ea66731a123c9f"
|
||||
|
@ -3004,6 +3047,13 @@
|
|||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@formatjs/intl-localematcher@0.6.0":
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.6.0.tgz#33cf0d33279572c990e02ab75a93122569878082"
|
||||
integrity sha512-4rB4g+3hESy1bHSBG3tDFaMY2CH67iT7yne1e+0CLTsGLDcmoEWWpJjjpWVaYgYfYuohIRuo0E+N536gd2ZHZA==
|
||||
dependencies:
|
||||
tslib "2"
|
||||
|
||||
"@formatjs/intl-pluralrules@^5.2.12":
|
||||
version "5.2.12"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/intl-pluralrules/-/intl-pluralrules-5.2.12.tgz#0433202e985c7853b8737e7127253e18474eced1"
|
||||
|
@ -9159,6 +9209,13 @@
|
|||
node-addon-api "^3.2.1"
|
||||
node-gyp-build "^4.3.0"
|
||||
|
||||
"@paulirish/trace_engine@0.0.44":
|
||||
version "0.0.44"
|
||||
resolved "https://registry.yarnpkg.com/@paulirish/trace_engine/-/trace_engine-0.0.44.tgz#27f2188856c4800e02a68e6f51b6ade9c460cfb8"
|
||||
integrity sha512-QjDv5qVaUXd5WZzE2ktKvqtGA17v4HFtj6MROCGkK57AZr9n0ZKgcx7dEFho+5EHZ6V6h1upW2eqheo8C4Y4dA==
|
||||
dependencies:
|
||||
third-party-web latest
|
||||
|
||||
"@pkgjs/parseargs@^0.11.0":
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
|
@ -9285,6 +9342,19 @@
|
|||
unbzip2-stream "^1.4.3"
|
||||
yargs "^17.7.2"
|
||||
|
||||
"@puppeteer/browsers@2.8.0":
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.8.0.tgz#9d592933cbefc66c37823770844b8cbac52607dd"
|
||||
integrity sha512-yTwt2KWRmCQAfhvbCRjebaSX8pV1//I0Y3g+A7f/eS7gf0l4eRJoUCvcYdVtboeU4CTOZQuqYbZNS8aBYb8ROQ==
|
||||
dependencies:
|
||||
debug "^4.4.0"
|
||||
extract-zip "^2.0.1"
|
||||
progress "^2.0.3"
|
||||
proxy-agent "^6.5.0"
|
||||
semver "^7.7.1"
|
||||
tar-fs "^3.0.8"
|
||||
yargs "^17.7.2"
|
||||
|
||||
"@readme/json-schema-ref-parser@^1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@readme/json-schema-ref-parser/-/json-schema-ref-parser-1.2.0.tgz#8552cde8f8ecf455398c59aa6e2cf5ed2d0f3d31"
|
||||
|
@ -9421,6 +9491,56 @@
|
|||
agentkeepalive "^4.1.3"
|
||||
lodash "^4.17.21"
|
||||
|
||||
"@sentry-internal/tracing@7.120.3":
|
||||
version "7.120.3"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.120.3.tgz#a54e67c39d23576a72b3f349c1a3fae13e27f2f1"
|
||||
integrity sha512-Ausx+Jw1pAMbIBHStoQ6ZqDZR60PsCByvHdw/jdH9AqPrNE9xlBSf9EwcycvmrzwyKspSLaB52grlje2cRIUMg==
|
||||
dependencies:
|
||||
"@sentry/core" "7.120.3"
|
||||
"@sentry/types" "7.120.3"
|
||||
"@sentry/utils" "7.120.3"
|
||||
|
||||
"@sentry/core@7.120.3":
|
||||
version "7.120.3"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.120.3.tgz#88ae2f8c242afce59e32bdee7f866d8788e86c03"
|
||||
integrity sha512-vyy11fCGpkGK3qI5DSXOjgIboBZTriw0YDx/0KyX5CjIjDDNgp5AGgpgFkfZyiYiaU2Ww3iFuKo4wHmBusz1uA==
|
||||
dependencies:
|
||||
"@sentry/types" "7.120.3"
|
||||
"@sentry/utils" "7.120.3"
|
||||
|
||||
"@sentry/integrations@7.120.3":
|
||||
version "7.120.3"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.120.3.tgz#ea6812b77dea7d0090a5cf85383f154b3bd5b073"
|
||||
integrity sha512-6i/lYp0BubHPDTg91/uxHvNui427df9r17SsIEXa2eKDwQ9gW2qRx5IWgvnxs2GV/GfSbwcx4swUB3RfEWrXrQ==
|
||||
dependencies:
|
||||
"@sentry/core" "7.120.3"
|
||||
"@sentry/types" "7.120.3"
|
||||
"@sentry/utils" "7.120.3"
|
||||
localforage "^1.8.1"
|
||||
|
||||
"@sentry/node@^7.0.0":
|
||||
version "7.120.3"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.120.3.tgz#59a54e1bfccffd28e7d502a5eefea615f07e13f5"
|
||||
integrity sha512-t+QtekZedEfiZjbkRAk1QWJPnJlFBH/ti96tQhEq7wmlk3VszDXraZvLWZA0P2vXyglKzbWRGkT31aD3/kX+5Q==
|
||||
dependencies:
|
||||
"@sentry-internal/tracing" "7.120.3"
|
||||
"@sentry/core" "7.120.3"
|
||||
"@sentry/integrations" "7.120.3"
|
||||
"@sentry/types" "7.120.3"
|
||||
"@sentry/utils" "7.120.3"
|
||||
|
||||
"@sentry/types@7.120.3":
|
||||
version "7.120.3"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.120.3.tgz#25f69ae27f0c8430f1863ad2a9ee9cab7fccf232"
|
||||
integrity sha512-C4z+3kGWNFJ303FC+FxAd4KkHvxpNFYAFN8iMIgBwJdpIl25KZ8Q/VdGn0MLLUEHNLvjob0+wvwlcRBBNLXOow==
|
||||
|
||||
"@sentry/utils@7.120.3":
|
||||
version "7.120.3"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.120.3.tgz#0cc891c315d3894eb80c2e7298efd7437e939a5d"
|
||||
integrity sha512-UDAOQJtJDxZHQ5Nm1olycBIsz2wdGX8SdzyGVHmD8EOQYAeDZQyIlQYohDe9nazdIOQLZCIc3fU0G9gqVLkaGQ==
|
||||
dependencies:
|
||||
"@sentry/types" "7.120.3"
|
||||
|
||||
"@sideway/address@^4.1.5":
|
||||
version "4.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5"
|
||||
|
@ -14243,15 +14363,20 @@ axe-core@^4.10.0:
|
|||
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.0.tgz#d9e56ab0147278272739a000880196cdfe113b59"
|
||||
integrity sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==
|
||||
|
||||
axe-core@^4.10.2:
|
||||
version "4.10.2"
|
||||
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.2.tgz#85228e3e1d8b8532a27659b332e39b7fa0e022df"
|
||||
integrity sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==
|
||||
|
||||
axe-core@^4.2.0, axe-core@^4.6.2:
|
||||
version "4.7.2"
|
||||
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.2.tgz#040a7342b20765cb18bb50b628394c21bccc17a0"
|
||||
integrity sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==
|
||||
|
||||
axios@^1.0.0, axios@^1.6.0, axios@^1.6.2, axios@^1.7.4, axios@^1.8.2:
|
||||
version "1.8.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.8.2.tgz#fabe06e241dfe83071d4edfbcaa7b1c3a40f7979"
|
||||
integrity sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==
|
||||
version "1.8.3"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.8.3.tgz#9ebccd71c98651d547162a018a1a95a4b4ed4de8"
|
||||
integrity sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==
|
||||
dependencies:
|
||||
follow-redirects "^1.15.6"
|
||||
form-data "^4.0.0"
|
||||
|
@ -14545,27 +14670,33 @@ bare-events@^2.0.0, bare-events@^2.2.0:
|
|||
resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.2.1.tgz#7b6d421f26a7a755e20bf580b727c84b807964c1"
|
||||
integrity sha512-9GYPpsPFvrWBkelIhOhTWtkeZxVxZOdb3VnFTCzlOo3OjvmTvzLoZFUT8kNFACx0vJej6QPney1Cf9BvzCNE/A==
|
||||
|
||||
bare-fs@^2.1.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-2.2.1.tgz#c1985d8d3e07a178956b072d3af67cb8c1fa9391"
|
||||
integrity sha512-+CjmZANQDFZWy4PGbVdmALIwmt33aJg8qTkVjClU6X4WmZkTPBDxRHiBn7fpqEWEfF3AC2io++erpViAIQbSjg==
|
||||
bare-fs@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-4.0.1.tgz#85844f34da819c76754d545323a8b23ed3617c76"
|
||||
integrity sha512-ilQs4fm/l9eMfWY2dY0WCIUplSUp7U0CT1vrqMg1MUdeZl4fypu5UP0XcDBK5WBQPJAKP1b7XEodISmekH/CEg==
|
||||
dependencies:
|
||||
bare-events "^2.0.0"
|
||||
bare-os "^2.0.0"
|
||||
bare-path "^2.0.0"
|
||||
streamx "^2.13.0"
|
||||
bare-path "^3.0.0"
|
||||
bare-stream "^2.0.0"
|
||||
|
||||
bare-os@^2.0.0, bare-os@^2.1.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/bare-os/-/bare-os-2.2.0.tgz#24364692984d0bd507621754781b31d7872736b2"
|
||||
integrity sha512-hD0rOPfYWOMpVirTACt4/nK8mC55La12K5fY1ij8HAdfQakD62M+H4o4tpfKzVGLgRDTuk3vjA4GqGXXCeFbag==
|
||||
bare-os@^3.0.1:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/bare-os/-/bare-os-3.6.0.tgz#1465dd7e1bebe0dec230097a23ad00f7db51f957"
|
||||
integrity sha512-BUrFS5TqSBdA0LwHop4OjPJwisqxGy6JsWVqV6qaFoe965qqtaKfDzHY5T2YA1gUL0ZeeQeA+4BBc1FJTcHiPw==
|
||||
|
||||
bare-path@^2.0.0, bare-path@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/bare-path/-/bare-path-2.1.0.tgz#830f17fd39842813ca77d211ebbabe238a88cb4c"
|
||||
integrity sha512-DIIg7ts8bdRKwJRJrUMy/PICEaQZaPGZ26lsSx9MJSwIhSrcdHn7/C8W+XmnG/rKi6BaRcz+JO00CjZteybDtw==
|
||||
bare-path@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bare-path/-/bare-path-3.0.0.tgz#b59d18130ba52a6af9276db3e96a2e3d3ea52178"
|
||||
integrity sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==
|
||||
dependencies:
|
||||
bare-os "^2.1.0"
|
||||
bare-os "^3.0.1"
|
||||
|
||||
bare-stream@^2.0.0:
|
||||
version "2.6.5"
|
||||
resolved "https://registry.yarnpkg.com/bare-stream/-/bare-stream-2.6.5.tgz#bba8e879674c4c27f7e27805df005c15d7a2ca07"
|
||||
integrity sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==
|
||||
dependencies:
|
||||
streamx "^2.21.0"
|
||||
|
||||
base64-js@1.3.1:
|
||||
version "1.3.1"
|
||||
|
@ -15483,6 +15614,16 @@ chroma-js@2.4.2, chroma-js@^2.1.0, chroma-js@^2.4.2:
|
|||
resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-2.4.2.tgz#dffc214ed0c11fa8eefca2c36651d8e57cbfb2b0"
|
||||
integrity sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A==
|
||||
|
||||
chrome-launcher@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-1.1.2.tgz#52eff6b3fd7f24b65192b2624a108dadbcca4b9d"
|
||||
integrity sha512-YclTJey34KUm5jB1aEJCq807bSievi7Nb/TU4Gu504fUYi3jw3KCIaH6L7nFWQhdEgH3V+wCh+kKD1P5cXnfxw==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
escape-string-regexp "^4.0.0"
|
||||
is-wsl "^2.2.0"
|
||||
lighthouse-logger "^2.0.1"
|
||||
|
||||
chrome-trace-event@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4"
|
||||
|
@ -15511,6 +15652,14 @@ chromium-bidi@1.1.0:
|
|||
mitt "3.0.1"
|
||||
zod "3.24.1"
|
||||
|
||||
chromium-bidi@2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-2.1.2.tgz#b0710279f993128d4e0b41c892209ea093217d97"
|
||||
integrity sha512-vtRWBK2uImo5/W2oG6/cDkkHSm+2t6VHgnj+Rcwhb0pP74OoUb4GipyRX/T/y39gYQPhioP0DPShn+A7P6CHNw==
|
||||
dependencies:
|
||||
mitt "^3.0.1"
|
||||
zod "^3.24.1"
|
||||
|
||||
ci-info@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
|
||||
|
@ -16098,6 +16247,18 @@ concaveman@*:
|
|||
robust-predicates "^2.0.4"
|
||||
tinyqueue "^2.0.3"
|
||||
|
||||
configstore@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
|
||||
integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==
|
||||
dependencies:
|
||||
dot-prop "^5.2.0"
|
||||
graceful-fs "^4.1.2"
|
||||
make-dir "^3.0.0"
|
||||
unique-string "^2.0.0"
|
||||
write-file-atomic "^3.0.0"
|
||||
xdg-basedir "^4.0.0"
|
||||
|
||||
connect-history-api-fallback@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8"
|
||||
|
@ -16425,6 +16586,16 @@ crypto-js@^4.2.0:
|
|||
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631"
|
||||
integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==
|
||||
|
||||
crypto-random-string@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
|
||||
integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
|
||||
|
||||
csp_evaluator@1.1.5:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/csp_evaluator/-/csp_evaluator-1.1.5.tgz#33788d695b7b539b17d5b6eba494431ce931faff"
|
||||
integrity sha512-EL/iN9etCTzw/fBnp0/uj0f5BOOGvZut2mzsiiBZ/FdT6gFQCKRO/tmcKOxn5drWZ2Ndm/xBb1SI4zwWbGtmIw==
|
||||
|
||||
css-box-model@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1"
|
||||
|
@ -17153,7 +17324,7 @@ debounce@^1.2.1:
|
|||
resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5"
|
||||
integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==
|
||||
|
||||
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0:
|
||||
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||
|
@ -17216,10 +17387,10 @@ decamelize@^6.0.0:
|
|||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-6.0.0.tgz#8cad4d916fde5c41a264a43d0ecc56fe3d31749e"
|
||||
integrity sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==
|
||||
|
||||
decimal.js@^10.4.1:
|
||||
version "10.4.1"
|
||||
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.1.tgz#be75eeac4a2281aace80c1a8753587c27ef053e7"
|
||||
integrity sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==
|
||||
decimal.js@10, decimal.js@^10.4.1:
|
||||
version "10.5.0"
|
||||
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.5.0.tgz#0f371c7cf6c4898ce0afb09836db73cd82010f22"
|
||||
integrity sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==
|
||||
|
||||
decko@^1.2.0:
|
||||
version "1.2.0"
|
||||
|
@ -17677,6 +17848,16 @@ devtools-protocol@0.0.1380148:
|
|||
resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1380148.tgz#7dcdad06515135b244ff05878ca8019e041c1c55"
|
||||
integrity sha512-1CJABgqLxbYxVI+uJY/UDUHJtJ0KZTSjNYJYKqd9FRoXT33WDakDHNxRapMEgzeJ/C3rcs01+avshMnPmKQbvA==
|
||||
|
||||
devtools-protocol@0.0.1413902:
|
||||
version "0.0.1413902"
|
||||
resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1413902.tgz#a0f00fe9eb25ab337a8f9656a29e0a1a69f42401"
|
||||
integrity sha512-yRtvFD8Oyk7C9Os3GmnFZLu53yAfsnyw1s+mLmHHUK0GQEc9zthHWvS1r67Zqzm5t7v56PILHIVZ7kmFMaL2yQ==
|
||||
|
||||
devtools-protocol@0.0.1423531:
|
||||
version "0.0.1423531"
|
||||
resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1423531.tgz#43ba906340fb8ffbda566711ead31f139b2a150a"
|
||||
integrity sha512-z6cOcajZWxk80zvFnkTGa7tj3oqF+C5SnOF1KSMeAr5/WW/nLNHlEpKr7voSzMz8IaUoq5rjdI0Mqv5k/BUkhg==
|
||||
|
||||
dezalgo@^1.0.0, dezalgo@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81"
|
||||
|
@ -17891,6 +18072,13 @@ dot-case@^3.0.4:
|
|||
no-case "^3.0.4"
|
||||
tslib "^2.0.3"
|
||||
|
||||
dot-prop@^5.2.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
|
||||
integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==
|
||||
dependencies:
|
||||
is-obj "^2.0.0"
|
||||
|
||||
dotenv-expand@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0"
|
||||
|
@ -19240,7 +19428,7 @@ fast-equals@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-2.0.0.tgz#bef2c423af3939f2c54310df54c57e64cd2adefc"
|
||||
integrity sha512-u6RBd8cSiLLxAiC04wVsLV6GBFDOXcTCgWkd3wEoFXgidPSoAJENqC9m7Jb2vewSvjBIfXV6icKeh3GTKfIaXA==
|
||||
|
||||
fast-fifo@^1.1.0, fast-fifo@^1.2.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==
|
||||
|
@ -21183,6 +21371,11 @@ http-https@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b"
|
||||
integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=
|
||||
|
||||
http-link-header@^1.1.1:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/http-link-header/-/http-link-header-1.1.3.tgz#b367b7a0ad1cf14027953f31aa1df40bb433da2a"
|
||||
integrity sha512-3cZ0SRL8fb9MUlU3mKM61FcQvPfXx2dBrZW3Vbg5CXa8jFlK8OaEpePenLe1oEXQduhz8b0QjsqfS59QP4AJDQ==
|
||||
|
||||
http-parser-js@>=0.5.1:
|
||||
version "0.5.3"
|
||||
resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9"
|
||||
|
@ -21381,6 +21574,11 @@ ignore@^7.0.3:
|
|||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.3.tgz#397ef9315dfe0595671eefe8b633fec6943ab733"
|
||||
integrity sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==
|
||||
|
||||
image-ssim@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/image-ssim/-/image-ssim-0.2.0.tgz#83b42c7a2e6e4b85505477fe6917f5dbc56420e5"
|
||||
integrity sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==
|
||||
|
||||
immediate@~3.0.5:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
|
||||
|
@ -21584,6 +21782,16 @@ intl-messageformat@10.5.12:
|
|||
"@formatjs/icu-messageformat-parser" "2.7.6"
|
||||
tslib "^2.4.0"
|
||||
|
||||
intl-messageformat@^10.5.3:
|
||||
version "10.7.15"
|
||||
resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.7.15.tgz#5cdc62139ef39ece1b083db32dae4d1c9fa5b627"
|
||||
integrity sha512-LRyExsEsefQSBjU2p47oAheoKz+EOJxSLDdjOaEjdriajfHsMXOmV/EhMvYSg9bAgCUHasuAC+mcUBe/95PfIg==
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract" "2.3.3"
|
||||
"@formatjs/fast-memoize" "2.2.6"
|
||||
"@formatjs/icu-messageformat-parser" "2.11.1"
|
||||
tslib "2"
|
||||
|
||||
invariant@^2.1.0, invariant@^2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
||||
|
@ -21983,6 +22191,11 @@ is-obj@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
|
||||
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
|
||||
|
||||
is-obj@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
|
||||
integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==
|
||||
|
||||
is-object@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470"
|
||||
|
@ -23006,6 +23219,11 @@ jpeg-exif@^1.1.4:
|
|||
resolved "https://registry.yarnpkg.com/jpeg-exif/-/jpeg-exif-1.1.4.tgz#781a65b6cd74f62cb1c493511020f8d3577a1c2b"
|
||||
integrity sha512-a+bKEcCjtuW5WTdgeXFzswSrdqi0jk4XlEtZlx5A94wCoBpFjfFTbo/Tra5SpNCl/YFZPvcV1dJc+TAYeg6ROQ==
|
||||
|
||||
jpeg-js@^0.4.1, jpeg-js@^0.4.4:
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.4.tgz#a9f1c6f1f9f0fa80cdb3484ed9635054d28936aa"
|
||||
integrity sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==
|
||||
|
||||
jquery@^3.7.1:
|
||||
version "3.7.1"
|
||||
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de"
|
||||
|
@ -23021,6 +23239,11 @@ js-levenshtein@^1.1.6:
|
|||
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
|
||||
integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==
|
||||
|
||||
js-library-detector@^6.7.0:
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/js-library-detector/-/js-library-detector-6.7.0.tgz#5075c71fcf835b71133bca13363b91509a39235a"
|
||||
integrity sha512-c80Qupofp43y4cJ7+8TTDN/AsDwLi5oOm/plBrWI+iQt485vKXCco+yVmOwEgdo9VOdsYTuV0UlTeetVPTriXA==
|
||||
|
||||
js-search@^1.4.3:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/js-search/-/js-search-1.4.3.tgz#23a86d7e064ca53a473930edc48615b6b1c1954a"
|
||||
|
@ -23659,6 +23882,13 @@ license-checker@^25.0.1:
|
|||
spdx-satisfies "^4.0.0"
|
||||
treeify "^1.1.0"
|
||||
|
||||
lie@3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e"
|
||||
integrity sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==
|
||||
dependencies:
|
||||
immediate "~3.0.5"
|
||||
|
||||
lie@~3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
|
||||
|
@ -23666,6 +23896,53 @@ lie@~3.3.0:
|
|||
dependencies:
|
||||
immediate "~3.0.5"
|
||||
|
||||
lighthouse-logger@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lighthouse-logger/-/lighthouse-logger-2.0.1.tgz#48895f639b61cca89346bb6f47f7403a3895fa02"
|
||||
integrity sha512-ioBrW3s2i97noEmnXxmUq7cjIcVRjT5HBpAYy8zE11CxU9HqlWHHeRxfeN1tn8F7OEMVPIC9x1f8t3Z7US9ehQ==
|
||||
dependencies:
|
||||
debug "^2.6.9"
|
||||
marky "^1.2.2"
|
||||
|
||||
lighthouse-stack-packs@1.12.2:
|
||||
version "1.12.2"
|
||||
resolved "https://registry.yarnpkg.com/lighthouse-stack-packs/-/lighthouse-stack-packs-1.12.2.tgz#dbe0ccdbc381784ef176f4f8c2367ac5b077d6ca"
|
||||
integrity sha512-Ug8feS/A+92TMTCK6yHYLwaFMuelK/hAKRMdldYkMNwv+d9PtWxjXEg6rwKtsUXTADajhdrhXyuNCJ5/sfmPFw==
|
||||
|
||||
lighthouse@^12.4.0:
|
||||
version "12.4.0"
|
||||
resolved "https://registry.yarnpkg.com/lighthouse/-/lighthouse-12.4.0.tgz#0ca978e6b3ef2c815c132866eb83fbb21845980a"
|
||||
integrity sha512-1p/YKQpMqfYVSKVOB43RG3xbnxkSUOG0zqVm/bxJHAaAHKrEACgFi8HZxD9CCTFrt+d/Q/x9gjDyeUDarm1SIg==
|
||||
dependencies:
|
||||
"@paulirish/trace_engine" "0.0.44"
|
||||
"@sentry/node" "^7.0.0"
|
||||
axe-core "^4.10.2"
|
||||
chrome-launcher "^1.1.2"
|
||||
configstore "^5.0.1"
|
||||
csp_evaluator "1.1.5"
|
||||
devtools-protocol "0.0.1423531"
|
||||
enquirer "^2.3.6"
|
||||
http-link-header "^1.1.1"
|
||||
intl-messageformat "^10.5.3"
|
||||
jpeg-js "^0.4.4"
|
||||
js-library-detector "^6.7.0"
|
||||
lighthouse-logger "^2.0.1"
|
||||
lighthouse-stack-packs "1.12.2"
|
||||
lodash-es "^4.17.21"
|
||||
lookup-closest-locale "6.2.0"
|
||||
metaviewport-parser "0.3.0"
|
||||
open "^8.4.0"
|
||||
parse-cache-control "1.0.1"
|
||||
puppeteer-core "^24.3.0"
|
||||
robots-parser "^3.0.1"
|
||||
semver "^5.3.0"
|
||||
speedline-core "^1.4.3"
|
||||
third-party-web "^0.26.5"
|
||||
tldts-icann "^6.1.16"
|
||||
ws "^7.0.0"
|
||||
yargs "^17.3.1"
|
||||
yargs-parser "^21.0.0"
|
||||
|
||||
lilconfig@^2.0.3, lilconfig@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082"
|
||||
|
@ -23775,6 +24052,13 @@ loader-utils@^2.0.0, loader-utils@^2.0.4:
|
|||
emojis-list "^3.0.0"
|
||||
json5 "^2.1.2"
|
||||
|
||||
localforage@^1.8.1:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.10.0.tgz#5c465dc5f62b2807c3a84c0c6a1b1b3212781dd4"
|
||||
integrity sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==
|
||||
dependencies:
|
||||
lie "3.1.1"
|
||||
|
||||
locate-path@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
|
||||
|
@ -24018,6 +24302,11 @@ longest-streak@^2.0.0, longest-streak@^2.0.1:
|
|||
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4"
|
||||
integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==
|
||||
|
||||
lookup-closest-locale@6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/lookup-closest-locale/-/lookup-closest-locale-6.2.0.tgz#57f665e604fd26f77142d48152015402b607bcf3"
|
||||
integrity sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==
|
||||
|
||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
|
@ -24258,6 +24547,11 @@ marked@^4.3.0:
|
|||
resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3"
|
||||
integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==
|
||||
|
||||
marky@^1.2.2:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.5.tgz#55796b688cbd72390d2d399eaaf1832c9413e3c0"
|
||||
integrity sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==
|
||||
|
||||
mathml-tag-names@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3"
|
||||
|
@ -24584,6 +24878,11 @@ meta-png@1.0.6:
|
|||
resolved "https://registry.yarnpkg.com/meta-png/-/meta-png-1.0.6.tgz#34d78a403cc1c809978d3e9f89485a2700daafce"
|
||||
integrity sha512-eQtEi5E9axqwqA/sDK1dyhX9kYHCUe2m+45aQ3JHrozjGPs+/ab+hdhPp7A3GUNW+ZAbavrsg5xQ4r5jkGDX+A==
|
||||
|
||||
metaviewport-parser@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/metaviewport-parser/-/metaviewport-parser-0.3.0.tgz#6af1e99b5eaf250c049e0af1e84143a39750dea6"
|
||||
integrity sha512-EoYJ8xfjQ6kpe9VbVHvZTZHiOl4HL1Z18CrZ+qahvLXT7ZO4YTC2JMyt5FaUp9JJp6J4Ybb/z7IsCXZt86/QkQ==
|
||||
|
||||
methods@^1.1.2, methods@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
|
@ -24874,7 +25173,7 @@ mississippi@^3.0.0:
|
|||
stream-each "^1.1.0"
|
||||
through2 "^2.0.0"
|
||||
|
||||
mitt@3.0.1:
|
||||
mitt@3.0.1, mitt@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1"
|
||||
integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==
|
||||
|
@ -26465,6 +26764,11 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.6:
|
|||
pbkdf2 "^3.0.3"
|
||||
safe-buffer "^5.1.1"
|
||||
|
||||
parse-cache-control@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e"
|
||||
integrity sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==
|
||||
|
||||
parse-entities@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8"
|
||||
|
@ -27744,6 +28048,18 @@ puppeteer-core@24.1.1:
|
|||
typed-query-selector "^2.12.0"
|
||||
ws "^8.18.0"
|
||||
|
||||
puppeteer-core@^24.3.0:
|
||||
version "24.4.0"
|
||||
resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-24.4.0.tgz#a301c58344fe939b487704593681ea9f913fe6f8"
|
||||
integrity sha512-eFw66gCnWo0X8Hyf9KxxJtms7a61NJVMiSaWfItsFPzFBsjsWdmcNlBdsA1WVwln6neoHhsG+uTVesKmTREn/g==
|
||||
dependencies:
|
||||
"@puppeteer/browsers" "2.8.0"
|
||||
chromium-bidi "2.1.2"
|
||||
debug "^4.4.0"
|
||||
devtools-protocol "0.0.1413902"
|
||||
typed-query-selector "^2.12.0"
|
||||
ws "^8.18.1"
|
||||
|
||||
puppeteer@24.1.1:
|
||||
version "24.1.1"
|
||||
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-24.1.1.tgz#dadcfbe05b25a54aee7061325631145db568890b"
|
||||
|
@ -27797,11 +28113,6 @@ queue-microtask@^1.2.2:
|
|||
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
|
||||
|
||||
queue-tick@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/queue-tick/-/queue-tick-1.0.1.tgz#f6f07ac82c1fd60f82e098b417a80e52f1f4c142"
|
||||
integrity sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==
|
||||
|
||||
quick-format-unescaped@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz#6d6b66b8207aa2b35eef12be1421bb24c428f652"
|
||||
|
@ -29331,6 +29642,11 @@ rison-node@1.0.2:
|
|||
resolved "https://registry.yarnpkg.com/rison-node/-/rison-node-1.0.2.tgz#b7b5f37f39f5ae2a51a973a33c9aa17239a33e4b"
|
||||
integrity sha1-t7Xzfzn1ripRqXOjPJqhcjmjPks=
|
||||
|
||||
robots-parser@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/robots-parser/-/robots-parser-3.0.1.tgz#3d8a3cdfa8ac240cbb062a4bd16fcc0e0fb9ed23"
|
||||
integrity sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ==
|
||||
|
||||
robust-predicates@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-2.0.4.tgz#0a2367a93abd99676d075981707f29cfb402248b"
|
||||
|
@ -29788,7 +30104,7 @@ semver-compare@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
||||
integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==
|
||||
|
||||
"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0:
|
||||
"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0:
|
||||
version "5.7.2"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
|
||||
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
||||
|
@ -30581,6 +30897,15 @@ specificity@^0.4.1:
|
|||
resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.4.1.tgz#aab5e645012db08ba182e151165738d00887b019"
|
||||
integrity sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==
|
||||
|
||||
speedline-core@^1.4.3:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/speedline-core/-/speedline-core-1.4.3.tgz#4d6e7276e2063c2d36a375cb25a523ac73475319"
|
||||
integrity sha512-DI7/OuAUD+GMpR6dmu8lliO2Wg5zfeh+/xsdyJZCzd8o5JgFUjCeLsBDuZjIQJdwXS3J0L/uZYrELKYqx+PXog==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
image-ssim "^0.2.0"
|
||||
jpeg-js "^0.4.1"
|
||||
|
||||
split-on-first@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
|
||||
|
@ -30806,13 +31131,13 @@ stream-slicer@0.0.6:
|
|||
resolved "https://registry.yarnpkg.com/stream-slicer/-/stream-slicer-0.0.6.tgz#f86b2ac5c2440b7a0a87b71f33665c0788046138"
|
||||
integrity sha1-+GsqxcJEC3oKh7cfM2ZcB4gEYTg=
|
||||
|
||||
streamx@^2.12.0, streamx@^2.12.5, streamx@^2.13.0, streamx@^2.13.2, streamx@^2.14.0, streamx@^2.15.0:
|
||||
version "2.16.1"
|
||||
resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.16.1.tgz#2b311bd34832f08aa6bb4d6a80297c9caef89614"
|
||||
integrity sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==
|
||||
streamx@^2.12.0, streamx@^2.12.5, streamx@^2.13.2, streamx@^2.14.0, streamx@^2.15.0, streamx@^2.21.0:
|
||||
version "2.22.0"
|
||||
resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.22.0.tgz#cd7b5e57c95aaef0ff9b2aef7905afa62ec6e4a7"
|
||||
integrity sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==
|
||||
dependencies:
|
||||
fast-fifo "^1.1.0"
|
||||
queue-tick "^1.0.1"
|
||||
fast-fifo "^1.3.2"
|
||||
text-decoder "^1.1.0"
|
||||
optionalDependencies:
|
||||
bare-events "^2.2.0"
|
||||
|
||||
|
@ -31476,16 +31801,16 @@ tar-fs@^2.0.0:
|
|||
pump "^3.0.0"
|
||||
tar-stream "^2.1.4"
|
||||
|
||||
tar-fs@^3.0.4, 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==
|
||||
tar-fs@^3.0.4, tar-fs@^3.0.6, tar-fs@^3.0.8:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.8.tgz#8f62012537d5ff89252d01e48690dc4ebed33ab7"
|
||||
integrity sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==
|
||||
dependencies:
|
||||
pump "^3.0.0"
|
||||
tar-stream "^3.1.5"
|
||||
optionalDependencies:
|
||||
bare-fs "^2.1.1"
|
||||
bare-path "^2.1.0"
|
||||
bare-fs "^4.0.1"
|
||||
bare-path "^3.0.0"
|
||||
|
||||
tar-stream@^2.1.4:
|
||||
version "2.2.0"
|
||||
|
@ -31654,6 +31979,13 @@ test-exclude@^6.0.0:
|
|||
glob "^7.1.4"
|
||||
minimatch "^3.0.4"
|
||||
|
||||
text-decoder@^1.1.0:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.3.tgz#b19da364d981b2326d5f43099c310cc80d770c65"
|
||||
integrity sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==
|
||||
dependencies:
|
||||
b4a "^1.6.4"
|
||||
|
||||
text-diff@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/text-diff/-/text-diff-1.0.1.tgz#6c105905435e337857375c9d2f6ca63e453ff565"
|
||||
|
@ -31679,6 +32011,11 @@ thingies@^1.20.0:
|
|||
resolved "https://registry.yarnpkg.com/thingies/-/thingies-1.21.0.tgz#e80fbe58fd6fdaaab8fad9b67bd0a5c943c445c1"
|
||||
integrity sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==
|
||||
|
||||
third-party-web@^0.26.5, third-party-web@latest:
|
||||
version "0.26.5"
|
||||
resolved "https://registry.yarnpkg.com/third-party-web/-/third-party-web-0.26.5.tgz#c442b2a16db66a6064e05e0f060c9ed780f31709"
|
||||
integrity sha512-tDuKQJUTfjvi9Fcrs1s6YAQAB9mzhTSbBZMfNgtWNmJlHuoFeXO6dzBFdGeCWRvYL50jQGK0jPsBZYxqZQJ2SA==
|
||||
|
||||
thread-stream@^2.0.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.3.0.tgz#4fc07fb39eff32ae7bad803cb7dd9598349fed33"
|
||||
|
@ -31807,10 +32144,17 @@ tinyqueue@^2.0.3:
|
|||
resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-2.0.3.tgz#64d8492ebf39e7801d7bd34062e29b45b2035f08"
|
||||
integrity sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==
|
||||
|
||||
tldts-core@^6.1.46:
|
||||
version "6.1.46"
|
||||
resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.1.46.tgz#062d64981ee83f934f875c178a97e42bcd13bef7"
|
||||
integrity sha512-zA3ai/j4aFcmbqTvTONkSBuWs0Q4X4tJxa0gV9sp6kDbq5dAhQDSg0WUkReEm0fBAKAGNj+wPKCCsR8MYOYmwA==
|
||||
tldts-core@^6.1.46, tldts-core@^6.1.78:
|
||||
version "6.1.78"
|
||||
resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.1.78.tgz#47b477d9742870daa01dbd5ff9a598a48379728c"
|
||||
integrity sha512-jS0svNsB99jR6AJBmfmEWuKIgz91Haya91Z43PATaeHJ24BkMoNRb/jlaD37VYjb0mYf6gRL/HOnvS1zEnYBiw==
|
||||
|
||||
tldts-icann@^6.1.16:
|
||||
version "6.1.78"
|
||||
resolved "https://registry.yarnpkg.com/tldts-icann/-/tldts-icann-6.1.78.tgz#82909d0a1d9a278956aecaa6d49b3789bfd2130f"
|
||||
integrity sha512-IaM0vesvhlEGsEOG+UQfaW6AuQPB9MHI8sz9K8T8sUjj1rKxBp8SclNqUG8a3WQGv87VOoa+ICZrGXh/tnc/VA==
|
||||
dependencies:
|
||||
tldts-core "^6.1.78"
|
||||
|
||||
tldts@^6.1.32:
|
||||
version "6.1.46"
|
||||
|
@ -32113,6 +32457,11 @@ tsd@^0.31.1:
|
|||
path-exists "^4.0.0"
|
||||
read-pkg-up "^7.0.0"
|
||||
|
||||
tslib@2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.5.0, tslib@^2.6.2, tslib@^2.8.0:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
|
||||
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
|
||||
|
||||
tslib@2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
|
||||
|
@ -32133,11 +32482,6 @@ tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
|||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.5.0, tslib@^2.6.2, tslib@^2.8.0:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
|
||||
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
|
||||
|
||||
tslib@~2.4.0:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e"
|
||||
|
@ -32526,6 +32870,13 @@ unique-slug@^2.0.0:
|
|||
dependencies:
|
||||
imurmurhash "^0.1.4"
|
||||
|
||||
unique-string@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d"
|
||||
integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==
|
||||
dependencies:
|
||||
crypto-random-string "^2.0.0"
|
||||
|
||||
unist-builder@2.0.3, unist-builder@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436"
|
||||
|
@ -34051,15 +34402,15 @@ write-file-atomic@^4.0.2:
|
|||
imurmurhash "^0.1.4"
|
||||
signal-exit "^3.0.7"
|
||||
|
||||
ws@^7.3.1, ws@^7.4.2:
|
||||
ws@^7.0.0, ws@^7.3.1, ws@^7.4.2:
|
||||
version "7.5.10"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9"
|
||||
integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==
|
||||
|
||||
ws@^8.16.0, ws@^8.18.0, ws@^8.2.3, ws@^8.9.0:
|
||||
version "8.18.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
|
||||
integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==
|
||||
ws@^8.16.0, ws@^8.18.0, ws@^8.18.1, ws@^8.2.3, ws@^8.9.0:
|
||||
version "8.18.1"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb"
|
||||
integrity sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==
|
||||
|
||||
x-default-browser@^0.4.0:
|
||||
version "0.4.0"
|
||||
|
@ -34068,6 +34419,11 @@ x-default-browser@^0.4.0:
|
|||
optionalDependencies:
|
||||
default-browser-id "^1.0.4"
|
||||
|
||||
xdg-basedir@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
|
||||
integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
|
||||
|
||||
xml-crypto@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/xml-crypto/-/xml-crypto-6.0.1.tgz#81d224cf9f2cac9f15190bbb4ef93f53e1f8a8e8"
|
||||
|
@ -34389,7 +34745,7 @@ zod-to-json-schema@^3.22.3, zod-to-json-schema@^3.22.4, zod-to-json-schema@^3.22
|
|||
resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.1.tgz#f08c6725091aadabffa820ba8d50c7ab527f227a"
|
||||
integrity sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==
|
||||
|
||||
zod@3.24.1:
|
||||
zod@3.24.1, zod@^3.24.1:
|
||||
version "3.24.1"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.1.tgz#27445c912738c8ad1e9de1bea0359fa44d9d35ee"
|
||||
integrity sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue