@wordpress/e2e-tests 7.10.0 → 7.11.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 (35) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/jest.config.js +1 -4
  3. package/package.json +7 -7
  4. package/plugins/interactive-blocks/directive-body/block.json +14 -0
  5. package/plugins/interactive-blocks/directive-body/render.php +22 -0
  6. package/plugins/interactive-blocks/directive-body/view.js +11 -0
  7. package/plugins/interactive-blocks/directive-class/render.php +11 -0
  8. package/plugins/interactive-blocks/directive-effect/render.php +12 -0
  9. package/plugins/interactive-blocks/directive-effect/view.js +7 -0
  10. package/plugins/interactive-blocks/directive-init/block.json +14 -0
  11. package/plugins/interactive-blocks/directive-init/render.php +42 -0
  12. package/plugins/interactive-blocks/directive-init/view.js +64 -0
  13. package/plugins/interactive-blocks/directive-on/block.json +14 -0
  14. package/plugins/interactive-blocks/directive-on/render.php +52 -0
  15. package/plugins/interactive-blocks/directive-on/view.js +27 -0
  16. package/plugins/interactive-blocks/store-afterload/block.json +14 -0
  17. package/plugins/interactive-blocks/store-afterload/render.php +41 -0
  18. package/plugins/interactive-blocks/store-afterload/view.js +60 -0
  19. package/specs/editor/various/__snapshots__/inserting-blocks.test.js.snap +2 -2
  20. package/specs/editor/various/__snapshots__/rich-text.test.js.snap +15 -1
  21. package/specs/editor/various/block-editor-keyboard-shortcuts.test.js +3 -3
  22. package/specs/editor/various/reusable-blocks.test.js +4 -4
  23. package/specs/editor/various/rich-text.test.js +11 -0
  24. package/specs/experiments/blocks/post-comments-form.test.js +2 -2
  25. package/assets/large-post.html +0 -5553
  26. package/assets/small-post-with-containers.html +0 -77
  27. package/config/performance-reporter.js +0 -177
  28. package/config/setup-performance-test.js +0 -51
  29. package/jest.performance.config.js +0 -16
  30. package/specs/editor/plugins/block-variations.test.js +0 -191
  31. package/specs/performance/front-end-block-theme.test.js +0 -77
  32. package/specs/performance/front-end-classic-theme.test.js +0 -77
  33. package/specs/performance/post-editor.test.js +0 -369
  34. package/specs/performance/site-editor.test.js +0 -188
  35. package/specs/performance/utils.js +0 -146
