@wordpress/e2e-test-utils-playwright 1.36.1-next.738bb1424.0 → 1.37.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.
Files changed (227) hide show
  1. package/build/admin/create-new-post.js +48 -28
  2. package/build/admin/create-new-post.js.map +7 -1
  3. package/build/admin/edit-post.js +37 -17
  4. package/build/admin/edit-post.js.map +7 -1
  5. package/build/admin/get-page-error.js +33 -23
  6. package/build/admin/get-page-error.js.map +7 -1
  7. package/build/admin/index.js +58 -36
  8. package/build/admin/index.js.map +7 -1
  9. package/build/admin/visit-admin-page.js +44 -29
  10. package/build/admin/visit-admin-page.js.map +7 -1
  11. package/build/admin/visit-site-editor.js +73 -64
  12. package/build/admin/visit-site-editor.js.map +7 -1
  13. package/build/config.js +43 -11
  14. package/build/config.js.map +7 -1
  15. package/build/editor/click-block-options-menu-item.js +31 -14
  16. package/build/editor/click-block-options-menu-item.js.map +7 -1
  17. package/build/editor/click-block-toolbar-button.js +35 -13
  18. package/build/editor/click-block-toolbar-button.js.map +7 -1
  19. package/build/editor/get-blocks.js +61 -43
  20. package/build/editor/get-blocks.js.map +7 -1
  21. package/build/editor/get-edited-post-content.js +33 -12
  22. package/build/editor/get-edited-post-content.js.map +7 -1
  23. package/build/editor/index.js +96 -74
  24. package/build/editor/index.js.map +7 -1
  25. package/build/editor/insert-block.js +52 -21
  26. package/build/editor/insert-block.js.map +7 -1
  27. package/build/editor/open-document-settings-sidebar.js +39 -24
  28. package/build/editor/open-document-settings-sidebar.js.map +7 -1
  29. package/build/editor/preview.js +39 -18
  30. package/build/editor/preview.js.map +7 -1
  31. package/build/editor/publish-post.js +44 -42
  32. package/build/editor/publish-post.js.map +7 -1
  33. package/build/editor/save-draft.js +31 -15
  34. package/build/editor/save-draft.js.map +7 -1
  35. package/build/editor/select-blocks.js +48 -25
  36. package/build/editor/select-blocks.js.map +7 -1
  37. package/build/editor/set-content.js +36 -14
  38. package/build/editor/set-content.js.map +7 -1
  39. package/build/editor/set-is-fixed-toolbar.js +33 -15
  40. package/build/editor/set-is-fixed-toolbar.js.map +7 -1
  41. package/build/editor/set-preferences.js +40 -18
  42. package/build/editor/set-preferences.js.map +7 -1
  43. package/build/editor/show-block-toolbar.js +32 -16
  44. package/build/editor/show-block-toolbar.js.map +7 -1
  45. package/build/editor/site-editor.js +48 -41
  46. package/build/editor/site-editor.js.map +7 -1
  47. package/build/editor/switch-editor-tool.js +44 -30
  48. package/build/editor/switch-editor-tool.js.map +7 -1
  49. package/build/editor/switch-to-legacy-canvas.js +35 -14
  50. package/build/editor/switch-to-legacy-canvas.js.map +7 -1
  51. package/build/editor/transform-block-to.js +43 -21
  52. package/build/editor/transform-block-to.js.map +7 -1
  53. package/build/index.js +53 -18
  54. package/build/index.js.map +7 -1
  55. package/build/lighthouse/index.js +93 -55
  56. package/build/lighthouse/index.js.map +7 -1
  57. package/build/metrics/index.js +302 -251
  58. package/build/metrics/index.js.map +7 -1
  59. package/build/page-utils/drag-files.js +136 -112
  60. package/build/page-utils/drag-files.js.map +7 -1
  61. package/build/page-utils/emulate-network-conditions.js +95 -67
  62. package/build/page-utils/emulate-network-conditions.js.map +7 -1
  63. package/build/page-utils/index.js +58 -36
  64. package/build/page-utils/index.js.map +7 -1
  65. package/build/page-utils/is-current-url.js +33 -18
  66. package/build/page-utils/is-current-url.js.map +7 -1
  67. package/build/page-utils/keycodes.js +53 -39
  68. package/build/page-utils/keycodes.js.map +7 -1
  69. package/build/page-utils/press-keys.js +153 -130
  70. package/build/page-utils/press-keys.js.map +7 -1
  71. package/build/page-utils/set-browser-viewport.js +35 -42
  72. package/build/page-utils/set-browser-viewport.js.map +7 -1
  73. package/build/request-utils/blocks.js +51 -40
  74. package/build/request-utils/blocks.js.map +7 -1
  75. package/build/request-utils/comments.js +59 -45
  76. package/build/request-utils/comments.js.map +7 -1
  77. package/build/request-utils/gutenberg-experiments.js +63 -38
  78. package/build/request-utils/gutenberg-experiments.js.map +7 -1
  79. package/build/request-utils/index.js +191 -155
  80. package/build/request-utils/index.js.map +7 -1
  81. package/build/request-utils/login.js +45 -18
  82. package/build/request-utils/login.js.map +7 -1
  83. package/build/request-utils/media.js +74 -64
  84. package/build/request-utils/media.js.map +7 -1
  85. package/build/request-utils/menus.js +121 -109
  86. package/build/request-utils/menus.js.map +7 -1
  87. package/build/request-utils/pages.js +63 -50
  88. package/build/request-utils/pages.js.map +7 -1
  89. package/build/request-utils/patterns.js +41 -24
  90. package/build/request-utils/patterns.js.map +7 -1
  91. package/build/request-utils/plugins.js +70 -74
  92. package/build/request-utils/plugins.js.map +7 -1
  93. package/build/request-utils/posts.js +55 -41
  94. package/build/request-utils/posts.js.map +7 -1
  95. package/build/request-utils/preferences.js +38 -17
  96. package/build/request-utils/preferences.js.map +7 -1
  97. package/build/request-utils/rest.js +155 -129
  98. package/build/request-utils/rest.js.map +7 -1
  99. package/build/request-utils/site-settings.js +40 -28
  100. package/build/request-utils/site-settings.js.map +7 -1
  101. package/build/request-utils/templates.js +60 -46
  102. package/build/request-utils/templates.js.map +7 -1
  103. package/build/request-utils/themes.js +80 -53
  104. package/build/request-utils/themes.js.map +7 -1
  105. package/build/request-utils/users.js +74 -72
  106. package/build/request-utils/users.js.map +7 -1
  107. package/build/request-utils/widgets.js +73 -55
  108. package/build/request-utils/widgets.js.map +7 -1
  109. package/build/test.js +130 -146
  110. package/build/test.js.map +7 -1
  111. package/build/types.js +18 -2
  112. package/build/types.js.map +7 -1
  113. package/build-types/index.d.ts +1 -1
  114. package/build-types/index.d.ts.map +1 -1
  115. package/package.json +2 -2
  116. package/build/admin/create-new-post.cjs +0 -51
  117. package/build/admin/create-new-post.cjs.map +0 -7
  118. package/build/admin/edit-post.cjs +0 -40
  119. package/build/admin/edit-post.cjs.map +0 -7
  120. package/build/admin/get-page-error.cjs +0 -36
  121. package/build/admin/get-page-error.cjs.map +0 -7
  122. package/build/admin/index.cjs +0 -59
  123. package/build/admin/index.cjs.map +0 -7
  124. package/build/admin/visit-admin-page.cjs +0 -47
  125. package/build/admin/visit-admin-page.cjs.map +0 -7
  126. package/build/admin/visit-site-editor.cjs +0 -77
  127. package/build/admin/visit-site-editor.cjs.map +0 -7
  128. package/build/config.cjs +0 -45
  129. package/build/config.cjs.map +0 -7
  130. package/build/editor/click-block-options-menu-item.cjs +0 -34
  131. package/build/editor/click-block-options-menu-item.cjs.map +0 -7
  132. package/build/editor/click-block-toolbar-button.cjs +0 -38
  133. package/build/editor/click-block-toolbar-button.cjs.map +0 -7
  134. package/build/editor/get-blocks.cjs +0 -64
  135. package/build/editor/get-blocks.cjs.map +0 -7
  136. package/build/editor/get-edited-post-content.cjs +0 -36
  137. package/build/editor/get-edited-post-content.cjs.map +0 -7
  138. package/build/editor/index.cjs +0 -97
  139. package/build/editor/index.cjs.map +0 -7
  140. package/build/editor/insert-block.cjs +0 -55
  141. package/build/editor/insert-block.cjs.map +0 -7
  142. package/build/editor/open-document-settings-sidebar.cjs +0 -42
  143. package/build/editor/open-document-settings-sidebar.cjs.map +0 -7
  144. package/build/editor/preview.cjs +0 -42
  145. package/build/editor/preview.cjs.map +0 -7
  146. package/build/editor/publish-post.cjs +0 -47
  147. package/build/editor/publish-post.cjs.map +0 -7
  148. package/build/editor/save-draft.cjs +0 -34
  149. package/build/editor/save-draft.cjs.map +0 -7
  150. package/build/editor/select-blocks.cjs +0 -51
  151. package/build/editor/select-blocks.cjs.map +0 -7
  152. package/build/editor/set-content.cjs +0 -39
  153. package/build/editor/set-content.cjs.map +0 -7
  154. package/build/editor/set-is-fixed-toolbar.cjs +0 -36
  155. package/build/editor/set-is-fixed-toolbar.cjs.map +0 -7
  156. package/build/editor/set-preferences.cjs +0 -43
  157. package/build/editor/set-preferences.cjs.map +0 -7
  158. package/build/editor/show-block-toolbar.cjs +0 -35
  159. package/build/editor/show-block-toolbar.cjs.map +0 -7
  160. package/build/editor/site-editor.cjs +0 -51
  161. package/build/editor/site-editor.cjs.map +0 -7
  162. package/build/editor/switch-editor-tool.cjs +0 -47
  163. package/build/editor/switch-editor-tool.cjs.map +0 -7
  164. package/build/editor/switch-to-legacy-canvas.cjs +0 -39
  165. package/build/editor/switch-to-legacy-canvas.cjs.map +0 -7
  166. package/build/editor/transform-block-to.cjs +0 -46
  167. package/build/editor/transform-block-to.cjs.map +0 -7
  168. package/build/index.cjs +0 -51
  169. package/build/index.cjs.map +0 -7
  170. package/build/lighthouse/index.cjs +0 -96
  171. package/build/lighthouse/index.cjs.map +0 -7
  172. package/build/metrics/index.cjs +0 -309
  173. package/build/metrics/index.cjs.map +0 -7
  174. package/build/page-utils/drag-files.cjs +0 -143
  175. package/build/page-utils/drag-files.cjs.map +0 -7
  176. package/build/page-utils/emulate-network-conditions.cjs +0 -99
  177. package/build/page-utils/emulate-network-conditions.cjs.map +0 -7
  178. package/build/page-utils/index.cjs +0 -59
  179. package/build/page-utils/index.cjs.map +0 -7
  180. package/build/page-utils/is-current-url.cjs +0 -36
  181. package/build/page-utils/is-current-url.cjs.map +0 -7
  182. package/build/page-utils/keycodes.cjs +0 -55
  183. package/build/page-utils/keycodes.cjs.map +0 -7
  184. package/build/page-utils/press-keys.cjs +0 -165
  185. package/build/page-utils/press-keys.cjs.map +0 -7
  186. package/build/page-utils/set-browser-viewport.cjs +0 -39
  187. package/build/page-utils/set-browser-viewport.cjs.map +0 -7
  188. package/build/request-utils/blocks.cjs +0 -56
  189. package/build/request-utils/blocks.cjs.map +0 -7
  190. package/build/request-utils/comments.cjs +0 -66
  191. package/build/request-utils/comments.cjs.map +0 -7
  192. package/build/request-utils/gutenberg-experiments.cjs +0 -66
  193. package/build/request-utils/gutenberg-experiments.cjs.map +0 -7
  194. package/build/request-utils/index.cjs +0 -194
  195. package/build/request-utils/index.cjs.map +0 -7
  196. package/build/request-utils/login.cjs +0 -48
  197. package/build/request-utils/login.cjs.map +0 -7
  198. package/build/request-utils/media.cjs +0 -83
  199. package/build/request-utils/media.cjs.map +0 -7
  200. package/build/request-utils/menus.cjs +0 -132
  201. package/build/request-utils/menus.cjs.map +0 -7
  202. package/build/request-utils/pages.cjs +0 -71
  203. package/build/request-utils/pages.cjs.map +0 -7
  204. package/build/request-utils/patterns.cjs +0 -44
  205. package/build/request-utils/patterns.cjs.map +0 -7
  206. package/build/request-utils/plugins.cjs +0 -81
  207. package/build/request-utils/plugins.cjs.map +0 -7
  208. package/build/request-utils/posts.cjs +0 -61
  209. package/build/request-utils/posts.cjs.map +0 -7
  210. package/build/request-utils/preferences.cjs +0 -41
  211. package/build/request-utils/preferences.cjs.map +0 -7
  212. package/build/request-utils/rest.cjs +0 -174
  213. package/build/request-utils/rest.cjs.map +0 -7
  214. package/build/request-utils/site-settings.cjs +0 -45
  215. package/build/request-utils/site-settings.cjs.map +0 -7
  216. package/build/request-utils/templates.cjs +0 -68
  217. package/build/request-utils/templates.cjs.map +0 -7
  218. package/build/request-utils/themes.cjs +0 -89
  219. package/build/request-utils/themes.cjs.map +0 -7
  220. package/build/request-utils/users.cjs +0 -83
  221. package/build/request-utils/users.cjs.map +0 -7
  222. package/build/request-utils/widgets.cjs +0 -79
  223. package/build/request-utils/widgets.cjs.map +0 -7
  224. package/build/test.cjs +0 -136
  225. package/build/test.cjs.map +0 -7
  226. package/build/types.cjs +0 -19
  227. package/build/types.cjs.map +0 -7
@@ -1,258 +1,309 @@
1
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
- };
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
110
91
  });
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,
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
122
118
  });
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()?');
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
174
137
  }
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));
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
+ );
181
227
  }
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
- }
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();
232
280
  }
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;
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();
255
300
  }
256
- }
257
- exports.Metrics = Metrics;
258
- //# sourceMappingURL=index.js.map
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.js.map
@@ -1 +1,7 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"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"}
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
+ }