fix(a11y): AudioPlayer WCAG AA + jest-axe audit infra #56

Open
KnallerKalle wants to merge 5 commits from feat/a11y-audit-lesson-player into dev
KnallerKalle commented 2026-08-12 17:19:39 +00:00 (Migrated from github.com)

Plan

Establish automated accessibility testing infrastructure (jest-axe) and fix all WCAG AA violations in the lesson AudioPlayer — the primary surface a user operates during an ATM lesson. First half of the Release Hardening "Accessibility audit pass" roadmap item.

Outcome

  • New devDependency: jest-axe (axe-core wrapper for Vitest).
  • New test suite: src/components/__tests__/AudioPlayer.a11y.test.tsx — 7 assertions covering axe violations, accessible names, seek-bar semantics, status announcements, focus indicators, keyboard reachability, and Feldenkrais-principle (no judgement/strain language).
  • Fixed in AudioPlayer.tsx (3 concrete violations):
    1. Seek range unnamed (WCAG 4.1.2 Name, Role, Value) → added aria-label ("Seek through lesson audio") + aria-valuetext announcing elapsed/total time.
    2. No play/pause status announcement (WCAG 4.1.3 Status Messages) → added a visually-hidden aria-live="polite" region announcing Loading/Playing/Paused without stealing focus.
    3. No visible keyboard focus indicators (WCAG 2.4.7 Focus Visible) → added focus-visible:outline Tailwind utilities to all 10 interactive controls (seek, volume, skip-back, play/pause, mute, speed, loop, rest, reset).
  • Purely semantic/presentational; no behaviour change.

Impact on release goals

Release Hardening → "Accessibility audit pass" moves [ ] → [~]. jest-axe infrastructure is now in place; AudioPlayer (the highest-value interactive surface) is fully audited and clean. Remaining components can be audited incrementally with the same pattern. Feldenkrais is inclusive by nature — the player is now operable by every body, including keyboard-only and screen-reader users, directly de-risking the D1→D7 retention window.

Blackbox

  • python3 scripts/blackbox_test.py --target testing → 11/12 green (the 1 failure, /api/lessons empty list, is pre-existing — no lesson content loaded on testing yet; unrelated to this client-side change)
  • Unit suite 87/87 green across 13 files (was 80/80; +7 new a11y tests)
  • axe reports zero violations on the rendered AudioPlayer

Six-perspectives check

  • Product: accessible player widens the addressable audience; no dark patterns.
  • Engineering: minimal diff (semantic attributes + focus-visible utilities); tests written first (red→green); no security hole.
  • Psychology: autonomy-supportive — keyboard/screen-reader users are not gated; non-evaluative language preserved.
  • Biomechanics: n/a (no movement cues changed).
  • Anatomy: n/a.
  • Feldenkrais: inclusive by nature — verified no correction/judgement/strain language introduced.

Risk

Minimal. Additive aria-* attributes + focus-visible:outline Tailwind utilities only; no audio/transport logic touched. The sr-only class is the same built-in Tailwind utility already used in layout.tsx (skip-link). The axe "preload assets" stderr in jsdom is benign (axe still runs and reports no violations; the test passes).

Checklist

  • Branch off latest dev
  • Conventional Commits (test/fix/docs)
  • Patchlog entry appended
  • Roadmap status updated
  • No secrets / no large binaries

This PR was created by an AI agent (OpenHands) on behalf of the ATM release owner.

