@@ -191,21 +191,20 @@ export function runTestCases(testCases: TestsCase[]) {
191
191
.intercom-lightweight-app {
192
192
display: none !important;
193
193
}
194
-
195
- /* Switch image rendering to pixelated */
196
- img {
197
- image-rendering: pixelated;
198
- }
199
194
` ,
200
195
threshold : screenshotOptions ?. threshold ?? undefined ,
201
196
fullPage : testEntry . fullPage ?? false ,
202
197
beforeScreenshot : async ( { runStabilization } ) => {
203
198
await runStabilization ( ) ;
204
199
await waitForIcons ( page ) ;
200
+ await roundImageSizes ( page ) ;
205
201
if ( screenshotOptions ?. waitForTOCScrolling !== false ) {
206
202
await waitForTOCScrolling ( page ) ;
207
203
}
208
204
} ,
205
+ afterScreenshot : async ( ) => {
206
+ await restoreImageSizes ( page ) ;
207
+ } ,
209
208
} ) ;
210
209
}
211
210
} ) ;
@@ -326,7 +325,14 @@ async function waitForIcons(page: Page) {
326
325
function loadImage ( src : string ) {
327
326
return new Promise ( ( resolve , reject ) => {
328
327
const img = new Image ( ) ;
329
- img . onload = ( ) => resolve ( img ) ;
328
+ img . onload = ( ) => {
329
+ // Wait two frames to ensure the image has been rendered
330
+ requestAnimationFrame ( ( ) => {
331
+ requestAnimationFrame ( ( ) => {
332
+ resolve ( true ) ;
333
+ } ) ;
334
+ } ) ;
335
+ } ;
330
336
img . onerror = ( _error ) => reject ( new Error ( `Failed to load image: ${ src } ` ) ) ;
331
337
img . src = src ;
332
338
} ) ;
@@ -348,6 +354,70 @@ async function waitForIcons(page: Page) {
348
354
} ) ;
349
355
}
350
356
357
+ /**
358
+ * Take all images, measure them and set their width and height to rounded values.
359
+ */
360
+ async function roundImageSizes ( page : Page ) {
361
+ await page . waitForFunction ( async ( ) => {
362
+ const images = Array . from ( document . querySelectorAll ( 'img' ) ) ;
363
+ await Promise . all (
364
+ images . map ( async ( img ) => {
365
+ return new Promise < void > ( ( resolve ) => {
366
+ const setDimensions = ( ) => {
367
+ // Mark it as stabilized
368
+ img . dataset . stabilized = 'true' ;
369
+ // Preserve the original width and height
370
+ img . dataset . originalWidth = img . style . width ?? '' ;
371
+ img . dataset . originalHeight = img . style . height ?? '' ;
372
+ const rect = img . getBoundingClientRect ( ) ;
373
+ img . style . width = `${ Math . round ( rect . width ) } px` ;
374
+ img . style . height = `${ Math . round ( rect . height ) } px` ;
375
+ resolve ( ) ;
376
+ } ;
377
+
378
+ if ( img . complete ) {
379
+ setDimensions ( ) ;
380
+ } else {
381
+ const cleanup = ( ) => {
382
+ img . removeEventListener ( 'load' , handleLoad ) ;
383
+ img . removeEventListener ( 'error' , handleError ) ;
384
+ } ;
385
+ const handleError = ( ) => {
386
+ cleanup ( ) ;
387
+ resolve ( ) ;
388
+ } ;
389
+ const handleLoad = ( ) => {
390
+ cleanup ( ) ;
391
+ setDimensions ( ) ;
392
+ } ;
393
+ img . addEventListener ( 'load' , handleLoad ) ;
394
+ img . addEventListener ( 'error' , handleError ) ;
395
+ }
396
+ } ) ;
397
+ } )
398
+ ) ;
399
+ return true ;
400
+ } ) ;
401
+ }
402
+
403
+ /**
404
+ * Restore images to their original size.
405
+ */
406
+ async function restoreImageSizes ( page : Page ) {
407
+ await page . evaluate ( ( ) => {
408
+ const images = Array . from ( document . querySelectorAll ( 'img[data-stabilized]' ) ) ;
409
+ images . forEach ( ( img ) => {
410
+ if ( img instanceof HTMLImageElement ) {
411
+ img . style . width = img . dataset . originalWidth ?? '' ;
412
+ img . style . height = img . dataset . originalHeight ?? '' ;
413
+ delete img . dataset . originalWidth ;
414
+ delete img . dataset . originalHeight ;
415
+ delete img . dataset . stabilized ;
416
+ }
417
+ } ) ;
418
+ } ) ;
419
+ }
420
+
351
421
/**
352
422
* Wait for TOC to be correctly scrolled into view.
353
423
*/
0 commit comments