@wordpress/e2e-test-utils-playwright 1.46.0 → 1.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build-types/admin/index.d.ts +3 -0
- package/build-types/admin/index.d.ts.map +1 -1
- package/build-types/admin/visit-site-editor.d.ts.map +1 -1
- package/build-types/admin/wait-for-site-editor.d.ts +12 -0
- package/build-types/admin/wait-for-site-editor.d.ts.map +1 -0
- package/build-types/metrics/index.d.ts +22 -5
- package/build-types/metrics/index.d.ts.map +1 -1
- package/build-types/request-utils/index.d.ts +3 -1
- package/build-types/request-utils/index.d.ts.map +1 -1
- package/build-types/request-utils/preferences.d.ts +11 -0
- package/build-types/request-utils/preferences.d.ts.map +1 -1
- package/package.json +4 -5
- package/src/admin/create-new-post.ts +47 -0
- package/src/admin/edit-post.ts +24 -0
- package/{build/admin/get-page-error.js → src/admin/get-page-error.ts} +12 -9
- package/src/admin/index.ts +52 -0
- package/src/admin/visit-admin-page.ts +43 -0
- package/src/admin/visit-site-editor.ts +62 -0
- package/src/admin/wait-for-site-editor.ts +52 -0
- package/src/config.ts +12 -0
- package/src/editor/click-block-options-menu-item.ts +18 -0
- package/src/editor/click-block-toolbar-button.ts +21 -0
- package/src/editor/get-blocks.ts +75 -0
- package/src/editor/get-edited-post-content.ts +19 -0
- package/src/editor/index.ts +95 -0
- package/src/editor/insert-block.ts +54 -0
- package/src/editor/open-document-settings-sidebar.ts +31 -0
- package/src/editor/preview.ts +32 -0
- package/src/editor/publish-post.ts +51 -0
- package/src/editor/save-draft.ts +20 -0
- package/src/editor/select-blocks.ts +48 -0
- package/src/editor/set-content.ts +24 -0
- package/src/editor/set-is-fixed-toolbar.ts +20 -0
- package/src/editor/set-preferences.ts +37 -0
- package/src/editor/show-block-toolbar.ts +20 -0
- package/src/editor/site-editor.ts +55 -0
- package/src/editor/switch-editor-tool.ts +34 -0
- package/src/editor/switch-to-legacy-canvas.ts +20 -0
- package/src/editor/transform-block-to.ts +34 -0
- package/src/index.ts +8 -0
- package/src/lighthouse/index.ts +75 -0
- package/src/metrics/index.ts +441 -0
- package/src/page-utils/drag-files.ts +173 -0
- package/src/page-utils/emulate-network-conditions.ts +101 -0
- package/src/page-utils/index.ts +54 -0
- package/src/page-utils/is-current-url.ts +20 -0
- package/src/page-utils/keycodes.ts +48 -0
- package/src/page-utils/press-keys.ts +195 -0
- package/{build → src}/page-utils/set-browser-viewport.js +14 -12
- package/src/request-utils/blocks.ts +58 -0
- package/src/request-utils/comments.ts +80 -0
- package/src/request-utils/gutenberg-experiments.ts +62 -0
- package/src/request-utils/index.ts +222 -0
- package/src/request-utils/login.ts +34 -0
- package/src/request-utils/media.ts +102 -0
- package/src/request-utils/menus.ts +145 -0
- package/src/request-utils/pages.ts +75 -0
- package/src/request-utils/patterns.ts +31 -0
- package/src/request-utils/plugins.ts +103 -0
- package/src/request-utils/posts.ts +69 -0
- package/src/request-utils/preferences.ts +63 -0
- package/{build/request-utils/records.js → src/request-utils/records.ts} +15 -10
- package/src/request-utils/rest.ts +222 -0
- package/src/request-utils/site-settings.ts +58 -0
- package/src/request-utils/templates.ts +83 -0
- package/src/request-utils/themes.ts +110 -0
- package/src/request-utils/users.ts +125 -0
- package/src/request-utils/widgets.js +68 -0
- package/src/test.ts +204 -0
- package/src/types.ts +13 -0
- package/build/admin/create-new-post.cjs +0 -51
- package/build/admin/create-new-post.cjs.map +0 -7
- package/build/admin/create-new-post.js +0 -31
- package/build/admin/create-new-post.js.map +0 -1
- package/build/admin/edit-post.cjs +0 -40
- package/build/admin/edit-post.cjs.map +0 -7
- package/build/admin/edit-post.js +0 -20
- package/build/admin/edit-post.js.map +0 -1
- package/build/admin/get-page-error.cjs +0 -36
- package/build/admin/get-page-error.cjs.map +0 -7
- package/build/admin/get-page-error.js.map +0 -1
- package/build/admin/index.cjs +0 -59
- package/build/admin/index.cjs.map +0 -7
- package/build/admin/index.js +0 -37
- package/build/admin/index.js.map +0 -1
- package/build/admin/visit-admin-page.cjs +0 -47
- package/build/admin/visit-admin-page.cjs.map +0 -7
- package/build/admin/visit-admin-page.js +0 -32
- package/build/admin/visit-admin-page.js.map +0 -1
- package/build/admin/visit-site-editor.cjs +0 -90
- package/build/admin/visit-site-editor.cjs.map +0 -7
- package/build/admin/visit-site-editor.js +0 -73
- package/build/admin/visit-site-editor.js.map +0 -1
- package/build/config.cjs +0 -45
- package/build/config.cjs.map +0 -7
- package/build/config.js +0 -13
- package/build/config.js.map +0 -1
- package/build/editor/click-block-options-menu-item.cjs +0 -34
- package/build/editor/click-block-options-menu-item.cjs.map +0 -7
- package/build/editor/click-block-options-menu-item.js +0 -17
- package/build/editor/click-block-options-menu-item.js.map +0 -1
- package/build/editor/click-block-toolbar-button.cjs +0 -38
- package/build/editor/click-block-toolbar-button.cjs.map +0 -7
- package/build/editor/click-block-toolbar-button.js +0 -16
- package/build/editor/click-block-toolbar-button.js.map +0 -1
- package/build/editor/get-blocks.cjs +0 -64
- package/build/editor/get-blocks.cjs.map +0 -7
- package/build/editor/get-blocks.js +0 -45
- package/build/editor/get-blocks.js.map +0 -1
- package/build/editor/get-edited-post-content.cjs +0 -36
- package/build/editor/get-edited-post-content.cjs.map +0 -7
- package/build/editor/get-edited-post-content.js +0 -15
- package/build/editor/get-edited-post-content.js.map +0 -1
- package/build/editor/index.cjs +0 -97
- package/build/editor/index.cjs.map +0 -7
- package/build/editor/index.js +0 -75
- package/build/editor/index.js.map +0 -1
- package/build/editor/insert-block.cjs +0 -55
- package/build/editor/insert-block.cjs.map +0 -7
- package/build/editor/insert-block.js +0 -23
- package/build/editor/insert-block.js.map +0 -1
- package/build/editor/open-document-settings-sidebar.cjs +0 -42
- package/build/editor/open-document-settings-sidebar.cjs.map +0 -7
- package/build/editor/open-document-settings-sidebar.js +0 -27
- package/build/editor/open-document-settings-sidebar.js.map +0 -1
- package/build/editor/preview.cjs +0 -42
- package/build/editor/preview.cjs.map +0 -7
- package/build/editor/preview.js +0 -21
- package/build/editor/preview.js.map +0 -1
- package/build/editor/publish-post.cjs +0 -47
- package/build/editor/publish-post.cjs.map +0 -7
- package/build/editor/publish-post.js +0 -45
- package/build/editor/publish-post.js.map +0 -1
- package/build/editor/save-draft.cjs +0 -34
- package/build/editor/save-draft.cjs.map +0 -7
- package/build/editor/save-draft.js +0 -18
- package/build/editor/save-draft.js.map +0 -1
- package/build/editor/select-blocks.cjs +0 -51
- package/build/editor/select-blocks.cjs.map +0 -7
- package/build/editor/select-blocks.js +0 -28
- package/build/editor/select-blocks.js.map +0 -1
- package/build/editor/set-content.cjs +0 -39
- package/build/editor/set-content.cjs.map +0 -7
- package/build/editor/set-content.js +0 -17
- package/build/editor/set-content.js.map +0 -1
- package/build/editor/set-is-fixed-toolbar.cjs +0 -36
- package/build/editor/set-is-fixed-toolbar.cjs.map +0 -7
- package/build/editor/set-is-fixed-toolbar.js +0 -18
- package/build/editor/set-is-fixed-toolbar.js.map +0 -1
- package/build/editor/set-preferences.cjs +0 -43
- package/build/editor/set-preferences.cjs.map +0 -7
- package/build/editor/set-preferences.js +0 -21
- package/build/editor/set-preferences.js.map +0 -1
- package/build/editor/show-block-toolbar.cjs +0 -35
- package/build/editor/show-block-toolbar.cjs.map +0 -7
- package/build/editor/show-block-toolbar.js +0 -19
- package/build/editor/show-block-toolbar.js.map +0 -1
- package/build/editor/site-editor.cjs +0 -51
- package/build/editor/site-editor.cjs.map +0 -7
- package/build/editor/site-editor.js +0 -44
- package/build/editor/site-editor.js.map +0 -1
- package/build/editor/switch-editor-tool.cjs +0 -47
- package/build/editor/switch-editor-tool.cjs.map +0 -7
- package/build/editor/switch-editor-tool.js +0 -33
- package/build/editor/switch-editor-tool.js.map +0 -1
- package/build/editor/switch-to-legacy-canvas.cjs +0 -39
- package/build/editor/switch-to-legacy-canvas.cjs.map +0 -7
- package/build/editor/switch-to-legacy-canvas.js +0 -18
- package/build/editor/switch-to-legacy-canvas.js.map +0 -1
- package/build/editor/transform-block-to.cjs +0 -46
- package/build/editor/transform-block-to.cjs.map +0 -7
- package/build/editor/transform-block-to.js +0 -24
- package/build/editor/transform-block-to.js.map +0 -1
- package/build/index.cjs +0 -51
- package/build/index.cjs.map +0 -7
- package/build/index.js +0 -19
- package/build/index.js.map +0 -1
- package/build/lighthouse/index.cjs +0 -96
- package/build/lighthouse/index.cjs.map +0 -7
- package/build/lighthouse/index.js +0 -61
- package/build/lighthouse/index.js.map +0 -1
- package/build/metrics/index.cjs +0 -309
- package/build/metrics/index.cjs.map +0 -7
- package/build/metrics/index.js +0 -258
- package/build/metrics/index.js.map +0 -1
- package/build/page-utils/drag-files.cjs +0 -143
- package/build/page-utils/drag-files.cjs.map +0 -7
- package/build/page-utils/drag-files.js +0 -119
- package/build/page-utils/drag-files.js.map +0 -1
- package/build/page-utils/emulate-network-conditions.cjs +0 -99
- package/build/page-utils/emulate-network-conditions.cjs.map +0 -7
- package/build/page-utils/emulate-network-conditions.js +0 -71
- package/build/page-utils/emulate-network-conditions.js.map +0 -1
- package/build/page-utils/index.cjs +0 -59
- package/build/page-utils/index.cjs.map +0 -7
- package/build/page-utils/index.js +0 -37
- package/build/page-utils/index.js.map +0 -1
- package/build/page-utils/is-current-url.cjs +0 -36
- package/build/page-utils/is-current-url.cjs.map +0 -7
- package/build/page-utils/is-current-url.js +0 -21
- package/build/page-utils/is-current-url.js.map +0 -1
- package/build/page-utils/keycodes.cjs +0 -55
- package/build/page-utils/keycodes.cjs.map +0 -7
- package/build/page-utils/keycodes.js +0 -41
- package/build/page-utils/keycodes.js.map +0 -1
- package/build/page-utils/press-keys.cjs +0 -165
- package/build/page-utils/press-keys.cjs.map +0 -7
- package/build/page-utils/press-keys.js +0 -141
- package/build/page-utils/press-keys.js.map +0 -1
- package/build/page-utils/set-browser-viewport.cjs +0 -39
- package/build/page-utils/set-browser-viewport.cjs.map +0 -7
- package/build/page-utils/set-browser-viewport.js.map +0 -1
- package/build/request-utils/blocks.cjs +0 -51
- package/build/request-utils/blocks.cjs.map +0 -7
- package/build/request-utils/blocks.js +0 -40
- package/build/request-utils/blocks.js.map +0 -1
- package/build/request-utils/comments.cjs +0 -66
- package/build/request-utils/comments.cjs.map +0 -7
- package/build/request-utils/comments.js +0 -52
- package/build/request-utils/comments.js.map +0 -1
- package/build/request-utils/gutenberg-experiments.cjs +0 -56
- package/build/request-utils/gutenberg-experiments.cjs.map +0 -7
- package/build/request-utils/gutenberg-experiments.js +0 -47
- package/build/request-utils/gutenberg-experiments.js.map +0 -1
- package/build/request-utils/index.cjs +0 -199
- package/build/request-utils/index.cjs.map +0 -7
- package/build/request-utils/index.js +0 -194
- package/build/request-utils/index.js.map +0 -1
- package/build/request-utils/login.cjs +0 -48
- package/build/request-utils/login.cjs.map +0 -7
- package/build/request-utils/login.js +0 -21
- package/build/request-utils/login.js.map +0 -1
- package/build/request-utils/media.cjs +0 -83
- package/build/request-utils/media.cjs.map +0 -7
- package/build/request-utils/media.js +0 -106
- package/build/request-utils/media.js.map +0 -1
- package/build/request-utils/menus.cjs +0 -128
- package/build/request-utils/menus.cjs.map +0 -7
- package/build/request-utils/menus.js +0 -116
- package/build/request-utils/menus.js.map +0 -1
- package/build/request-utils/pages.cjs +0 -66
- package/build/request-utils/pages.cjs.map +0 -7
- package/build/request-utils/pages.js +0 -53
- package/build/request-utils/pages.js.map +0 -1
- package/build/request-utils/patterns.cjs +0 -44
- package/build/request-utils/patterns.cjs.map +0 -7
- package/build/request-utils/patterns.js +0 -27
- package/build/request-utils/patterns.js.map +0 -1
- package/build/request-utils/plugins.cjs +0 -81
- package/build/request-utils/plugins.cjs.map +0 -7
- package/build/request-utils/plugins.js +0 -85
- package/build/request-utils/plugins.js.map +0 -1
- package/build/request-utils/posts.cjs +0 -56
- package/build/request-utils/posts.cjs.map +0 -7
- package/build/request-utils/posts.js +0 -42
- package/build/request-utils/posts.js.map +0 -1
- package/build/request-utils/preferences.cjs +0 -41
- package/build/request-utils/preferences.cjs.map +0 -7
- package/build/request-utils/preferences.js +0 -20
- package/build/request-utils/preferences.js.map +0 -1
- package/build/request-utils/records.cjs +0 -37
- package/build/request-utils/records.cjs.map +0 -7
- package/build/request-utils/records.js.map +0 -1
- package/build/request-utils/rest.cjs +0 -174
- package/build/request-utils/rest.cjs.map +0 -7
- package/build/request-utils/rest.js +0 -181
- package/build/request-utils/rest.js.map +0 -1
- package/build/request-utils/site-settings.cjs +0 -45
- package/build/request-utils/site-settings.cjs.map +0 -7
- package/build/request-utils/site-settings.js +0 -33
- package/build/request-utils/site-settings.js.map +0 -1
- package/build/request-utils/templates.cjs +0 -68
- package/build/request-utils/templates.cjs.map +0 -7
- package/build/request-utils/templates.js +0 -54
- package/build/request-utils/templates.js.map +0 -1
- package/build/request-utils/themes.cjs +0 -92
- package/build/request-utils/themes.cjs.map +0 -7
- package/build/request-utils/themes.js +0 -69
- package/build/request-utils/themes.js.map +0 -1
- package/build/request-utils/users.cjs +0 -83
- package/build/request-utils/users.cjs.map +0 -7
- package/build/request-utils/users.js +0 -81
- package/build/request-utils/users.js.map +0 -1
- package/build/request-utils/widgets.cjs +0 -79
- package/build/request-utils/widgets.cjs.map +0 -7
- package/build/request-utils/widgets.js +0 -61
- package/build/request-utils/widgets.js.map +0 -1
- package/build/test.cjs +0 -136
- package/build/test.cjs.map +0 -7
- package/build/test.js +0 -189
- package/build/test.js.map +0 -1
- package/build/types.cjs +0 -19
- package/build/types.cjs.map +0 -7
- package/build/types.js +0 -3
- package/build/types.js.map +0 -1
package/build/metrics/index.cjs
DELETED
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// packages/e2e-test-utils-playwright/src/metrics/index.ts
|
|
21
|
-
var metrics_exports = {};
|
|
22
|
-
__export(metrics_exports, {
|
|
23
|
-
Metrics: () => Metrics
|
|
24
|
-
});
|
|
25
|
-
module.exports = __toCommonJS(metrics_exports);
|
|
26
|
-
var import_path = require("path");
|
|
27
|
-
var Metrics = class {
|
|
28
|
-
browser;
|
|
29
|
-
page;
|
|
30
|
-
trace;
|
|
31
|
-
webVitals = {};
|
|
32
|
-
constructor({ page }) {
|
|
33
|
-
this.page = page;
|
|
34
|
-
this.browser = page.context().browser();
|
|
35
|
-
this.trace = { traceEvents: [] };
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Returns durations from the Server-Timing header.
|
|
39
|
-
*
|
|
40
|
-
* @param fields Optional fields to filter.
|
|
41
|
-
*/
|
|
42
|
-
async getServerTiming(fields = []) {
|
|
43
|
-
return this.page.evaluate(
|
|
44
|
-
(f) => performance.getEntriesByType(
|
|
45
|
-
"navigation"
|
|
46
|
-
)[0].serverTiming.reduce(
|
|
47
|
-
(acc, entry) => {
|
|
48
|
-
if (f.length === 0 || f.includes(entry.name)) {
|
|
49
|
-
acc[entry.name] = entry.duration;
|
|
50
|
-
}
|
|
51
|
-
return acc;
|
|
52
|
-
},
|
|
53
|
-
{}
|
|
54
|
-
),
|
|
55
|
-
fields
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Returns time to first byte (TTFB) using the Navigation Timing API.
|
|
60
|
-
*
|
|
61
|
-
* @see https://web.dev/ttfb/#measure-ttfb-in-javascript
|
|
62
|
-
*
|
|
63
|
-
* @return TTFB value.
|
|
64
|
-
*/
|
|
65
|
-
async getTimeToFirstByte() {
|
|
66
|
-
return await this.page.evaluate(() => {
|
|
67
|
-
const { responseStart, startTime } = performance.getEntriesByType(
|
|
68
|
-
"navigation"
|
|
69
|
-
)[0];
|
|
70
|
-
return responseStart - startTime;
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Returns the Largest Contentful Paint (LCP) value using the dedicated API.
|
|
75
|
-
*
|
|
76
|
-
* @see https://w3c.github.io/largest-contentful-paint/
|
|
77
|
-
* @see https://web.dev/lcp/#measure-lcp-in-javascript
|
|
78
|
-
*
|
|
79
|
-
* @return LCP value.
|
|
80
|
-
*/
|
|
81
|
-
async getLargestContentfulPaint() {
|
|
82
|
-
return await this.page.evaluate(
|
|
83
|
-
() => new Promise((resolve) => {
|
|
84
|
-
new PerformanceObserver((entryList) => {
|
|
85
|
-
const entries = entryList.getEntries();
|
|
86
|
-
const largestPaintEntry = entries.at(-1);
|
|
87
|
-
resolve(largestPaintEntry?.startTime || 0);
|
|
88
|
-
}).observe({
|
|
89
|
-
type: "largest-contentful-paint",
|
|
90
|
-
buffered: true
|
|
91
|
-
});
|
|
92
|
-
})
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Returns the Cumulative Layout Shift (CLS) value using the dedicated API.
|
|
97
|
-
*
|
|
98
|
-
* @see https://github.com/WICG/layout-instability
|
|
99
|
-
* @see https://web.dev/cls/#measure-layout-shifts-in-javascript
|
|
100
|
-
*
|
|
101
|
-
* @return CLS value.
|
|
102
|
-
*/
|
|
103
|
-
async getCumulativeLayoutShift() {
|
|
104
|
-
return await this.page.evaluate(
|
|
105
|
-
() => new Promise((resolve) => {
|
|
106
|
-
let CLS = 0;
|
|
107
|
-
new PerformanceObserver((l) => {
|
|
108
|
-
const entries = l.getEntries();
|
|
109
|
-
entries.forEach((entry) => {
|
|
110
|
-
if (!entry.hadRecentInput) {
|
|
111
|
-
CLS += entry.value;
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
resolve(CLS);
|
|
115
|
-
}).observe({
|
|
116
|
-
type: "layout-shift",
|
|
117
|
-
buffered: true
|
|
118
|
-
});
|
|
119
|
-
})
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Returns the loading durations using the Navigation Timing API. All the
|
|
124
|
-
* durations exclude the server response time.
|
|
125
|
-
*
|
|
126
|
-
* @return Object with loading metrics durations.
|
|
127
|
-
*/
|
|
128
|
-
async getLoadingDurations() {
|
|
129
|
-
return await this.page.evaluate(() => {
|
|
130
|
-
const [
|
|
131
|
-
{
|
|
132
|
-
requestStart,
|
|
133
|
-
responseStart,
|
|
134
|
-
responseEnd,
|
|
135
|
-
domContentLoadedEventEnd,
|
|
136
|
-
loadEventEnd
|
|
137
|
-
}
|
|
138
|
-
] = performance.getEntriesByType(
|
|
139
|
-
"navigation"
|
|
140
|
-
);
|
|
141
|
-
const paintTimings = performance.getEntriesByType(
|
|
142
|
-
"paint"
|
|
143
|
-
);
|
|
144
|
-
const firstPaintStartTime = paintTimings.find(
|
|
145
|
-
({ name }) => name === "first-paint"
|
|
146
|
-
).startTime;
|
|
147
|
-
const firstContentfulPaintStartTime = paintTimings.find(
|
|
148
|
-
({ name }) => name === "first-contentful-paint"
|
|
149
|
-
).startTime;
|
|
150
|
-
return {
|
|
151
|
-
// Server side metric.
|
|
152
|
-
serverResponse: responseStart - requestStart,
|
|
153
|
-
// For client side metrics, consider the end of the response (the
|
|
154
|
-
// browser receives the HTML) as the start time (0).
|
|
155
|
-
firstPaint: firstPaintStartTime - responseEnd,
|
|
156
|
-
domContentLoaded: domContentLoadedEventEnd - responseEnd,
|
|
157
|
-
loaded: loadEventEnd - responseEnd,
|
|
158
|
-
firstContentfulPaint: firstContentfulPaintStartTime - responseEnd,
|
|
159
|
-
timeSinceResponseEnd: performance.now() - responseEnd
|
|
160
|
-
};
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Starts Chromium tracing with predefined options for performance testing.
|
|
165
|
-
*
|
|
166
|
-
* @param options Options to pass to `browser.startTracing()`.
|
|
167
|
-
*/
|
|
168
|
-
async startTracing(options = {}) {
|
|
169
|
-
return await this.browser.startTracing(this.page, {
|
|
170
|
-
screenshots: false,
|
|
171
|
-
categories: ["devtools.timeline"],
|
|
172
|
-
...options
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Stops Chromium tracing and saves the trace.
|
|
177
|
-
*/
|
|
178
|
-
async stopTracing() {
|
|
179
|
-
const traceBuffer = await this.browser.stopTracing();
|
|
180
|
-
const traceJSON = JSON.parse(traceBuffer.toString());
|
|
181
|
-
this.trace = traceJSON;
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* @return Durations of all traced `keydown`, `keypress`, and `keyup`
|
|
185
|
-
* events.
|
|
186
|
-
*/
|
|
187
|
-
getTypingEventDurations() {
|
|
188
|
-
return [
|
|
189
|
-
this.getEventDurations("keydown"),
|
|
190
|
-
this.getEventDurations("keypress"),
|
|
191
|
-
this.getEventDurations("keyup")
|
|
192
|
-
];
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* @return Durations of all traced `focus` and `focusin` events.
|
|
196
|
-
*/
|
|
197
|
-
getSelectionEventDurations() {
|
|
198
|
-
return [
|
|
199
|
-
this.getEventDurations("focus"),
|
|
200
|
-
this.getEventDurations("focusin")
|
|
201
|
-
];
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* @return Durations of all traced `click` events.
|
|
205
|
-
*/
|
|
206
|
-
getClickEventDurations() {
|
|
207
|
-
return [this.getEventDurations("click")];
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* @return Durations of all traced `mouseover` and `mouseout` events.
|
|
211
|
-
*/
|
|
212
|
-
getHoverEventDurations() {
|
|
213
|
-
return [
|
|
214
|
-
this.getEventDurations("mouseover"),
|
|
215
|
-
this.getEventDurations("mouseout")
|
|
216
|
-
];
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* @param eventType Type of event to filter.
|
|
220
|
-
* @return Durations of all events of a given type.
|
|
221
|
-
*/
|
|
222
|
-
getEventDurations(eventType) {
|
|
223
|
-
if (this.trace.traceEvents.length === 0) {
|
|
224
|
-
throw new Error(
|
|
225
|
-
"No trace events found. Did you forget to call stopTracing()?"
|
|
226
|
-
);
|
|
227
|
-
}
|
|
228
|
-
return this.trace.traceEvents.filter(
|
|
229
|
-
(item) => item.cat === "devtools.timeline" && item.name === "EventDispatch" && item?.args?.data?.type === eventType && !!item.dur
|
|
230
|
-
).map((item) => item.dur ? item.dur / 1e3 : 0);
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Initializes the web-vitals library upon next page navigation.
|
|
234
|
-
*
|
|
235
|
-
* Defaults to automatically triggering the navigation,
|
|
236
|
-
* but it can also be done manually.
|
|
237
|
-
*
|
|
238
|
-
* @example
|
|
239
|
-
* ```js
|
|
240
|
-
* await metrics.initWebVitals();
|
|
241
|
-
* console.log( await metrics.getWebVitals() );
|
|
242
|
-
* ```
|
|
243
|
-
*
|
|
244
|
-
* @example
|
|
245
|
-
* ```js
|
|
246
|
-
* await metrics.initWebVitals( false );
|
|
247
|
-
* await page.goto( '/some-other-page' );
|
|
248
|
-
* console.log( await metrics.getWebVitals() );
|
|
249
|
-
* ```
|
|
250
|
-
*
|
|
251
|
-
* @param reload Whether to force navigation by reloading the current page.
|
|
252
|
-
*/
|
|
253
|
-
async initWebVitals(reload = true) {
|
|
254
|
-
await this.page.addInitScript({
|
|
255
|
-
path: (0, import_path.join)(
|
|
256
|
-
__dirname,
|
|
257
|
-
"../../../../node_modules/web-vitals/dist/web-vitals.umd.cjs"
|
|
258
|
-
)
|
|
259
|
-
});
|
|
260
|
-
await this.page.exposeFunction(
|
|
261
|
-
"__reportVitals__",
|
|
262
|
-
(data) => {
|
|
263
|
-
const measurement = JSON.parse(data);
|
|
264
|
-
this.webVitals[measurement.name] = measurement.value;
|
|
265
|
-
}
|
|
266
|
-
);
|
|
267
|
-
await this.page.addInitScript(() => {
|
|
268
|
-
const reportVitals = (measurement) => window.__reportVitals__(JSON.stringify(measurement));
|
|
269
|
-
window.addEventListener("DOMContentLoaded", () => {
|
|
270
|
-
window.webVitals.onCLS(reportVitals);
|
|
271
|
-
window.webVitals.onFCP(reportVitals);
|
|
272
|
-
window.webVitals.onFID(reportVitals);
|
|
273
|
-
window.webVitals.onINP(reportVitals);
|
|
274
|
-
window.webVitals.onLCP(reportVitals);
|
|
275
|
-
window.webVitals.onTTFB(reportVitals);
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
if (reload) {
|
|
279
|
-
await this.page.reload();
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Returns web vitals as collected by the web-vitals library.
|
|
284
|
-
*
|
|
285
|
-
* If the web-vitals library hasn't been loaded on the current page yet,
|
|
286
|
-
* it will be initialized with a page reload.
|
|
287
|
-
*
|
|
288
|
-
* Reloads the page to force web-vitals to report all collected metrics.
|
|
289
|
-
*
|
|
290
|
-
* @return {WebVitalsMeasurements} Web vitals measurements.
|
|
291
|
-
*/
|
|
292
|
-
async getWebVitals() {
|
|
293
|
-
this.webVitals = {};
|
|
294
|
-
const hasScript = await this.page.evaluate(
|
|
295
|
-
// @ts-expect-error This is valid but web-vitals does not register the global types.
|
|
296
|
-
() => typeof window.webVitals !== "undefined"
|
|
297
|
-
);
|
|
298
|
-
if (!hasScript) {
|
|
299
|
-
await this.initWebVitals();
|
|
300
|
-
}
|
|
301
|
-
await this.page.reload();
|
|
302
|
-
return this.webVitals;
|
|
303
|
-
}
|
|
304
|
-
};
|
|
305
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
306
|
-
0 && (module.exports = {
|
|
307
|
-
Metrics
|
|
308
|
-
});
|
|
309
|
-
//# sourceMappingURL=index.cjs.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/metrics/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * External dependencies\n */\nimport type { Page, Browser } from '@playwright/test';\nimport { join } from 'path';\n// resolution-mode support in TypeScript 5.3 will resolve this.\n// See https://devblogs.microsoft.com/typescript/announcing-typescript-5-3-beta/\n// @ts-expect-error\nimport type { Metric } from 'web-vitals';\n\ntype EventType =\n\t| 'click'\n\t| 'focus'\n\t| 'focusin'\n\t| 'keydown'\n\t| 'keypress'\n\t| 'keyup'\n\t| 'mouseout'\n\t| 'mouseover';\n\ninterface TraceEvent {\n\tcat: string;\n\tname: string;\n\tdur?: number;\n\targs: {\n\t\tdata?: {\n\t\t\ttype: EventType;\n\t\t};\n\t};\n}\n\ninterface Trace {\n\ttraceEvents: TraceEvent[];\n}\n\ntype MetricsConstructorProps = {\n\tpage: Page;\n};\n\ninterface WebVitalsMeasurements {\n\tCLS?: number;\n\tFCP?: number;\n\tFID?: number;\n\tINP?: number;\n\tLCP?: number;\n\tTTFB?: number;\n}\n\nexport class Metrics {\n\tbrowser: Browser;\n\tpage: Page;\n\ttrace: Trace;\n\n\twebVitals: WebVitalsMeasurements = {};\n\n\tconstructor( { page }: MetricsConstructorProps ) {\n\t\tthis.page = page;\n\t\tthis.browser = page.context().browser()!;\n\t\tthis.trace = { traceEvents: [] };\n\t}\n\n\t/**\n\t * Returns durations from the Server-Timing header.\n\t *\n\t * @param fields Optional fields to filter.\n\t */\n\tasync getServerTiming( fields: string[] = [] ) {\n\t\treturn this.page.evaluate< Record< string, number >, string[] >(\n\t\t\t( f: string[] ) =>\n\t\t\t\t(\n\t\t\t\t\tperformance.getEntriesByType(\n\t\t\t\t\t\t'navigation'\n\t\t\t\t\t) as PerformanceNavigationTiming[]\n\t\t\t\t )[ 0 ].serverTiming.reduce(\n\t\t\t\t\t( acc, entry ) => {\n\t\t\t\t\t\tif ( f.length === 0 || f.includes( entry.name ) ) {\n\t\t\t\t\t\t\tacc[ entry.name ] = entry.duration;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn acc;\n\t\t\t\t\t},\n\t\t\t\t\t{} as Record< string, number >\n\t\t\t\t),\n\t\t\tfields\n\t\t);\n\t}\n\n\t/**\n\t * Returns time to first byte (TTFB) using the Navigation Timing API.\n\t *\n\t * @see https://web.dev/ttfb/#measure-ttfb-in-javascript\n\t *\n\t * @return TTFB value.\n\t */\n\tasync getTimeToFirstByte() {\n\t\treturn await this.page.evaluate< number >( () => {\n\t\t\tconst { responseStart, startTime } = (\n\t\t\t\tperformance.getEntriesByType(\n\t\t\t\t\t'navigation'\n\t\t\t\t) as PerformanceNavigationTiming[]\n\t\t\t )[ 0 ];\n\t\t\treturn responseStart - startTime;\n\t\t} );\n\t}\n\n\t/**\n\t * Returns the Largest Contentful Paint (LCP) value using the dedicated API.\n\t *\n\t * @see https://w3c.github.io/largest-contentful-paint/\n\t * @see https://web.dev/lcp/#measure-lcp-in-javascript\n\t *\n\t * @return LCP value.\n\t */\n\tasync getLargestContentfulPaint() {\n\t\treturn await this.page.evaluate< number >(\n\t\t\t() =>\n\t\t\t\tnew Promise( ( resolve ) => {\n\t\t\t\t\tnew PerformanceObserver( ( entryList ) => {\n\t\t\t\t\t\tconst entries = entryList.getEntries();\n\t\t\t\t\t\t// The last entry is the largest contentful paint.\n\t\t\t\t\t\tconst largestPaintEntry = entries.at( -1 );\n\n\t\t\t\t\t\tresolve( largestPaintEntry?.startTime || 0 );\n\t\t\t\t\t} ).observe( {\n\t\t\t\t\t\ttype: 'largest-contentful-paint',\n\t\t\t\t\t\tbuffered: true,\n\t\t\t\t\t} );\n\t\t\t\t} )\n\t\t);\n\t}\n\n\t/**\n\t * Returns the Cumulative Layout Shift (CLS) value using the dedicated API.\n\t *\n\t * @see https://github.com/WICG/layout-instability\n\t * @see https://web.dev/cls/#measure-layout-shifts-in-javascript\n\t *\n\t * @return CLS value.\n\t */\n\tasync getCumulativeLayoutShift() {\n\t\treturn await this.page.evaluate< number >(\n\t\t\t() =>\n\t\t\t\tnew Promise( ( resolve ) => {\n\t\t\t\t\tlet CLS = 0;\n\n\t\t\t\t\tnew PerformanceObserver( ( l ) => {\n\t\t\t\t\t\tconst entries = l.getEntries() as LayoutShift[];\n\n\t\t\t\t\t\tentries.forEach( ( entry ) => {\n\t\t\t\t\t\t\tif ( ! entry.hadRecentInput ) {\n\t\t\t\t\t\t\t\tCLS += entry.value;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t\tresolve( CLS );\n\t\t\t\t\t} ).observe( {\n\t\t\t\t\t\ttype: 'layout-shift',\n\t\t\t\t\t\tbuffered: true,\n\t\t\t\t\t} );\n\t\t\t\t} )\n\t\t);\n\t}\n\n\t/**\n\t * Returns the loading durations using the Navigation Timing API. All the\n\t * durations exclude the server response time.\n\t *\n\t * @return Object with loading metrics durations.\n\t */\n\tasync getLoadingDurations() {\n\t\treturn await this.page.evaluate( () => {\n\t\t\tconst [\n\t\t\t\t{\n\t\t\t\t\trequestStart,\n\t\t\t\t\tresponseStart,\n\t\t\t\t\tresponseEnd,\n\t\t\t\t\tdomContentLoadedEventEnd,\n\t\t\t\t\tloadEventEnd,\n\t\t\t\t},\n\t\t\t] = performance.getEntriesByType(\n\t\t\t\t'navigation'\n\t\t\t) as PerformanceNavigationTiming[];\n\t\t\tconst paintTimings = performance.getEntriesByType(\n\t\t\t\t'paint'\n\t\t\t) as PerformancePaintTiming[];\n\n\t\t\tconst firstPaintStartTime = paintTimings.find(\n\t\t\t\t( { name } ) => name === 'first-paint'\n\t\t\t)!.startTime;\n\n\t\t\tconst firstContentfulPaintStartTime = paintTimings.find(\n\t\t\t\t( { name } ) => name === 'first-contentful-paint'\n\t\t\t)!.startTime;\n\n\t\t\treturn {\n\t\t\t\t// Server side metric.\n\t\t\t\tserverResponse: responseStart - requestStart,\n\t\t\t\t// For client side metrics, consider the end of the response (the\n\t\t\t\t// browser receives the HTML) as the start time (0).\n\t\t\t\tfirstPaint: firstPaintStartTime - responseEnd,\n\t\t\t\tdomContentLoaded: domContentLoadedEventEnd - responseEnd,\n\t\t\t\tloaded: loadEventEnd - responseEnd,\n\t\t\t\tfirstContentfulPaint:\n\t\t\t\t\tfirstContentfulPaintStartTime - responseEnd,\n\t\t\t\ttimeSinceResponseEnd: performance.now() - responseEnd,\n\t\t\t};\n\t\t} );\n\t}\n\n\t/**\n\t * Starts Chromium tracing with predefined options for performance testing.\n\t *\n\t * @param options Options to pass to `browser.startTracing()`.\n\t */\n\tasync startTracing( options = {} ) {\n\t\treturn await this.browser.startTracing( this.page, {\n\t\t\tscreenshots: false,\n\t\t\tcategories: [ 'devtools.timeline' ],\n\t\t\t...options,\n\t\t} );\n\t}\n\n\t/**\n\t * Stops Chromium tracing and saves the trace.\n\t */\n\tasync stopTracing() {\n\t\tconst traceBuffer = await this.browser.stopTracing();\n\t\tconst traceJSON = JSON.parse( traceBuffer.toString() );\n\n\t\tthis.trace = traceJSON;\n\t}\n\n\t/**\n\t * @return Durations of all traced `keydown`, `keypress`, and `keyup`\n\t * events.\n\t */\n\tgetTypingEventDurations() {\n\t\treturn [\n\t\t\tthis.getEventDurations( 'keydown' ),\n\t\t\tthis.getEventDurations( 'keypress' ),\n\t\t\tthis.getEventDurations( 'keyup' ),\n\t\t];\n\t}\n\n\t/**\n\t * @return Durations of all traced `focus` and `focusin` events.\n\t */\n\tgetSelectionEventDurations() {\n\t\treturn [\n\t\t\tthis.getEventDurations( 'focus' ),\n\t\t\tthis.getEventDurations( 'focusin' ),\n\t\t];\n\t}\n\n\t/**\n\t * @return Durations of all traced `click` events.\n\t */\n\tgetClickEventDurations() {\n\t\treturn [ this.getEventDurations( 'click' ) ];\n\t}\n\n\t/**\n\t * @return Durations of all traced `mouseover` and `mouseout` events.\n\t */\n\tgetHoverEventDurations() {\n\t\treturn [\n\t\t\tthis.getEventDurations( 'mouseover' ),\n\t\t\tthis.getEventDurations( 'mouseout' ),\n\t\t];\n\t}\n\n\t/**\n\t * @param eventType Type of event to filter.\n\t * @return Durations of all events of a given type.\n\t */\n\tgetEventDurations( eventType: EventType ) {\n\t\tif ( this.trace.traceEvents.length === 0 ) {\n\t\t\tthrow new Error(\n\t\t\t\t'No trace events found. Did you forget to call stopTracing()?'\n\t\t\t);\n\t\t}\n\n\t\treturn this.trace.traceEvents\n\t\t\t.filter(\n\t\t\t\t( item: TraceEvent ): boolean =>\n\t\t\t\t\titem.cat === 'devtools.timeline' &&\n\t\t\t\t\titem.name === 'EventDispatch' &&\n\t\t\t\t\titem?.args?.data?.type === eventType &&\n\t\t\t\t\t!! item.dur\n\t\t\t)\n\t\t\t.map( ( item ) => ( item.dur ? item.dur / 1000 : 0 ) );\n\t}\n\n\t/**\n\t * Initializes the web-vitals library upon next page navigation.\n\t *\n\t * Defaults to automatically triggering the navigation,\n\t * but it can also be done manually.\n\t *\n\t * @example\n\t * ```js\n\t * await metrics.initWebVitals();\n\t * console.log( await metrics.getWebVitals() );\n\t * ```\n\t *\n\t * @example\n\t * ```js\n\t * await metrics.initWebVitals( false );\n\t * await page.goto( '/some-other-page' );\n\t * console.log( await metrics.getWebVitals() );\n\t * ```\n\t *\n\t * @param reload Whether to force navigation by reloading the current page.\n\t */\n\tasync initWebVitals( reload = true ) {\n\t\tawait this.page.addInitScript( {\n\t\t\tpath: join(\n\t\t\t\t__dirname,\n\t\t\t\t'../../../../node_modules/web-vitals/dist/web-vitals.umd.cjs'\n\t\t\t),\n\t\t} );\n\n\t\tawait this.page.exposeFunction(\n\t\t\t'__reportVitals__',\n\t\t\t( data: string ) => {\n\t\t\t\tconst measurement: Metric = JSON.parse( data );\n\t\t\t\tthis.webVitals[ measurement.name ] = measurement.value;\n\t\t\t}\n\t\t);\n\n\t\tawait this.page.addInitScript( () => {\n\t\t\tconst reportVitals = ( measurement: unknown ) =>\n\t\t\t\twindow.__reportVitals__( JSON.stringify( measurement ) );\n\n\t\t\twindow.addEventListener( 'DOMContentLoaded', () => {\n\t\t\t\t// @ts-expect-error This is valid but web-vitals does not register the global types.\n\t\t\t\twindow.webVitals.onCLS( reportVitals );\n\t\t\t\t// @ts-expect-error This is valid but web-vitals does not register the global types.\n\t\t\t\twindow.webVitals.onFCP( reportVitals );\n\t\t\t\t// @ts-expect-error This is valid but web-vitals does not register the global types.\n\t\t\t\twindow.webVitals.onFID( reportVitals );\n\t\t\t\t// @ts-expect-error This is valid but web-vitals does not register the global types.\n\t\t\t\twindow.webVitals.onINP( reportVitals );\n\t\t\t\t// @ts-expect-error This is valid but web-vitals does not register the global types.\n\t\t\t\twindow.webVitals.onLCP( reportVitals );\n\t\t\t\t// @ts-expect-error This is valid but web-vitals does not register the global types.\n\t\t\t\twindow.webVitals.onTTFB( reportVitals );\n\t\t\t} );\n\t\t} );\n\n\t\tif ( reload ) {\n\t\t\t// By reloading the page the script will be applied.\n\t\t\tawait this.page.reload();\n\t\t}\n\t}\n\n\t/**\n\t * Returns web vitals as collected by the web-vitals library.\n\t *\n\t * If the web-vitals library hasn't been loaded on the current page yet,\n\t * it will be initialized with a page reload.\n\t *\n\t * Reloads the page to force web-vitals to report all collected metrics.\n\t *\n\t * @return {WebVitalsMeasurements} Web vitals measurements.\n\t */\n\tasync getWebVitals() {\n\t\t// Reset values.\n\t\tthis.webVitals = {};\n\n\t\tconst hasScript = await this.page.evaluate(\n\t\t\t// @ts-expect-error This is valid but web-vitals does not register the global types.\n\t\t\t() => typeof window.webVitals !== 'undefined'\n\t\t);\n\n\t\tif ( ! hasScript ) {\n\t\t\tawait this.initWebVitals();\n\t\t}\n\n\t\t// Trigger navigation so the web-vitals library reports values on unload.\n\t\tawait this.page.reload();\n\n\t\treturn this.webVitals;\n\t}\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
package/build/metrics/index.js
DELETED
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Metrics = void 0;
|
|
4
|
-
const path_1 = require("path");
|
|
5
|
-
class Metrics {
|
|
6
|
-
browser;
|
|
7
|
-
page;
|
|
8
|
-
trace;
|
|
9
|
-
webVitals = {};
|
|
10
|
-
constructor({ page }) {
|
|
11
|
-
this.page = page;
|
|
12
|
-
this.browser = page.context().browser();
|
|
13
|
-
this.trace = { traceEvents: [] };
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Returns durations from the Server-Timing header.
|
|
17
|
-
*
|
|
18
|
-
* @param fields Optional fields to filter.
|
|
19
|
-
*/
|
|
20
|
-
async getServerTiming(fields = []) {
|
|
21
|
-
return this.page.evaluate((f) => performance.getEntriesByType('navigation')[0].serverTiming.reduce((acc, entry) => {
|
|
22
|
-
if (f.length === 0 || f.includes(entry.name)) {
|
|
23
|
-
acc[entry.name] = entry.duration;
|
|
24
|
-
}
|
|
25
|
-
return acc;
|
|
26
|
-
}, {}), fields);
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Returns time to first byte (TTFB) using the Navigation Timing API.
|
|
30
|
-
*
|
|
31
|
-
* @see https://web.dev/ttfb/#measure-ttfb-in-javascript
|
|
32
|
-
*
|
|
33
|
-
* @return TTFB value.
|
|
34
|
-
*/
|
|
35
|
-
async getTimeToFirstByte() {
|
|
36
|
-
return await this.page.evaluate(() => {
|
|
37
|
-
const { responseStart, startTime } = performance.getEntriesByType('navigation')[0];
|
|
38
|
-
return responseStart - startTime;
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Returns the Largest Contentful Paint (LCP) value using the dedicated API.
|
|
43
|
-
*
|
|
44
|
-
* @see https://w3c.github.io/largest-contentful-paint/
|
|
45
|
-
* @see https://web.dev/lcp/#measure-lcp-in-javascript
|
|
46
|
-
*
|
|
47
|
-
* @return LCP value.
|
|
48
|
-
*/
|
|
49
|
-
async getLargestContentfulPaint() {
|
|
50
|
-
return await this.page.evaluate(() => new Promise((resolve) => {
|
|
51
|
-
new PerformanceObserver((entryList) => {
|
|
52
|
-
const entries = entryList.getEntries();
|
|
53
|
-
// The last entry is the largest contentful paint.
|
|
54
|
-
const largestPaintEntry = entries.at(-1);
|
|
55
|
-
resolve(largestPaintEntry?.startTime || 0);
|
|
56
|
-
}).observe({
|
|
57
|
-
type: 'largest-contentful-paint',
|
|
58
|
-
buffered: true,
|
|
59
|
-
});
|
|
60
|
-
}));
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Returns the Cumulative Layout Shift (CLS) value using the dedicated API.
|
|
64
|
-
*
|
|
65
|
-
* @see https://github.com/WICG/layout-instability
|
|
66
|
-
* @see https://web.dev/cls/#measure-layout-shifts-in-javascript
|
|
67
|
-
*
|
|
68
|
-
* @return CLS value.
|
|
69
|
-
*/
|
|
70
|
-
async getCumulativeLayoutShift() {
|
|
71
|
-
return await this.page.evaluate(() => new Promise((resolve) => {
|
|
72
|
-
let CLS = 0;
|
|
73
|
-
new PerformanceObserver((l) => {
|
|
74
|
-
const entries = l.getEntries();
|
|
75
|
-
entries.forEach((entry) => {
|
|
76
|
-
if (!entry.hadRecentInput) {
|
|
77
|
-
CLS += entry.value;
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
resolve(CLS);
|
|
81
|
-
}).observe({
|
|
82
|
-
type: 'layout-shift',
|
|
83
|
-
buffered: true,
|
|
84
|
-
});
|
|
85
|
-
}));
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Returns the loading durations using the Navigation Timing API. All the
|
|
89
|
-
* durations exclude the server response time.
|
|
90
|
-
*
|
|
91
|
-
* @return Object with loading metrics durations.
|
|
92
|
-
*/
|
|
93
|
-
async getLoadingDurations() {
|
|
94
|
-
return await this.page.evaluate(() => {
|
|
95
|
-
const [{ requestStart, responseStart, responseEnd, domContentLoadedEventEnd, loadEventEnd, },] = performance.getEntriesByType('navigation');
|
|
96
|
-
const paintTimings = performance.getEntriesByType('paint');
|
|
97
|
-
const firstPaintStartTime = paintTimings.find(({ name }) => name === 'first-paint').startTime;
|
|
98
|
-
const firstContentfulPaintStartTime = paintTimings.find(({ name }) => name === 'first-contentful-paint').startTime;
|
|
99
|
-
return {
|
|
100
|
-
// Server side metric.
|
|
101
|
-
serverResponse: responseStart - requestStart,
|
|
102
|
-
// For client side metrics, consider the end of the response (the
|
|
103
|
-
// browser receives the HTML) as the start time (0).
|
|
104
|
-
firstPaint: firstPaintStartTime - responseEnd,
|
|
105
|
-
domContentLoaded: domContentLoadedEventEnd - responseEnd,
|
|
106
|
-
loaded: loadEventEnd - responseEnd,
|
|
107
|
-
firstContentfulPaint: firstContentfulPaintStartTime - responseEnd,
|
|
108
|
-
timeSinceResponseEnd: performance.now() - responseEnd,
|
|
109
|
-
};
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Starts Chromium tracing with predefined options for performance testing.
|
|
114
|
-
*
|
|
115
|
-
* @param options Options to pass to `browser.startTracing()`.
|
|
116
|
-
*/
|
|
117
|
-
async startTracing(options = {}) {
|
|
118
|
-
return await this.browser.startTracing(this.page, {
|
|
119
|
-
screenshots: false,
|
|
120
|
-
categories: ['devtools.timeline'],
|
|
121
|
-
...options,
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Stops Chromium tracing and saves the trace.
|
|
126
|
-
*/
|
|
127
|
-
async stopTracing() {
|
|
128
|
-
const traceBuffer = await this.browser.stopTracing();
|
|
129
|
-
const traceJSON = JSON.parse(traceBuffer.toString());
|
|
130
|
-
this.trace = traceJSON;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* @return Durations of all traced `keydown`, `keypress`, and `keyup`
|
|
134
|
-
* events.
|
|
135
|
-
*/
|
|
136
|
-
getTypingEventDurations() {
|
|
137
|
-
return [
|
|
138
|
-
this.getEventDurations('keydown'),
|
|
139
|
-
this.getEventDurations('keypress'),
|
|
140
|
-
this.getEventDurations('keyup'),
|
|
141
|
-
];
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* @return Durations of all traced `focus` and `focusin` events.
|
|
145
|
-
*/
|
|
146
|
-
getSelectionEventDurations() {
|
|
147
|
-
return [
|
|
148
|
-
this.getEventDurations('focus'),
|
|
149
|
-
this.getEventDurations('focusin'),
|
|
150
|
-
];
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* @return Durations of all traced `click` events.
|
|
154
|
-
*/
|
|
155
|
-
getClickEventDurations() {
|
|
156
|
-
return [this.getEventDurations('click')];
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* @return Durations of all traced `mouseover` and `mouseout` events.
|
|
160
|
-
*/
|
|
161
|
-
getHoverEventDurations() {
|
|
162
|
-
return [
|
|
163
|
-
this.getEventDurations('mouseover'),
|
|
164
|
-
this.getEventDurations('mouseout'),
|
|
165
|
-
];
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* @param eventType Type of event to filter.
|
|
169
|
-
* @return Durations of all events of a given type.
|
|
170
|
-
*/
|
|
171
|
-
getEventDurations(eventType) {
|
|
172
|
-
if (this.trace.traceEvents.length === 0) {
|
|
173
|
-
throw new Error('No trace events found. Did you forget to call stopTracing()?');
|
|
174
|
-
}
|
|
175
|
-
return this.trace.traceEvents
|
|
176
|
-
.filter((item) => item.cat === 'devtools.timeline' &&
|
|
177
|
-
item.name === 'EventDispatch' &&
|
|
178
|
-
item?.args?.data?.type === eventType &&
|
|
179
|
-
!!item.dur)
|
|
180
|
-
.map((item) => (item.dur ? item.dur / 1000 : 0));
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Initializes the web-vitals library upon next page navigation.
|
|
184
|
-
*
|
|
185
|
-
* Defaults to automatically triggering the navigation,
|
|
186
|
-
* but it can also be done manually.
|
|
187
|
-
*
|
|
188
|
-
* @example
|
|
189
|
-
* ```js
|
|
190
|
-
* await metrics.initWebVitals();
|
|
191
|
-
* console.log( await metrics.getWebVitals() );
|
|
192
|
-
* ```
|
|
193
|
-
*
|
|
194
|
-
* @example
|
|
195
|
-
* ```js
|
|
196
|
-
* await metrics.initWebVitals( false );
|
|
197
|
-
* await page.goto( '/some-other-page' );
|
|
198
|
-
* console.log( await metrics.getWebVitals() );
|
|
199
|
-
* ```
|
|
200
|
-
*
|
|
201
|
-
* @param reload Whether to force navigation by reloading the current page.
|
|
202
|
-
*/
|
|
203
|
-
async initWebVitals(reload = true) {
|
|
204
|
-
await this.page.addInitScript({
|
|
205
|
-
path: (0, path_1.join)(__dirname, '../../../../node_modules/web-vitals/dist/web-vitals.umd.cjs'),
|
|
206
|
-
});
|
|
207
|
-
await this.page.exposeFunction('__reportVitals__', (data) => {
|
|
208
|
-
const measurement = JSON.parse(data);
|
|
209
|
-
this.webVitals[measurement.name] = measurement.value;
|
|
210
|
-
});
|
|
211
|
-
await this.page.addInitScript(() => {
|
|
212
|
-
const reportVitals = (measurement) => window.__reportVitals__(JSON.stringify(measurement));
|
|
213
|
-
window.addEventListener('DOMContentLoaded', () => {
|
|
214
|
-
// @ts-expect-error This is valid but web-vitals does not register the global types.
|
|
215
|
-
window.webVitals.onCLS(reportVitals);
|
|
216
|
-
// @ts-expect-error This is valid but web-vitals does not register the global types.
|
|
217
|
-
window.webVitals.onFCP(reportVitals);
|
|
218
|
-
// @ts-expect-error This is valid but web-vitals does not register the global types.
|
|
219
|
-
window.webVitals.onFID(reportVitals);
|
|
220
|
-
// @ts-expect-error This is valid but web-vitals does not register the global types.
|
|
221
|
-
window.webVitals.onINP(reportVitals);
|
|
222
|
-
// @ts-expect-error This is valid but web-vitals does not register the global types.
|
|
223
|
-
window.webVitals.onLCP(reportVitals);
|
|
224
|
-
// @ts-expect-error This is valid but web-vitals does not register the global types.
|
|
225
|
-
window.webVitals.onTTFB(reportVitals);
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
if (reload) {
|
|
229
|
-
// By reloading the page the script will be applied.
|
|
230
|
-
await this.page.reload();
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* Returns web vitals as collected by the web-vitals library.
|
|
235
|
-
*
|
|
236
|
-
* If the web-vitals library hasn't been loaded on the current page yet,
|
|
237
|
-
* it will be initialized with a page reload.
|
|
238
|
-
*
|
|
239
|
-
* Reloads the page to force web-vitals to report all collected metrics.
|
|
240
|
-
*
|
|
241
|
-
* @return {WebVitalsMeasurements} Web vitals measurements.
|
|
242
|
-
*/
|
|
243
|
-
async getWebVitals() {
|
|
244
|
-
// Reset values.
|
|
245
|
-
this.webVitals = {};
|
|
246
|
-
const hasScript = await this.page.evaluate(
|
|
247
|
-
// @ts-expect-error This is valid but web-vitals does not register the global types.
|
|
248
|
-
() => typeof window.webVitals !== 'undefined');
|
|
249
|
-
if (!hasScript) {
|
|
250
|
-
await this.initWebVitals();
|
|
251
|
-
}
|
|
252
|
-
// Trigger navigation so the web-vitals library reports values on unload.
|
|
253
|
-
await this.page.reload();
|
|
254
|
-
return this.webVitals;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
exports.Metrics = Metrics;
|
|
258
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"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"}
|