fix(ui): a looping pulse stops for reduced motion; the e2e waits for skeleton bones, not for any pulse

- Seven looping pulses (a running job's dot, the scheduler's progress bar, a queued download, the
  download tray, a playlist upload, a channel's full-history action, the setup wizard's test mail)
  ran regardless of prefers-reduced-motion, which docs/DESIGN.md promises to respect: each is
  motion-safe now, held by a contract test.
- The a11y suite's "settled" wait took every aria-hidden pulse for a loading skeleton, so the
  Scheduler legend's running dot, which pulses for good, kept it waiting until it timed out. A
  skeleton bone now says it is one (data-skeleton) and the wait looks for that.
This commit is contained in:
2026-10-18 21:40:52 +02:00
parent 5082636f15
commit b842e4e871
10 changed files with 52 additions and 11 deletions
+3 -4
View File
@@ -13,11 +13,10 @@ import { gotoPage, openApp, openFirstVideo } from "./helpers";
// Chromium only (playwright.config.ts leaves it out of the other projects).
const TAGS = ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"];
/** Wait until nothing is loading: no QueryState spinner and no skeleton bone left. */
/** Wait until nothing is loading: no QueryState spinner and no skeleton bone left. A bone says it is
* one (`data-skeleton`): a pulse alone is not loading — a running job's dot pulses as long as it runs. */
async function settled(page: Page): Promise<void> {
await expect(
page.locator('[role="status"] .animate-spin, [aria-hidden="true"].animate-pulse'),
).toHaveCount(0);
await expect(page.locator('[role="status"] .animate-spin, [data-skeleton]')).toHaveCount(0);
}
async function violations(page: Page): Promise<string[]> {