|
| 1 | +# Bisecting a Regression Across Published Playwright Versions |
| 2 | + |
| 3 | +When a user reports a regression between two published Playwright versions (e.g. "works in 1.58, broken in 1.59.1"), reproduce both side by side from npm — do **not** try to bisect against the monorepo source. Reading the compiled JS in `node_modules/playwright/lib/**` is faster and avoids build/branch confusion. |
| 4 | + |
| 5 | +## Setup (two side-by-side installs) |
| 6 | + |
| 7 | +Use `~/tmp/<version-tag>/` (NOT `/tmp/`) — the user's shell sessions live in `~/tmp`. |
| 8 | + |
| 9 | +```bash |
| 10 | +mkdir -p ~/tmp/<good>/tests ~/tmp/<bad>/tests |
| 11 | + |
| 12 | +# Skip `npm init playwright@latest` — it's interactive and the scaffold |
| 13 | +# pulls in 3 projects (chromium/firefox/webkit) which produces 6 test runs |
| 14 | +# from a single spec and is confusing. Do this instead: |
| 15 | +( cd ~/tmp/<good> && npm init -y && npm install @playwright/test@<good-ver> && npx playwright install chromium) |
| 16 | +( cd ~/tmp/<bad> && npm init -y && npm install @playwright/test@<bad-ver> && npx playwright install chromium ) |
| 17 | +``` |
| 18 | + |
| 19 | +Write a **minimal** `playwright.config.ts` with a single chromium project — the default scaffold's 3-project config will run the same spec 6 times and obscure output: |
| 20 | + |
| 21 | +```ts |
| 22 | +import { defineConfig, devices } from '@playwright/test'; |
| 23 | +export default defineConfig({ |
| 24 | + testDir: './tests', |
| 25 | + projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], |
| 26 | +}); |
| 27 | +``` |
| 28 | + |
| 29 | +Drop the repro spec (and any helper files) into both folders identically. Run: |
| 30 | + |
| 31 | +```bash |
| 32 | +( cd ~/tmp/<good> && npx playwright test ) |
| 33 | +( cd ~/tmp/<bad> && npx playwright test ) |
| 34 | +``` |
| 35 | + |
| 36 | +Confirm the difference is real before investigating. |
| 37 | + |
| 38 | +## Investigating the diff in node_modules |
| 39 | + |
| 40 | +The compiled JS in `node_modules/playwright-core/lib/` and `node_modules/playwright/lib/` is the source of truth for what shipped. |
| 41 | + |
| 42 | +In recent versions of Playwright these are bundled, so you can't compare |
| 43 | +on per-file basis. You can extract files from bundles via grep though and compare. |
| 44 | + |
| 45 | +Once you've found a candidate function, diff it across the two versions. Patches are usually 1–3 lines. |
| 46 | + |
| 47 | +## Verifying the hypothesis |
| 48 | + |
| 49 | +Edit the compiled JS in `~/tmp/<bad>/node_modules/playwright/lib/...` directly and re-run the test. No build step is needed — Node loads the JS as-is. Revert when done (or just delete the folder). |
| 50 | + |
| 51 | +For stack-trace bugs in particular, a `console.log(new Error().stack)` inserted at the capture site (e.g. inside `expect.js`'s `captureRawStack`) instantly shows whether the issue is microtask-boundary related vs. a stack-filter regression vs. something else. |
| 52 | + |
| 53 | +## Reporting |
| 54 | + |
| 55 | +When the root cause is confirmed: |
| 56 | + |
| 57 | +1. Quote the offending lines from `node_modules/.../lib/...` of the **bad** version, with file path. |
| 58 | +2. Show the equivalent code from the **good** version for contrast. |
| 59 | +3. Explain *why* the change breaks the user's case (don't just point at the diff). |
| 60 | +4. Propose and verify a minimal fix by patching the bad install in place. |
| 61 | + |
| 62 | +Post the writeup as a comment on the original issue with `gh issue comment <number> --repo microsoft/playwright --body "$(cat <<'EOF' ... EOF)"`. |
| 63 | + |
| 64 | +## Pitfalls |
| 65 | + |
| 66 | +- **Don't run `npm init playwright@latest`** — it's interactive and `--quiet` does not skip the prompts. `npm init -y` + `npm install @playwright/test@<ver>` is faster and deterministic. |
| 67 | +- **Don't use the scaffold's default config** — the 3 browser projects multiply test runs by 3 and confuse the output. One chromium project is enough for 99% of repros. |
| 68 | +- **Don't `cd` between commands in a single Bash call without `&&`** — the shell cwd resets between tool invocations. |
| 69 | +- **`/tmp/` is not `~/tmp/`** — pick one and stay consistent. The user's interactive shells default to `~/tmp/`, so prefer that. |
| 70 | +- **Don't `rm -rf` an existing `~/tmp/<ver>/`** without checking — it may be the user's prior work. Edit in place instead. |
| 71 | +- **Don't try to map the bug to monorepo source first.** The shipped JS is what the user is running; source may have already been refactored or fixed on `main`. Investigate `node_modules/` first, then map the fix back to source only when proposing the upstream patch. |
0 commit comments