@@ -316,30 +316,73 @@ test('small-and-fast', async ({ page }) => {
316
316
} ) ;
317
317
318
318
test ( 'dark mode' , async ( { page } ) => {
319
+ // Helper: returns relative luminance in range [0, 1]
320
+ const getPageBrightness = async ( ) => {
321
+ const screenshot = await page . screenshot ( { type : 'png' } ) ;
322
+ const base64 = screenshot . toString ( 'base64' ) ;
323
+
324
+ return await page . evaluate ( ( b64 ) => {
325
+ return new Promise ( ( resolve ) => {
326
+ const img = new Image ( ) ;
327
+ img . src = `data:image/png;base64,${ b64 } ` ;
328
+ img . onload = ( ) => {
329
+ const canvas = document . createElement ( 'canvas' ) ;
330
+ canvas . width = canvas . height = 1 ;
331
+ const ctx = canvas . getContext ( '2d' ) ;
332
+ ctx . drawImage ( img , 0 , 0 , 1 , 1 ) ;
333
+ const [ r , g , b ] = ctx . getImageData ( 0 , 0 , 1 , 1 ) . data ;
334
+
335
+ // Calculate brightness, for more details, see
336
+ // https://en.wikipedia.org/wiki/Relative_luminance#Relative_luminance_and_%22gamma_encoded%22_colorspaces
337
+ const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b ;
338
+
339
+ // Normalize to [0, 1]
340
+ resolve ( luminance / 255 ) ;
341
+ } ;
342
+ img . onerror = ( ) => resolve ( - 1 ) ; // error indicator
343
+ } ) ;
344
+ } , base64 ) ;
345
+ } ;
346
+
319
347
await page . setViewportSize ( devices [ 'iPhone X' ] . viewport ) ;
348
+ await page . goto ( url ) ;
320
349
321
- await page . goto ( ` ${ url } ` ) ;
350
+ // Ensure consistent test state
322
351
await page . evaluate ( ( ) => {
323
352
document . querySelector ( '#tagline' ) . innerHTML = '--dark-mode-for-dark-times' ;
324
353
} ) ;
354
+
325
355
const darkModeButton = page . locator ( '#dark-mode-button' ) ;
326
356
327
- const o = { maxDiffPixels : 30 } ;
328
- await expect ( page ) . toHaveScreenshot ( { name : 'light-mode.png' , ...o } ) ;
357
+ // 1. Light mode
358
+ const lightBrightness = await getPageBrightness ( ) ;
359
+ expect ( lightBrightness ) . toBeCloseTo ( 0.85 , 0.1 ) ; // e.g., 0.75–0.95
360
+
361
+ // 2. Toggle to dark mode
329
362
await darkModeButton . click ( ) ;
330
- await expect ( page ) . toHaveScreenshot ( { name : 'dark-mode.png' , ...o } ) ;
363
+ const darkBrightness = await getPageBrightness ( ) ;
364
+ expect ( darkBrightness ) . toBeCloseTo ( 0.25 , 0.1 ) ; // e.g., 0.15–0.35
331
365
332
- // Now, try again, but this time with system's preference being dark mode
366
+ // 3. Verify dark < light
367
+ expect ( darkBrightness ) . toBeLessThan ( lightBrightness ) ;
333
368
369
+ // --- Test system preference: prefers-color-scheme: dark ---
334
370
await page . emulateMedia ( { colorScheme : 'dark' } ) ;
335
- await page . evaluate ( ( ) => window . localStorage . clear ( ) ) ;
336
- await page . evaluate ( ( ) => window . sessionStorage . clear ( ) ) ;
371
+ await page . evaluate ( ( ) => {
372
+ localStorage . clear ( ) ;
373
+ sessionStorage . clear ( ) ;
374
+ } ) ;
337
375
await page . reload ( ) ;
338
376
await page . evaluate ( ( ) => {
339
377
document . querySelector ( '#tagline' ) . innerHTML = '--dark-mode-for-dark-times' ;
340
378
} ) ;
341
379
342
- await expect ( page ) . toHaveScreenshot ( { name : 'dark-mode.png' , ...o } ) ;
380
+ // Should start in dark mode
381
+ const autoDarkBrightness = await getPageBrightness ( ) ;
382
+ expect ( autoDarkBrightness ) . toBeCloseTo ( 0.25 , 0.1 ) ;
383
+
384
+ // Toggle to light
343
385
await darkModeButton . click ( ) ;
344
- await expect ( page ) . toHaveScreenshot ( { name : 'light-mode.png' , ...o } ) ;
345
- } )
386
+ const autoLightBrightness = await getPageBrightness ( ) ;
387
+ expect ( autoLightBrightness ) . toBeCloseTo ( 0.85 , 0.1 ) ;
388
+ } ) ;
0 commit comments