Inspector

Pause a browser run, inspect the page, and choose better locators while developing tests.

The inspector is a development tool. Use it when you need to understand the live page: what the browser rendered, which element receives the click, why a locator is ambiguous, or what changed after an action.

It is not a CI strategy. On CI, prefer traces and screenshots. Locally, the inspector helps you build the test before you make it headless and repeatable.

When to use it

Use the inspector when:

  • a locator matches nothing or too many elements,
  • a click targets the wrong visible element,
  • a frame or popup boundary is unclear,
  • a test passes too quickly to observe,
  • you need to inspect browser state before writing assertions.

Tip
Start with the inspector to understand the page, then encode that understanding as semantic locators and assertions. Do not leave the test dependent on manual inspection.

Start the inspector explicitly

Launch through PlaywrightFactory, enable the inspector on the browser builder, then pause at the state you need to examine:

php
use Playwright\PlaywrightFactory;

$playwright = PlaywrightFactory::create();
$browser = $playwright->chromium()
    ->withHeadless(false)
    ->withInspector()
    ->launch();

$context = $browser->newContext();
$page = $context->newPage();
$page->goto('https://app.example.test/settings');
$page->pause();

pause() blocks automation until you resume the run. Remove it, headed mode, and inspector configuration once the test is stable.

For a headed PHPUnit run without the inspector, pass a config built with PlaywrightConfigBuilder::fromEnv() to the provided test trait, then set PW_HEADLESS=false. The trait does not load that setting automatically.

Inspect locators

The inspector is most useful when improving locators. A good locator should describe the user-facing contract:

php
$page->getByRole('button', ['name' => 'Create account'])->click();

If the inspector shows that the button has no accessible name, the test has found a product issue. Fix the UI or use a deliberate fallback. Do not jump directly to a brittle CSS selector.

Pause around the uncertain step

When a test has one suspicious action, reduce the problem:

php
$page->goto('https://app.example.com/settings');

$page->getByRole('button', ['name' => 'Danger zone'])->click();

$page->pause();

$page->getByRole('button', ['name' => 'Delete account'])->click();

Look for:

  • an overlay covering the target,
  • a disabled control,
  • a hidden frame,
  • a different URL than expected,
  • validation text that explains why the flow stopped.

Move from inspector to artifacts

Once the test is part of the suite, make it debuggable without a desktop:

  • record a trace for failing CI runs,
  • save screenshots at failure points,
  • collect console messages for browser-side errors,
  • keep downloaded/generated files when the file is part of the contract.

Warning
A headed browser can make a flaky test look understandable, but it does not make it deterministic. The final test should wait for product state, not for your eyes.

Verification checklist

  • The failing step has been isolated.
  • Locators were checked against the rendered page.
  • The final test can run headless.
  • CI has trace or screenshot evidence for the same failure class.

Go next