Doramagic Project Pack · Human Manual

playwright

Related topics: Package Ecosystem and Monorepo Structure, Test Runner and Execution Engine

Playwright Introduction and Project Overview

Related topics: Package Ecosystem and Monorepo Structure, Test Runner and Execution Engine

Section Related Pages

Continue reading this section for the full explanation and source context.

Section 2.1 Core Packages

Continue reading this section for the full explanation and source context.

Section 2.2 High-Level Architecture

Continue reading this section for the full explanation and source context.

Section 2.3 Channel Owner System

Continue reading this section for the full explanation and source context.

Related topics: Package Ecosystem and Monorepo Structure, Test Runner and Execution Engine

Playwright Introduction and Project Overview

1. Overview

Playwright is a powerful end-to-end testing framework developed by Microsoft that enables reliable browser automation. It supports testing across multiple browsers (Chromium, Firefox, WebKit) with a single unified API, making it ideal for modern web application testing.

The project provides comprehensive tools for browser automation, test execution, debugging, and trace inspection. Playwright is designed to handle complex web scenarios including single-page applications, modern JavaScript frameworks, and sophisticated user interactions.

Sources: packages/playwright-core/src/tools/cli-client/skill/SKILL.md

2. Project Architecture

2.1 Core Packages

The Playwright project is organized as a monorepo with several key packages:

PackagePurpose
playwrightMain package with full test runner and all browser support
playwright-coreCore browser automation library without bundled browsers
trace-viewerWeb-based trace analysis and visualization tool
html-reporterTest report generation and visualization
injectedIn-browser script injection utilities

2.2 High-Level Architecture

graph TD
    A[Playwright Test Runner] --> B[playwright-core]
    B --> C[Browser Drivers]
    C --> D[Chromium]
    C --> E[Firefox]
    C --> F[WebKit]
    B --> G[Connection Layer]
    G --> H[Channel Owners]
    H --> I[Page]
    H --> J[Request/Response]
    H --> K[Route]
    H --> L[Tracing]
    H --> M[WebSocket]
    A --> N[HTML Reporter]
    A --> O[Trace Viewer]

Sources: packages/playwright-core/src/client/connection.ts

2.3 Channel Owner System

Playwright uses a channel-based communication system where various browser objects are managed through factory functions:

graph LR
    A[Local Utils] --> B[Page]
    A --> C[Playwright]
    A --> D[Request]
    A --> E[Response]
    A --> F[Route]
    A --> G[Tracing]
    A --> H[WebSocket]

The connection layer registers object factories for different types:

Page: (parent, type, guid, init) => new Page(parent, type, guid, init),
Request: (parent, type, guid, init) => new Request(parent, type, guid, init),
Response: (parent, type, guid, init) => new Response(parent, type, guid, init),
Route: (parent, type, guid, init) => new Route(parent, type, guid, init),
Tracing: (parent, type, guid, init) => new Tracing(parent, type, guid, init),

Sources: packages/playwright-core/src/client/connection.ts:1-20

3. Browser Automation Capabilities

3.1 CLI Client (playwright-cli)

The CLI client provides an interactive shell for browser automation tasks:

Command CategoryFeatures
Navigationgoto, back, forward, reload
Interactionclick, fill, type, check, select
Capturescreenshot, pdf, snapshot
Tabstab-list, tab-new, tab-close, tab-select
Storagestate-save, state-load, cookie-*, localstorage-*
Networkroute, unroute, route-list

Sources: packages/playwright-core/src/tools/cli-client/skill/SKILL.md

3.2 Injected Script API

When Playwright injects scripts into web pages, a dedicated API becomes available:

window.playwright = {
  $: (selector: string, strict?: boolean) => this._querySelector(selector, !!strict),
  $$: (selector: string) => this._querySelectorAll(selector),
  inspect: (selector: string) => this._inspect(selector),
  selector: (element: Element) => this._selector(element),
  generateLocator: (element: Element, language?: Language) => this._generateLocator(element, language),
  ariaSnapshot: (element?: Element, options?: AriaTreeOptions) => this._ariaSnapshot(element, options),
  resume: () => this._resume(),
  ...new Locator(this._injectedScript, ''),
};

The injected script is automatically installed on page load and provides DOM querying, locator generation, and ARIA snapshot capabilities.

Sources: packages/injected/src/consoleApi.ts

3.3 ARIA Role Utilities

Playwright automatically maps HTML elements to ARIA roles for accessibility testing:

ElementRole Mapping
<H1> - <H6>heading
<BUTTON>button
<A>link
<INPUT type="search">searchbox / combobox (with list)
<DIALOG>dialog
<NAV>navigation
<HEADER>banner (unless landmark prevented)
<FOOTER>contentinfo (unless landmark prevented)
<IMG alt="">presentation (empty alt, no title)
'INPUT': (e: Element) => {
  const type = (e as HTMLInputElement).type.toLowerCase();
  if (type === 'search')
    return e.hasAttribute('list') ? 'combobox' : 'searchbox';
  // ...
}

Sources: packages/injected/src/roleUtils.ts

4. Test Execution Framework

4.1 Running Tests

Playwright tests are executed using the standard Playwright test runner:

# Run all tests
PLAYWRIGHT_HTML_OPEN=never npx playwright test

# Run with custom npm script
PLAYWRIGHT_HTML_OPEN=never npm run special-test-command

The environment variable PLAYWRIGHT_HTML_OPEN=never prevents the interactive HTML report from opening automatically.

Sources: packages/playwright-core/src/tools/cli-client/skill/references/playwright-tests.md

4.2 Debug Mode

Debugging tests uses the CLI debug mode which pauses execution and provides debugging instructions:

PLAYWRIGHT_HTML_OPEN=never npx playwright test --debug=cli

When debugging instructions appear with a session name (e.g., tw-abcdef), attach using:

playwright-cli attach tw-abcdef

Available debugging commands:

CommandPurpose
playwright-cli resumeResume test execution
playwright-cli snapshotGet inventory of interactive elements
playwright-cli click e5Interact with element by ref
playwright-cli evalRead URL/state
playwright-cli show --annotateRequest user annotation

Sources: packages/playwright-core/src/tools/cli-client/skill/references/playwright-tests.md

5. Browser Session Management

5.1 Named Sessions

Playwright CLI supports multiple named browser sessions:

# Create new browser session named "mysession" with persistent profile
playwright-cli -s=mysession open example.com --persistent

# Use specific session
playwright-cli -s=mysession click e6

# Close named browser
playwright-cli -s=mysession close

# Delete user data for persistent session
playwright-cli -s=mysession delete-data

5.2 Global Session Management

# List all browser sessions
playwright-cli list

# Close all browsers
playwright-cli close-all

# Forcefully kill all browser processes
playwright-cli kill-all

5.3 Environment Variable

Set a default session via environment variable:

export PLAYWRIGHT_CLI_SESSION="mysession"
playwright-cli open example.com  # Uses "mysession" automatically

Sources: packages/playwright-core/src/tools/cli-client/skill/references/session-management.md

6. Trace Viewer

6.1 Overview

The Trace Viewer is a Progressive Web App for analyzing Playwright traces locally without sending data elsewhere:

graph LR
    A[Playwright Test] --> B[Trace.zip]
    B --> C[Trace Viewer]
    C --> D[Actions View]
    C --> E[Requests View]
    C --> F[Console View]
    C --> G[Snapshots]

6.2 CLI Trace Commands

# Open and inspect trace
npx playwright trace open <trace.zip>

# List all actions
npx playwright trace actions

# Filter actions by pattern
npx playwright trace actions --grep "click"

# Show only failed actions
npx playwright trace actions --errors-only

# View specific action details
npx playwright trace action <action-id>

# View DOM snapshot for action
npx playwright trace snapshot <action-id>

# Evaluate JavaScript on snapshot
npx playwright trace snapshot <action-id> -- eval "document.body.outerHTML"

# Export attachments
npx playwright trace attachments
npx playwright trace attachment 1 -o out.png

6.3 Typical Investigation Workflow

# 1. Open the trace
npx playwright trace open test-results/my-test/trace.zip

# 2. View all actions
npx playwright trace actions

# 3. Find failed actions
npx playwright trace actions --errors-only

# 4. Inspect specific action
npx playwright trace action 12

# 5. View page state at that moment
npx playwright trace snapshot 12

# 6. Query DOM for details
npx playwright trace snapshot 12 -- eval "document.querySelector('.error-message').textContent"

# 7. Check network failures
npx playwright trace requests --failed

# 8. Check console errors
npx playwright trace console --errors-only

Sources: packages/playwright-core/src/tools/trace/SKILL.md

6.4 Trace Viewer UI Components

The trace viewer web application includes:

ComponentFilePurpose
WorkbenchLoaderworkbenchLoader.tsxMain application entry, handles file uploads and drag-drop
BrowserFramebrowserFrame.tsxRenders browser chrome with address bar
MetadataViewmetadataView.tsxDisplays test metadata (viewport, user agent, baseURL)
TestCaseViewtestCaseView.tsxShows individual test case details and results

The workbench loader provides a progressive web app experience with local-only processing:

<div className='info'>Playwright Trace Viewer is a Progressive Web App, it does not send your trace anywhere,
  it opens it locally.</div>

Sources: packages/trace-viewer/src/ui/workbenchLoader.tsx

7. Key Features Summary

FeatureDescription
Cross-browserChromium, Firefox, WebKit support with single API
Auto-waitingActions wait for elements to be actionable
Web-first assertionsBuilt-in assertion library
TracingComprehensive action tracing and debugging
LocatorsMultiple strategies: CSS, ARIA, text, role
Network interceptionMock and modify network requests
Storage stateSave/restore authentication and cookies
CLI toolsInteractive browser automation shell

8. Architecture Diagram: End-to-End Test Flow

sequenceDiagram
    participant T as Test
    participant R as Playwright Runner
    participant C as CLI Client
    participant P as Browser
    participant TV as Trace Viewer

    T->>R: npx playwright test
    R->>P: Launch browser
    R->>P: Inject script
    T->>C: playwright-cli attach
    Note over C,P: Interactive debugging
    P->>TV: Generate trace.zip
    TV->>T: Analyze failures

9. Resources and Further Reading

  • Main Documentation: Playwright CLI capabilities and commands
  • Test Debugging: Debug mode and CLI attachment workflow
  • Trace Analysis: Using trace viewer for post-mortem analysis
  • Session Management: Multi-browser concurrent testing patterns
  • Storage State: Authentication and state persistence patterns

Sources: packages/playwright-core/src/tools/cli-client/skill/SKILL.md

Package Ecosystem and Monorepo Structure

Related topics: Playwright Introduction and Project Overview, Client-Server Communication Architecture

Section Related Pages

Continue reading this section for the full explanation and source context.

Section playwright

Continue reading this section for the full explanation and source context.

Section playwright-core

Continue reading this section for the full explanation and source context.

Section Console API Installation

Continue reading this section for the full explanation and source context.

Related topics: Playwright Introduction and Project Overview, Client-Server Communication Architecture

Package Ecosystem and Monorepo Structure

Playwright is organized as a monorepo using npm workspaces, enabling centralized version management and shared tooling across multiple specialized packages. The repository contains the main playwright package alongside browser-specific packages, core libraries, and supporting tools.

Repository Overview

The Playwright monorepo follows a multi-package architecture where:

  • The root package.json defines shared scripts, build tooling, and workspace configuration
  • Individual packages under packages/ contain focused, modular functionality
  • Examples under examples/ demonstrate real-world usage patterns
graph TD
    Root[Root package.json<br/>v1.61.0-next] --> Core[playwright-core]
    Root --> Main[playwright]
    Root --> Chromium[playwright-browser-chromium]
    Root --> Firefox[playwright-browser-firefox]
    Root --> Webkit[playwright-browser-webkit]
    Root --> Injected[injected]
    Root --> TraceViewer[trace-viewer]
    Root --> HtmlReporter[html-reporter]
    
    Core --> Injected
    Main --> Core
    Chromium --> Core
    Firefox --> Core
    Webkit --> Core

Core Packages

playwright

The main public package that provides the high-level API for browser automation. It re-exports types and utilities from playwright-core while bundling browser automation capabilities.

playwright-core

The foundational package containing all browser automation logic. This package:

  • Defines client-side abstractions (Page, Request, Response, Route, WebSocket, Worker)
  • Manages channel-based communication between client and server
  • Implements the LocalUtils factory for shared utilities

The connection layer registers object factories for all domain objects:

registerObjectFactories({
  LocalUtils: (parent, type, guid, init) => {
    const result = new LocalUtils(parent, type, guid, init);
    if (!this._localUtils)
      this._localUtils = result;
    return result;
  },
  Page: (parent, type, guid, init) => new Page(parent, type, guid, init),
  Request: (parent, type, guid, init) => new Request(parent, type, guid, init),
  Response: (parent, type, guid, init) => new Response(parent, type, guid, init),
  Route: (parent, type, guid, init) => new Route(parent, type, guid, init),
  Tracing: (parent, type, guid, init) => new Tracing(parent, type, guid, init),
  WebSocket: (parent, type, guid, init) => new WebSocket(parent, type, guid, init),
  Worker: (parent, type, guid, init) => new Worker(parent, type, guid, init),
});

Sources: packages/playwright-core/src/client/connection.ts:10-35

Browser Packages

Browser-specific packages provide automatic browser installation and management. Each package depends on playwright-core.

PackagePurposeDependencies
playwright-browser-chromiumChromium browser supportplaywright-core
playwright-browser-firefoxFirefox browser supportplaywright-core
playwright-browser-webkitWebKit browser supportplaywright-core

The browser packages expose a standard interface:

{
  "name": "@playwright/browser-webkit",
  "version": "1.61.0-next",
  "exports": {
    ".": {
      "types": "./index.d.ts",
      "import": "./index.mjs",
      "require": "./index.js",
      "default": "./index.js"
    }
  },
  "dependencies": {
    "playwright-core": "1.61.0-next"
  }
}

Sources: packages/playwright-browser-webkit/package.json

Injected Scripts Package

The injected package contains scripts that run within the browser context, providing accessibility utilities and developer inspection capabilities.

Console API Installation

The injected script installs a playwright object onto window when install() is called:

install() {
  if (this._injectedScript.window.playwright)
    return;
  this._injectedScript.window.playwright = {
    $: (selector: string, strict?: boolean) => this._querySelector(selector, !!strict),
    $$: (selector: string) => this._querySelectorAll(selector),
    inspect: (selector: string) => this._inspect(selector),
    selector: (element: Element) => this._selector(element),
    generateLocator: (element: Element, language?: Language) => this._generateLocator(element, language),
    ariaSnapshot: (element?: Element, options?: AriaTreeOptions) => {
      return this._injectedScript.ariaSnapshot(element || this._injectedScript.document.body, options || { mode: 'default' });
    },
    resume: () => this._resume(),
    ...new Locator(this._injectedScript, ''),
  };
}

Sources: packages/injected/src/consoleApi.ts:10-30

Role Utilities

The roleUtils.ts file maps HTML elements to their ARIA roles for accessibility testing:

'DIALOG': () => 'dialog',
'FORM': (e: Element) => hasExplicitAccessibleName(e) ? 'form' : null,
'HEADER': (e: Element) => closestCrossShadow(e, kAncestorPreventingLandmark) ? null : 'banner',
'IMG': (e: Element) => (e.getAttribute('alt') === '') && !e.getAttribute('title') && !hasGlobalAriaAttribute(e) && !hasTabIndex(e) ? 'presentation' : 'img',

