DEV Community

kadir
kadir

Posted on

Debugging & Developer Experience (Playwright + TypeScript, Ch.6)

Sooner or later a test fails with something like expect(locator).toBeVisible()
failed
. What now? Guessing and re-running is slow and miserable. The good news:
Playwright ships an excellent set of tools that show you exactly what happened. This
is the chapter you'll come back to every time something breaks.

We add a handful of npm scripts so each tool is one short command. (A "script" in
package.json is just a saved command you run with npm run <name>.)

Code for this chapter is tagged ch-06 in the repo:
https://github.com/aktibaba/playwright-qa-course — see the scripts in
package.json and the reporter/trace config in playwright.config.ts.

// package.json — "scripts" are shortcuts you run with `npm run <name>`
"scripts": {
  "test":        "playwright test",
  "test:ui":     "playwright test --ui",      // time-travel UI mode
  "test:debug":  "playwright test --debug",   // step through, line by line
  "test:report": "playwright show-report",    // open the last HTML report
  "codegen":     "playwright codegen http://localhost:3000"
}
Enter fullscreen mode Exit fullscreen mode

UI Mode — start here

npm run test:ui
Enter fullscreen mode Exit fullscreen mode

UI Mode opens a little control panel: a list of every test, a live browser pane, and
a time-travel timeline. Run a test and you get one row per action (goto, fill,
click, assertion). Hover any action and the browser pane jumps to that exact
moment
— you see the page as it was, plus the network requests, the console, and the
locator that was used. Change a test file and it re-runs automatically on save.

This is exactly how you'd catch the strict-mode flake from Chapter 3: step to the
failing assertion and the timeline highlights getByRole('heading', { name: 'inkwell'
})
matching two elements — the banner and the "Welcome to Inkwell" article. The
bug becomes obvious in seconds instead of minutes.

The Trace Viewer — for failures you didn't watch

UI Mode is great when you're sitting there. But what about a failure on CI (the
server that runs your tests automatically) that you didn't see? That's what a
trace is for.

A trace is a complete recording of a test run — every action, DOM snapshots
before and after, network calls, console logs, and the source line. You open it in
a viewer and scrub through it like a video.

Our config records one automatically when a test fails and retries:

// playwright.config.ts
use: { trace: "on-first-retry", screenshot: "only-on-failure" }
Enter fullscreen mode Exit fullscreen mode

on-first-retry is the production-friendly choice: no slowdown on passing runs, but
the moment a test fails and Playwright retries it, a full trace is captured. Open the
HTML report (which embeds the trace and a failure screenshot) with:

npm run test:report
Enter fullscreen mode Exit fullscreen mode

To force a trace locally even without a retry, add --trace on:

npx playwright test article-editor --trace on
Enter fullscreen mode Exit fullscreen mode

On CI you upload the playwright-report/ folder as an "artifact" (a file the CI run
saves), download it, and open any failure's trace on your own machine. This is the
single biggest upgrade to debugging a flaky pipeline.

The Inspector — step through live

npm run test:debug
Enter fullscreen mode Exit fullscreen mode

--debug opens the Playwright Inspector, a debugger for your test. Execution
pauses before each action; you click "step" to run one command at a time and watch
the browser react. It also has a locator picker — hover the page and it tells you
the recommended locator for whatever you point at.

You can also pause at an exact spot in your own code:

await page.pause(); // execution stops here and hands you the Inspector
Enter fullscreen mode Exit fullscreen mode

This is how you'd dissect the login redirect race from Chapter 5: pause right after
the submit click and watch the app fire its navigate("/") out from under you.

Codegen — record locators, don't guess them

npm run codegen
Enter fullscreen mode Exit fullscreen mode

codegen opens Inkwell and writes test code as you click around, automatically
choosing good role-based locators. It's not meant to produce finished tests — it's the
fastest way to discover the right locator for a fiddly element, which you then lift
into a Page Object. Treat its output as a first draft, never the final test.

The VS Code extension

If you use VS Code, install the official Playwright extension. It puts the whole
loop in your editor: a ▶ icon next to each test to run or debug it, breakpoints in test
code, and "Pick locator" / "Record at cursor" buttons. It replaces most of the
command-line flags above with a click.

A debugging workflow

When something breaks, in this order:

  1. npm run test:ui — reproduce it and time-travel to the failing step.
  2. npm run test:report — if it only fails on CI, open the trace from the downloaded artifact.
  3. page.pause() + npm run test:debug — when you need to poke at the live page.
  4. npm run codegen — when the real question is "what locator should this be?".

Notice none of these involve sprinkling console.log everywhere or adding
waitForTimeout. The tools show you the state directly — that's the whole point.

Next up

That wraps Part 1 — you can find elements, assert, model pages with Page Objects,
handle forms and dialogs, and debug all of it. Part 2 is the heart of the course:
we turn these Page Objects and our repeated setup into fixtures, so a test just
asks for loginPage (already built) or user (already created) and receives it.
Chapter 7 — Custom fixtures: beyond beforeEach. Tag: ch-07.

Following along? Star the repo
and tell me which Playwright debugging tool you reach for first.

Top comments (0)