@@ -38,7 +38,9 @@ describe('onLCP()', async function () {
38
38
browserSupportsPrerender = await browser . execute ( ( ) => {
39
39
return 'onprerenderingchange' in document ;
40
40
} ) ;
41
+ } ) ;
41
42
43
+ beforeEach ( async function ( ) {
42
44
await navigateTo ( 'about:blank' ) ;
43
45
await clearBeacons ( ) ;
44
46
} ) ;
@@ -129,7 +131,12 @@ describe('onLCP()', async function () {
129
131
await imagesPainted ( ) ;
130
132
131
133
await beaconCountIs ( 2 ) ;
132
- const [ lcp1 , lcp2 ] = await getBeacons ( ) ;
134
+ const beacons = await getBeacons ( ) ;
135
+ // Firefox sometimes sents <p>, then <h1>
136
+ // so grab last two
137
+ assert ( beacons . length >= 2 ) ;
138
+ const lcp1 = beacons . at ( - 2 ) ;
139
+ const lcp2 = beacons . at ( - 1 ) ;
133
140
134
141
assert ( lcp1 . value > 0 ) ;
135
142
assert ( lcp1 . id . match ( / ^ v 5 - \d + - \d + $ / ) ) ;
@@ -157,15 +164,24 @@ describe('onLCP()', async function () {
157
164
// Wait until all images are loaded and fully rendered.
158
165
await imagesPainted ( ) ;
159
166
167
+ // Wait until web-vitals is loaded
168
+ await webVitalsLoaded ( ) ;
169
+
170
+ // Click on the h1.
171
+ const h1 = await $ ( 'h1' ) ;
172
+ await h1 . click ( ) ;
173
+
174
+ await beaconCountIs ( 1 ) ;
175
+ await clearBeacons ( ) ;
176
+
160
177
// Wait a bit to allow the prerender to happen
161
178
await browser . pause ( 1000 ) ;
162
179
163
180
const prerenderLink = await $ ( '#prerender-link' ) ;
164
181
await prerenderLink . click ( ) ;
165
182
166
- // Check the beacon has come in
167
- await beaconCountIs ( 1 ) ;
168
- await clearBeacons ( ) ;
183
+ // Wait a bit for the navigation to start
184
+ await browser . pause ( 500 ) ;
169
185
170
186
// Wait until all images are loaded and fully rendered.
171
187
await imagesPainted ( ) ;
@@ -183,6 +199,7 @@ describe('onLCP()', async function () {
183
199
assert . strictEqual ( lcp . rating , 'good' ) ;
184
200
assert . strictEqual ( lcp . entries [ 0 ] . startTime - activationStart , lcp . value ) ;
185
201
assert . strictEqual ( lcp . navigationType , 'prerender' ) ;
202
+ await clearBeacons ( ) ;
186
203
} ) ;
187
204
188
205
it ( 'does not report if the browser does not support LCP (including bfcache restores)' , async function ( ) {
@@ -223,9 +240,19 @@ describe('onLCP()', async function () {
223
240
it ( 'does not report if the document was hidden at page load time' , async function ( ) {
224
241
if ( ! browserSupportsLCP ) this . skip ( ) ;
225
242
226
- await navigateTo ( '/test/lcp?hidden=1' , { readyState : 'interactive' } ) ;
227
-
228
- await stubVisibilityChange ( 'visible' ) ;
243
+ // Can't mock visibility-state entries so load in a new blank tab:
244
+ const originalHandle = await browser . getWindowHandle ( ) ;
245
+ await browser . execute (
246
+ "window.open('http://localhost:9090/test/lcp', '_blank')" ,
247
+ ) ;
248
+ // immediately switch back before page load starts—annoyingly you can't
249
+ // open in a hidden tab as ChromeDriver foregrounds it, but this works.
250
+ await browser . switchToWindow ( originalHandle ) ;
251
+ await browser . pause ( 500 ) ;
252
+ // Then switch to the new tab to do our tests
253
+ const handles = await browser . getWindowHandles ( ) ;
254
+ const newTabHandle = handles . find ( ( h ) => h !== originalHandle ) ;
255
+ await browser . switchToWindow ( newTabHandle ) ;
229
256
230
257
// Click on the h1.
231
258
const h1 = await $ ( 'h1' ) ;
@@ -236,12 +263,48 @@ describe('onLCP()', async function () {
236
263
237
264
const beacons = await getBeacons ( ) ;
238
265
assert . strictEqual ( beacons . length , 0 ) ;
266
+
267
+ // Reset everything
268
+ await browser . closeWindow ( ) ;
269
+ await browser . switchToWindow ( originalHandle ) ;
239
270
} ) ;
240
271
241
- it ( 'does not report if the document was hidden before library loaded' , async function ( ) {
272
+ it ( 'does not report if hidden before library loaded and visibilitystate supported ' , async function ( ) {
242
273
if ( ! browserSupportsLCP ) this . skip ( ) ;
243
274
if ( ! browserSupportsVisibilityState ) this . skip ( ) ;
244
275
276
+ // Don't load the library until we click
277
+ await navigateTo ( '/test/lcp?loadAfterInput=1&imgDelay=500' ) ;
278
+
279
+ // Can't mock visibility-state entries so switch to a blank tab and back
280
+ // to emit real entries:
281
+ const handle1 = await browser . getWindowHandle ( ) ;
282
+ await browser . newWindow ( 'https://example.com' ) ;
283
+ await browser . pause ( 500 ) ;
284
+ await browser . closeWindow ( ) ;
285
+ await browser . switchToWindow ( handle1 ) ;
286
+
287
+ // Click on the h1 to load the library
288
+ const h1 = await $ ( 'h1' ) ;
289
+ await h1 . click ( ) ;
290
+
291
+ // Wait until web-vitals is loaded
292
+ await webVitalsLoaded ( ) ;
293
+
294
+ // Wait a bit to ensure no beacons were sent.
295
+ await browser . pause ( 1000 ) ;
296
+
297
+ // Click on the h1 again now it's loaded to trigger LCP
298
+ await h1 . click ( ) ;
299
+
300
+ const beacons = await getBeacons ( ) ;
301
+ assert . strictEqual ( beacons . length , 0 ) ;
302
+ } ) ;
303
+
304
+ it ( 'does report if hidden before library loaded and visibilitystate not supported' , async function ( ) {
305
+ if ( ! browserSupportsLCP ) this . skip ( ) ;
306
+ if ( browserSupportsVisibilityState ) this . skip ( ) ;
307
+
245
308
// Don't load the library until we click
246
309
await navigateTo ( '/test/lcp?loadAfterInput=1' ) ;
247
310
@@ -260,14 +323,14 @@ describe('onLCP()', async function () {
260
323
// Wait until web-vitals is loaded
261
324
await webVitalsLoaded ( ) ;
262
325
263
- // Click on the h1 again not it's loaded to trigger LCP
326
+ // Click on the h1 again now it's loaded to trigger LCP
264
327
await h1 . click ( ) ;
265
328
266
329
// Wait a bit to ensure no beacons were sent.
267
330
await browser . pause ( 1000 ) ;
268
331
269
- const beacons = await getBeacons ( ) ;
270
- assert . strictEqual ( beacons . length , 0 ) ;
332
+ await beaconCountIs ( 1 ) ;
333
+ assertStandardReportsAreCorrect ( await getBeacons ( ) ) ;
271
334
} ) ;
272
335
273
336
it ( 'does not report if the document changes to hidden before the first render' , async function ( ) {
@@ -333,11 +396,7 @@ describe('onLCP()', async function () {
333
396
const h1 = await $ ( 'h1' ) ;
334
397
await h1 . click ( ) ;
335
398
336
- // Wait a bit to ensure no additional beacons were sent.
337
- await browser . pause ( 1000 ) ;
338
-
339
399
await beaconCountIs ( 1 ) ;
340
-
341
400
const [ lcp1 ] = await getBeacons ( ) ;
342
401
343
402
assert ( lcp1 . value > 0 ) ;
@@ -355,7 +414,9 @@ describe('onLCP()', async function () {
355
414
await navigateTo ( '/test/lcp?reportAllChanges=1&imgDelay=0&imgHidden=1' ) ;
356
415
357
416
await beaconCountIs ( 1 ) ;
358
- const [ lcp ] = await getBeacons ( ) ;
417
+ // Firefox sometimes sends a <p> and then <h1> beacon, so grab last one
418
+ let beacons = await getBeacons ( ) ;
419
+ const lcp = beacons . at ( - 1 ) ;
359
420
360
421
assert ( lcp . value > 0 ) ;
361
422
assert . strictEqual ( lcp . name , 'LCP' ) ;
@@ -376,7 +437,7 @@ describe('onLCP()', async function () {
376
437
// Wait a bit to ensure no beacons were sent.
377
438
await browser . pause ( 1000 ) ;
378
439
379
- const beacons = await getBeacons ( ) ;
440
+ beacons = await getBeacons ( ) ;
380
441
assert . strictEqual ( beacons . length , 0 ) ;
381
442
} ) ;
382
443
@@ -426,7 +487,19 @@ describe('onLCP()', async function () {
426
487
it ( 'reports if the page is restored from bfcache even when the document was hidden at page load time' , async function ( ) {
427
488
if ( ! browserSupportsLCP ) this . skip ( ) ;
428
489
429
- await navigateTo ( '/test/lcp?hidden=1' , { readyState : 'interactive' } ) ;
490
+ // Can't mock visibility-state entries so load in a new blank tab:
491
+ const originalHandle = await browser . getWindowHandle ( ) ;
492
+ await browser . execute (
493
+ "window.open('http://localhost:9090/test/lcp', '_blank')" ,
494
+ ) ;
495
+ // immediately switch back before page load starts—annoyingly you can't
496
+ // open in a hidden tab as ChromeDriver foregrounds it, but this works.
497
+ await browser . switchToWindow ( originalHandle ) ;
498
+ await browser . pause ( 500 ) ;
499
+ // Then switch to the new tab to do our tests
500
+ const handles = await browser . getWindowHandles ( ) ;
501
+ const newTabHandle = handles . find ( ( h ) => h !== originalHandle ) ;
502
+ await browser . switchToWindow ( newTabHandle ) ;
430
503
431
504
await stubVisibilityChange ( 'visible' ) ;
432
505
@@ -466,6 +539,10 @@ describe('onLCP()', async function () {
466
539
assert . strictEqual ( lcp2 . rating , 'good' ) ;
467
540
assert . strictEqual ( lcp2 . entries . length , 0 ) ;
468
541
assert . strictEqual ( lcp2 . navigationType , 'back-forward-cache' ) ;
542
+
543
+ // Reset everything
544
+ await browser . closeWindow ( ) ;
545
+ await browser . switchToWindow ( originalHandle ) ;
469
546
} ) ;
470
547
471
548
it ( 'reports restore as nav type for wasDiscarded' , async function ( ) {
@@ -669,6 +746,13 @@ describe('onLCP()', async function () {
669
746
670
747
await navigateTo ( '/test/lcp?attribution=1&prerender=1' ) ;
671
748
749
+ // Wait until web-vitals is loaded
750
+ await webVitalsLoaded ( ) ;
751
+
752
+ // Click on the h1.
753
+ const h1 = await $ ( 'h1' ) ;
754
+ await h1 . click ( ) ;
755
+
672
756
await beaconCountIs ( 1 ) ;
673
757
await clearBeacons ( ) ;
674
758
@@ -678,7 +762,8 @@ describe('onLCP()', async function () {
678
762
const prerenderLink = await $ ( '#prerender-link' ) ;
679
763
await prerenderLink . click ( ) ;
680
764
681
- await beaconCountIs ( 1 ) ;
765
+ // Wait a bit for the navigation to start
766
+ await browser . pause ( 500 ) ;
682
767
683
768
// Wait until all images are loaded and fully rendered.
684
769
await imagesPainted ( ) ;
@@ -837,7 +922,11 @@ const assertStandardReportsAreCorrect = (beacons) => {
837
922
} ;
838
923
839
924
const assertFullReportsAreCorrect = ( beacons ) => {
840
- const [ lcp1 , lcp2 ] = beacons ;
925
+ // Firefox sometimes sents <p>, then <h1>
926
+ // so grab last two
927
+ assert ( beacons . length >= 2 ) ;
928
+ const lcp1 = beacons . at ( - 2 ) ;
929
+ const lcp2 = beacons . at ( - 1 ) ;
841
930
842
931
assert ( lcp1 . value < 500 ) ; // Less than the image load delay.
843
932
assert ( lcp1 . id . match ( / ^ v 5 - \d + - \d + $ / ) ) ;
0 commit comments