Sources: packages/injected/src/roleUtils.ts:1-50

Tooling Packages

trace-viewer

A React-based Progressive Web Application for inspecting Playwright trace files. The trace viewer provides:

  • Drop-zone interface for loading trace files locally
  • Progress dialogs for trace processing
  • Version display showing the Playwright version
  • No data transmission—opens files locally
<div className='info'>Playwright Trace Viewer is a Progressive Web App, it does not send your trace anywhere,
  it opens it locally.</div>
<div className='version'>Playwright v{__APP_VERSION__}</div>

Sources: packages/trace-viewer/src/ui/workbenchLoader.tsx:1-30

html-reporter

Generates HTML test reports with:

  • Test case location linking
  • Duration tracking
  • Project and tag labeling
  • Annotation display
  • Retry labeling for failed tests
<CopyToClipboardContainer value={`${test.location.file}:${test.location.line}`}>
  {test.location.file}:{test.location.line}
</CopyToClipboardContainer>
<TraceLink test={test} trailingSeparator={true} />
<div className='test-case-duration'>{msToString(test.duration)}</div>

Sources: packages/html-reporter/src/testCaseView.tsx:1-30

CLI Tools

playwright-cli

A command-line tool for browser automation and page interaction. Available commands include:

# Core commands
playwright-cli open                          # Open browser
playwright-cli goto <url>                    # Navigate
playwright-cli click <element>               # Click element
playwright-cli type <text>                   # Type text

# Snapshot and evaluation
playwright-cli snapshot                      # Get page snapshot
playwright-cli eval "code"                   # Execute JS

# Tab management
playwright-cli tab-list                      # List tabs
playwright-cli tab-new <url>                 # New tab

# State management
playwright-cli state-save <file>             # Save state
playwright-cli state-load <file>            # Load state

# Network interception
playwright-cli route "<pattern>"             # Intercept routes

playwright-trace

Inspect trace files from the command line:

npx playwright trace open <trace.zip>       # Open and extract trace
npx playwright trace actions                 # List all actions
npx playwright trace action <action-id>      # View action details
npx playwright trace console                 # View console messages
npx playwright trace errors                  # View errors
npx playwright trace snapshot <action-id>    # View DOM snapshot
npx playwright trace close                   # Close trace

Build and Test Scripts

The root package.json defines comprehensive test and lint scripts:

ScriptPurpose
ctestChromium tests
ftestFirefox tests
wtestWebKit tests
atestAndroid tests
etestElectron tests
itestInstallation tests
stestStress tests
biditestBiDi protocol tests
ttestPlaywright Test runner tests
lintFull linting suite
tscTypeScript compilation
{
  "scripts": {
    "ctest": "playwright test --config=tests/library/playwright.config.ts --project=chromium-*",
    "ftest": "playwright test --config=tests/library/playwright.config.ts --project=firefox-*",
    "wtest": "playwright test --config=tests/library/playwright.config.ts --project=webkit-*",
    "test": "playwright test --config=tests/library/playwright.config.ts",
    "eslint": "eslint --cache",
    "tsc": "tsc -p ."
  }
}

Sources: package.json:1-50

Monorepo Structure Summary

graph TD
    subgraph "Root"
        RootPkg[package.json<br/>v1.61.0-next]
    end
    
    subgraph "Core Packages"
        Core[playwright-core<br/>Automation core]
        Injected[injected<br/>Browser scripts]
    end
    
    subgraph "Public Packages"
        Main[playwright<br/>Main API]
        Chromium[playwright-browser-chromium]
        Firefox[playwright-browser-firefox]
        Webkit[playwright-browser-webkit]
    end
    
    subgraph "Tooling"
        CLI[playwright-cli<br/>CLI tool]
        Trace[playwright-trace<br/>Trace CLI]
        Viewer[trace-viewer<br/>Trace PWA]
        Reporter[html-reporter<br/>Test reports]
    end
    
    subgraph "Examples"
        Todo[todomvc]
        Svgomg[svgomg]
    end
    
    Main --> Core
    Chromium --> Core
    Firefox --> Core
    Webkit --> Core
    CLI --> Core
    Trace --> Core
    Viewer --> Core
    Reporter --> Core
    Core --> Injected

Package Versioning

All packages in the monorepo share the same version number for consistency:

{
  "version": "1.61.0-next",
  "engines": {
    "node": ">=18"
  }
}

Browser packages declare explicit dependencies on playwright-core:

"dependencies": {
  "playwright-core": "1.61.0-next"
}

This ensures version alignment across the ecosystem while allowing independent releases when necessary.

Sources: packages/playwright-core/src/client/connection.ts:10-35

Client-Server Communication Architecture

Related topics: Package Ecosystem and Monorepo Structure, Browser Launch and Process Management

Section Related Pages

Continue reading this section for the full explanation and source context.

Section ChannelOwner (Client-Side Base Class)

Continue reading this section for the full explanation and source context.

Section Connection (Client-Side Hub)

Continue reading this section for the full explanation and source context.

Section Dispatcher (Server-Side Handler)

Continue reading this section for the full explanation and source context.

Related topics: Package Ecosystem and Monorepo Structure, Browser Launch and Process Management

Client-Server Communication Architecture

Overview

Playwright's Client-Server Communication Architecture enables the automation of web browsers through a well-defined message-passing system. The architecture separates the client API (used by test developers) from the server-side browser automation engine, allowing tests to control Chromium, Firefox, and WebKit browsers running either locally or in remote environments.

High-Level Architecture

graph TD
    subgraph Client["Client Side (Node.js)"]
        API[Test API<br/>playwright.click()]
        CO[ChannelOwner<br/>Base Class]
        CONN[Connection]
    end
    
    subgraph Server["Server Side (Node.js + Browser)"]
        DIS[Dispatcher]
        CH[Channel Handlers]
        BR[Browser<br/>Chromium/Firefox/WebKit]
    end
    
    API --> CO
    CO --> CONN
    CONN -->|Protocol Messages| DIS
    DIS --> CH
    CH --> BR
    
    style Client fill:#e1f5fe
    style Server fill:#fff3e0

The architecture follows a factory pattern where the Connection class registers object factories for all protocol-defined objects. When the client creates a Page or BrowserContext, the corresponding factory is invoked to create a client-side proxy object.

Core Components

ChannelOwner (Client-Side Base Class)

The ChannelOwner class serves as the base for all client-side objects that communicate with the server. It provides:

  • Message routing: Sends commands to the server and receives responses
  • Event handling: Subscribes to server-side events
  • Lifecycle management: Tracks object disposal and cleanup
PropertyTypeDescription
channelChannelThe communication channel to the server
connectionConnectionReference to the parent connection
guidstringUnique identifier for this object
parent`ChannelOwner \null`Parent object in the hierarchy

Sources: packages/playwright-core/src/client/channelOwner.ts

Connection (Client-Side Hub)

The Connection class manages all client-server communication and object lifecycle.

// Connection registers factories for all protocol objects
registerObjectFactories(factories: Record<string, ChannelFactory>) {
  // Creates appropriate client-side objects for each type
}

Registered Object Factories:

Object TypeFactory CreatesPurpose
BrowserBrowser instanceMain browser process
BrowserContextContext instanceIsolated browsing sessions
PagePage instanceSingle tab/page
RequestRequest instanceHTTP request tracking
ResponseResponse instanceHTTP response data
RouteRoute instanceNetwork request interception
TracingTracing instanceTrace collection
WebSocketWebSocket instanceWebSocket communication
WorkerWorker instanceWeb Workers
LocalUtilsUtility instanceLocal utility functions

Sources: packages/playwright-core/src/client/connection.ts:1-50

Dispatcher (Server-Side Handler)

The Dispatcher class is the server-side counterpart that handles messages from clients.

graph LR
    MSG[Incoming<br/>Message] --> DIS[Dispatcher]
    DIS -->|Route| HAND[Channel Handler]
    HAND -->|Execute| BR[Browser API]
    BR -->|Result| RES[Response<br/>to Client]

Key responsibilities:

  • Deserialize incoming messages
  • Route to appropriate channel handler
  • Execute browser automation commands
  • Send responses back to client

Sources: packages/playwright-core/src/server/dispatchers/dispatcher.ts

Protocol Channels

The protocol defines typed channels for all communication between client and server.

// Generated from protocol definitions
interface Channels {
  Browser: {
    // Methods
    newContext(options?: BrowserNewContextOptions): Promise<BrowserContext>;
    close(): Promise<void>;
    // Events
    on('disconnected', callback: () => void): void;
  };
  Page: {
    click(selector: string, options?: PageClickOptions): Promise<void>;
    fill(selector: string, value: string): Promise<void>;
    // ...
  };
}

Sources: packages/protocol/src/channels.d.ts

Communication Flow

Method Invocation Flow

sequenceDiagram
    participant Client as Test Code
    participant CO as ChannelOwner
    participant CONN as Connection
    participant Wire as Wire Protocol
    participant DIS as Dispatcher
    participant Impl as Implementation
    
    Client->>CO: page.click('#button')
    CO->>CONN: sendMessage('click', args)
    CONN->>Wire: serialize & send
    Wire->>DIS: deliver message
    DIS->>Impl: invoke method
    Impl-->>DIS: return result
    DIS-->>Wire: send response
    Wire-->>CONN: receive response
    CONN-->>CO: deserialize result
    CO-->>Client: Promise resolves

Object Creation Flow

When a client requests a new object (e.g., browser.newContext()):

  1. Server creates the implementation object
  2. Server creates a dispatcher wrapper
  3. Server returns the new object's channel reference to client
  4. Client's connection factory creates appropriate ChannelOwner subclass
  5. Client receives a proxy object to interact with the new object
graph TD
    subgraph Server["Server"]
        IMPL[Implementation]
        DISP[Dispatcher]
    end
    
    subgraph Client["Client"]
        FACT[Factory]
        PROXY[ChannelOwner Proxy]
    end
    
    IMPL -->|creates| DISP
    DISP -->|returns guid| FACT
    FACT -->|creates| PROXY

Remote Connections

Playwright supports remote browser connections through PlaywrightConnection.

graph TD
    subgraph Local["Test Machine"]
        TEST[Test Code]
        CLIENT[Local Client]
    end
    
    subgraph Remote["Remote Machine"]
        SERVER[Playwright Server]
        BROWSER[Browser]
    end
    
    TEST --> CLIENT
    CLIENT -->|WebSocket| SERVER
    SERVER --> BROWSER

The remote connection maintains the same channel-based communication but uses WebSocket transport instead of in-process communication.

Sources: packages/playwright-core/src/remote/playwrightConnection.ts

Message Protocol

Message Structure

interface ProtocolMessage {
  id: string;           // Unique message ID
  guid: string;         // Target object GUID
  method: string;       // Method name
  params?: object;     // Method parameters
  type: 'request' | 'response' | 'event';
}

Event Subscription

Clients subscribe to server-side events through the channel system:

// Server emits event
dispatcher.dispatchEvent('eventName', payload);

// Client receives via callback
page.on('close', () => {
  console.log('Page closed');
});

Object Hierarchy

graph TD
    P[Playwright] --> BC[Browser]
    BC --> BCT[BrowserContext]
    BCT --> PGE[Page]
    
    PGE --> W[Worker]
    PGE --> R[Route]
    
    BCT --> RS[Request]
    BCT --> RS2[Response]
    
    style P fill:#c8e6c9
    style BC fill:#fff9c4
    style BCT fill:#bbdefb
    style PGE fill:#ffccbc

All objects inherit from ChannelOwner and maintain references to their parent connection.

Error Handling

The architecture handles errors through:

  1. Sync errors: Caught and returned as rejected promises
  2. Async errors: Propagated through the message response
  3. Disconnection: Server sends 'disconnected' event to notify clients
try {
  await page.click('#missing');
} catch (e) {
  // Error contains reason and stack
  console.log(e.message); // Target closed, did you mean to close the browser?
}

Key Design Patterns

Factory Pattern

Object factories in Connection create the appropriate ChannelOwner subclass based on protocol type.

Proxy Pattern

ChannelOwner instances are proxies that forward method calls to the server.

Observer Pattern

Event subscriptions allow clients to react to server-side state changes.

Promise-based Async

All operations return Promises, enabling async/await usage in tests.

Summary

Playwright's Client-Server Communication Architecture provides:

  • Type safety: Protocol definitions ensure consistent interfaces
  • Location transparency: Local and remote execution use the same API
  • Extensibility: New object types can be added to the protocol
  • Performance: Optimized message serialization and batching
  • Debuggability: Clear message flow between components

Sources: packages/playwright-core/src/client/channelOwner.ts

Browser Launch and Process Management

Related topics: Client-Server Communication Architecture, Browser Implementations and Protocol Support

Section Related Pages

Continue reading this section for the full explanation and source context.

Section High-Level Components

Continue reading this section for the full explanation and source context.

Section Core Component Roles

Continue reading this section for the full explanation and source context.

Section Out-of-Process Mode

Continue reading this section for the full explanation and source context.

Related topics: Client-Server Communication Architecture, Browser Implementations and Protocol Support

Browser Launch and Process Management

Overview

Browser Launch and Process Management is a core subsystem in Playwright responsible for spawning, communicating with, and lifecycle-managing browser processes. This subsystem abstracts the complexity of launching different browser types (Chromium, Firefox, WebKit) across different environments, handling both in-process and out-of-process execution models while maintaining reliable communication channels.

The system provides:

  • Cross-browser abstraction - Unified API for launching Chromium, Firefox, and WebKit
  • Process lifecycle management - Spawning, health monitoring, graceful termination
  • Dual execution modes - In-process and out-of-process browser execution
  • Transport layer abstraction - Message-based IPC between Node.js and browser processes
  • Resource cleanup - Proper disposal of browser instances and associated resources

Sources: packages/playwright-core/src/server/browserType.ts:1-50

Architecture

High-Level Components

graph TD
    A[Playwright Client API] --> B[BrowserType]
    B --> C{Launch Mode}
    C -->|Out-of-Process| D[OutOfProcess]
    C -->|In-Process| E[InProcess]
    D --> F[ProcessLauncher]
    D --> G[Transport Layer]
    E --> H[BrowserProcess]
    F --> I[Browser Executable]
    G --> J[Browser Server]
    H --> I

Core Component Roles

ComponentPackageResponsibility
BrowserTypeplaywright-coreEntry point for browser launching, delegates to appropriate implementation
OutOfProcessplaywright-coreManages out-of-process browser execution with separate server process
InProcessplaywright-coreManages in-process browser execution within Node.js
ProcessLauncherutilsCore process spawning and management utilities
Transportplaywright-coreMessage-based IPC communication layer
Browserplaywright-coreAbstract browser base class with lifecycle management

Sources: packages/playwright-core/src/server/browserType.ts:1-100

Launch Modes

Playwright supports two distinct browser launch modes, each suited for different use cases.

Out-of-Process Mode

The out-of-process (OOP) mode spawns browser processes as separate OS processes, with communication handled via WebSocket or pipe-based transport layers.

Characteristics:

  • Process isolation - Browser crashes do not affect the Node.js process
  • Cross-language support - Enables Playwright bindings in languages other than Node.js
  • Resource efficiency - Better for running multiple browser instances
  • Security - Browser runs in separate sandboxed process
graph LR
    A[Node.js Process] <-->|WebSocket/Pipes| B[Browser Server Process]
    B --> C[Browser Executable]

