Implementation:Microsoft Playwright Recorder ForContext
| Knowledge Sources | |
|---|---|
| Domains | Testing, Code_Generation, Event_Capture |
| Last Updated | 2026-02-11 00:00 GMT |
Overview
Concrete tool for capturing user interactions in a browser context and converting them to structured action representations, provided by the Playwright library.
Description
The Recorder class is the server-side engine that orchestrates interaction recording within a Playwright browser context. The static Recorder.forContext() method is the primary entry point, creating or retrieving a Recorder instance bound to a specific BrowserContext.
The Recorder operates through a dual-context architecture:
Server-side (Node.js):
- The Recorder constructor (L114-150) sets up the signal processor, debugger integration, and instrumentation listeners.
- The
_install()method (L158-251) registers page bindings (__pw_recorderPerformActionand__pw_recorderRecordAction) and injects the recorder script into every frame of every page. - The signal processor tracks navigation events, popup creation, dialog appearances, and downloads, attaching them as signals to the corresponding action.
In-page (browser):
- An injected recorder script listens for DOM events (click, input, change, keydown, etc.) in every frame.
- When a user action is detected, the script generates candidate selectors for the target element and calls the registered page bindings to report the action back to the server.
- The script also handles hover highlighting and selector preview in assertion modes.
The two bindings serve different purposes:
__pw_recorderPerformAction: Used for actions that need to be performed by Playwright (click, fill, check) to ensure proper event dispatching and waiting. The recorder callsperformAction()fromrecorderRunner.tsto execute the action programmatically.__pw_recorderRecordAction: Used for actions that should only be recorded without re-execution (navigation, page open/close) because they are already happening naturally.
Actions flow through the RecorderSignalProcessor which:
- Receives the raw action from the page binding.
- Waits for any associated signals (navigation, popup, dialog) to be collected.
- Emits the finalized
ActionInContextviaRecorderEvent.ActionAdded. - The action is then forwarded to all registered code generators for translation.
The RecorderApp (at recorderApp.ts:L48-344) provides the inspector UI, displaying generated code, recording controls, and language selection tabs.
Usage
Use this class when you need to:
- Enable interaction recording on a browser context programmatically.
- Build custom recording workflows that extend the default codegen behavior.
- Integrate recording into testing tools or IDE extensions.
Code Reference
Source Location
- Repository: playwright
- File:
packages/playwright-core/src/server/recorder.ts - Lines: L71-598
Signature
class Recorder {
static async forContext(
context: BrowserContext,
params: channels.BrowserContextEnableRecorderParams
): Promise<Recorder>;
// Constructor (L114-150)
constructor(
context: BrowserContext,
params: channels.BrowserContextEnableRecorderParams
);
// Install recorder into context (L158-251)
private async _install(): Promise<void>;
// Mode management (L269-281)
setMode(mode: Mode): void;
// Recording state check (L454-456)
private _isRecording(): boolean;
}
Import
// Internal server-side class - not a public API import
// Used via context._enableRecorder() which delegates to Recorder.forContext()
// Defined in packages/playwright-core/src/server/recorder.ts
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| context | BrowserContext | Yes | The browser context to instrument for recording. All pages and frames within this context will be monitored. |
| params.mode | Mode | No | Initial recording mode. Defaults to 'recording'. Options: 'recording', 'inspecting', 'assertingText', 'assertingVisibility', 'assertingValue', 'assertingSnapshot', 'standby'.
|
| params.language | string | No | Target language for code generation. Defaults to 'playwright-test'.
|
| params.testIdAttributeName | string | No | Custom attribute name for test ID selectors. Defaults to Playwright's built-in test ID attribute. |
| params.outputFile | string | No | File path to write generated code to. If omitted, code is only displayed in the inspector. |
| params.handleSIGINT | boolean | No | Whether to handle SIGINT (Ctrl+C) for graceful shutdown. Defaults to true in CLI mode.
|
| params.launchOptions | LaunchOptions | No | Launch options to embed in the generated test code header. |
| params.contextOptions | BrowserContextOptions | No | Context options to embed in the generated test code header. |
Outputs
| Name | Type | Description |
|---|---|---|
| Recorder instance | Recorder | The configured recorder, actively monitoring the context. |
| RecorderEvent.ActionAdded | Event | Emitted for each finalized action, carrying the ActionInContext record.
|
| Inspector UI | RecorderApp | Visual inspector window showing generated code, controls, and language tabs. |
| Page bindings | Function | Two bindings injected into every frame: __pw_recorderPerformAction and __pw_recorderRecordAction.
|
| Generated code | string | Real-time generated code pushed to the inspector via _pushAllSources().
|
Usage Examples
Basic Example
// Enable recording on a browser context (internal API)
const recorder = await Recorder.forContext(context, {
mode: 'recording',
language: 'playwright-test',
testIdAttributeName: 'data-testid',
outputFile: 'tests/recorded.spec.ts',
handleSIGINT: true,
launchOptions: { headless: false },
contextOptions: { viewport: { width: 1280, height: 720 } },
});
// Listen for recorded actions
recorder.on('actionAdded', (action: ActionInContext) => {
console.log('Recorded action:', action.action.name, action.action.selector);
});
Page Binding Flow
// The injected recorder script in the browser calls:
// For actions that need to be performed (click, fill, etc.):
window.__pw_recorderPerformAction({
name: 'click',
selector: 'getByRole("button", { name: "Submit" })',
position: { x: 150, y: 30 },
signals: [],
button: 'left',
modifiers: 0,
clickCount: 1,
});
// For actions that are only recorded (navigation, page open/close):
window.__pw_recorderRecordAction({
name: 'navigate',
url: 'https://example.com/dashboard',
signals: [],
});
Signal Processing Flow
// When a click triggers a navigation:
// 1. __pw_recorderPerformAction({ name: 'click', selector: '...' })
// 2. performAction() executes the click via Playwright API
// 3. Navigation event is detected by instrumentation
// 4. RecorderSignalProcessor attaches navigation signal to the click action
// 5. Finalized action emitted:
{
frame: { pageAlias: 'page', framePath: [] },
action: {
name: 'click',
selector: 'getByRole("link", { name: "Dashboard" })',
signals: [{ name: 'navigation', url: 'https://example.com/dashboard' }],
},
}