Fast, but not zero

Speeding up the e2e suite by cranking animation speed risked breaking the one test that watches an animation happen. Reduced motion turned out to be the wrong kind of fast.

The snake animates at 150 milliseconds per letter by default, real enough to watch, needlessly slow for a Playwright suite that submits dozens of words in a single run. The question behind speeding it up wasn’t whether it could be done, settings already control the speed, but whether doing it would quietly break the one test that watches an animation actually happen, the narrow-viewport check that has to catch a word mid-flight to prove it never overflows the page.

The first thing that looked like an answer wasn’t one. The game already has a reduced-motion setting, and forcing it on would have been the smallest possible change, except reduced motion doesn’t mean fast, it means instant: every step of an animation collapses into a single frame, so a test asserting on an in-progress animating state has nothing left to catch. Zero and fast are different problems with the same symptom.

What shipped instead seeds a real, nonzero, just much shorter animation speed for the whole suite, through Playwright’s own storage state rather than the game’s reduced-motion setting:

storageState: {
  cookies: [],
  origins: [
    {
      origin: 'http://localhost:5173',
      localStorage: [{ name: 'twas-settings', value: JSON.stringify({ animationStepMs: 20 }) }]
    }
  ]
}

The one test that still needed the real speed opts back into it on its own, since a twenty-millisecond animation could finish and settle before its own multi-second window ever caught it mid-flight:

await page.addInitScript(() => {
  localStorage.setItem('twas-settings', JSON.stringify({ animationStepMs: 150 }));
});

No production code changed anywhere in this; the entire fix lives in test configuration, one file exempting itself from a suite-wide default rather than the default bending around one file’s needs. The animation-heavy tests measured real, if modest, savings, a few tenths of a second per test rather than a dramatic collapse, but multiplied across a suite that submits words constantly, that adds up to a noticeably shorter run without giving up the one test that actually needs to watch something move.