The OutOfProcess class handles:

  1. Spawning the browser server executable
  2. Establishing transport connection
  3. Handshake and version negotiation
  4. Proxying API calls to the browser

Sources: packages/playwright-core/src/outofprocess.ts:1-80

In-Process Mode

The in-process mode runs browser execution within the Node.js process itself, useful for scenarios requiring tighter integration.

Characteristics:

  • Direct execution - No inter-process communication overhead
  • Debugging simplicity - Easier to debug browser and client code together
  • Shared memory - Direct access to browser resources
  • Limited isolation - Browser crashes may affect Node.js process

The InProcess class provides a simplified launch path that instantiates browser internals directly without spawning separate processes.

Sources: packages/playwright-core/src/inprocess.ts:1-60

Mode Selection

// Out-of-process (default)
const browser = await chromium.launch({ headless: true });

// In-process via browser type's `launchServer`
const server = await chromium.launchServer({ headless: true });

Process Lifecycle

Launch Sequence

sequenceDiagram
    participant Client
    participant BrowserType
    participant Launcher
    participant Browser
    participant Transport

    Client->>BrowserType: launch(options)
    BrowserType->>Launcher: spawn(executable, args)
    Launcher->>Browser: new Browser(transport)
    Browser->>Transport: connect()
    Transport-->>Browser: connection established
    Browser->>Browser: initialize()
    Browser-->>BrowserType: ready
    BrowserType-->>Client: Browser instance

Lifecycle States

StateDescriptionTransitions
LaunchingProcess is being spawnedConnected or Failed
ConnectedTransport layer establishedInitialized or Closed
InitializedBrowser fully readyClosed
FailedLaunch or initialization failedTerminal state
ClosedBrowser process terminatedTerminal state

Sources: packages/playwright-core/src/server/browser.ts:1-150

Termination

Browser termination follows a controlled shutdown sequence:

  1. Graceful close request - Send close command to browser
  2. Resource cleanup - Dispose contexts, pages, and handlers
  3. Process termination - Kill the browser executable if still running
  4. Transport cleanup - Close connections and cleanup pipes
graph TD
    A[Browser.close called] --> B{Force kill?}
    B -->|No| C[Graceful shutdown]
    B -->|Yes| D[Kill process]
    C --> E[Wait for exit]
    E --> F[Force kill if timeout]
    D --> G[Cleanup resources]
    F --> G
    G --> H[Done]

Transport Layer

The transport layer enables message-based communication between the Node.js client and browser process.

Message Protocol

Messages follow a structured format with JSON-serialized headers and binary payloads:

┌─────────────────────────────────────────┐
│ Message Header (JSON)                   │
│ { id, method, params, binaryLength }    │
├─────────────────────────────────────────┤
│ Binary Payload (if binaryLength > 0)    │
└─────────────────────────────────────────┘

Transport Implementations

TypeUse CasePackage
PipeTransportLocal Windows processesplaywright-core
StdioTransportUnix domain socketsplaywright-core
WebSocketTransportRemote/cloud browsersplaywright-core

Sources: packages/playwright-core/src/server/transport.ts:1-100

Connection Establishment

class Transport {
  constructor(connection: Connection) {
    this._connection = connection;
  }

  async connect(pipe: Pipe): Promise<void> {
    // Establish connection to browser process
  }

  send(message: ProtocolMessage): void {
    // Serialize and send message
  }

  async close(): Promise<void> {
    // Graceful transport shutdown
  }
}

Process Launcher

The ProcessLauncher utility provides cross-platform process spawning and management.

Launch Options

OptionTypeDescription
executablePathstringPath to browser executable
argsstring[]Command-line arguments
envRecord<string,string>Environment variables
cwdstringWorking directory
stdio`'pipe' \'inherit'`Standard IO mode
detachbooleanRun in detached mode
timeoutnumberLaunch timeout in ms

Sources: packages/utils/processLauncher.ts:1-120

Process Monitoring

The launcher maintains process health through:

  1. Exit detection - Monitoring for unexpected process termination
  2. Output capture - Collecting stdout/stderr for debugging
  3. Resource limits - Optional memory and CPU limits
  4. Cleanup hooks - Automatic resource disposal on exit

Error Handling

interface LaunchError {
  reason: 'executable-not-found' | 'timeout' | 'crash' | 'protocol-error';
  message: string;
  stack?: string;
}

Browser Type Registry

Each browser type (Chromium, Firefox, WebKit) extends the base BrowserType class with browser-specific logic.

Browser Executable Resolution

graph TD
    A[launch called] --> B{Find browser?}
    B -->|User path| C[Validate executable]
    B -->|Default| D[Check installed browsers]
    C -->|Valid| E[Launch browser]
    C -->|Invalid| F[Throw error]
    D -->|Found| E
    D -->|Not found| G[Prompt installation]

BrowserType Interface

interface BrowserType {
  name(): string;
  executablePath(): string;
  launch(options?: LaunchOptions): Promise<Browser>;
  launchServer(options?: LaunchOptions): Promise<BrowserServer>;
  launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise<BrowserContext>;
  executable(): string;
  defaultArgs(options?: LaunchOptions): string[];
}

Sources: packages/playwright-core/src/server/browserType.ts:100-200

Configuration Options

Common Launch Options

OptionDefaultDescription
headlesstrueRun browser in headless mode
args[]Additional browser arguments
channelundefinedBrowser channel (e.g., 'chrome', 'msedge')
chromiumSandboxtrueEnable Chromium sandbox (Linux)
devtoolsfalseOpen DevTools on launch
downloadPathundefinedCustom download directory
envprocess.envEnvironment variables
executablePathundefinedCustom browser executable path
firefoxUserPrefs{}Firefox-specific preferences
proxyundefinedProxy configuration
timeout30000Launch timeout in milliseconds
viewport{ width: 1280, height: 720 }Default viewport size

Browser-Specific Options

#### Chromium

OptionTypeDescription
chromiumSandboxbooleanEnable Linux sandbox
proxyProxySettingsHTTP/SOCKS proxy
downloadContentTypesstring[]Content types to download

#### Firefox

OptionTypeDescription
firefoxUserPrefs`Record<string, string \number \boolean>`Gecko preferences
firefoxExtensionPathsstring[]Extension directories

#### WebKit

OptionTypeDescription
wkWebKitExperimentalSimulateSaturationbooleanSimulate saturation
wkWebKitExperimentalLayoutMetricsbooleanEnable layout metrics

Integration with CLI Tools

The browser launch system integrates with Playwright's CLI tooling for interactive browser automation.

CLI Session Management

# Open browser with named session
playwright-cli -s=mysession open https://example.com

# Create persistent profile
playwright-cli open https://example.com --persistent

# Browser selection
playwright-cli open https://example.com --browser=firefox

The CLI layer uses the same BrowserType APIs to establish browser sessions, with session state managed through the browser's context persistence mechanisms.

Best Practices

Resource Management

  1. Always close browsers - Use browser.close() in try/finally blocks
  2. Handle launch failures - Wrap launch calls in try/catch for graceful error handling
  3. Use context isolation - Launch separate contexts instead of separate browsers when possible
  4. Set appropriate timeouts - Adjust timeouts for slow environments

Launch Example

import { chromium } from 'playwright';

async function run() {
  let browser;
  try {
    browser = await chromium.launch({
      headless: true,
      timeout: 30000,
      args: ['--disable-gpu', '--no-sandbox'],
    });
    
    const context = await browser.newContext();
    const page = await context.newPage();
    
    // Perform actions...
    
  } catch (error) {
    console.error('Browser launch failed:', error);
  } finally {
    if (browser) {
      await browser.close();
    }
  }
}

Summary

The Browser Launch and Process Management system provides a robust foundation for browser automation in Playwright. By abstracting the complexities of process spawning, inter-process communication, and lifecycle management, it enables developers to work with browsers through a clean, consistent API regardless of the underlying browser type or execution environment.

Key takeaways:

  • Dual execution modes support both isolated (OOP) and integrated (in-process) browser execution
  • Transport abstraction enables reliable message passing across different IPC mechanisms
  • Lifecycle management ensures proper resource cleanup and graceful degradation
  • Browser type registry provides consistent APIs across Chromium, Firefox, and WebKit

Sources: packages/playwright-core/src/server/browserType.ts:1-50

Test Runner and Execution Engine

Related topics: Playwright Introduction and Project Overview, Locators, Selectors, and Element Interaction, Assertions, Matchers, and Expect API

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Core Components

Continue reading this section for the full explanation and source context.

Section Loading Pipeline

Continue reading this section for the full explanation and source context.

Section Configuration Files

Continue reading this section for the full explanation and source context.

Related topics: Playwright Introduction and Project Overview, Locators, Selectors, and Element Interaction, Assertions, Matchers, and Expect API

Test Runner and Execution Engine

The Playwright Test Runner is the core execution engine responsible for discovering, scheduling, and running end-to-end tests across multiple browsers and processes. It provides a complete test isolation model, automatic retry logic, parallel execution, and seamless integration with fixtures for test setup and teardown.

Architecture Overview

The test runner follows a multi-process architecture designed for scalability and isolation. At a high level, it consists of a central TestRunner process that coordinates test execution, multiple Worker processes that execute tests in isolated browser contexts, and a Dispatcher that manages the assignment of tests to available workers.

graph TD
    A[TestRunner<br/>Main Process] --> B[Dispatcher<br/>Test Assignment]
    B --> C[Worker Host 1<br/>Process]
    B --> D[Worker Host 2<br/>Process]
    B --> E[Worker Host N<br/>Process]
    C --> F[Browser Context 1]
    D --> G[Browser Context 2]
    E --> H[Browser Context N]
    F --> I[Page 1]
    G --> J[Page 2]
    H --> K[Page N]

Core Components

ComponentFile LocationResponsibility
TestRunnerpackages/playwright/src/runner/testRunner.tsEntry point; orchestrates the full test run lifecycle
Dispatcherpackages/playwright/src/runner/dispatcher.tsDistributes tests to workers and tracks completion
TestLoaderpackages/playwright/src/common/testLoader.tsDiscovers and parses test files
Fixturespackages/playwright/src/common/fixtures.tsManages test fixtures and dependencies
PoolBuilderpackages/playwright/src/common/poolBuilder.tsCreates and manages browser context pools
WorkerHostpackages/playwright/src/runner/workerHost.tsManages worker process lifecycle
WorkerMainpackages/playwright/src/worker/workerMain.tsWorker process entry point; runs actual tests

Sources: packages/playwright/src/runner/testRunner.ts:1-50 Sources: packages/playwright/src/runner/dispatcher.ts:1-60

Test Discovery and Loading

The test discovery process begins with the TestLoader, which recursively scans the project for test files matching the configured patterns. Playwright supports both .spec.ts and .spec.js file extensions by default, though these patterns are fully configurable through playwright.config.ts.

Loading Pipeline

graph LR
    A[Test Files<br/>*.spec.ts] --> B[TestLoader]
    B --> C[Parse Test Cases]
    C --> D[Extract Fixtures]
    D --> E[Build Test Tree]
    E --> F[Dispatcher]

The TestLoader performs the following operations:

  1. File Discovery — Scans the specified test directory for files matching the glob patterns defined in the configuration.
  2. Syntax Parsing — Parses each test file to extract test, test.describe, and test.beforeEach declarations.
  3. Fixture Extraction — Identifies fixture dependencies declared via test.use() or fixture function signatures.
  4. Test Tree Construction — Builds a hierarchical structure representing test suites and individual test cases.

Sources: packages/playwright/src/common/testLoader.ts:1-80

Configuration Files

Playwright recognizes two primary configuration file formats:

FileFormatPriority
playwright.config.tsTypeScriptHighest
playwright.config.jsJavaScriptLower
playwright.config.mjsES ModuleLower

The configuration defines critical execution parameters including:

// Example playwright.config.ts structure
export default defineConfig({
  timeout: 30000,           // Per-test timeout in milliseconds
  retries: 0,               // Number of retries on failure
  workers: process.env.CI ? 1 : undefined,  // Parallel workers
  reporter: 'html',         // Output format
  use: {
    baseURL: 'http://localhost',
    headless: true,
    viewport: { width: 1280, height: 720 },
    ignoreHTTPSErrors: false,
  },
  projects: [
    { name: 'chromium', use: { browserName: 'chromium' } },
    { name: 'firefox', use: { browserName: 'firefox' } },
    { name: 'webkit', use: { browserName: 'webkit' } },
  ],
});

Sources: package.json:test-scripts Sources: README.md:test-configuration

Worker Process Model

Each worker process operates as an independent execution unit, running in a separate Node.js process for complete isolation. The WorkerHost manages the lifecycle of these processes, handling creation, communication, and graceful termination.

Worker Lifecycle

stateDiagram-v2
    [*] --> Spawning: Start Worker
    Spawning --> Initializing: Worker PID obtained
    Initializing --> Ready: Fixtures initialized
    Ready --> Running: Test assigned
    Running --> Ready: Test complete
    Running --> Retrying: Test failed, retries remaining
    Retrying --> Running: Retry attempt
    Retrying --> Failed: No retries left
    Running --> Failed: Test failed, no retries
    Ready --> Shutdown: All tests complete
    Failed --> [*]: Worker terminated
    Shutdown --> [*]: Cleanup complete

Worker Communication

Workers communicate with the main process through an IPC (Inter-Process Communication) channel. The protocol supports the following message types:

Message TypeDirectionPurpose
initMain → WorkerInitialize worker with config
runMain → WorkerExecute a specific test
stopMain → WorkerCancel running test
doneWorker → MainReport test result
errorWorker → MainReport runtime error
teardownMain → WorkerGraceful shutdown

Sources: packages/playwright/src/runner/workerHost.ts:1-100 Sources: packages/playwright/src/worker/workerMain.ts:1-50

Dispatcher and Test Assignment

The Dispatcher is the central coordinator responsible for assigning tests to available workers while respecting configured parallelism limits. It maintains a queue of pending tests and dynamically allocates them based on worker availability.

Test Assignment Algorithm

graph TD
    A[Test Queue] --> B{Workers Available?}
    B -->|Yes| C[Pop Next Test]
    C --> D{Test has deps?}
    D -->|No| E[Assign to available worker]
    D -->|Yes| F[Wait for deps]
    F --> D
    E --> G[Execute Test]
    G --> H[Test Result]
    H --> I{Success?}
    I -->|Yes| J[Mark complete]
    I -->|No| K{Retries left?}
    K -->|Yes| L[Re-queue for retry]
    K -->|No| M[Mark failed]
    J --> A
    L --> A
    M --> A

The dispatcher implements the following strategies:

  • Load Balancing — Tests are distributed evenly across workers to maximize throughput.
  • Retry Logic — Failed tests are automatically re-queued up to the configured retry count.
  • Serial Execution per Worker — Each worker processes one test at a time to maintain isolation.
  • Sharding — Tests can be sharded across multiple machines using --shard flag.

Sources: packages/playwright/src/runner/dispatcher.ts:50-200

Parallelism Configuration

Config OptionCLI FlagDescription
workers--workersNumber of parallel worker processes
retries--retriesNumber of retry attempts per failed test
timeout--timeoutPer-test timeout in milliseconds
shard--shard=N/MShard tests across M machines, run shard N
# Run with 4 workers
npx playwright test --workers=4

# Run with retries and extended timeout
npx playwright test --retries=2 --timeout=60000

# Run shard 1 of 3
npx playwright test --shard=1/3

Fixture System

