[READ-ONLY] a fast, modern browser for the npm registry
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

ci: pool a11y tests until failure is detected (#833)

authored by

Wojciech Maj and committed by
GitHub
6ef447b0 3114183f

+66 -16
+66 -16
test/nuxt/a11y.spec.ts
··· 13 13 // Track mounted containers for cleanup 14 14 const mountedContainers: HTMLElement[] = [] 15 15 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 + 16 32 /** 17 33 * Run axe accessibility audit on a mounted component. 18 34 * Mounts the component in an isolated container to avoid cross-test pollution. ··· 29 45 container.appendChild(el) 30 46 31 47 // 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) 45 49 } 46 50 47 51 // Clean up mounted containers after each test ··· 2117 2121 }, 2118 2122 ] 2119 2123 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 + 2120 2162 for (const { name, mount } of components) { 2121 2163 describe(`${name} colors`, () => { 2122 2164 for (const [colorMode, bgTheme] of pairs) { 2123 2165 it(`${colorMode}/${bgTheme}`, async () => { 2124 2166 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 + } 2128 2178 }) 2129 2179 } 2130 2180 })