|
| 1 | +# Accessibility Testing |
| 2 | + |
| 3 | +Automated accessibility checks using [Playwright](https://playwright.dev/) and |
| 4 | +[axe-core](https://github.com/dequelabs/axe-core) via |
| 5 | +[@axe-core/playwright](https://www.npmjs.com/package/@axe-core/playwright). |
| 6 | + |
| 7 | +## Compliance Target |
| 8 | + |
| 9 | +Our goal is [Section 508](https://www.section508.gov/) compliance. The revised Section 508 |
| 10 | +standard (2017) incorporates [WCAG 2.0 Level AA](https://www.w3.org/TR/WCAG20/) by reference, |
| 11 | +so meeting WCAG 2.0 AA satisfies 508 requirements. Our tests use axe's `wcag2a`, `wcag2aa`, |
| 12 | +`wcag21a`, and `wcag21aa` tag set, covering WCAG 2.0 and 2.1 at Levels A and AA. |
| 13 | + |
| 14 | +## Usage |
| 15 | + |
| 16 | +### Single page (against a running dev server) |
| 17 | + |
| 18 | +```sh |
| 19 | +npm run a11y:page -w @bdc/site -- http://localhost:4321/resources/faqs |
| 20 | +``` |
| 21 | + |
| 22 | +Multiple URLs can be passed: |
| 23 | + |
| 24 | +```sh |
| 25 | +npm run a11y:page -w @bdc/site -- http://localhost:4321/about http://localhost:4321/resources/costs |
| 26 | +``` |
| 27 | + |
| 28 | +### Smoke test (builds, then tests key pages) |
| 29 | + |
| 30 | +```sh |
| 31 | +npm run a11y:smoke -w @bdc/site |
| 32 | +``` |
| 33 | + |
| 34 | +### Full site (builds, then tests every page in the sitemap) |
| 35 | + |
| 36 | +```sh |
| 37 | +npm run a11y:full -w @bdc/site |
| 38 | +``` |
| 39 | + |
| 40 | +## Shared Configuration |
| 41 | + |
| 42 | +All tests use the fixture in `axe-test.ts`, which configures axe-core with: |
| 43 | + |
| 44 | +- **WCAG tags**: `wcag2a`, `wcag2aa`, `wcag21a`, `wcag21aa` |
| 45 | +- **Disabled rules**: `frame-tested` (axe cannot inject into cross-origin iframes like YouTube embeds) |
| 46 | + |
| 47 | +The Playwright config (`../playwright.config.ts`) includes a `webServer` entry that starts |
| 48 | +`astro preview` on port 4321. With `reuseExistingServer: true`, it reuses an already-running |
| 49 | +server (e.g., `astro dev`) when available. |
| 50 | + |
| 51 | +## Adding Exceptions |
| 52 | + |
| 53 | +If a specific element triggers a false positive, you can exclude it per-test: |
| 54 | + |
| 55 | +```ts |
| 56 | +const results = await makeAxeBuilder() |
| 57 | + .exclude('.some-selector') // exclude from all rules |
| 58 | + .analyze(); |
| 59 | +``` |
| 60 | + |
| 61 | +Or disable a specific rule: |
| 62 | + |
| 63 | +```ts |
| 64 | +const results = await makeAxeBuilder() |
| 65 | + .disableRules(['color-contrast']) |
| 66 | + .analyze(); |
| 67 | +``` |
| 68 | + |
| 69 | +See the [Playwright accessibility testing docs](https://playwright.dev/docs/accessibility-testing) |
| 70 | +for more options including `include()`, `withRules()`, and snapshot-based approaches. |
0 commit comments