Fixtures provide a dependency injection mechanism for test setup and teardown. They ensure that resources are properly initialized before tests run and cleaned up afterward.

Fixture Types

TypeScopeUsage
staticAcross all testsGlobal configuration
workerPer worker processShared within one worker
testPer test executionFresh for each test
sessionAcross all workersShared global state
import { test as baseTest, expect } from '@playwright/test';

// Define a fixture with automatic cleanup
export const test = baseTest.extend({
  // Auto-cleanup database for each test
  database: async ({}, use) => {
    const db = await createTestDatabase();
    await use(db);
    await db.cleanup();
  },
  
  // Reuse authenticated page across all tests in a worker
  authenticatedPage: async ({ browser }, use) => {
    const context = await browser.newContext();
    const page = await context.newPage();
    await page.goto('/login');
    await page.fill('#username', 'testuser');
    await page.fill('#password', 'testpass');
    await page.click('#submit');
    await use(page);
    await context.close();
  },
});

Sources: packages/playwright/src/common/fixtures.ts:1-100

Built-in Fixtures

Playwright provides several built-in fixtures that are automatically available to all tests:

FixtureTypeDescription
pagetestFresh page for each test
contexttestFresh browser context
browserworkerBrowser instance shared in worker
requesttestAPIRequestContext for REST testing
testPlaywright test object

Browser Context Pooling

The PoolBuilder manages a pool of browser contexts to optimize resource usage. Rather than creating a new context for each test (which can be expensive), the pool maintains a set of reusable contexts.

Pooling Strategy

graph TD
    A[Test Request] --> B{Idle Context Available?}
    B -->|Yes| C[Use Pooled Context]
    B -->|No| D{Max Pool Size Reached?}
    D -->|No| E[Create New Context]
    D -->|Yes| F[Wait for Available]
    E --> C
    F --> C
    C --> G[Test Execution]
    G --> H{Context Satisfies Test?}
    H -->|Yes| I[Return to Pool]
    H -->|No| J[Destroy Context]
    J --> K[Create Fresh Context]
    K --> I

Context Configuration

Each project can define its own context configuration:

export default defineConfig({
  projects: [
    {
      name: 'chromium',
      use: {
        browserName: 'chromium',
        viewport: { width: 1920, height: 1080 },
        permissions: ['geolocation'],
        storageState: './auth.json',
        launchOptions: {
          args: ['--disable-dev-shm-usage'],
        },
      },
    },
  ],
});

Sources: packages/playwright/src/common/poolBuilder.ts:1-80

Debug Mode and CLI Integration

Playwright provides a CLI-based debugging mode that allows interactive inspection of test execution. When running with --debug=cli, the test runner pauses at the start and exposes a debug session.

Debug Workflow

graph TD
    A[npx playwright test --debug=cli] --> B[Test Paused at Start]
    B --> C[Debugging Instructions<br/>Session: tw-XXXX]
    C --> D[playwright-cli attach tw-XXXX]
    D --> E[Interactive Commands]
    E --> F[snapshot, click, fill, etc.]
    F --> G[Test Continues]
    G --> H[Capture Results]
    H --> I[Generate Report]

Debug Commands

CommandPurpose
playwright-cli snapshotGet current page snapshot with element refs
playwright-cli click <ref>Click an element by its reference
playwright-cli fill <ref> <text>Fill input field
playwright-cli eval <expression>Execute JavaScript in page context
playwright-cli resumeContinue test execution
playwright-cli screenshotCapture current page state
# Start test in debug mode
PLAYWRIGHT_HTML_OPEN=never npx playwright test --debug=cli

# In another terminal, attach to the debug session
playwright-cli attach tw-abcdef

# Explore the page
playwright-cli snapshot
playwright-cli click e15
playwright-cli eval "document.title"

Sources: packages/playwright-core/src/tools/cli-client/skill/references/playwright-tests.md:1-50

Tracing and Debugging

Playwright includes a comprehensive tracing system that captures detailed execution information for post-mortem analysis.

Trace Contents

CategoryCaptured Data
ActionsClicks, fills, navigations with timestamps
DOM SnapshotsBefore/after state for each action
ScreenshotsVisual state at key moments
NetworkAll HTTP requests/responses
ConsoleConsole.log output and errors
ErrorsStack traces for failures

Trace Commands

# Open a trace file
npx playwright trace open trace.zip

# List all actions
npx playwright trace actions

# View specific action details
npx playwright trace action <action-id>

# Get DOM snapshot at an action
npx playwright trace snapshot <action-id>

# View console errors
npx playwright trace console --errors-only
graph LR
    A[Test Execution] --> B[trace-{timestamp}.trace]
    A --> C[trace-{timestamp}.network]
    A --> D[resources/]
    B --> E[Action Log]
    C --> F[Network Activity]
    D --> G[Cached Assets]
    E --> H[Trace Viewer]
    F --> H
    G --> H

Sources: packages/playwright-core/src/tools/trace/SKILL.md:1-80

Execution Flow Summary

The complete test execution flow follows these stages:

sequenceDiagram
    participant User
    participant TestRunner
    participant TestLoader
    participant Dispatcher
    participant WorkerHost
    participant Worker

    User->>TestRunner: npx playwright test
    TestRunner->>TestLoader: Load tests
    TestLoader-->>TestRunner: Test tree
    TestRunner->>Dispatcher: Initialize
    TestRunner->>WorkerHost: Spawn workers
    WorkerHost->>Worker: Start process
    
    loop For each test
        Dispatcher->>WorkerHost: Assign test
        WorkerHost->>Worker: Run test
        Worker->>PoolBuilder: Request context
        PoolBuilder-->>Worker: Context
        Worker->>Fixtures: Setup fixtures
        Fixtures-->>Worker: Fixture values
        Worker->>Worker: Execute test body
        Worker->>Fixtures: Teardown fixtures
        Worker-->>WorkerHost: Test result
        WorkerHost-->>Dispatcher: Result
    end
    
    Dispatcher-->>TestRunner: All complete
    TestRunner->>User: Report

Command-Line Interface

Common Commands

CommandDescription
npx playwright testRun all tests
npx playwright test <file>Run specific file
npx playwright test --debugRun in debug mode
npx playwright test --listList all tests without running
npx playwright show-reportOpen HTML report

Configuration via CLI

# Override config values
npx playwright test --project=chromium --timeout=30000

# Run only matching tests
npx playwright test --grep="login"

# Run only failed tests from last run
npx playwright test --last-failed

# Update snapshots
npx playwright test --update-snapshots

Integration with Trace Viewer

The trace viewer is a Progressive Web App that opens trace files locally without sending data anywhere. It provides visual debugging capabilities.

graph TD
    A[Trace.zip] --> B[WorkbenchLoader]
    B --> C[TraceModel]
    C --> D[Actions Panel]
    C --> E[Screenshots Panel]
    C --> F[Network Panel]
    C --> G[Console Panel]
    D --> H[Unified Timeline]
    E --> H
    F --> H
    G --> H

To use the trace viewer:

  1. Run a test that generates a trace (using trace: 'on' in config)
  2. Locate the trace file in test-results/<test-name>/trace.zip
  3. Open at trace.playwright.dev or via CLI

Sources: packages/trace-viewer/src/ui/workbenchLoader.tsx:1-60

Summary

The Playwright Test Runner provides a production-grade testing infrastructure with:

  • Multi-process isolation ensuring test independence
  • Automatic resource management through fixture cleanup
  • Flexible parallelism configurable per project and CI environment
  • Rich debugging via CLI integration and trace playback
  • Cross-browser support executing tests on Chromium, Firefox, and WebKit
  • Comprehensive reporting with built-in HTML reports and trace viewer

The architecture cleanly separates concerns between test discovery (TestLoader), orchestration (Dispatcher), execution (Workers), and resource management (Fixtures, PoolBuilder), making it both maintainable and extensible.

Sources: packages/playwright/src/runner/testRunner.ts:1-50

Locators, Selectors, and Element Interaction

Related topics: Test Runner and Execution Engine, Assertions, Matchers, and Expect API

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Core Locator Methods

Continue reading this section for the full explanation and source context.

Section Locator vs ElementHandle

Continue reading this section for the full explanation and source context.

Section Selector Engine Types

Continue reading this section for the full explanation and source context.

Related topics: Test Runner and Execution Engine, Assertions, Matchers, and Expect API

Locators, Selectors, and Element Interaction

This page describes how Playwright locates DOM elements and interacts with them programmatically. The system consists of client-side Locator APIs, an in-browser Injected Script that evaluates selectors, and a server-side Selector Manager that registers and manages selector engines.

Architecture Overview

Playwright uses a layered architecture for element location:

LayerPackageResponsibility
Client APIplaywright-core/src/client/locator.tsFluent locator interface exposed to test authors
Server Managerplaywright-core/src/server/selectors.tsRegisters selector engines, manages context
Injected Scriptpackages/injected/src/Runs in browser context, evaluates selectors
graph TD
    A[Test Author Code] --> B[Locator API]
    B --> C[Selector Manager]
    C --> D[Registered Selector Engines]
    D --> E[Injected Script]
    E --> F[Browser DOM]
    
    B -->|locator.click/hover/fill| G[Action Commands]
    E -->|querySelector, querySelectorAll| F

Sources: packages/playwright-core/src/client/locator.ts Sources: packages/playwright-core/src/server/selectors.ts

Locator API

The Locator class provides a fluent API for finding and interacting with elements. It differs from ElementHandle by using *strict* mode by default and automatically retrying until elements are actionable.

Core Locator Methods

MethodDescription
click()Click the element
fill()Fill input field with text
hover()Hover over element
dblclick()Double-click element
check() / uncheck()Toggle checkbox/radio
selectOption()Select option(s) from dropdown
scrollIntoViewIfNeeded()Scroll element into view
tap()Perform tap gesture
dragAndDrop()Drag and drop operations

Locator vs ElementHandle

AspectLocatorElementHandle
EvaluationRe-evaluated on each actionCaptured once
Strict modeEnabled by defaultMust be manually enforced
RetriesAuto-retries until actionableSingle attempt
Shadow DOMTraverses automaticallyManual shadow traversal

The injected script exposes locator helpers via window.playwright:

this._injectedScript.window.playwright = {
  $: (selector: string, strict?: boolean) => this._querySelector(selector, !!strict),
  $$: (selector: string) => this._querySelectorAll(selector),
  inspect: (selector: string) => this._inspect(selector),
  selector: (element: Element) => this._selector(element),
  generateLocator: (element: Element, language?: Language) => this._generateLocator(element, language),
  ariaSnapshot: (element?: Element, options?: AriaTreeOptions) => { ... },
  resume: () => this._resume(),
  ...new Locator(this._injectedScript, ''),
};

Sources: packages/injected/src/consoleApi.ts:1-30

Selector Engine Architecture

Playwright supports multiple built-in selector engines that can be combined using the >> combinator.

Selector Engine Types

EnginePrefixExampleDescription
CSS(default)div.buttonStandard CSS selectors
Rolerole/role=button[name="Submit"]ARIA role matching
Texttext/text="Log In"Text content matching
Test IDtestId=testId=submit-btndata-testid attribute
Labellabel=label=UsernameForm label association
Alt Textalt=alt=Profile PhotoImage alt attributes
Titletitle=title=SettingsTitle attribute
XPathxpath=xpath=//button[1]XPath expressions
Regex/regex//^submit.*$/iPattern matching

Selector Evaluation Flow

graph LR
    A[Selector String] --> B[Parse & Split by >>]
    B --> C[Engine Registry Lookup]
    C --> D{Engine Type?}
    D -->|CSS| E[query/queryAll]
    D -->|Role| F[Role Selector Engine]
    D -->|Text| G[Text Selector Engine]
    D -->|Other| H[Custom Engine]
    E --> I[Evaluate in DOM]
    F --> I
    G --> I
    H --> I
    I --> J[Match Results]

Engine Registration

Selector engines are registered with the SelectorEngine class:

type SelectorEngine = {
  name: string;
  create?(root: Preview<Element>, target: Element, context: SelectorInjectedContext): Selector;
  query(root: Element, selector: Selector): Element | null;
  queryAll?(root: Element, selector: Selector): Element[];
};

Sources: packages/injected/src/selectorEngine.ts

Role Selector Engine

The role selector engine matches elements by their ARIA role with optional name and properties filters.

Supported ARIA Roles

The engine recognizes all standard ARIA roles including: button, link, checkbox, radio, textbox, searchbox, combobox, listbox, menu, menuitem, tab, tablist, dialog, alertdialog, and many more.

Role Selector Syntax

role=button[name="Submit"]
role=link[name="Documentation"]
role=textbox[name="Email"][include-hidden]
role=menuitemcheckbox[name="Bold"][checked]

Role Matching Logic

graph TD
    A[Input: role=button] --> B[Get all elements with role=button]
    B --> C{has name filter?}
    C -->|Yes| D[Filter by accessible name]
    C -->|No| E[Return all matches]
    D --> F{Matches found?}
    F -->|Yes| E
    F -->|No| G[Return empty]
    E --> H[Apply other filters]

Sources: packages/injected/src/roleSelectorEngine.ts

Selector Evaluator

The SelectorEvaluator class performs actual DOM matching using registered engines.

Key Methods

MethodSignaturePurpose
query(selector: ParsedSelector, root: Element, strict: boolean)Find single element
queryAll(selector: ParsedSelector, root: Element)Find all matches
parseSelector(selector: string)Parse selector string
preusable()Create context for reuse

Selector Parsing

Selectors are parsed into a structured format:

type ParsedSelector = {
  parsed: {
    engineName: string;
    strict: boolean;
    chain: {
      engine: string;
      selector: string;
      distance: number;
      shadow: ShadowRootLevel[];
    }[];
  };
};

Sources: packages/injected/src/selectorEvaluator.ts

Selector Generator

The selector generator suggests optimal selectors for elements during codegen and when using playwright codegen.

Generation Strategy

PrioritySelector TypeExample
1Test ID[data-testid="submit"]
2Accessiblerole=button[name="Submit"]
3Texttext="Submit"
4CSS#submit-btn
5Relativenth=5

Generator Implementation

The generator analyzes elements and ranks candidate selectors by:

  1. Uniqueness - Does this selector match exactly one element?
  2. Stability - Will this selector survive UI changes?
  3. Readability - Is this selector meaningful to humans?
  4. Brevity - Shorter selectors preferred when equivalent

Sources: packages/injected/src/selectorGenerator.ts

Injected Script Integration

The InjectedScript class provides the bridge between Node.js and browser contexts.

Architecture

graph TD
    A[Playwright Node.js] -->|Evaluate| B[InjectedScript]
    B --> C[Query Selector Engines]
    B --> D[Locator Generation]
    B --> E[ARIA Snapshot]
    B --> F[Console API]
    
    C --> G[DOM Manipulation]
    D --> H[Selector Suggestions]
    E --> I[Accessibility Tree]
    
    G --> J[User Actions]
    J -->|click, hover, type| K[Event Dispatch]

Console API Methods

MethodDescription
playwright.$()Query single element
playwright.$$()Query all elements
playwright.inspect()Highlight element
playwright.selector()Generate selector for element
playwright.generateLocator()Generate in specific language
playwright.ariaSnapshot()Get accessibility snapshot

Sources: packages/injected/src/injectedScript.ts

Using Locators with playwright-cli

The CLI tool supports all selector types for element interaction:

Element Targeting Methods

# Using snapshot refs (from playwright-cli snapshot)
playwright-cli click e15

