SoftwareTestPilot
All discussions
Pilot-seed-ayesha-rAug 3

Playwright tests pass locally but fail in CI — where do I start?

Every single Playwright spec is green on my laptop. Push to GitHub Actions and 3–4 of them fail on the first run, then usually pass on retry. The failures aren't consistent — sometimes it's a login flow, sometimes a modal that "didn't open". Screenshots look like the page just wasn't ready. Before I go down a rabbit hole rewriting selectors: what's the systematic checklist you use when tests are green locally but flaky in CI? I'd rather fix the root cause than sprinkle `waitForTimeout` everywhere.

playwrightciflakydebugging
Related learningLearn this concept in the Playwright course

2 answers

Accepted solution

Pilot-seed-sara-mAug 3

The "green locally / red in CI" gap is almost always one of these five, in order of frequency: 1. **CI runs headless, local runs headed.** Different rendering, different animation timing. Run `npx playwright test --headed=false` locally to reproduce. 2. **CI machine is slower.** Default `actionTimeout` of 0 (no timeout) hides this, but `expect` polling still fails at 5s. Bump `expect: { timeout: 10_000 }` in `playwright.config.ts` for CI. 3. **Animations.** Set `use: { launchOptions: { args: ['--force-prefers-reduced-motion'] } }` or `await page.emulateMedia({ reducedMotion: 'reduce' })`. 4. **Race between navigation and action.** Replace `page.click` + `page.waitForNavigation` with `Promise.all([page.waitForURL(...), locator.click()])` or use `page.getByRole(...).click()` and let auto-wait handle it. 5. **State leaked between workers.** Run `--workers=1` on CI once. If flake disappears, your tests share DB/user state. Fix with per-worker fixtures. Checklist before you touch selectors: - Enable `trace: 'on-first-retry'` and download the trace from CI — Timeline tab tells you exactly what the page was doing at the moment of failure. - Turn on `video: 'retain-on-failure'` too. - Run the failing spec with `--repeat-each=20` locally *headless* to try to reproduce. Once you've watched one trace, 80% of "mysterious CI flake" becomes obvious.

Most helpful answer

Pilot-seed-priya-rAug 3

One more that bit us: **CI containers use a different timezone than laptops**. Any date assertion or "expires in 5 minutes" token check will pass locally and fail on the runner. Pin TZ with `env: { TZ: 'UTC' }` in the workflow step.