Scans five pages with axe-core (shipped with the hub, runs offline) and fails on the critical and serious WCAG 2.1 AA problems, grouped by rule. The full report is saved as a11y-report.html with the run.
508accessibilitydemofreight version: 1.0 DEMO-022__freight_accessibility.py group: Freight extras
Runs
6
Pass rate
67%
4 passed / 2 failed
Avg duration
6s
p95 7s
Estimate
6s
avg of last 10 judged runs
Flakiness
0.40
0 stable · 1 alternates
Current streak
2
passed
Duration per run point color = outcome; dashed = 7-run average; click a point to open the run
Step timing trends the same step compared across the last 6 runs — slowest steps first, one line each
How long it takes distribution of 6 runs — two humps mean two different behaviours hiding behind one average
fastest 6s · slowest 7s
Why this test failed grouped by message, last 90 days
| times | message | last | |
|---|---|---|---|
| 2 | AssertionError: WCAG 2.1 AA: 4 rule(s) broken (details: a11y-report.h… | Sep 24 | open |
Outcomes by target version
What this test does plain language, derived from the code
- site = Freight(page, ctx)
- audit = Audit(page, ctx)
- for label, path in PAGES:
- with ctx.timed(f"scan: {label}"):
- site.open(path)
- page.wait_for_load_state("networkidle")
- audit.scan(label)
- site.sign_in()
- ⏱ Timed phase: scan: staff dashboard
- site.open("ops/")
- page.wait_for_load_state("networkidle")
- audit.scan("staff dashboard")
- report = audit.save_report()
- ctx.log(f"report saved: {report.name}")
- audit.assert_clean()
Show the code
"""Accessibility (WCAG 2.1 AA -- what Section 508 points to), on every release.
Scans the pages most visitors use with axe-core, the engine behind most
commercial accessibility scanners, shipped in _lib/axe/ so it runs offline.
Fails on the problems a screen-reader or keyboard user actually runs into
(axe's "critical" and "serious"), grouped by rule with the pages they are on;
the full report -- every element, the HTML it quotes, how to fix it -- is
saved as a11y-report.html with the run's files.
Acme Freight 2.0.0's redesign breaks four rules at once (the page language,
a skip link hidden from screen readers, the map's text alternative, brand
colours with too little contrast). A visual check sees none of them: the
pages look fine. That is the point of running both.
"""
from _lib.a11y import Audit
from _lib.freight import Freight
PAGES = [("home page", ""), ("tracking", "track/?id=AF-100001"),
("quote, step 1", "quote/?restart=1"), ("staff sign-in", "login/")]
def run(page, ctx):
site = Freight(page, ctx)
audit = Audit(page, ctx)
for label, path in PAGES:
with ctx.timed(f"scan: {label}"):
site.open(path)
page.wait_for_load_state("networkidle")
audit.scan(label)
site.sign_in()
with ctx.timed("scan: staff dashboard"):
site.open("ops/")
page.wait_for_load_state("networkidle")
audit.scan("staff dashboard")
report = audit.save_report()
ctx.log(f"report saved: {report.name}")
audit.assert_clean()
All runs
| Run | Status | Queued | Duration | Version | Trigger | Batch |
|---|---|---|---|---|---|---|
| #362 | passed | 2026-09-24 22:05:07 | 6s | 3.0.0 | group | group: Freight extras |
| #347 | passed | 2026-09-24 20:41:19 | 6s | 3.0.0 | cli-adopted | 3 tests (terminal) |
| #344 | failed | 2026-09-24 20:41:04 | 7s | 2.1.0 | cli-adopted | 3 tests (terminal) |
| #341 | failed | 2026-09-24 20:40:49 | 6s | 2.0.0 | cli-adopted | 3 tests (terminal) |
| #338 | passed | 2026-09-24 20:40:35 | 6s | 1.1.0 | cli-adopted | 3 tests (terminal) |
| #335 | passed | 2026-09-24 20:40:21 | 7s | 1.0.0 | cli-adopted | 3 tests (terminal) |