# CSS selectors
playwright-cli click "#main > button.submit"

# Role locators
playwright-cli click "getByRole('button', { name: 'Submit' })"

# Test IDs
playwright-cli click "getByTestId('submit-button')"

Interaction Commands

CommandDescriptionExample
clickClick elementplaywright-cli click e5
fillType into inputplaywright-cli fill e4 "hello world"
hoverHover over elementplaywright-cli hover e4
selectSelect dropdown optionplaywright-cli select e9 "option-value"
check/uncheckToggle checkboxplaywright-cli check e12
dragDrag and dropplaywright-cli drop e4 --data="text/plain=hello"
uploadUpload fileplaywright-cli upload ./document.pdf

Sources: packages/playwright-core/src/tools/cli-client/skill/SKILL.md

Selector Manager

The server-side SelectorManager handles registration and lifecycle of selector engines across browser contexts.

Manager Responsibilities

ResponsibilityDescription
Engine RegistrationRegister built-in and custom engines
Context ManagementCreate/destroy selector contexts
Session HandlingMaintain state across browser sessions
Channel CommunicationBridge between server and injected script

Custom Selector Registration

// Register a custom selector engine
await test.selectors.register({
  name: 'my-selector',
  query: async (root, selector) => {
    return root.querySelector(selector);
  },
  queryAll: async (root, selector) => {
    return [...root.querySelectorAll(selector)];
  }
});

Sources: packages/playwright-core/src/server/selectors.ts

Element Interaction Flow

sequenceDiagram
    participant T as Test Code
    participant L as Locator API
    participant S as Selector Manager
    participant I as Injected Script
    participant B as Browser DOM

    T->>L: locator.click("button")
    L->>S: query("button")
    S->>I: evaluate querySelector
    I->>B: query DOM
    B->>I: return Element
    I->>S: return Element
    S->>L: return Element
    L->>L: waitForElement
    L->>T: click complete

Best Practices

Preferred Selector Order

  1. Test IDs (data-testid) — Most stable and explicit
  2. Role + Name — Semantically meaningful and accessible
  3. Text Content — Human-readable but may change
  4. CSS Classes/IDs — Fast but brittle
  5. XPath — Last resort; hard to maintain

Anti-Patterns to Avoid

Anti-PatternProblemAlternative
Index-based nth=Breaks with layout changesUse role/name filtering
Deep CSS pathsFragile to DOM changesUse semantic selectors
Dynamic attributesUnstable in CIUse stable test IDs
CoordinatesResolution-dependentUse element targets

Summary

Playwright's locator and selector system provides a flexible, multi-engine approach to DOM element identification:

  • Locator API offers a fluent, retry-based interface for test authors
  • Multiple selector engines handle CSS, ARIA roles, text, and custom selectors
  • Injected Script enables browser-side evaluation without round-trips
  • Selector Generator helps discover optimal selectors during development

The architecture prioritizes accessibility (role selectors), stability (test IDs), and developer experience (fluent API) while maintaining performance through optimized DOM queries.

Sources: packages/playwright-core/src/client/locator.ts

Assertions, Matchers, and Expect API

Related topics: Test Runner and Execution Engine, Locators, Selectors, and Element Interaction

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Expect Implementation

Continue reading this section for the full explanation and source context.

Section Matchers Module

Continue reading this section for the full explanation and source context.

Section Isomorphic Utilities

Continue reading this section for the full explanation and source context.

Related topics: Test Runner and Execution Engine, Locators, Selectors, and Element Interaction

Assertions, Matchers, and Expect API

Playwright's assertion system provides a powerful, auto-retrying mechanism for validating application state during end-to-end testing. The expect API combined with matchers enables test authors to write expressive, readable assertions that automatically wait for conditions to be met rather than requiring manual polling or arbitrary timeouts.

Overview

Playwright's assertion framework is built on three core concepts that work together to provide reliable test assertions:

ComponentPurpose
Expect APICore assertion function that wraps values and provides matcher methods
MatchersIndividual comparison functions that validate specific conditions
Expect UtilsShared utility functions for handling timeouts, polling, and error messages

The architecture follows a layered approach where the expect function creates an expectation object that chains matcher methods. Each matcher returns either a pass result or throws an error with detailed context about what failed.

graph TD
    A[Test Code] --> B[expect value]
    B --> C[Expectation Object]
    C --> D[Matcher Methods]
    D --> E{Auto-retry Loop}
    E -->|condition met| F[Pass - Continue]
    E -->|condition not met| G[Wait and Retry]
    G --> E
    E -->|timeout exceeded| H[Throw ExpectationError]
    F --> I[Test Continues]
    H --> J[Test Fails]

Core Files and Structure

Expect Implementation

The main expect function is defined in packages/playwright/src/matchers/expect.ts. This file exports the expect function and the Expect class that handles the retry logic and matcher invocation.

Key responsibilities:

  • Creating expectation objects from actual values
  • Managing auto-retry mechanisms with configurable timeouts
  • Formatting error messages with expected vs. actual values
  • Supporting both synchronous and asynchronous expectations

Matchers Module

The matchers are defined in packages/playwright/src/matchers/matchers.ts. This file contains all built-in matcher functions that can be chained off the expect call.

Isomorphic Utilities

Shared assertion utilities in packages/isomorphic/expectUtils.ts and packages/isomorphic/assert.ts provide platform-agnostic functionality used across different Playwright packages.

Expect API Reference

Basic Usage

import { test, expect } from '@playwright/test';

test('login page', async ({ page }) => {
  await page.goto('/login');
  
  // Basic equality assertion
  await expect(page).toHaveTitle('Login');
  
  // Locator assertion with auto-wait
  await expect(page.getByRole('button', { name: 'Submit' })).toBeVisible();
  
  // Text content assertion
  await expect(page.locator('.error')).toHaveText('Invalid credentials');
});

Configuration Options

OptionTypeDefaultDescription
timeoutnumberMatcher's defaultMaximum time to retry the assertion
message`string \function`auto-generatedCustom error message on failure
containsText`string \RegExp`-Pattern that should appear in error

Built-in Matchers

Web-First Assertions

Playwright provides specialized "web-first" assertions optimized for UI testing. These assertions automatically wait for the expected state before failing.

#### Visibility and Presence

MatcherDescription
toBeVisible()Element is visible and not obscured
toBeHidden()Element is not visible
toBeAttached()Element is present in DOM
toBeEnabled()Element is enabled (not disabled)
toBeDisabled()Element is disabled
toBeEditable()Element is editable
toBeFocused()Element has focus

#### Content Assertions

MatcherDescription
toHaveText(expected, options?)Element contains exact or partial text
toContainText(expected)Element contains text (partial match)
toHaveValue(value)Input element has specific value
toHaveValues(values)Multiple select or checkbox group values
toHaveTitle(title)Page has specific title
toHaveURL(url)Page has specific URL
toHaveScreenshot(name, options?)Element/page matches screenshot

#### Form and Input Assertions

MatcherDescription
toBeChecked()Checkbox or radio is checked
toHaveChecked()Checkbox with specific state
toBeSelected()Option is selected in select element
toBeRequired()Input is marked as required
toBeValid()Input passes validation constraints

Negation

All matchers support negation using .not:

await expect(page.getByRole('button')).not.toBeDisabled();
await expect(page.locator('.loading')).not.toBeVisible();

Snapshot Testing

Playwright supports snapshot testing through dedicated matchers that compare rendered output against stored baselines.

Visual Snapshots

The toMatchSnapshot matcher captures and compares images:

test('screenshot comparison', async ({ page }) => {
  await page.goto('/dashboard');
  await expect(page).toMatchScreenshot('dashboard.png', {
    fullPage: true,
    animations: 'disabled'
  });
});

Parameters:

ParameterTypeDescription
namestringSnapshot file name
options?.fullPagebooleanCapture entire scrollable page
options?.animations`'disabled' \'allow'`Animation handling
options?.masklocator[]Elements to mask in screenshot
options?.thresholdnumberPixel matching threshold 0-1

Aria Snapshots

The toMatchAriaSnapshot matcher compares the semantic structure of the page:

test('page structure', async ({ page }) => {
  await page.goto('/form');
  await expect(page).toMatchAriaSnapshot(`
    - heading "Create Account"
    - textbox "Email"
    - textbox "Password"
    - button "Submit"
  `);
});

Parameters:

ParameterTypeDescription
snapshotstringExpected ARIA tree structure
options?.timeoutnumberRetry timeout in ms
options?.matcher`string \RegExp`Custom snapshot matcher

Updating Snapshots

When UI changes are intentional, update snapshots using the CLI:

npx playwright test --update-snapshots
# or
npx playwright test -u

Custom Matchers

Defining Custom Matchers

Extend the expect object with custom matchers for project-specific assertions:

// expect.d.ts or custom expect file
import { expect as baseExpect } from '@playwright/test';

export { test } from '@playwright/test';

export const expect = baseExpect.extend({
  async toHaveAnalyticsEvent(
    locator: Locator,
    eventName: string,
    options?: { timeout?: number }
  ) {
    const timeout = options?.timeout ?? 1000;
    const analyticsData: string[] = [];
    
    const listener = (event: ConsoleMessage) => {
      if (event.type() === 'log') {
        analyticsData.push(event.text());
      }
    };
    
    locator.page().on('console', listener);
    
    try {
      await page.waitForFunction(
        (name) => window.analytics?.events?.includes(name),
        eventName,
        { timeout }
      );
      return { pass: true };
    } catch {
      return {
        pass: false,
        message: () => `Expected analytics event "${eventName}" was not fired`,
      };
    } finally {
      locator.page().off('console', listener);
    }
  },
});

Using Custom Matchers

import { expect } from './expect';

test('analytics tracking', async ({ page }) => {
  await page.goto('/products');
  await page.click('.buy-button');
  
  // Uses custom matcher
  await expect(page).toHaveAnalyticsEvent('purchase_initiated');
});

Auto-Retry Behavior

Playwright assertions automatically retry until the condition is met or timeout expires. This eliminates flaky tests caused by timing issues.

Retry Loop Flow

sequenceDiagram
    participant T as Test
    participant E as Expect
    participant M as Matcher
    participant P as Page

    T->>E: expect(locator).toBeVisible()
    Note over E: Create Expectation
    loop Retry until timeout
        E->>M: Compare current state
        M->>P: Query element state
        alt Condition met
            M-->>E: Pass
            E-->>T: Continue
        else Condition not met
            M-->>E: Fail
            E->>E: Wait (default: 100ms)
        end
    end
    Note over E: Timeout exceeded
    E-->>T: Throw ExpectationError

Timeout Configuration

// Per-assertion timeout
await expect(page.locator('.loading')).toBeHidden({ timeout: 5000 });

// Global default timeout
// In playwright.config.ts:
export default {
  expect: {
    timeout: 5000,
  },
};

Timeout Inheritance

Configuration LocationValue
Assertion option{ timeout: 3000 }
expect config section5000
Test fixtureInherited
Default1000 (1 second)

Error Messages

Playwright generates detailed, actionable error messages when assertions fail.

Error Message Structure

expect(received).toHaveText(expected)

Expected string: "Welcome, John"
Received string: "Welcome, Guest"

Custom Messages

await expect(page.locator('.balance')).toHaveText(
  '$100.00',
  { message: 'Balance should reflect completed transaction' }
);

// Or use a function for dynamic messages
await expect(page.locator('.status')).toHaveText(
  'Active',
  { message: () => `Expected status for user ${userId} to be Active` }
);

TypeScript Integration

Type Safety

All matchers are fully typed and provide autocomplete support:

// TypeScript infers expected type
await expect(page.locator('input')).toHaveValue('hello');

// For complex matchers, types are enforced
await expect(page).toHaveScreenshot('button.png', {
  // options type is inferred
  fullPage: true,
  animations: 'disabled'
});

Generic Assertions

For custom assertion types, use generics:

expect.extend({
  async toHaveData属性<T>(
    this: jest.MatcherContext,
    received: T,
    key: string,
    value: unknown
  ) {
    const data = (received as any)[key];
    return {
      pass: data === value,
      message: () => `Expected ${key} to be ${value}, got ${data}`,
    };
  },
});

Best Practices

Prefer Web-First Assertions

Always use Playwright's built-in web-first assertions over raw comparisons:

// ❌ Fragile - no auto-wait
expect(await page.textContent('button')).toBe('Submit');

// ✅ Reliable - auto-waits and handles timing
await expect(page.getByRole('button')).toHaveText('Submit');

Combine Matchers

Chain multiple matchers for comprehensive checks:

await expect(page.getByRole('textbox', { name: 'Email' }))
  .toBeVisible()
  .toBeEnabled()
  .toBeFocused()
  .toHaveAttribute('type', 'email');

Use Descriptive Names

Name expectations clearly for better test output:

// ❌ Unclear
await expect(page.locator('.main')).toHaveScreenshot('shot.png');

// ✅ Clear intent
await expect(page).toMatchScreenshot('checkout-page-cart-items.png');

Summary

The Assertions, Matchers, and Expect API form the foundation of Playwright's verification capabilities. Key takeaways:

AspectKey Point
Auto-retryAssertions automatically wait for conditions, reducing flakiness
Web-firstBuilt specifically for dynamic web applications
Rich matchersComprehensive set of UI-specific assertions
Snapshot supportVisual and semantic snapshot testing built-in
ExtensibilityCustom matchers via expect.extend
TypeScriptFull type safety and autocomplete support

The system is designed to make tests reliable by default, allowing developers to focus on test logic rather than timing and synchronization concerns.

Source: https://github.com/microsoft/playwright / Human Manual

Browser Implementations and Protocol Support

Related topics: Browser Launch and Process Management, CLI, MCP Server, and Agent Integration

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Chromium Architecture

Continue reading this section for the full explanation and source context.

Section Browser Type (chromium.ts)

Continue reading this section for the full explanation and source context.

Section Browser Instance (crBrowser.ts)

Continue reading this section for the full explanation and source context.

Related topics: Browser Launch and Process Management, CLI, MCP Server, and Agent Integration

Browser Implementations and Protocol Support

Overview

Playwright's browser implementation architecture provides a unified automation API across three major browser engines: Chromium, Firefox, and WebKit. The architecture abstracts browser-specific differences through a common interface while supporting multiple protocols for communication between the Node.js process and browser instances. This design enables developers to write browser automation code once and execute it across different browsers without modification.

The browser implementations are organized in the packages/playwright-core/src/server/ directory, with each browser type having its own subdirectory containing browser-specific initialization, connection, and protocol handling code. This modular structure allows for independent development and maintenance of each browser's implementation while sharing common infrastructure through the core playwright-core package.

Architecture Overview

graph TD
    subgraph "Playwright Core API"
        A[chromium.launch()] --> B[BrowserType]
        C[firefox.launch()] --> B
        D[webkit.launch()] --> B
    end
    
    subgraph "Protocol Layer"
        B --> E[CDP Connection]
        B --> F[BiDi Protocol]
    end
    
    subgraph "Browser Implementations"
        E --> G[Chromium Browser]
        E --> H[WebKit Browser]
        F --> I[Firefox Browser]
        F --> J[Chromium via BiDi]
        F --> K[WebKit via BiDi]
    end
    
    subgraph "Browser Processes"
        G --> L[Chromium Process]
        H --> M[WebKit Process]
        I --> N[Firefox + Juggler]
    end

Browser Package Structure

Playwright provides separate packages for each browser to optimize installation and distribution. The packages enable automatic installation of browser binaries when imported.

