Skip to content

Making Sure the App Works for Everyone (Accessibility Verification)

WorkWingman checks its key app flows and routes for common accessibility failures for people using screen readers (software that reads the page aloud) and keyboard-only navigation. We run four kinds of checks, from automatic tests to a human listening to the whole app. (Automated tools can't prove everything is accessible — they catch the common, machine-checkable problems, which is why the human check at the end still matters.)

Why Accessibility Matters

One in four adults in the US has some kind of disability. Screen readers let blind and low-vision users navigate by hearing the page read aloud. Keyboard-only navigation helps people who can't use a mouse (due to injury, tremor, or repetitive strain). Accessible apps work for everyone—and they're also simpler, more robust, and legally required in many contexts.

The Four Checks

1. Automatic Rule Check (Fastest, Most Thorough)

What we do: We load every page in the app and run a robot that checks for common accessibility mistakes (like missing labels on form fields, or text that's too faint to read).

What it catches: 22 pages, hundreds of potential problems checked in seconds. Think of it like a spell-checker for accessibility.

When it runs: Every time someone pushes code (GitHub Actions, the cloud build system). Takes about 5 minutes.

What it misses: A screen-reader user might say, "That button label doesn't make sense," but the robot can only check that there is a label.

How to run it yourself:

npm run test:a11y


2. Real Data + Keyboard Test (Local, More Real)

What we do: We run the same robot check again, but this time with real job data from your machine. We also test that the keyboard works: pressing Tab lands on the skip-to-main-content link, pressing Escape closes dialogs correctly, and arrow keys move focus between tabs.

What it catches: Everything in check #1, plus problems that only show up when there's real data (e.g., a custom job title that's unexpectedly long and creates a contrast problem). Also verifies that keyboard shortcuts work as expected.

When it runs: Locally only, on your machine. Never in GitHub because it could read your real job data and upload it.

What it misses: The app is browsed with a mouse and keyboard, but not with a real screen reader. We don't know yet if a screen reader actually says the right thing.

How to run it:

npm run test:a11y:live

Needs the WorkWingman app to be running in the background (or this test will start it automatically). Reads your token from the app's local token file.


3. Real Screen Reader (Real NVDA, Spoken Output)

What we do: We launch the real NVDA screen reader (Windows only) and have it navigate the app the same way a blind person would: tabbing to the first interactive element, pressing arrow keys to move through navigation, etc. We listen to what NVDA speaks out loud and check that the app announces the right things.

What it catches: Things the robot and keyboard tests can't: Is the skip-to-content link actually announced on the first Tab? When a form field gets focus, does NVDA say "Email, edit text" or just "edit text"? When a dialog opens, does NVDA announce what it is?

When it runs: Locally only, on a real desktop (not over Remote Desktop, which doesn't work with screen readers). You need to run it manually—it takes your keyboard and mouse for 3 minutes, so we don't run it in the cloud.

One-time setup (do this once per machine):

npx @guidepup/setup
This downloads a private version of NVDA that Playwright can control. No admin needed.

How to run it:

npm run test:a11y:sr
Then leave the machine alone for 3 minutes while NVDA speaks aloud and navigates the app.

What it misses: Only one person (the automation) is listening. A human might notice that something sounds weird but isn't technically broken. It also only checks what NVDA decides to say — not whether that sound actually reaches your speakers (see 3b).


3b. Audible-Path Check (Bonus — Does the Sound Actually Come Out?)

What we do: Check #3 reads what NVDA intends to say by tapping the screen reader directly. But there's a gap: what if NVDA speaks, but the audio is muted, routed to the wrong device, or garbled? This check closes it. A small local tool (audio-loop-mcp) speaks a phrase, records what actually comes out of the computer's speakers, transcribes it back with local speech-to-text, and confirms the words match.

What it catches: "The screen reader is running but I hear nothing / it's garbled" — a broken audible path that a text-layer check can't see.

Verified: it heard "Skip to main content. Account needed to continue." back at 100% match — the real phrases from the app's skip link and the apply-flow account-wall pause.

When it runs: Locally, as a quick pre-flight before an NVDA session (if the audio path is broken, don't trust the screen-reader run). Everything stays on your machine — local speech-to-text, no cloud.


4. Human Listen (Qualitative, Irreplaceable)

What we do: A real person opens the app, turns on NVDA or Windows Narrator, and listens to the whole experience. They pay attention to things that are technically correct but sound wrong: "Does that link name make sense? Is there an unexpected silence? Does the navigation feel natural?"

What it catches: The human judgment that automation can't: usability, whether the interface feels accessible, whether someone could actually get their job done.

When it runs: Whenever someone (a designer, tester, or user) has time to listen and give feedback.

How to do it: Follow the screen-reader walkthrough checklist. It's a 10-minute script for Andrew or any team member to listen to the app and note what works and what feels off.


Data Privacy (We Don't Steal Your Job Data)

Checks #2 and #3 read your real jobs and profile information (so they test with real-world data, not fake test data). We protect that data:

  • We never send it anywhere: All checks run on your machine only. Your data never leaves your computer.
  • We block writes: If any part of the app accidentally tries to save, update, or send data, the test catches it and fails immediately. It's not just a warning—the test stops.
  • The test report stays on your computer only: The report (which might include snippets of your profile text in error descriptions) is saved locally so you can read it, is never uploaded anywhere, and is automatically deleted the next time you start a fresh test run — so an old report never lingers indefinitely.
  • Special case—LinkedIn: If you're connected to LinkedIn, the onboarding flow tries to look up your profile there. During the test, we stub that call out (return empty) so the app keeps working but we don't actually contact LinkedIn. No external network calls, just the flow of data inside your machine.

What These Tests Prove (and Don't)

What Proven By Not Proven By
Form fields have labels Checks #1, #2 Check #3 (a label might exist but be announced wrong)
Color contrast is dark enough Checks #1, #2 Check #3, #4 (synth settings change how clearly things are read)
NVDA actually speaks the label Checks #3 Checks #1, #2 (automated checkers can't listen)
Keyboard Tab/Escape work Check #2 Checks #1, #3, #4 (different ways of measuring)
The experience feels natural Check #4 Checks #1–3 (a human decides)

The four checks together give us confidence that the app works for everyone.


Running Them Yourself

# Automated rule check (runs in CI, you can run it locally too)
npm run test:a11y

# Keyboard + real data (local only)
npm run test:a11y:live

# Real NVDA (local, Windows, manual only)
npm run test:a11y:sr

# Human listen (no command—just turn on NVDA and try the app)

All three automated tests write a report file when they're done, so you can see what they found.


Glossary

  • WCAG 2.2 AA: The accessibility standard we aim for. "WCAG" = Web Content Accessibility Guidelines. "AA" is a level (higher than A, lower than AAA). "2.2" is the version.
  • axe-core: The free tool we use to check for accessibility problems.
  • Screen reader: Software that reads a webpage aloud (NVDA on Windows, VoiceOver on Mac, TalkBack on Android).
  • NVDA: A free, open-source screen reader for Windows.
  • Keyboard-only navigation: Using Tab, Shift+Tab, Enter, Escape, and arrow keys instead of a mouse.
  • Focus trap: When a dialog opens, pressing Tab cycles only through elements inside the dialog (not the page behind it). Escape closes the dialog and returns focus to what opened it.
  • LocalJsonStore: WorkWingman's way of storing your data locally as JSON files (not a database).