@@ -273,6 +273,57 @@ const assertTopologyReadout = async (page, expected) => {
273273 ) ;
274274} ;
275275
276+ const parseRgbColor = ( value ) => {
277+ const channels = value . match ( / [ \d . ] + / g) ?. slice ( 0 , 3 ) . map ( Number ) ;
278+ assert . equal ( channels ?. length , 3 , `Expected an RGB color, got "${ value } ".` ) ;
279+ return channels ;
280+ } ;
281+
282+ const relativeLuminance = ( channels ) =>
283+ channels
284+ . map ( ( channel ) => channel / 255 )
285+ . map ( ( channel ) => ( channel <= 0.04045 ? channel / 12.92 : ( ( channel + 0.055 ) / 1.055 ) ** 2.4 ) )
286+ . reduce (
287+ ( luminance , channel , index ) => luminance + channel * [ 0.2126 , 0.7152 , 0.0722 ] [ index ] ,
288+ 0
289+ ) ;
290+
291+ const contrastRatio = ( foreground , background ) => {
292+ const lighter = Math . max ( relativeLuminance ( foreground ) , relativeLuminance ( background ) ) ;
293+ const darker = Math . min ( relativeLuminance ( foreground ) , relativeLuminance ( background ) ) ;
294+ return ( lighter + 0.05 ) / ( darker + 0.05 ) ;
295+ } ;
296+
297+ const verifyCodeBlockContrast = async ( page , baseUrl ) => {
298+ await page . setViewportSize ( { width : 1440 , height : 900 } ) ;
299+ await page . goto ( `${ baseUrl } ?ecosystem=all-three&mode=light` , {
300+ waitUntil : "domcontentloaded"
301+ } ) ;
302+ await page . waitForFunction ( ( ) => document . body . dataset . demoReady === "true" ) ;
303+
304+ for ( const mode of [ "light" , "dark" , "contrast" ] ) {
305+ await setControl ( page , "modeSelect" , mode ) ;
306+ const blocks = await page . locator ( ".demo-code-card pre" ) . evaluateAll ( ( preElements ) =>
307+ preElements . map ( ( preElement ) => {
308+ const codeElement = preElement . querySelector ( "code" ) ;
309+ return {
310+ background : getComputedStyle ( preElement ) . backgroundColor ,
311+ color : getComputedStyle ( codeElement ) . color
312+ } ;
313+ } )
314+ ) ;
315+
316+ assert . equal ( blocks . length , 2 , `${ mode } : expected both copy-ready code blocks.` ) ;
317+ for ( const [ index , block ] of blocks . entries ( ) ) {
318+ const ratio = contrastRatio ( parseRgbColor ( block . color ) , parseRgbColor ( block . background ) ) ;
319+ assert (
320+ ratio >= 4.5 ,
321+ `${ mode } code block ${ index + 1 } has ${ ratio . toFixed ( 2 ) } :1 contrast; expected at least 4.5:1.`
322+ ) ;
323+ }
324+ }
325+ } ;
326+
276327const layoutSnapshot = async ( page ) =>
277328 page . evaluate ( ( ) => {
278329 const documentElement = document . documentElement ;
@@ -953,6 +1004,7 @@ try {
9531004 await verifyBreakoutGeometry ( page , server . baseUrl ) ;
9541005 await verifyProfileAndUtilityIsolation ( page , server . baseUrl ) ;
9551006 await verifyPrimitiveOverflow ( page , server . baseUrl ) ;
1007+ await verifyCodeBlockContrast ( page , server . baseUrl ) ;
9561008 await verifyInteractions ( page , server . baseUrl ) ;
9571009
9581010 assert . deepEqual ( pageErrors , [ ] , `Page errors:\n${ pageErrors . join ( "\n" ) } ` ) ;
0 commit comments