An argument is not a test
I believed this site handled reduced motion correctly because the code said so. When I finally tested it, the first test reported a bug that did not exist.
- Engineering
- Accessibility
- Testing
This site is animation-heavy. On desktop, the identity section pins in place while roles scroll through it; the career timeline is designed to move horizontally as you scroll down. For people who have asked their operating system for reduced motion, none of that should happen.
For a while I was confident it did not, because of how the code was written. The animation setup uses media queries, and the desktop branch — the only place anything gets pinned — only applies when the viewport is wide and the user has not asked for reduced motion. So under reduced motion, the pinning code is never even constructed.
That reasoning was correct. It was also not evidence.
Writing the test
So I wrote tests that check it in a real browser. ScrollTrigger, the library doing the pinning, wraps each pinned element in a spacer. Counting those spacers is a direct measure of whether any pinning was built.
With reduced motion, the test expects zero spacers, all content visible without scrolling, and a noticeably shorter page — pin spacers add a lot of height. A companion test checks that with motion allowed, desktop does pin. Without that, the reduced-motion test would also pass if pinning had simply been removed from the site altogether.
The test that lied
The first version failed. It found a pin spacer under what it believed was reduced motion.
That looked like a real accessibility bug, and I nearly filed it as one. Instead I checked what the page itself thought: asked the browser whether the reduced-motion media query matched. It did not. The test framework option I had used to request reduced motion had never reached the page. The site was behaving correctly for a normal desktop visitor, and the test was measuring the wrong environment while reporting it as a finding.
The fix was to set the preference explicitly, then assert that it took effect before measuring anything. Now if the emulation ever silently fails again, the test fails at the precondition with a clear message instead of producing a confident false result.
What it taught me
- Reasoning about code is not the same as observing behaviour. The argument was right; I still did not know it was right until something checked.
- A test that measures the wrong thing is worse than no test. It produces findings you trust.
- Assert your preconditions. Any test that depends on an emulated condition — a viewport, a preference, a network state, a logged-in user — should check that condition first.
The same suite now covers keyboard operation (skip link first, every navigation link reachable, focus always visible, the mobile menu trapping and restoring focus) and touch (details readable without hover, nothing pinned on a phone). All of it had been "true by construction". Now it is true by test.