Playwright grid · flake analytics
Tame the flaky test.
Self-hosted Playwright grid with flake analytics built in.
MIT licensed · One Postgres, one container · Runs in your VPC
How it works
One reporter. One Postgres. Your tests stay yours.
- 01
Drop in the reporter
Add `@brittlehq/playwright-reporter` to your config. Run tests like you do today.
- 02
Run tests anywhere
CI, laptop, container. Anywhere Playwright runs. No agent, no daemon.
- 03
Triage from the dashboard
Open the run, click the failing env. Flakes and regressions are tagged inline.
$ pnpm test
Running 24 tests using 3 workers
- ✓ search box accepts query input (1.2s)
- ✓ article infobox renders metadata (0.9s)
- ✗ search results echo query [webkit] (3.1s)
- ✓ history page renders revisions (1.4s)
[@brittlehq/playwright-reporter]
→ uploaded 24 sessions · 1 failed
→ brittle.dev/p/web/runs/rh-9j2
1 failed · 23 passed (12.4s)
What's different
Triage that matches how flaky tests actually fail.
tests/search
- search results echoes query webkit REGRESSED
- autocomplete dropdown appears chromium KNOWN
tests/visual
- article first-paint chrome firefox NEW
per-env aggregation
See the failing browser, not just the test.
TestCase rows are keyed per env, so a WebKit-only failure gets its own row.
search results echoes query
chromium-130 · tests/search/search.spec.ts:36
Video
ready
Trace
ready
Screenshot
ready
Timeline
- 00:00.0 page.goto · /search
- 00:01.2 expect.toHaveText · "results"
- 00:03.4 TimeoutError · locator not visible
grid runtime
Every session, replayable.
Video, HAR, and trace come back with every session.
search results echoes query
Failed 3.1s- page.goto · /wiki/Albert_Einstein 0.8s
- expect.toBeVisible · h1 0.3s
- expect.toHaveText · "Einstein" 2.0s
test replay
Watch the failure happen.
Scrub the recording, jump to the failing step, open the trace.
chromium-x/desktop
webkit-x/desktop
firefox-x/desktop
per-env signals
One test, every browser, every classification.
Small multiples per env. Stable on chromium and flaky on webkit reads as exactly that.
Integration
Four lines.
The rest is your test code.
Sits alongside your existing reporters. Forwards results, traces, and screenshots.
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests',
// drop in the brittle reporter
reporter: [
['@brittlehq/playwright-reporter', {
hubUrl: process.env.BRITTLE_HUB_URL,
token: process.env.BRITTLE_TOKEN,
}],
],
projects: [
{ name: 'chromium' },
{ name: 'firefox' },
{ name: 'webkit' },
],
});
Open source · MIT
Run it on brittle.dev, or run it yourself.
Hub, dashboard, reporter, node executors. All MIT-licensed.