@@ -1,369 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import path from 'path';
5
-
6
- /**
7
- * WordPress dependencies
8
- */
9
- import {
10
- activateTheme,
11
- createNewPost,
12
- saveDraft,
13
- insertBlock,
14
- openGlobalBlockInserter,
15
- closeGlobalBlockInserter,
16
- openListView,
17
- closeListView,
18
- canvas,
19
- } from '@wordpress/e2e-test-utils';
20
-
21
- /**
22
- * Internal dependencies
23
- */
24
- import {
25
- readFile,
26
- deleteFile,
27
- saveResultsFile,
28
- getTraceFilePath,
29
- getTypingEventDurations,
30
- getClickEventDurations,
31
- getHoverEventDurations,
32
- getSelectionEventDurations,
33
- getLoadingDurations,
34
- sum,
35
- } from './utils';
36
-
37
- jest.setTimeout( 1000000 );
38
-
39
- async function loadHtmlIntoTheBlockEditor( html ) {
40
- await page.evaluate( ( _html ) => {
41
- const { parse } = window.wp.blocks;
42
- const { dispatch } = window.wp.data;
43
- const blocks = parse( _html );
44
-
45
- blocks.forEach( ( block ) => {
46
- if ( block.name === 'core/image' ) {
47
- delete block.attributes.id;
48
- delete block.attributes.url;
49
- }
50
- } );
51
-
52
- dispatch( 'core/block-editor' ).resetBlocks( blocks );
53
- }, html );
54
- }
55
-
56
- async function load1000Paragraphs() {
57
- await page.evaluate( () => {
58
- const { createBlock } = window.wp.blocks;
59
- const { dispatch } = window.wp.data;
60
- const blocks = Array.from( { length: 1000 } ).map( () =>
61
- createBlock( 'core/paragraph' )
62
- );
63
- dispatch( 'core/block-editor' ).resetBlocks( blocks );
64
- } );
65
- }
66
-
67
- describe( 'Post Editor Performance', () => {
68
- const results = {
69
- serverResponse: [],
70
- firstPaint: [],
71
- domContentLoaded: [],
72
- loaded: [],
73
- firstContentfulPaint: [],
74
- firstBlock: [],
75
- type: [],
76
- typeContainer: [],
77
- focus: [],
78
- listViewOpen: [],
79
- inserterOpen: [],
80
- inserterHover: [],
81
- inserterSearch: [],
82
- };
83
- const traceFilePath = getTraceFilePath();
84
-
85
- let traceResults;
86
-
87
- beforeAll( async () => {
88
- // See https://github.com/WordPress/gutenberg/pull/50905/files#r1209014677;
89
- await activateTheme( 'gutenberg-test-themes/twentytwentyone' );
90
- } );
91
-
92
- afterAll( async () => {
93
- saveResultsFile( __filename, results );
94
- deleteFile( traceFilePath );
95
- } );
96
-
97
- beforeEach( async () => {
98
- await createNewPost();
99
- // Disable auto-save to avoid impacting the metrics.
100
- await page.evaluate( () => {
101
- window.wp.data.dispatch( 'core/editor' ).updateEditorSettings( {
102
- autosaveInterval: 100000000000,
103
- localAutosaveInterval: 100000000000,
104
- } );
105
- } );
106
- } );
107
-
108
- it( 'Loading', async () => {
109
- await loadHtmlIntoTheBlockEditor(
110
- readFile( path.join( __dirname, '../../assets/large-post.html' ) )
111
- );
112
- await saveDraft();
113
- const draftURL = await page.url();
114
-
115
- // Number of sample measurements to take.
116
- const samples = 5;
117
- // Number of throwaway measurements to perform before recording samples.
118
- // Having at least one helps ensure that caching quirks don't manifest in
119
- // the results.
120
- const throwaway = 1;
121
-
122
- let i = throwaway + samples;
123
- while ( i-- ) {
124
- await page.close();
125
- page = await browser.newPage();
126
-
127
- await page.goto( draftURL );
128
- await page.waitForSelector( '.edit-post-layout', {
129
- timeout: 120000,
130
- } );
131
- await canvas().waitForSelector( '.wp-block', { timeout: 120000 } );
132
-
133
- if ( i < samples ) {
134
- const {
135
- serverResponse,
136
- firstPaint,
137
- domContentLoaded,
138
- loaded,
139
- firstContentfulPaint,
140
- firstBlock,
141
- } = await getLoadingDurations();
142
-
143
- results.serverResponse.push( serverResponse );
144
- results.firstPaint.push( firstPaint );
145
- results.domContentLoaded.push( domContentLoaded );
146
- results.loaded.push( loaded );
147
- results.firstContentfulPaint.push( firstContentfulPaint );
148
- results.firstBlock.push( firstBlock );
149
- }
150
- }
151
- } );
152
-
153
- it( 'Typing', async () => {
154
- await loadHtmlIntoTheBlockEditor(
155
- readFile( path.join( __dirname, '../../assets/large-post.html' ) )
156
- );
157
- await insertBlock( 'Paragraph' );
158
- let i = 20;
159
- await page.tracing.start( {
160
- path: traceFilePath,
161
- screenshots: false,
162
- categories: [ 'devtools.timeline' ],
163
- } );
164
- while ( i-- ) {
165
- // Wait for the browser to be idle before starting the monitoring.
166
- // The timeout should be big enough to allow all async tasks tor run.
167
- // And also to allow Rich Text to mark the change as persistent.
168
- // eslint-disable-next-line no-restricted-syntax
169
- await page.waitForTimeout( 2000 );
170
- await page.keyboard.type( 'x' );
171
- }
172
- await page.tracing.stop();
173
- traceResults = JSON.parse( readFile( traceFilePath ) );
174
- const [ keyDownEvents, keyPressEvents, keyUpEvents ] =
175
- getTypingEventDurations( traceResults );
176
- if (
177
- keyDownEvents.length === keyPressEvents.length &&
178
- keyPressEvents.length === keyUpEvents.length
179
- ) {
180
- // The first character typed triggers a longer time (isTyping change)
181
- // It can impact the stability of the metric, so we exclude it.
182
- for ( let j = 1; j < keyDownEvents.length; j++ ) {
183
- results.type.push(
184
- keyDownEvents[ j ] + keyPressEvents[ j ] + keyUpEvents[ j ]
185
- );
186
- }
187
- }
188
- } );
189
-
190
- it( 'Typing within containers', async () => {
191
- await loadHtmlIntoTheBlockEditor(
192
- readFile(
193
- path.join(
194
- __dirname,
195
- '../../assets/small-post-with-containers.html'
196
- )
197
- )
198
- );
199
- // Select the block where we type in
200
- await canvas().waitForSelector( 'p[aria-label="Paragraph block"]' );
201
- await canvas().click( 'p[aria-label="Paragraph block"]' );
202
- // Ignore firsted typed character because it's different
203
- // It probably deserves a dedicated metric.
204
- // (isTyping triggers so it's slower)
205
- await page.keyboard.type( 'x' );
206
-
207
- let i = 10;
208
- await page.tracing.start( {
209
- path: traceFilePath,
210
- screenshots: false,
211
- categories: [ 'devtools.timeline' ],
212
- } );
213
-
214
- while ( i-- ) {
215
- // Wait for the browser to be idle before starting the monitoring.
216
- // eslint-disable-next-line no-restricted-syntax
217
- await page.waitForTimeout( 500 );
218
- await page.keyboard.type( 'x' );
219
- }
220
- // eslint-disable-next-line no-restricted-syntax
221
- await page.waitForTimeout( 500 );
222
- await page.tracing.stop();
223
- traceResults = JSON.parse( readFile( traceFilePath ) );
224
- const [ keyDownEvents, keyPressEvents, keyUpEvents ] =
225
- getTypingEventDurations( traceResults );
226
- if (
227
- keyDownEvents.length === keyPressEvents.length &&
228
- keyPressEvents.length === keyUpEvents.length
229
- ) {
230
- // The first character typed triggers a longer time (isTyping change)
231
- // It can impact the stability of the metric, so we exclude it.
232
- for ( let j = 1; j < keyDownEvents.length; j++ ) {
233
- results.typeContainer.push(
234
- keyDownEvents[ j ] + keyPressEvents[ j ] + keyUpEvents[ j ]
235
- );
236
- }
237
- }
238
- } );
239
-
240
- it( 'Selecting blocks', async () => {
241
- await load1000Paragraphs();
242
- const paragraphs = await canvas().$$( '.wp-block' );
243
- await paragraphs[ 0 ].click();
244
- for ( let j = 1; j <= 10; j++ ) {
245
- // Wait for the browser to be idle before starting the monitoring.
246
- // eslint-disable-next-line no-restricted-syntax
247
- await page.waitForTimeout( 1000 );
248
- await page.tracing.start( {
249
- path: traceFilePath,
250
- screenshots: false,
251
- categories: [ 'devtools.timeline' ],
252
- } );
253
- await paragraphs[ j ].click();
254
- await page.tracing.stop();
255
- traceResults = JSON.parse( readFile( traceFilePath ) );
256
- const allDurations = getSelectionEventDurations( traceResults );
257
- results.focus.push(
258
- allDurations.reduce( ( acc, eventDurations ) => {
259
- return acc + sum( eventDurations );
260
- }, 0 )
261
- );
262
- }
263
- } );
264
-
265
- it( 'Opening persistent list view', async () => {
266
- await load1000Paragraphs();
267
- for ( let j = 0; j < 10; j++ ) {
268
- await page.tracing.start( {
269
- path: traceFilePath,
270
- screenshots: false,
271
- categories: [ 'devtools.timeline' ],
272
- } );
273
- await openListView();
274
- await page.tracing.stop();
275
- traceResults = JSON.parse( readFile( traceFilePath ) );
276
- const [ mouseClickEvents ] = getClickEventDurations( traceResults );
277
- for ( let k = 0; k < mouseClickEvents.length; k++ ) {
278
- results.listViewOpen.push( mouseClickEvents[ k ] );
279
- }
280
- await closeListView();
281
- }
282
- } );
283
-
284
- it( 'Opening the inserter', async () => {
285
- await load1000Paragraphs();
286
- for ( let j = 0; j < 10; j++ ) {
287
- await page.tracing.start( {
288
- path: traceFilePath,
289
- screenshots: false,
290
- categories: [ 'devtools.timeline' ],
291
- } );
292
- await openGlobalBlockInserter();
293
- await page.tracing.stop();
294
- traceResults = JSON.parse( readFile( traceFilePath ) );
295
- const [ mouseClickEvents ] = getClickEventDurations( traceResults );
296
- for ( let k = 0; k < mouseClickEvents.length; k++ ) {
297
- results.inserterOpen.push( mouseClickEvents[ k ] );
298
- }
299
- await closeGlobalBlockInserter();
300
- }
301
- } );
302
-
303
- it( 'Searching the inserter', async () => {
304
- await load1000Paragraphs();
305
- await openGlobalBlockInserter();
306
- for ( let j = 0; j < 10; j++ ) {
307
- // Wait for the browser to be idle before starting the monitoring.
308
- // eslint-disable-next-line no-restricted-syntax
309
- await page.waitForTimeout( 500 );
310
- await page.tracing.start( {
311
- path: traceFilePath,
312
- screenshots: false,
313
- categories: [ 'devtools.timeline' ],
314
- } );
315
- await page.keyboard.type( 'p' );
316
- await page.tracing.stop();
317
- traceResults = JSON.parse( readFile( traceFilePath ) );
318
- const [ keyDownEvents, keyPressEvents, keyUpEvents ] =
319
- getTypingEventDurations( traceResults );
320
- if (
321
- keyDownEvents.length === keyPressEvents.length &&
322
- keyPressEvents.length === keyUpEvents.length
323
- ) {
324
- results.inserterSearch.push(
325
- sum( keyDownEvents ) +
326
- sum( keyPressEvents ) +
327
- sum( keyUpEvents )
328
- );
329
- }
330
- await page.keyboard.press( 'Backspace' );
331
- }
332
- await closeGlobalBlockInserter();
333
- } );
334
-
335
- it( 'Hovering Inserter Items', async () => {
336
- await load1000Paragraphs();
337
- const paragraphBlockItem =
338
- '.block-editor-inserter__menu .editor-block-list-item-paragraph';
339
- const headingBlockItem =
340
- '.block-editor-inserter__menu .editor-block-list-item-heading';
341
- await openGlobalBlockInserter();
342
- await page.waitForSelector( paragraphBlockItem );
343
- await page.hover( paragraphBlockItem );
344
- await page.hover( headingBlockItem );
345
- for ( let j = 0; j < 10; j++ ) {
346
- // Wait for the browser to be idle before starting the monitoring.
347
- // eslint-disable-next-line no-restricted-syntax
348
- await page.waitForTimeout( 200 );
349
- await page.tracing.start( {
350
- path: traceFilePath,
351
- screenshots: false,
352
- categories: [ 'devtools.timeline' ],
353
- } );
354
- await page.hover( paragraphBlockItem );
355
- await page.hover( headingBlockItem );
356
- await page.tracing.stop();
357
-
358
- traceResults = JSON.parse( readFile( traceFilePath ) );
359
- const [ mouseOverEvents, mouseOutEvents ] =
360
- getHoverEventDurations( traceResults );
361
- for ( let k = 0; k < mouseOverEvents.length; k++ ) {
362
- results.inserterHover.push(
363
- mouseOverEvents[ k ] + mouseOutEvents[ k ]
364
- );
365
- }
366
- }
367
- await closeGlobalBlockInserter();
368
- } );
369
- } );
@@ -1,188 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import path from 'path';
5
-
6
- /**
7
- * WordPress dependencies
8
- */
9
- import {
10
- activateTheme,
11
- canvas,
12
- createNewPost,
13
- visitSiteEditor,
14
- saveDraft,
15
- insertBlock,
16
- deleteAllTemplates,
17
- enterEditMode,
18
- } from '@wordpress/e2e-test-utils';
19
-
20
- /**
21
- * Internal dependencies
22
- */
23
- import {
24
- readFile,
25
- deleteFile,
26
- saveResultsFile,
27
- getTraceFilePath,
28
- getTypingEventDurations,
29
- getLoadingDurations,
30
- sequence,
31
- } from './utils';
32
-
33
- jest.setTimeout( 1000000 );
34
-
35
- const results = {
36
- serverResponse: [],
37
- firstPaint: [],
38
- domContentLoaded: [],
39
- loaded: [],
40
- firstContentfulPaint: [],
41
- firstBlock: [],
42
- type: [],
43
- typeContainer: [],
44
- focus: [],
45
- inserterOpen: [],
46
- inserterHover: [],
47
- inserterSearch: [],
48
- listViewOpen: [],
49
- };
50
-
51
- let postId;
52
-
53
- describe( 'Site Editor Performance', () => {
54
- beforeAll( async () => {
55
- await activateTheme( 'emptytheme' );
56
- await deleteAllTemplates( 'wp_template' );
57
- await deleteAllTemplates( 'wp_template_part' );
58
-
59
- const html = readFile(
60
- path.join( __dirname, '../../assets/large-post.html' )
61
- );
62
-
63
- await createNewPost( { postType: 'page' } );
64
-
65
- await page.evaluate( ( _html ) => {
66
- const { parse } = window.wp.blocks;
67
- const { dispatch } = window.wp.data;
68
- const blocks = parse( _html );
69
-
70
- blocks.forEach( ( block ) => {
71
- if ( block.name === 'core/image' ) {
72
- delete block.attributes.id;
73
- delete block.attributes.url;
74
- }
75
- } );
76
-
77
- dispatch( 'core/block-editor' ).resetBlocks( blocks );
78
- }, html );
79
- await saveDraft();
80
-
81
- postId = await page.evaluate( () =>
82
- new URL( document.location ).searchParams.get( 'post' )
83
- );
84
- } );
85
-
86
- afterAll( async () => {
87
- saveResultsFile( __filename, results );
88
- await deleteAllTemplates( 'wp_template' );
89
- await deleteAllTemplates( 'wp_template_part' );
90
- } );
91
-
92
- // Number of loading measurements to take.
93
- const loadingSamples = 3;
94
- // Number of throwaway measurements to perform before recording samples.
95
- // Having at least one helps ensure that caching quirks don't manifest
96
- // in the results.
97
- const loadingSamplesThrowaway = 1;
98
- const loadingIterations = sequence(
99
- 1,
100
- loadingSamples + loadingSamplesThrowaway
101
- );
102
- it.each( loadingIterations )(
103
- `Loading (%i of ${ loadingIterations.length })`,
104
- async ( i ) => {
105
- // Open the test page in Site Editor.
106
- await visitSiteEditor( {
107
- postId,
108
- postType: 'page',
109
- } );
110
-
111
- // Wait for the first block.
112
- await canvas().waitForSelector( '.wp-block' );
113
-
114
- // Save results.
115
- if ( i > loadingSamplesThrowaway ) {
116
- const {
117
- serverResponse,
118
- firstPaint,
119
- domContentLoaded,
120
- loaded,
121
- firstContentfulPaint,
122
- firstBlock,
123
- } = await getLoadingDurations();
124
-
125
- results.serverResponse.push( serverResponse );
126
- results.firstPaint.push( firstPaint );
127
- results.domContentLoaded.push( domContentLoaded );
128
- results.loaded.push( loaded );
129
- results.firstContentfulPaint.push( firstContentfulPaint );
130
- results.firstBlock.push( firstBlock );
131
- }
132
-
133
- expect( true ).toBe( true );
134
- }
135
- );
136
-
137
- it( 'Typing', async () => {
138
- // Open the test page in Site Editor.
139
- await visitSiteEditor( {
140
- postId,
141
- postType: 'page',
142
- } );
143
-
144
- // Wait for the first block to be ready.
145
- await canvas().waitForSelector( '.wp-block' );
146
-
147
- // Get inside the post content.
148
- await enterEditMode();
149
-
150
- // Select the post content block wrapper.
151
- await canvas().click( '.wp-block-post-content' );
152
-
153
- // Select the first paragraph in the post content block.
154
- const firstParagraph = await canvas().waitForXPath(
155
- '//p[contains(text(), "Lorem ipsum dolor sit amet")]'
156
- );
157
- await firstParagraph.click();
158
-
159
- await insertBlock( 'Paragraph' );
160
-
161
- // Start tracing.
162
- const traceFilePath = getTraceFilePath();
163
- await page.tracing.start( {
164
- path: traceFilePath,
165
- screenshots: false,
166
- categories: [ 'devtools.timeline' ],
167
- } );
168
-
169
- // Type "x" 200 times.
170
- await page.keyboard.type( new Array( 200 ).fill( 'x' ).join( '' ) );
171
-
172
- // Stop tracing and save results.
173
- await page.tracing.stop();
174
- const traceResults = JSON.parse( readFile( traceFilePath ) );
175
- const [ keyDownEvents, keyPressEvents, keyUpEvents ] =
176
- getTypingEventDurations( traceResults );
177
- for ( let i = 0; i < keyDownEvents.length; i++ ) {
178
- results.type.push(
179
- keyDownEvents[ i ] + keyPressEvents[ i ] + keyUpEvents[ i ]
180
- );
181
- }
182
-
183
- // Delete the original trace file.
184
- deleteFile( traceFilePath );
185
-
186
- expect( true ).toBe( true );
187
- } );
188
- } );
@@ -1,146 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import path from 'path';
5
- import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'fs';
6
-
7
- export function readFile( filePath ) {
8
- return existsSync( filePath )
9
- ? readFileSync( filePath, 'utf8' ).trim()
10
- : '';
11
- }
12
-
13
- export function deleteFile( filePath ) {
14
- if ( existsSync( filePath ) ) {
15
- unlinkSync( filePath );
16
- }
17
- }
18
-
19
- export function getTraceFilePath() {
20
- return path.join( process.env.WP_ARTIFACTS_PATH, '/trace.json' );
21
- }
22
-
23
- export function saveResultsFile( testFilename, results ) {
24
- const resultsFilename =
25
- process.env.RESULTS_FILENAME ||
26
- path.basename( testFilename, '.js' ) + '.performance-results.json';
27
-
28
- return writeFileSync(
29
- path.join( process.env.WP_ARTIFACTS_PATH, resultsFilename ),
30
- JSON.stringify( results, null, 2 )
31
- );
32
- }
33
-
34
- function isEvent( item ) {
35
- return (
36
- item.cat === 'devtools.timeline' &&
37
- item.name === 'EventDispatch' &&
38
- item.dur &&
39
- item.args &&
40
- item.args.data
41
- );
42
- }
43
-
44
- function isKeyDownEvent( item ) {
45
- return isEvent( item ) && item.args.data.type === 'keydown';
46
- }
47
-
48
- function isKeyPressEvent( item ) {
49
- return isEvent( item ) && item.args.data.type === 'keypress';
50
- }
51
-
52
- function isKeyUpEvent( item ) {
53
- return isEvent( item ) && item.args.data.type === 'keyup';
54
- }
55
-
56
- function isFocusEvent( item ) {
57
- return isEvent( item ) && item.args.data.type === 'focus';
58
- }
59
-
60
- function isFocusInEvent( item ) {
61
- return isEvent( item ) && item.args.data.type === 'focusin';
62
- }
63
-
64
- function isClickEvent( item ) {
65
- return isEvent( item ) && item.args.data.type === 'click';
66
- }
67
-
68
- function isMouseOverEvent( item ) {
69
- return isEvent( item ) && item.args.data.type === 'mouseover';
70
- }
71
-
72
- function isMouseOutEvent( item ) {
73
- return isEvent( item ) && item.args.data.type === 'mouseout';
74
- }
75
-
76
- function getEventDurationsForType( trace, filterFunction ) {
77
- return trace.traceEvents
78
- .filter( filterFunction )
79
- .map( ( item ) => item.dur / 1000 );
80
- }
81
-
82
- export function getTypingEventDurations( trace ) {
83
- return [
84
- getEventDurationsForType( trace, isKeyDownEvent ),
85
- getEventDurationsForType( trace, isKeyPressEvent ),
86
- getEventDurationsForType( trace, isKeyUpEvent ),
87
- ];
88
- }
89
-
90
- export function getSelectionEventDurations( trace ) {
91
- return [
92
- getEventDurationsForType( trace, isFocusEvent ),
93
- getEventDurationsForType( trace, isFocusInEvent ),
94
- ];
95
- }
96
-
97
- export function getClickEventDurations( trace ) {
98
- return [ getEventDurationsForType( trace, isClickEvent ) ];
99
- }
100
-
101
- export function getHoverEventDurations( trace ) {
102
- return [
103
- getEventDurationsForType( trace, isMouseOverEvent ),
104
- getEventDurationsForType( trace, isMouseOutEvent ),
105
- ];
106
- }
107
-
108
- export async function getLoadingDurations() {
109
- return await page.evaluate( () => {
110
- const [
111
- {
112
- requestStart,
113
- responseStart,
114
- responseEnd,
115
- domContentLoadedEventEnd,
116
- loadEventEnd,
117
- },
118
- ] = performance.getEntriesByType( 'navigation' );
119
- const paintTimings = performance.getEntriesByType( 'paint' );
120
- return {
121
- // Server side metric.
122
- serverResponse: responseStart - requestStart,
123
- // For client side metrics, consider the end of the response (the
124
- // browser receives the HTML) as the start time (0).
125
- firstPaint:
126
- paintTimings.find( ( { name } ) => name === 'first-paint' )
127
- .startTime - responseEnd,
128
- domContentLoaded: domContentLoadedEventEnd - responseEnd,
129
- loaded: loadEventEnd - responseEnd,
130
- firstContentfulPaint:
131
- paintTimings.find(
132
- ( { name } ) => name === 'first-contentful-paint'
133
- ).startTime - responseEnd,
134
- // This is evaluated right after Puppeteer found the block selector.
135
- firstBlock: performance.now() - responseEnd,
136
- };
137
- } );
138
- }
139
-
140
- export function sum( arr ) {
141
- return arr.reduce( ( a, b ) => a + b, 0 );
142
- }
143
-
144
- export function sequence( start, length ) {
145
- return Array.from( { length }, ( _, i ) => i + start );
146
- }