Skip to content

Commit e1f0615

Browse files
committed
Add example of Pa11y in GitLab CI
1 parent 59f35bc commit e1f0615

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed

docs/guides/automated-tests.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,118 @@ Try this out by saving the file as `pa11y.config.js`, then:
9393
npm install -g pa11y-ci
9494
pa11y-ci --config pa11y.config.js
9595
```
96+
97+
### Accessibility testing in GitLab CI
98+
99+
Here is a practical example of combining [Pa11y](https://pa11y.org/) and django-pattern-library in GitLab CI to run automated accessibility tests. This three-stage build first compiles a project’s static assets (CSS, JS), then generates pattern library static files with Django (with the [`render_patterns` command](../reference/api.md#render_patterns) command can be), and finally tests those static pages with Pa11y.
100+
101+
```yaml
102+
static:
103+
image: node:16
104+
stage: build
105+
script:
106+
- npm ci
107+
- npm run build:prod
108+
artifacts:
109+
name: "static-$CI_JOB_ID"
110+
paths:
111+
- ./demosite/static_compiled
112+
expire_in: 30 mins
113+
114+
test_python:
115+
image: python:3.9
116+
stage: test
117+
dependencies:
118+
- static
119+
services:
120+
- postgres:12.3
121+
variables:
122+
DJANGO_SETTINGS_MODULE: demosite.settings.production
123+
GIT_STRATEGY: none
124+
script:
125+
- pip install poetry==1.1.8
126+
- poetry install
127+
128+
- python manage.py collectstatic --verbosity 0 --noinput --clear
129+
130+
# Render all django-pattern-library patterns, saving a list of the rendered files.
131+
- python manage.py render_patterns --wrap-fragment 2>&1 >/dev/null | tee dpl-list.txt
132+
- mv dpl-list.txt dpl-rendered-patterns && cp -R static dpl-rendered-patterns/static && mv dpl-rendered-patterns ../dpl-rendered-patterns
133+
artifacts:
134+
name: "test_patterns-$CI_JOB_ID"
135+
paths:
136+
- ./dpl-rendered-patterns
137+
expire_in: 30 mins
138+
139+
pa11y:
140+
image: registry.gitlab.com/gitlab-org/ci-cd/accessibility:6.1.1
141+
stage: accessibility
142+
dependencies:
143+
- test_python
144+
variables:
145+
TEST_ORIGIN: http://localhost:4000
146+
script:
147+
# Serve files locally, in the background, waiting for the server to start before we run the test suite.
148+
- npm install -g http-server@14
149+
- http-server ./dpl-rendered-patterns --port 4000 &
150+
- pa11y-ci -j --config pa11y.config.js > dpl-rendered-patterns/gl-accessibility.json
151+
artifacts:
152+
# Create artifacts even if the tests fail.
153+
when: always
154+
expire_in: 1 week
155+
paths:
156+
- dpl-rendered-patterns
157+
reports:
158+
accessibility: dpl-rendered-patterns/gl-accessibility.json
159+
```
160+
161+
Here is the `pa11y.config.js`, which will determine what to test based on the output of `render_patterns`, as listed in the `dpl-list.txt` file:
162+
163+
```js
164+
const path = require("path");
165+
const fs = require("fs");
166+
167+
const defaults = {
168+
chromeLaunchConfig: {
169+
// Needed to run Pa11y in GitLab CI.
170+
args: ["--no-sandbox"],
171+
},
172+
standard: "WCAG2AA",
173+
runners: ["axe"],
174+
};
175+
176+
// Assume we run tests over a live django-pattern-library instance, unless TEST_ORIGIN is set;
177+
const local = "http://localhost:8000/pattern-library/render-pattern/patterns";
178+
const origin = process.env.TEST_ORIGIN || local;
179+
180+
let urls = [];
181+
182+
// In CI mode, retrieve the URLs to test from dpl-rendered-patterns.
183+
if (process.env.CI) {
184+
const list = path.join(__dirname, "dpl-rendered-patterns", "dpl-list.txt");
185+
const patterns = fs.readFileSync(list, "utf-8").split("\n").filter((p) => p);
186+
187+
urls = patterns.map((p) => `${origin}/${p.replace("patterns/", "")}`);
188+
}
189+
190+
// Convert the list of URLs to configuration objects.
191+
urls = [...new Set(urls)].map((url) => {
192+
const config = {
193+
url,
194+
screenCapture: `dpl-rendered-patterns/${url.replace(origin, "")}.png`,
195+
};
196+
197+
if (url.endsWith("tab-nav-item.html")) {
198+
config.ignore = [...defaults.ignore, "aria-required-parent"];
199+
}
200+
201+
return config;
202+
});
203+
204+
console.log(`Initialising pa11y-ci on ${urls.length} URLs`);
205+
206+
module.exports = {
207+
defaults,
208+
urls,
209+
};
210+
```

0 commit comments

Comments
 (0)