Package NameDescriptionAuto-InstallMain Export
playwright-chromiumChromium browser supportYeschromium
@playwright/browser-chromiumChromium browser supportYeschromium
playwrightAll browsersYeschromium, firefox, webkit
playwright-coreAll browsersNochromium, firefox, webkit
@playwright/browser-webkitWebKit browser supportYeswebkit
playwright-browser-webkitWebKit browser supportYeswebkit

Each package exports a chromium, firefox, or webkit object that provides the BrowserType interface for launching browser instances. The packages share common dependencies through playwright-core, which contains the actual implementation logic.

Chromium Implementation

The Chromium implementation consists of two main components: the browser type definition and the actual browser instance management.

Chromium Architecture

graph TD
    A[chromium.launch()] --> B[Chromium#44;BrowserType]
    B --> C[ChromiumBrowser#44;ConnectedBrowser]
    C --> D[CDP Session]
    C --> E[ChromiumBrowserContext]
    D --> F[Chrome DevTools Protocol]
    E --> G[ChromiumPage]
    G --> F

Browser Type (`chromium.ts`)

The Chromium browser type class extends the base BrowserType interface and provides the specific configuration for launching Chromium instances. This file contains:

  • Launch options: Configuration for headless mode, viewport, user agent, and other browser settings
  • Browser binary path: Resolution logic for finding the Chromium executable
  • Connection establishment: Code for establishing CDP connections to the browser
  • Feature detection: Capabilities and features specific to Chromium

Browser Instance (`crBrowser.ts`)

The Chromium browser instance class manages the lifecycle of a connected Chromium browser. Key responsibilities include:

  • Page management: Creating and tracking page instances
  • Context management: Handling browser contexts for isolation
  • CDP session handling: Managing DevTools protocol sessions
  • Process management: Monitoring and terminating the browser process

Firefox Implementation

Firefox requires special handling due to its architecture. Unlike Chromium and WebKit which support CDP directly, Firefox uses a patched version called Juggler.

Firefox Architecture with Juggler

graph TD
    A[firefox.launch()] --> B[Firefox#44;BrowserType]
    B --> C[FFBrowser#44;ConnectedBrowser]
    C --> D[Juggler Bridge]
    D --> E[CDP to Juggler Translation]
    E --> F[Firefox Browser Process]
    
    subgraph "Browser Patches"
        G[Juggler Protocol]
        H[CDP Emulator]
        I[Automation Hooks]
    end
    
    D --> G
    G --> H
    G --> I

Juggler Protocol Handler

The Firefox implementation uses Juggler, a custom protocol handler that bridges Playwright's CDP-based API with Firefox's automation capabilities. The Juggler component:

  • Patches Firefox: Modifies Firefox behavior to enable automation
  • Protocol translation: Converts CDP commands to Firefox-specific commands
  • Event forwarding: Streams events from Firefox back to Playwright

This architecture allows Playwright to provide a consistent API across all browsers while accommodating Firefox's different internal architecture.

Browser Type (`firefox.ts`)

The Firefox browser type handles:

  • Binary detection: Locating the Firefox executable
  • Profile management: Creating temporary profiles for isolation
  • Launch configuration: Setting up Firefox-specific options
  • Juggler injection: Ensuring Juggler is properly initialized

Browser Instance (`ffBrowser.ts`)

The Firefox browser instance provides:

  • Page tracking: Managing page instances within Firefox
  • Context handling: Isolating browsing contexts
  • Protocol communication: Managing Juggler-based communication

WebKit Implementation

WebKit powers Safari and other browsers. Playwright's WebKit implementation provides support for this browser engine through a combination of native CDP support and custom protocol handling.

WebKit Architecture

graph TD
    A[webkit.launch()] --> B[WebKit#44;BrowserType]
    B --> C[WKBrowser#44;ConnectedBrowser]
    C --> D[WebKit Protocol Handler]
    D --> E[CDP Compatible Layer]
    E --> F[WebKit Browser Process]
    
    C --> G[WebKitBrowserContext]
    G --> H[WKPage]
    H --> D

Browser Type (`webkit.ts`)

The WebKit browser type includes:

  • Executable resolution: Finding WebKit-based browsers
  • Launch parameters: Configuring WebKit-specific options
  • Connection setup: Establishing protocol communication

Browser Instance (`wkBrowser.ts`)

The WebKit browser instance manages:

  • Page lifecycle: Creating and managing page instances
  • Protocol sessions: Handling WebKit's protocol communication
  • Feature compatibility: Ensuring WebKit-specific features work correctly

BiDi Protocol Support

The WebDriver BiDi (Bidirectional) protocol is a standardized web automation protocol that provides bidirectional communication between automation tools and browsers. Playwright's support for BiDi enables:

  • Standardization: Using the W3C-standardized protocol
  • Cross-browser compatibility: A single protocol approach
  • Reduced complexity: Simpler protocol handling compared to CDP

BiDi Architecture

graph TD
    A[BiDi Browser Connection] --> B[BidiBrowser#44;ConnectedBrowser]
    B --> C[BiDi Session]
    C --> D[Command Handler]
    C --> E[Event Handler]
    
    D --> F[Browser Commands]
    E --> G[Browser Events]
    
    B --> H[BrowserContext]
    H --> I[Page]
    
    subgraph "BiDi Protocol Messages"
        J[JSON-RPC 2.0]
        K[WebSocket Transport]
    end
    
    C --> J
    J --> K

BiDi Browser (`bidiBrowser.ts`)

The BiDi browser implementation provides:

  • Session management: Creating and maintaining BiDi sessions
  • Command routing: Dispatching commands to appropriate handlers
  • Event subscription: Managing browser event subscriptions
  • Context isolation: Supporting multiple browser contexts

Protocol Communication

Playwright supports multiple communication protocols for interacting with browsers. Understanding these protocols helps in debugging and extending Playwright's capabilities.

Chrome DevTools Protocol (CDP)

CDP is the primary protocol used by Chromium and partially by WebKit. It provides:

  • Complete browser control: Full access to browser features
  • Rich debugging: Detailed debugging capabilities
  • Real-time events: Immediate event notifications

WebDriver BiDi

BiDi is the W3C-standardized protocol for browser automation:

  • Cross-browser support: Standard protocol across all browsers
  • Bidirectional communication: Events flow both directions
  • Simpler model: Less complex than CDP for basic operations

Protocol Selection

FeatureCDPBiDi
Browser supportChromium, WebKitAll browsers
Event subscriptionFullFull
PerformanceOptimizedStandard
StandardizationGoogle-specificW3C standard

Launch Configuration

Each browser type accepts launch options that configure how the browser instance is created.

Common Launch Options

OptionTypeDescriptionChromiumFirefoxWebKit
headlessbooleanRun without visible UI
argsstring[]Additional browser arguments
executablePathstringCustom browser executable
timeoutnumberLaunch timeout in ms
viewportViewportDefault page viewport
userAgentstringCustom user agent
localestringBrowser locale
proxyProxyConfigProxy settings

Headless Mode

Headless mode runs the browser without visible UI, essential for CI/CD environments and server-side automation. All three browsers support headless execution with identical behavior.

Persistent Contexts

Playwright supports persistent browser contexts that maintain state across sessions:

graph LR
    A[User Data Directory] --> B[Browser Profile]
    B --> C[Cookies]
    B --> D[Local Storage]
    B --> E[Session Storage]
    B --> F[Cache]

Browser Contexts and Pages

Architecture

graph TD
    Browser --> Context1[BrowserContext]
    Browser --> Context2[BrowserContext]
    
    Context1 --> Page1[Page]
    Context1 --> Page2[Page]
    Context2 --> Page3[Page]
    
    Page1 --> CDPSession[CDP Session]
    Page2 --> CDPSession

BrowserContext

Browser contexts provide isolation between different automation sessions:

  • Separate storage: Each context has its own cookies, cache, and storage
  • Independent state: Actions in one context don't affect others
  • Parallel execution: Contexts can run simultaneously
  • Resource isolation: Memory and process isolation

Page

Pages represent individual browser tabs or windows:

  • Navigation: Loading URLs and managing history
  • Interaction: Clicking, typing, and other user actions
  • Evaluation: Running JavaScript in the page context
  • Capture: Taking screenshots and generating PDFs

Process Architecture

Browser Process Model

graph TD
    subgraph "Node.js Process"
        A[Playwright API]
        B[Connection]
    end
    
    subgraph "Browser Process"
        C[Browser Main Process]
        D[Renderer Process 1]
        E[Renderer Process 2]
        F[Renderer Process N]
    end
    
    B --> C
    C --> D
    C --> E
    C --> F

Process Communication

The communication between Node.js and browser processes varies by browser:

  • Chromium: Direct CDP over WebSocket or pipe
  • Firefox: Juggler bridge acting as intermediary
  • WebKit: CDP-compatible protocol over WebSocket

Version Compatibility

Playwright maintains compatibility matrices for browser versions to ensure stable automation:

Playwright VersionChromiumFirefoxWebKit
1.61.0-nextLatestLatestLatest
Stable releasesBundledBundledBundled

Browser binaries are downloaded and managed by Playwright's installer, ensuring version compatibility between the library and browser binaries.

Extension Points

The browser implementation architecture supports extension through:

Custom Browser Executables

const browser = await chromium.launch({
  executablePath: '/path/to/custom/chromium'
});

Protocol Interceptors

Extensions can intercept and modify protocol messages for debugging or custom behavior.

Custom Context Options

Browser contexts accept custom options specific to each browser implementation.

Troubleshooting

Browser Installation Issues

# Install all browsers
npx playwright install

# Install specific browser
npx playwright install chromium
npx playwright install firefox
npx playwright install webkit

Connection Issues

Connection problems typically manifest as timeout errors during launch or operation. The trace viewer tool (npx playwright trace) helps diagnose these issues by capturing detailed protocol communication.

Platform-Specific Considerations

Each browser may have platform-specific requirements:

  • Chromium: Generally has few platform-specific issues
  • Firefox: Requires Juggler patches for all platforms
  • WebKit: May require platform-specific dependencies

Summary

Playwright's browser implementation architecture provides a robust, extensible foundation for cross-browser automation. By abstracting browser-specific details through a common interface while supporting multiple communication protocols, Playwright enables developers to write reliable browser automation code that works consistently across Chromium, Firefox, and WebKit.

The architecture's modular design allows for independent browser implementations while sharing common infrastructure, making it possible to add new browser support or extend existing capabilities without affecting the overall system.

Source: https://github.com/microsoft/playwright / Human Manual

Trace Viewer and Debugging Tools

Related topics: Test Runner and Execution Engine, CLI, MCP Server, and Agent Integration

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Core Components

Continue reading this section for the full explanation and source context.

Section File Structure

Continue reading this section for the full explanation and source context.

Section Trace Archive

Continue reading this section for the full explanation and source context.

Related topics: Test Runner and Execution Engine, CLI, MCP Server, and Agent Integration

Trace Viewer and Debugging Tools

Overview

Playwright's Trace Viewer and Debugging Tools provide comprehensive execution tracing capabilities for debugging and analyzing browser automation tests. The tracing system captures detailed execution traces including DOM snapshots, screenshots, network activity, and console logs, enabling developers to reconstruct and analyze exactly what happened during test execution.

The trace infrastructure consists of three main components:

ComponentPurposeLocation
Trace RecorderCaptures actions, snapshots, and metadata during test executionpackages/playwright-core/src/server/trace/recorder/
Trace ViewerProgressive Web App for visual trace inspectionpackages/trace-viewer/
Trace ModelData structures and loading logic for trace filespackages/isomorphic/trace/

Sources: packages/trace-viewer/src/index.tsx

Architecture

graph TD
    A[Test Execution] --> B[Tracing Recorder]
    B --> C[Snapshotter]
    B --> D[Action Logger]
    B --> E[Network Monitor]
    
    C --> F[DOM Snapshots]
    D --> G[Action Log]
    E --> H[Network Events]
    
    F --> I[trace-{timestamp}.trace]
    G --> I
    H --> J[trace-{timestamp}.network]
    
    I --> K[Trace ZIP Archive]
    J --> K
    K --> L[Trace Viewer PWA]
    K --> M[playwright trace CLI]

Core Components

#### Trace Recorder (packages/playwright-core/src/server/trace/recorder/tracing.ts)

The Tracing class manages the recording process for browser contexts. It initializes snapshot capture, action logging, and network monitoring.

MethodDescription
start()Initializes trace recording with snapshotter and action collectors
stop()Finalizes and writes trace files
snapshot()Captures current DOM state

#### Snapshotter (packages/playwright-core/src/server/trace/recorder/snapshotter.ts)

Captures DOM snapshots before and after each action, enabling reconstruction of page state at any point during test execution.

Sources: packages/playwright-core/src/server/trace/recorder/snapshotter.ts

#### Trace Model (packages/isomorphic/trace/traceModel.ts)

The TraceModel class represents the in-memory structure of a trace file, containing:

PropertyTypeDescription
actionsActionTrace[]All recorded actions
eventsTraceEvent[]Network, console, and other events
snapshotsSnapshot[]DOM snapshots

#### Trace Loader (packages/isomorphic/trace/traceLoader.ts)

Handles parsing and loading of trace files from disk or network.

Sources: packages/isomorphic/trace/traceLoader.ts

Trace File Format

When tracing starts, Playwright creates a traces/ directory containing several files:

File Structure

FileFormatContents
trace-{timestamp}.traceBinary/JSONAction log with DOM snapshots, screenshots, timing
trace-{timestamp}.networkBinary/JSONComplete network activity including headers, bodies, timing
resources/DirectoryCached resources (images, fonts, scripts)

Trace Archive

All trace files are packaged into a .zip archive for easy sharing and analysis:

# Default location
test-results/{test-name}/trace.zip

Captured Data Categories

CategoryDetails
ActionsClicks, fills, hovers, keyboard input, navigations
DOMFull DOM snapshot before/after each action
ScreenshotsVisual state at each step
NetworkAll requests, responses, headers, bodies, timing
ConsoleBrowser console messages and stdout/stderr
ErrorsError messages with stack traces

Sources: packages/playwright-core/src/tools/cli-client/skill/references/tracing.md

Trace Viewer UI

The Trace Viewer is a Progressive Web App that runs locally in the browser without sending trace data anywhere.

graph LR
    A[Open trace.zip] --> B[Extract & Parse]
    B --> C[Action Timeline]
    B --> D[Snapshot View]
    B --> E[Network Log]
    B --> F[Console Output]

Key Features

FeatureDescription
Action TimelineVisual representation of all actions with timing
DOM SnapshotsInteractive DOM inspection at any action point
Network LogFilterable view of all HTTP requests/responses
Console ViewConsole messages with filtering by type
Error TrackingConsolidated view of all errors with stack traces

Loading Traces

Traces can be loaded in multiple ways:

  1. Local File: Drop .zip file directly into the viewer
  2. URL Parameter: Pass ?trace= with trace URL
  3. Upload Button: Select file via browser dialog

The viewer displays a progress indicator during trace loading:

<Dialog open={showProgressDialog} isModal={true}>
  <div className='progress-content'>
    <div className='title'>Loading Playwright Trace...</div>
    <div className='progress-wrapper'>
      <div className='inner-progress' 
        style={{ width: progress.total ? (100 * progress.done / progress.total) + '%' : 0 }}>
      </div>
    </div>
  </div>
</Dialog>

Sources: packages/trace-viewer/src/ui/workbench.tsx

CLI Commands

Trace Recording Commands

CommandDescription
playwright-cli tracing-startStart trace recording
playwright-cli tracing-stopStop trace recording and save

Trace Inspection Commands

CommandDescription
npx playwright trace open <trace.zip>Open and extract trace
npx playwright trace closeRemove extracted trace data
npx playwright trace actionsList all actions
npx playwright trace actions --grep "click"Filter actions by pattern
npx playwright trace actions --errors-onlyShow only failed actions
npx playwright trace action <id>Show details for one action
npx playwright trace requestsList all network requests
npx playwright trace requests --failedShow only failed requests
npx playwright trace request <id>Show request details
npx playwright trace consoleShow console messages
npx playwright trace console --errors-onlyShow only errors
npx playwright trace errorsShow all errors with stack traces
npx playwright trace snapshot <id>Get DOM snapshot
npx playwright trace attachmentsList trace attachments

Example Workflow

# 1. Open trace and view metadata
npx playwright trace open test-results/my-test/trace.zip

# 2. List all actions
npx playwright trace actions

# 3. Show only failed actions
npx playwright trace actions --errors-only

# 4. Get details for specific action
npx playwright trace action 12

# 5. View DOM at that point
npx playwright trace snapshot 12

# 6. Check for network failures
npx playwright trace requests --failed

# 7. View console errors
npx playwright trace console --errors-only

Sources: packages/playwright-core/src/tools/trace/SKILL.md

Integration with Test Debugging

Debug Mode

Run tests in debug mode with CLI integration:

PLAYWRIGHT_HTML_OPEN=never npx playwright test --debug=cli

This command:

  1. Pauses test execution at start
  2. Prints debugging instructions with session name
  3. Allows attaching via playwright-cli to explore the page

Attaching to Test Session

# After starting debug mode, attach to the printed session
playwright-cli attach tw-abcdef

Available exploration commands while attached:

CommandDescription
playwright-cli snapshotGet current DOM snapshot
playwright-cli click <ref>Interact with elements
playwright-cli eval <js>Execute JavaScript
playwright-cli show --annotateLaunch annotation dashboard
playwright-cli resumeResume test execution

Spec-Driven Testing Workflow

The debugging tools integrate with Playwright's spec-driven testing approach:

  1. Create seed test that navigates to the application
  2. Run seed in debug mode and attach via CLI
  3. Explore the app to understand interactive surfaces
  4. Write spec file documenting expected behavior
  5. Generate tests from the spec

Sources: packages/playwright-core/src/tools/cli-client/skill/references/playwright-tests.md

API Reference

JavaScript Execution in CLI

Execute arbitrary JavaScript in the browser context:

# Basic evaluation
playwright-cli eval "document.title"

# With return value
playwright-cli run-code "async page => await page.title()"

# Read from clipboard
playwright-cli run-code "async page => {
  await page.context().grantPermissions(['clipboard-read']);
  return await page.evaluate(() => navigator.clipboard.readText());
}"

Page Information

# Get page title
playwright-cli run-code "async page => await page.title()"

# Get current URL
playwright-cli run-code "async page => page.url()"

# Get viewport size
playwright-cli run-code "async page => page.viewportSize()"

Snapshot with Custom Depth

# Default snapshot
playwright-cli snapshot

# Snapshot with element bounding boxes
playwright-cli snapshot --boxes

# Limited depth for performance
playwright-cli snapshot --depth=4

# Snapshot specific element
playwright-cli snapshot "#main"

Sources: packages/playwright-core/src/tools/cli-client/skill/references/running-code.md

Storage State Management

Saving Authentication State

# Step 1: Login and save state
playwright-cli open https://app.example.com/login
playwright-cli snapshot
playwright-cli fill e1 "[email protected]"
playwright-cli fill e2 "password123"
playwright-cli click e3
playwright-cli state-save auth.json

# Step 2: Later, restore state
playwright-cli state-load auth.json
playwright-cli open https://app.example.com/dashboard
# Already authenticated
CommandDescription
playwright-cli cookie-listList all cookies
playwright-cli cookie-get <name>Get specific cookie
playwright-cli cookie-set <name> <value>Set a cookie
playwright-cli cookie-delete <name>Delete a cookie
playwright-cli cookie-clearClear all cookies

Local/Session Storage

# List storage items
playwright-cli localstorage-list
playwright-cli sessionstorage-list

# Get specific value
playwright-cli localstorage-get theme
playwright-cli sessionstorage-get step

# Set value
playwright-cli localstorage-set theme dark
playwright-cli sessionstorage-set step 3

# Delete/Clear
playwright-cli localstorage-delete theme
playwright-cli localstorage-clear

Sources: packages/playwright-core/src/tools/cli-client/skill/references/storage-state.md

Advanced Features

Persistent Profiles

Browser profiles can be persisted to disk for testing scenarios requiring persistent state:

# Auto-generated profile location
playwright-cli open https://example.com --persistent

# Custom profile directory
playwright-cli open https://example.com --profile=/path/to/profile

# Create named session with persistent profile
playwright-cli -s=mysession open example.com --persistent

Network Interception

# Mock responses
playwright-cli route "**/*.jpg" --status=404
playwright-cli route "https://api.example.com/**" --body='{"mock": true}'

# List and remove routes
playwright-cli route-list
playwright-cli unroute "**/*.jpg"

Highlighting Elements

# Highlight an element
playwright-cli highlight e5

# Highlight with custom style
playwright-cli highlight e5 --style="outline: 3px dashed red"

# Hide highlights
playwright-cli highlight --hide

Video Recording

# Start video recording
playwright-cli video-start video.webm

# Add chapter markers
playwright-cli video-chapter "Chapter Title" --description="Details" --duration=2000

# Stop recording
playwright-cli video-stop

Best Practices

PracticeDescription
Use --debug=cliAlways debug through test execution, not direct URL opening
Capture specific actionsUse --grep flags to narrow focus during investigation
Save authentication stateReuse authenticated sessions instead of repeating login
Use raw outputPipe CLI output to tools like jq for scripting
Clean up tracesRun playwright-cli trace close after investigation

Raw Output for Scripting

# Get JSON output for processing
playwright-cli list --json

# Pipe to jq for data extraction
playwright-cli --raw eval "JSON.stringify(performance.timing)" | jq '.loadEventEnd - .navigationStart'

# Save to file
playwright-cli --raw snapshot > before.yml

Sources: packages/playwright-core/src/tools/cli-client/skill/SKILL.md

Sources: packages/trace-viewer/src/index.tsx

CLI, MCP Server, and Agent Integration

Related topics: Trace Viewer and Debugging Tools

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Purpose and Scope

Continue reading this section for the full explanation and source context.

Section Core Commands

Continue reading this section for the full explanation and source context.

Section Snapshot and Inspection

Continue reading this section for the full explanation and source context.

Related topics: Trace Viewer and Debugging Tools

CLI, MCP Server, and Agent Integration

Overview

Playwright provides a comprehensive command-line interface (CLI), MCP (Model Context Protocol) server, and agent integration system that enables automated browser control, testing, and inspection workflows. These three interconnected components form the foundation of Playwright's external interaction layer, allowing developers and AI agents to programmatically control browsers, execute tests, and analyze application behavior.

The CLI layer (playwright-cli) provides a human-readable command interface for browser automation, while the MCP server exposes these capabilities to AI agents and automated systems. The agent integration system coordinates between tools, manages browser sessions, and maintains state across operations.

Architecture Overview

graph TD
    A[User / AI Agent] --> B[CLI Interface<br/>playwright-cli]
    A --> C[MCP Server<br/>Model Context Protocol]
    B --> D[Tool Backend<br/>packages/playwright-core/src/tools/backend/tools.ts]
    C --> D
    D --> E[Browser Factory<br/>browserFactory.ts]
    E --> F[Browser Pool<br/>Chromium, Firefox, WebKit]
    D --> G[Session Manager]
    G --> H[State: Cookies, LocalStorage,<br/>SessionStorage]
    D --> I[Trace Viewer<br/>trace viewer package]

CLI (`playwright-cli`)

Purpose and Scope

The playwright-cli tool provides a command-line interface for browser automation and testing. It is defined in packages/playwright-core/src/tools/cli-client/cli.ts and offers a comprehensive set of commands for interacting with browsers without writing code directly.

The CLI accepts commands like open, goto, click, fill, snapshot, and many others, making browser automation accessible through a simple shell interface.

Core Commands

#### Browser Lifecycle

CommandDescription
playwright-cli open [url]Opens a new browser and optionally navigates to URL
playwright-cli closeCloses the current browser session
playwright-cli close-allCloses all browser sessions
playwright-cli kill-allForcefully terminates all browser processes

#### Navigation

CommandDescription
playwright-cli goto <url>Navigate to the specified URL
playwright-cli go-backNavigate back in browser history
playwright-cli go-forwardNavigate forward in browser history
playwright-cli reloadReload the current page

#### Element Interaction

CommandDescriptionExample
playwright-cli click <ref>Click an element by refplaywright-cli click e15
playwright-cli dblclick <ref>Double-click an elementplaywright-cli dblclick e7
playwright-cli fill <ref> <text>Fill input fieldplaywright-cli fill e5 "text"
playwright-cli type <text>Type text into focused elementplaywright-cli type "search"
playwright-cli press <key>Press a keyboard keyplaywright-cli press Enter
playwright-cli select <ref> <value>Select dropdown optionplaywright-cli select e9 "value"
playwright-cli check <ref>Check a checkboxplaywright-cli check e12
playwright-cli uncheck <ref>Uncheck a checkboxplaywright-cli uncheck e12
playwright-cli hover <ref>Hover over an elementplaywright-cli hover e4
playwright-cli drag <src> <target>Drag element to targetplaywright-cli drag e2 e8

#### Data Input

CommandDescription
playwright-cli upload <path>Upload file to element
playwright-cli drop <ref> --path=<file>Drop file onto element
playwright-cli drop <ref> --data=<type>=<data>Drop data onto element

Snapshot and Inspection

The snapshot command captures the current page state, including interactive elements with their refs:

playwright-cli snapshot
playwright-cli snapshot --filename=state.yaml
playwright-cli snapshot "#main"
playwright-cli snapshot --depth=4
playwright-cli snapshot --boxes

Elements can be targeted using refs from snapshots, CSS selectors, or Playwright locators:

# Using ref
playwright-cli click e15

# Using CSS selector
playwright-cli click "#main > button.submit"

# Using role locator
playwright-cli click "getByRole('button', { name: 'Submit' })"

Sources: packages/playwright-core/src/tools/cli-client/skill/SKILL.md

Storage Management

# State persistence
playwright-cli state-save [filename]
playwright-cli state-load [filename]

# Cookies
playwright-cli cookie-list [--domain=<domain>]
playwright-cli cookie-get <name>
playwright-cli cookie-set <name> <value> [--domain=<domain>] [--httpOnly] [--secure]
playwright-cli cookie-delete <name>
playwright-cli cookie-clear

# LocalStorage
playwright-cli localstorage-list
playwright-cli localstorage-get <key>
playwright-cli localstorage-set <key> <value>
playwright-cli localstorage-delete <key>
playwright-cli localstorage-clear

# SessionStorage
playwright-cli sessionstorage-list
playwright-cli sessionstorage-get <key>
playwright-cli sessionstorage-set <key> <value>
playwright-cli sessionstorage-delete <key>
playwright-cli sessionstorage-clear

Sources: packages/playwright-core/src/tools/cli-client/skill/references/session-management.md

Network Interception

# Mock network responses
playwright-cli route "**/*.jpg" --status=404
playwright-cli route "https://api.example.com/**" --body='{"mock": true}'
playwright-cli route-list
playwright-cli unroute "**/*.jpg"
playwright-cli unroute

Tracing

# Start/stop trace recording
playwright-cli tracing-start
playwright-cli tracing-stop

# Video chapters
playwright-cli video-start <file.webm>
playwright-cli video-chapter "Title" --description="Details" --duration=2000
playwright-cli video-stop

Sources: packages/playwright-core/src/tools/cli-client/skill/references/tracing.md

Tab Management

playwright-cli tab-list
playwright-cli tab-new [url]
playwright-cli tab-close [index]
playwright-cli tab-select <index>

Dialog Handling

playwright-cli dialog-accept [text]
playwright-cli dialog-dismiss

Advanced: JavaScript Execution

playwright-cli run-code "async page => await page.title()"
playwright-cli eval "document.title"
playwright-cli eval "el => el.textContent" <ref>

Sources: packages/playwright-core/src/tools/cli-client/skill/references/running-code.md

Browser Sessions

Sessions allow multiple independent browser instances with optional persistence:

# Named session with persistent profile
playwright-cli -s=mysession open https://example.com --persistent

# With custom profile directory
playwright-cli -s=mysession open https://example.com --profile=/path/to/profile

# Session management
playwright-cli -s=mysession click e6
playwright-cli -s=mysession close
playwright-cli -s=mysession delete-data

# List and cleanup
playwright-cli list
playwright-cli close-all
playwright-cli kill-all

Session name can be set via environment variable:

export PLAYWRIGHT_CLI_SESSION="mysession"

MCP Server Integration

Purpose and Architecture

The MCP (Model Context Protocol) server provides programmatic access to Playwright's browser automation capabilities for AI agents. The server is defined in packages/playwright-core/src/tools/mcp/index.ts and exposes a standardized interface for browser control operations.

graph LR
    A[AI Agent] -->|MCP Protocol| B[MCP Server<br/>index.ts]
    B --> C[Browser Factory<br/>browserFactory.ts]
    B --> D[Browser Model<br/>browserModel.ts]
    C --> E[Chromium]
    C --> F[Firefox]
    C --> G[WebKit]
    D --> H[Browser State<br/>and Context]

Browser Factory (`browserFactory.ts`)

The BrowserFactory class is responsible for creating and managing browser instances. It provides methods for launching browsers with various configurations:

class BrowserFactory {
  async launch(options?: BrowserLaunchOptions): Promise<Browser>;
  async connect(browserWSEndpoint: string): Promise<Browser>;
  async close(): Promise<void>;
}

The factory handles:

  • Browser type selection (Chromium, Firefox, WebKit)
  • Launch option configuration
  • Browser connection management
  • Resource cleanup

Sources: packages/playwright-core/src/tools/mcp/browserFactory.ts

Browser Model (`browserModel.ts`)

The BrowserModel maintains state and context for browser instances:

class BrowserModel {
  id: string;
  browser: Browser;
  context: BrowserContext;
  pages: Page[];
  sessionName?: string;
  createdAt: Date;
}

Key responsibilities:

  • Tracking active pages and contexts
  • Managing browser lifecycle
  • Providing access to current state
  • Handling browser events

Sources: packages/playwright-core/src/tools/mcp/browserModel.ts

MCP Tool Interface

The MCP server exposes tools through the tools.ts backend:

// Defined in packages/playwright-core/src/tools/backend/tools.ts
export interface Tool {
  name: string;
  description: string;
  execute(params: ToolParams): Promise<ToolResult>;
}

Available tool categories include:

  • Navigation tools (goto, back, forward, reload)
  • Interaction tools (click, fill, select, hover)
  • Inspection tools (snapshot, screenshot, content)
  • Storage tools (cookies, localStorage, sessionStorage)

Dashboard and Visualization

Dashboard Application (`dashboardApp.ts`)

The Playwright dashboard provides a visual interface for analyzing test results and traces:

graph TD
    A[Test Execution] --> B[Trace Files<br/>.zip format]
    B --> C[Trace Viewer]
    C --> D[Dashboard App<br/>dashboardApp.ts]
    D --> E[Action Timeline]
    D --> F[Network Log]
    D --> G[Console Output]
    D --> H[Screenshots]

The dashboard displays:

  • Test action timeline with timing information
  • Network request/response logs
  • Console messages and errors
  • DOM snapshots at each step
  • Screenshots for visual verification

Sources: packages/playwright-core/src/tools/dashboard/dashboardApp.ts

Trace Viewer (`workbenchLoader.tsx`)

The trace viewer is a Progressive Web App that loads locally without sending data externally:

// Loading states
interface LoadState {
  showFileUploadDropArea: boolean;
  showProgressDialog: boolean;
  processingErrorMessage?: string;
  traceURL?: string;
}

Key features:

  • Drag-and-drop trace file loading
  • File browser selection
  • Progress indication during trace parsing
  • Local-only processing for privacy

Sources: packages/trace-viewer/src/ui/workbenchLoader.tsx

Dashboard React Component

The main dashboard component renders the UI:

// packages/dashboard/src/dashboard.tsx
export const Dashboard: React.FC<DashboardProps> = ({ traceData }) => {
  // Renders action tree, network log, console output, snapshots
};

Spec-Driven Testing Workflow

The CLI supports a specification-driven testing workflow documented in spec-driven-testing.md:

graph LR
    A[Write Spec File<br/>specs/feature.plan.md] --> B[Generate Tests]
    B --> C[Execute Tests]
    C --> D[Generate Traces]
    D --> E[Analyze Results]
    E --> F[Annotate & Feedback]

Spec File Structure

# <Feature> Test Plan

## Application Overview
<Description>

## Test Scenarios

### 1. <Group Name>
**Seed:** `tests/seed.spec.ts`

#### 1.1. <scenario-name>
**File:** `tests/<group>/<scenario>.spec.ts`
**Steps:**
  1. <User step>
     - expect: <outcome>
  2. <Next step>
     - expect: <outcome>

Test Generation Flow

  1. Create seed test that navigates to the app
  2. Explore app using playwright-cli attach and snapshot
  3. Write spec file with test scenarios
  4. Generate actual test code from spec
  5. Execute and capture traces
  6. Review results in trace viewer

Sources: packages/playwright-core/src/tools/cli-client/skill/references/spec-driven-testing.md

Trace CLI Tool

Command Reference

# Open and analyze traces
npx playwright trace open <trace.zip>
npx playwright trace close

# List actions
npx playwright trace actions
npx playwright trace actions --grep "click"
npx playwright trace actions --errors-only

# View specific action
npx playwright trace action <action-id>

# View requests, console, errors
npx playwright trace requests
npx playwright trace console
npx playwright trace errors

# Get DOM snapshot
npx playwright trace snapshot <action-id>

Sources: packages/playwright-core/src/tools/trace/SKILL.md

Trace File Structure

When tracing is enabled, Playwright creates:

File/DirectoryContent
trace-{timestamp}.traceAction log with DOM snapshots, screenshots, timing
trace-{timestamp}.networkComplete network activity log
resources/Cached resources for replay

Tool Backend Architecture

The tool backend (packages/playwright-core/src/tools/backend/tools.ts) serves as the coordination layer:

graph TD
    A[CLI / MCP Server] --> B[Tool Backend<br/>tools.ts]
    B --> C[Browser Tool]
    B --> D[Page Tool]
    B --> E[Storage Tool]
    B --> F[Trace Tool]
    C --> G[Playwright Core API]
    D --> G
    E --> G
    F --> G

Tool Categories

CategoryTools
Browserlaunch, connect, close, context
Navigationgoto, back, forward, reload
Interactionclick, fill, select, hover, drag, type, press
Snapshotsnapshot, screenshot, pdf
Storagecookies, localStorage, sessionStorage
Networkroute, unroute, route-list

Package Structure

PackagePurpose
playwrightMain package with all browser support
@playwright/testTesting framework with reporters
playwright-coreCore API without browser binaries
@playwright/browser-chromiumChromium browser support
@playwright/browser-firefoxFirefox browser support
@playwright/browser-webkitWebKit browser support

Sources: package.json, packages/playwright-test/package.json, packages/playwright-webkit/package.json

Environment Variables

VariablePurpose
PLAYWRIGHT_CLI_SESSIONDefault session name for CLI
PLAYWRIGHT_HTML_OPENControls browser launch behavior in tests
PLAYWRIGHT_BROWSERS_PATHCustom browser installation directory

Error Handling Patterns

# Try-catch in run-code
playwright-cli run-code "async page => {
  try {
    await page.getByRole('button', { name: 'Submit' }).click({ timeout: 1000 });
    return 'clicked';
  } catch (e) {
    return 'element not found';
  }
}"

Installation and Usage

CLI Installation

# Use via npx (no installation required)
npx --no-install playwright-cli --version

# Or install globally
npm install -g playwright-cli

Testing Commands

From the root package.json:

ScriptPurpose
npm run testRun library tests
npm run ctestChromium tests only
npm run ftestFirefox tests only
npm run wtestWebKit tests only
npm run biditestBidi protocol tests

Summary

The Playwright CLI, MCP Server, and Agent Integration system provides a layered approach to browser automation:

  1. CLI Layer: Human-friendly command interface for browser automation tasks
  2. MCP Layer: Programmatic interface for AI agents and automated systems
  3. Tool Backend: Coordination layer that manages browser factories and models
  4. Dashboard/Trace Viewer: Visualization tools for analyzing test results

These components work together to enable comprehensive browser testing and automation workflows, from simple interactive sessions to complex AI-driven testing scenarios.

Sources: packages/playwright-core/src/tools/cli-client/skill/SKILL.md

Doramagic Pitfall Log

Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.

high [Feature]: Fail tests on page errors

First-time setup may fail or require extra isolation and rollback planning.

high [Feature]: Ubuntu 26.04 LTS support

First-time setup may fail or require extra isolation and rollback planning.

high [Feature]: trace correlation hooks for external observability/replay systems

First-time setup may fail or require extra isolation and rollback planning.

high [Feature]: support signal in waitFor* APIs

The project should not be treated as fully validated until this signal is reviewed.

Doramagic Pitfall Log

Doramagic extracted 16 source-linked risk signals. Review them before installing or handing real data to the project.

1. Installation risk: [Feature]: Fail tests on page errors

  • Severity: high
  • Finding: Installation risk is backed by a source signal: [Feature]: Fail tests on page errors. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/microsoft/playwright/issues/40880

2. Installation risk: [Feature]: Ubuntu 26.04 LTS support

  • Severity: high
  • Finding: Installation risk is backed by a source signal: [Feature]: Ubuntu 26.04 LTS support. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/microsoft/playwright/issues/40117

3. Installation risk: [Feature]: trace correlation hooks for external observability/replay systems

  • Severity: high
  • Finding: Installation risk is backed by a source signal: [Feature]: trace correlation hooks for external observability/replay systems. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/microsoft/playwright/issues/40887

4. Project risk: [Feature]: support signal in waitFor* APIs

  • Severity: high
  • Finding: Project risk is backed by a source signal: [Feature]: support signal in waitFor* APIs. Treat it as a review item until the current version is checked.
  • User impact: The project should not be treated as fully validated until this signal is reviewed.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/microsoft/playwright/issues/40578

5. Maintenance risk: [BUG] "NS_BINDING_ABORTED" error in Firefox

  • Severity: high
  • Finding: Maintenance risk is backed by a source signal: [BUG] "NS_BINDING_ABORTED" error in Firefox. Treat it as a review item until the current version is checked.
  • User impact: Users cannot judge support quality until recent activity, releases, and issue response are checked.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/microsoft/playwright/issues/20749

6. Security or permission risk: Developers should check this security_permissions risk before relying on the project: [Bug]: MCP createUserDataDir writes profile data to PLAYWRIGHT_BROWSERS_PATH, fails when path is read-only

  • Severity: high
  • Finding: Developers should check this security_permissions risk before relying on the project: [Bug]: MCP createUserDataDir writes profile data to PLAYWRIGHT_BROWSERS_PATH, fails when path is read-only
  • User impact: Developers may expose sensitive permissions or credentials: [Bug]: MCP createUserDataDir writes profile data to PLAYWRIGHT_BROWSERS_PATH, fails when path is read-only
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [Bug]: MCP createUserDataDir writes profile data to PLAYWRIGHT_BROWSERS_PATH, fails when path is read-only. Context: Observed when using node, docker, playwright, linux
  • Evidence: failure_mode_cluster:github_issue | fmev_32d5131674a6cea46a3dd9fea57edcee | https://github.com/microsoft/playwright/issues/40892 | [Bug]: MCP createUserDataDir writes profile data to PLAYWRIGHT_BROWSERS_PATH, fails when path is read-only

7. Security or permission risk: [Feature]: Trace viewer: Add timeout-risk highlighting for actions in Playwright traces

  • Severity: high
  • Finding: Security or permission risk is backed by a source signal: [Feature]: Trace viewer: Add timeout-risk highlighting for actions in Playwright traces. Treat it as a review item until the current version is checked.
  • User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/microsoft/playwright/issues/40681

8. Installation risk: Developers should check this installation risk before relying on the project: [Bug]: In VS Code, tests are not displayed in the Testing section.

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: [Bug]: In VS Code, tests are not displayed in the Testing section.
  • User impact: Developers may fail before the first successful local run: [Bug]: In VS Code, tests are not displayed in the Testing section.
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [Bug]: In VS Code, tests are not displayed in the Testing section.. Context: Observed when using node, playwright, windows, macos
  • Evidence: failure_mode_cluster:github_issue | fmev_429f2bbd1fa3334bca8aae5ee7df68b8 | https://github.com/microsoft/playwright/issues/40481 | [Bug]: In VS Code, tests are not displayed in the Testing section.

9. Installation risk: Developers should check this installation risk before relying on the project: [Bug]: Reporter ignores NO_COLOR — colors and cursor codes still emitted with NO_COLOR=1

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: [Bug]: Reporter ignores NO_COLOR — colors and cursor codes still emitted with NO_COLOR=1
  • User impact: Developers may fail before the first successful local run: [Bug]: Reporter ignores NO_COLOR — colors and cursor codes still emitted with NO_COLOR=1
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [Bug]: Reporter ignores NO_COLOR — colors and cursor codes still emitted with NO_COLOR=1. Context: Observed when using node, playwright
  • Evidence: failure_mode_cluster:github_issue | fmev_09c75aac9731971717426ccfbe72651b | https://github.com/microsoft/playwright/issues/40904 | [Bug]: Reporter ignores NO_COLOR — colors and cursor codes still emitted with NO_COLOR=1

10. Installation risk: Developers should check this installation risk before relying on the project: [Bug]: VSCode extension aborts run after a single slow (>10s) API test — subsequent tests never execute despite

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: [Bug]: VSCode extension aborts run after a single slow (>10s) API test — subsequent tests never execute despite
  • User impact: Developers may fail before the first successful local run: [Bug]: VSCode extension aborts run after a single slow (>10s) API test — subsequent tests never execute despite
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [Bug]: VSCode extension aborts run after a single slow (>10s) API test — subsequent tests never execute despite. Context: Observed when using node, playwright, windows
  • Evidence: failure_mode_cluster:github_issue | fmev_bd2b1ca9bdfc4104afb98768ab5f87d4 | https://github.com/microsoft/playwright/issues/40889 | [Bug]: VSCode extension aborts run after a single slow (>10s) API test — subsequent tests never execute despite

11. Installation risk: Developers should check this installation risk before relying on the project: [Bug]: WebKit on Windows hangs when CONNECT proxy closes socket after 407 doesn't reconnect with credentials

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: [Bug]: WebKit on Windows hangs when CONNECT proxy closes socket after 407 doesn't reconnect with credentials
  • User impact: Developers may fail before the first successful local run: [Bug]: WebKit on Windows hangs when CONNECT proxy closes socket after 407 doesn't reconnect with credentials
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [Bug]: WebKit on Windows hangs when CONNECT proxy closes socket after 407 doesn't reconnect with credentials. Context: Observed when using node, playwright, windows, linux
  • Evidence: failure_mode_cluster:github_issue | fmev_f50999f1a6066b929ea1a2971fefc95a | https://github.com/microsoft/playwright/issues/40768 | [Bug]: WebKit on Windows hangs when CONNECT proxy closes socket after 407 doesn't reconnect with credentials

12. Installation risk: Developers should check this installation risk before relying on the project: [Bug]: playwright-cli open fails with EINVAL when session name is long on macOS due to unix socket path length

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: [Bug]: playwright-cli open fails with EINVAL when session name is long on macOS due to unix socket path length
  • User impact: Developers may fail before the first successful local run: [Bug]: playwright-cli open fails with EINVAL when session name is long on macOS due to unix socket path length
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [Bug]: playwright-cli open fails with EINVAL when session name is long on macOS due to unix socket path length. Context: Observed when using node, playwright, macos
  • Evidence: failure_mode_cluster:github_issue | fmev_0f40df2fb212e08cdc02306a91f914c1 | https://github.com/microsoft/playwright/issues/40878 | [Bug]: playwright-cli open fails with EINVAL when session name is long on macOS due to unix socket path length

Source: Doramagic discovery, validation, and Project Pack records

Community Discussion Evidence

These external discussion links are review inputs, not standalone proof that the project is production-ready.

Sources 12

Count of project-level external discussion links exposed on this manual page.

Use Review before install

Open the linked issues or discussions before treating the pack as ready for your environment.

Community Discussion Evidence

Doramagic exposes project-level community discussion separately from official documentation. Review these links before using playwright with real data or production workflows.

  • [[Feature]: Expose securityDetails() on APIResponse for HTTPS monitoring](https://github.com/microsoft/playwright/issues/40905) - github / github_issue
  • [[Bug]: Reporter ignores NO_COLOR — colors and cursor codes still emitted](https://github.com/microsoft/playwright/issues/40904) - github / github_issue
  • [[Bug]: Unable to Listen to Download Event While Using window.showSaveFil](https://github.com/microsoft/playwright/issues/31162) - github / github_issue
  • [[Feature]: Fail tests on page errors](https://github.com/microsoft/playwright/issues/40880) - github / github_issue
  • [[Feature]: trace correlation hooks for external observability/replay sys](https://github.com/microsoft/playwright/issues/40887) - github / github_issue
  • [[Bug]: Trace viewer does not capture some dynamically added CSS classes](https://github.com/microsoft/playwright/issues/40895) - github / github_issue
  • [[Regression]: install-deps --dry-run can no longer be used to generate i](https://github.com/microsoft/playwright/issues/40885) - github / github_issue
  • [[Feature]: Trace viewer: Add timeout-risk highlighting for actions in Pl](https://github.com/microsoft/playwright/issues/40681) - github / github_issue
  • [[Bug]: In VS Code, tests are not displayed in the Testing section.](https://github.com/microsoft/playwright/issues/40481) - github / github_issue
  • [[Bug]: playwright-cli open fails with EINVAL when session name is long o](https://github.com/microsoft/playwright/issues/40878) - github / github_issue
  • [[BUG] "NS_BINDING_ABORTED" error in Firefox](https://github.com/microsoft/playwright/issues/20749) - github / github_issue
  • [[Feature]: Ubuntu 26.04 LTS support](https://github.com/microsoft/playwright/issues/40117) - GitHub / issue

Source: Project Pack community evidence and pitfall evidence