Playwright

Playwright Auto-Wait and Trace Viewer: Essential Tips for New Users

The two features that separate productive Playwright users from frustrated ones. Understanding auto-wait and the trace viewer will save you hours of debugging.

0

Generates standard Playwright files you can inspect, modify, and run in any CI pipeline.

Assrt SDK

1. How auto-wait works under the hood

Auto-wait is Playwright's built-in mechanism for handling the timing gap between requesting an action and the page being ready for that action. When you call page.click('button'), Playwright does not immediately send a click event. Instead, it waits until the button is attached to the DOM, visible, stable (not animating), enabled, and not obscured by another element. Only when all these conditions are met does the click execute.

This is fundamentally different from older tools like Selenium, where you had to manually add waits before every interaction. In Selenium, a test might look like: wait for element to appear, wait for element to be clickable, then click. In Playwright, you just click. The framework handles the timing. This eliminates an entire category of flaky test failures caused by incorrect or insufficient waits.

Auto-wait uses a polling mechanism internally. It checks the actionability conditions in a tight loop with short intervals (not fixed sleep calls). If the conditions are not met within the timeout (30 seconds by default), the action fails with a descriptive error message that tells you exactly which condition was not satisfied. This timeout is configurable per action, per test, or globally in your Playwright configuration.

The practical impact is that Playwright tests are more reliable out of the box. You do not need to learn patterns like "explicit waits" or "fluent waits" from older frameworks. You write the interaction you want, and Playwright waits for the right moment. This makes test authoring faster and produces tests that are less likely to break due to timing issues.

2. Actionability checks and why they prevent flaky tests

Each Playwright action runs a specific set of actionability checks before executing. The click action checks that the element is visible, stable, enabled, and receives events. The fill action checks that the element is visible, enabled, and editable. The check action verifies the element is a checkbox or radio button. Understanding which checks apply to which actions helps you diagnose failures quickly.

The "stable" check deserves special attention. Playwright considers an element stable when its bounding box has not changed between two consecutive animation frames. This means Playwright automatically waits for CSS transitions, animations, and layout shifts to complete before interacting. This single check prevents the most common source of flaky tests: clicking on an element that is still moving due to an animation.

The "receives events" check ensures that no other element (such as a modal overlay, tooltip, or loading spinner) is blocking the target element. In older frameworks, a click on a button behind an overlay would silently click the overlay instead, causing mysterious test failures. Playwright detects this situation and waits for the overlay to disappear.

When an actionability check fails after the timeout, Playwright provides a detailed error message. Instead of a generic "element not clickable" error, you get messages like "element is not visible" or "element is obscured by another element at coordinates (x, y)." These messages make debugging significantly faster because you know exactly which condition failed.

Try Assrt for free

Open-source AI testing framework. No signup required.

Get Started

3. Trace viewer: your time-travel debugger

The Playwright trace viewer is a visual debugging tool that records everything that happens during a test run: every action, every network request, every console message, and a screenshot before and after each step. You can replay the entire test execution step by step, inspecting the page state at any point in time.

Enable tracing by adding trace: 'on-first-retry' to your Playwright configuration. This records a trace only when a test fails and is retried, which keeps the performance overhead minimal in passing runs. The trace file is a zip archive that you open with npx playwright show-trace trace.zip or by uploading it to trace.playwright.dev.

The trace viewer shows a timeline of actions on the left, a screenshot of the page state in the center, and detailed information (network requests, console logs, DOM snapshots) on the right. You can click on any action to see the page state before and after that action executed. This is invaluable for understanding why a test failed: you can see exactly what the page looked like when Playwright tried to click a button that was not visible.

For CI environments, configure your pipeline to save trace files as artifacts on test failure. This way, when a test fails in CI, you can download the trace and debug locally without needing to reproduce the failure. This is especially useful for tests that fail intermittently, because the trace captures the exact conditions that caused the failure.

4. A practical debugging workflow for failing tests

When a Playwright test fails, follow this systematic workflow instead of adding random waits or retries. First, read the error message carefully. Playwright error messages are specific and actionable. "Locator resolved to 0 elements" means the selector is wrong or the element does not exist. "Element is not visible" means the element exists but is hidden. "Timeout exceeded" means an operation took too long.

Second, if the error is not immediately clear, run the test with the trace viewer enabled: npx playwright test --trace on. Open the resulting trace and step through the test execution. Look at the screenshot at the point of failure. Is the element on the page? Is it behind a modal? Is the page still loading?

Third, use Playwright's headed mode for live debugging: npx playwright test --headed --debug. This opens a real browser window and pauses before each step, letting you inspect the page state interactively. You can use the browser's developer tools to examine elements, check network requests, and verify CSS properties.

Resist the urge to fix test failures by adding page.waitForTimeout() calls. Fixed timeouts are the primary cause of flaky tests and slow test suites. If auto-wait is not handling your case correctly, the right fix is usually to wait for a specific condition (a network response, a visible element, or a URL change) rather than waiting for an arbitrary number of milliseconds.

5. Common pitfalls and how to avoid them

The most common pitfall for new Playwright users is fighting the auto-wait system instead of working with it. If you find yourself adding waitForTimeout calls, you are almost certainly solving the wrong problem. The correct approach is to identify what condition you are actually waiting for and use the appropriate Playwright API to wait for that condition.

Another common issue is not using locators correctly. Playwright locators are lazy; they do not resolve until you perform an action on them. This means you can create a locator at the top of your test and use it later, even if the element does not exist yet when the locator is created. Misunderstanding this leads to unnecessarily complex test code with manual waits between locator creation and usage.

New users also often overlook the expect auto-retry feature. Playwright assertions like await expect(locator).toBeVisible() automatically retry until the condition is met or the timeout expires. You do not need to manually poll or loop. This is different from Jest or Mocha assertions, which evaluate once and fail immediately.

Tools like Assrt generate tests that follow Playwright best practices by default: role-based locators, proper assertions with auto-retry, and no hard-coded waits. If you are starting from scratch, this can save significant time compared to learning these patterns through trial and error. The generated tests serve as examples of idiomatic Playwright code that you can learn from and extend.

Ready to automate your testing?

Assrt discovers test scenarios, writes Playwright tests from plain English, and self-heals when your UI changes.

$npm install @assrt/sdk