@@ -13,6 +13,22 @@ declare const axe: {
1313// Track mounted containers for cleanup
1414const mountedContainers : HTMLElement [ ] = [ ]
1515
16+ const axeRunOptions : RunOptions = {
17+ // Only compute violations to reduce work per run
18+ resultTypes : [ 'violations' ] ,
19+ // Disable rules that don't apply to isolated component testing
20+ rules : {
21+ // These rules check page-level concerns that don't apply to isolated components
22+ 'landmark-one-main' : { enabled : false } ,
23+ 'region' : { enabled : false } ,
24+ 'page-has-heading-one' : { enabled : false } ,
25+ // Duplicate landmarks are expected when testing multiple header/footer components
26+ 'landmark-no-duplicate-banner' : { enabled : false } ,
27+ 'landmark-no-duplicate-contentinfo' : { enabled : false } ,
28+ 'landmark-no-duplicate-main' : { enabled : false } ,
29+ } ,
30+ }
31+
1632/**
1733 * Run axe accessibility audit on a mounted component.
1834 * Mounts the component in an isolated container to avoid cross-test pollution.
@@ -29,19 +45,7 @@ async function runAxe(wrapper: VueWrapper): Promise<AxeResults> {
2945 container . appendChild ( el )
3046
3147 // Run axe only on the isolated container
32- return axe . run ( container , {
33- // Disable rules that don't apply to isolated component testing
34- rules : {
35- // These rules check page-level concerns that don't apply to isolated components
36- 'landmark-one-main' : { enabled : false } ,
37- 'region' : { enabled : false } ,
38- 'page-has-heading-one' : { enabled : false } ,
39- // Duplicate landmarks are expected when testing multiple header/footer components
40- 'landmark-no-duplicate-banner' : { enabled : false } ,
41- 'landmark-no-duplicate-contentinfo' : { enabled : false } ,
42- 'landmark-no-duplicate-main' : { enabled : false } ,
43- } ,
44- } )
48+ return axe . run ( container , axeRunOptions )
4549}
4650
4751// Clean up mounted containers after each test
@@ -2117,14 +2121,60 @@ describe('background theme accessibility', () => {
21172121 } ,
21182122 ]
21192123
2124+ /**
2125+ * For performance, we pool axe runs for each theme combination, optimistically assuming no
2126+ * violations will occur. If violations are found in the pooled run, we re-run axe on individual
2127+ * components for precise results.
2128+ */
2129+ const pooledResults = new Map < string , Promise < AxeResults > > ( )
2130+
2131+ function getPooledResults ( colorMode : string , bgTheme : string ) {
2132+ const key = `${ colorMode } :${ bgTheme } `
2133+ const cached = pooledResults . get ( key )
2134+ if ( cached ) return cached
2135+
2136+ const promise = ( async ( ) => {
2137+ const wrappers = await Promise . all ( components . map ( ( { mount } ) => mount ( ) ) )
2138+ const poolContainer = document . createElement ( 'div' )
2139+ poolContainer . id = `a11y-theme-pool-${ colorMode } -${ bgTheme } `
2140+ document . body . appendChild ( poolContainer )
2141+ mountedContainers . push ( poolContainer )
2142+
2143+ try {
2144+ for ( const wrapper of wrappers ) {
2145+ const el = wrapper . element . cloneNode ( true ) as HTMLElement
2146+ poolContainer . appendChild ( el )
2147+ }
2148+
2149+ await nextTick ( )
2150+ return await axe . run ( poolContainer , axeRunOptions )
2151+ } finally {
2152+ for ( const wrapper of wrappers ) {
2153+ wrapper . unmount ( )
2154+ }
2155+ }
2156+ } ) ( )
2157+
2158+ pooledResults . set ( key , promise )
2159+ return promise
2160+ }
2161+
21202162 for ( const { name, mount } of components ) {
21212163 describe ( `${ name } colors` , ( ) => {
21222164 for ( const [ colorMode , bgTheme ] of pairs ) {
21232165 it ( `${ colorMode } /${ bgTheme } ` , async ( ) => {
21242166 applyTheme ( colorMode , bgTheme )
2125- const results = await runAxe ( await mount ( ) )
2126- await nextTick ( )
2127- expect ( results . violations ) . toEqual ( [ ] )
2167+
2168+ const pooled = await getPooledResults ( colorMode , bgTheme )
2169+ if ( pooled . violations . length === 0 ) return
2170+
2171+ const wrapper = await mount ( )
2172+ try {
2173+ const results = await runAxe ( wrapper )
2174+ expect ( results . violations ) . toEqual ( [ ] )
2175+ } finally {
2176+ wrapper . unmount ( )
2177+ }
21282178 } )
21292179 }
21302180 } )
0 commit comments