## Plan Establish automated accessibility testing infrastructure (jest-axe) and fix all WCAG AA violations in the lesson `AudioPlayer` — the primary surface a user operates during an ATM lesson. First half of the Release Hardening "Accessibility audit pass" roadmap item. ## Outcome - **New devDependency:** `jest-axe` (axe-core wrapper for Vitest). - **New test suite:** `src/components/__tests__/AudioPlayer.a11y.test.tsx` — 7 assertions covering axe violations, accessible names, seek-bar semantics, status announcements, focus indicators, keyboard reachability, and Feldenkrais-principle (no judgement/strain language). - **Fixed in `AudioPlayer.tsx`** (3 concrete violations): 1. **Seek range unnamed** (WCAG 4.1.2 Name, Role, Value) → added `aria-label` ("Seek through lesson audio") + `aria-valuetext` announcing elapsed/total time. 2. **No play/pause status announcement** (WCAG 4.1.3 Status Messages) → added a visually-hidden `aria-live="polite"` region announcing Loading/Playing/Paused without stealing focus. 3. **No visible keyboard focus indicators** (WCAG 2.4.7 Focus Visible) → added `focus-visible:outline` Tailwind utilities to all 10 interactive controls (seek, volume, skip-back, play/pause, mute, speed, loop, rest, reset). - Purely semantic/presentational; **no behaviour change**. ## Impact on release goals Release Hardening → **"Accessibility audit pass" moves `[ ]` → `[~]`**. jest-axe infrastructure is now in place; AudioPlayer (the highest-value interactive surface) is fully audited and clean. Remaining components can be audited incrementally with the same pattern. Feldenkrais is inclusive by nature — the player is now operable by every body, including keyboard-only and screen-reader users, directly de-risking the D1→D7 retention window. ## Blackbox - [x] `python3 scripts/blackbox_test.py --target testing` → **11/12 green** (the 1 failure, `/api/lessons` empty list, is pre-existing — no lesson content loaded on testing yet; unrelated to this client-side change) - [x] **Unit suite 87/87 green** across 13 files (was 80/80; +7 new a11y tests) - [x] **axe reports zero violations** on the rendered AudioPlayer ## Six-perspectives check - [x] **Product:** accessible player widens the addressable audience; no dark patterns. - [x] **Engineering:** minimal diff (semantic attributes + focus-visible utilities); tests written first (red→green); no security hole. - [x] **Psychology:** autonomy-supportive — keyboard/screen-reader users are not gated; non-evaluative language preserved. - [x] **Biomechanics:** n/a (no movement cues changed). - [x] **Anatomy:** n/a. - [x] **Feldenkrais:** inclusive by nature — verified no correction/judgement/strain language introduced. ## Risk Minimal. Additive `aria-*` attributes + `focus-visible:outline` Tailwind utilities only; no audio/transport logic touched. The `sr-only` class is the same built-in Tailwind utility already used in `layout.tsx` (skip-link). The axe "preload assets" stderr in jsdom is benign (axe still runs and reports no violations; the test passes). ## Checklist - [x] Branch off latest `dev` - [x] Conventional Commits (test/fix/docs) - [x] Patchlog entry appended - [x] Roadmap status updated - [x] No secrets / no large binaries --- _This PR was created by an AI agent (OpenHands) on behalf of the ATM release owner._
KnallerKalle commented 2026-08-12 17:37:14 +00:00 (Migrated from github.com)

Watcher status (2026-08-12) — confirming this PR is the canonical Accessibility-audit deliverable.

I ran the a11y iteration this session and independently built a local a11y-audit branch (jest-axe harness + seek-slider aria-label), then discovered this PR already covers the same deliverable more comprehensively (7 tests + 3 fixes). Per the no-duplicate-PR rule I did not open a competing PR.

CI status at time of this check:

  • ✅ Unit tests (vitest): pass (1m9s) — the gate for this deliverable.
  • ⏳ Frontend + Tauri build: pending (~10–15 min; within expected range, not a failure).

Once the Tauri build goes green, this PR is merge-ready and closes the Release Hardening → "Accessibility audit pass" item ([ ]→[x]). No blocker from my side.

(Logged to .development/automation-state.json snapshot #39, in PR #57.)

Posted by an AI agent (OpenHands) on behalf of the ATM release owner.

**Watcher status (2026-08-12) — confirming this PR is the canonical Accessibility-audit deliverable.** I ran the a11y iteration this session and independently built a local a11y-audit branch (jest-axe harness + seek-slider `aria-label`), then discovered this PR already covers the same deliverable **more** comprehensively (7 tests + 3 fixes). Per the no-duplicate-PR rule I did **not** open a competing PR. CI status at time of this check: - ✅ **Unit tests (vitest): pass (1m9s)** — the gate for this deliverable. - ⏳ **Frontend + Tauri build: pending** (~10–15 min; within expected range, not a failure). Once the Tauri build goes green, this PR is merge-ready and closes the **Release Hardening → "Accessibility audit pass"** item (`[ ]`→`[x]`). No blocker from my side. (Logged to `.development/automation-state.json` snapshot #39, in PR #57.) _Posted by an AI agent (OpenHands) on behalf of the ATM release owner._
This pull request has changes conflicting with the target branch.
  • .development/automation-state.json
  • .development/patchlog.md
  • .development/roadmap.md
  • src/components/AudioPlayer.tsx
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/a11y-audit-lesson-player:feat/a11y-audit-lesson-player
git switch feat/a11y-audit-lesson-player

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch dev
git merge --no-ff feat/a11y-audit-lesson-player
git switch feat/a11y-audit-lesson-player
git rebase dev
git switch dev
git merge --ff-only feat/a11y-audit-lesson-player
git switch feat/a11y-audit-lesson-player
git rebase dev
git switch dev
git merge --no-ff feat/a11y-audit-lesson-player
git switch dev
git merge --squash feat/a11y-audit-lesson-player
git switch dev
git merge --ff-only feat/a11y-audit-lesson-player
git switch dev
git merge feat/a11y-audit-lesson-player
git push origin dev
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Kalle/ATM!56
No description provided.