Modern bidirectional communication protocol for advanced browser automation, real-time monitoring, and enhanced debugging capabilities with WebDriver BiDi.
BiDi browsing context management for advanced page lifecycle control and monitoring.
/**
* BiDi browsing context for advanced browser control
*/
class BrowsingContext {
constructor(driver: WebDriver, id?: string);
/** Create new browsing context */
static create(driver: WebDriver, type: string, options?: CreateContextOptions): Promise<BrowsingContext>;
/** Navigate to URL with advanced options */
navigate(url: string, options?: NavigateOptions): Promise<NavigateResult>;
/** Get browsing context tree */
getTree(options?: GetTreeOptions): Promise<ContextInfo[]>;
/** Get all top-level contexts */
static getTopLevelContexts(driver: WebDriver): Promise<BrowsingContext[]>;
/** Close browsing context */
close(): Promise<void>;
/** Activate browsing context */
activate(): Promise<void>;
/** Reload page with options */
reload(options?: ReloadOptions): Promise<NavigateResult>;
/** Set viewport dimensions */
setViewport(width: number, height: number, devicePixelRatio?: number): Promise<void>;
/** Print page to PDF */
printPage(options?: PrintOptions): Promise<PrintResult>;
/** Capture screenshot */
captureScreenshot(options?: ScreenshotOptions): Promise<string>;
/** Capture box screenshot */
captureBoxScreenshot(x: number, y: number, width: number, height: number): Promise<string>;
/** Capture element screenshot */
captureElementScreenshot(element: ElementReference): Promise<string>;
/** Handle user prompt */
handleUserPrompt(accept?: boolean, userText?: string): Promise<void>;
/** Traverse history */
traverseHistory(delta: number): Promise<void>;
/** Navigate forward */
forward(): Promise<void>;
/** Navigate back */
back(): Promise<void>;
/** Locate nodes using BiDi locators */
locateNodes(locator: Locator, options?: LocateOptions): Promise<NodeInfo[]>;
/** Locate single node */
locateNode(locator: Locator, options?: LocateOptions): Promise<NodeInfo>;
/** Locate element as WebElement */
locateElement(locator: Locator): Promise<WebElement>;
/** Locate elements as WebElement array */
locateElements(locator: Locator): Promise<WebElement[]>;
}Usage Examples:
const { BrowsingContext } = require('selenium-webdriver');
// Create new tab
let newContext = await BrowsingContext.create(driver, 'tab');
await newContext.navigate('https://example.com');
// Navigate with readiness state
let result = await newContext.navigate('https://example.com/page2', {
wait: 'complete'
});
console.log('Navigation result:', result);
// Get context tree
let contextTree = await newContext.getTree({ maxDepth: 2 });
console.log('Context tree:', contextTree);
// Set viewport for responsive testing
await newContext.setViewport(375, 812, 3.0); // iPhone 12 Pro dimensions
// Capture screenshots
let fullScreenshot = await newContext.captureScreenshot();
let elementScreenshot = await newContext.captureElementScreenshot({
sharedId: 'element-id',
handle: 'element-handle'
});
// Print to PDF
let pdfResult = await newContext.printPage({
orientation: 'portrait',
scale: 1.0,
background: true,
width: 8.27, // A4 width in inches
height: 11.7 // A4 height in inches
});
// Handle prompts
await newContext.handleUserPrompt(true, 'User input text');
// History navigation
await newContext.back();
await newContext.forward();
await newContext.traverseHistory(-2); // Go back 2 pagesAdvanced locator strategies specific to the BiDi protocol.
/**
* BiDi-specific element locators
*/
class Locator {
/** CSS selector locator */
static css(selector: string): Locator;
/** XPath locator */
static xpath(xpath: string): Locator;
/** Inner text locator with options */
static innerText(text: string, options?: InnerTextOptions): Locator;
}
interface InnerTextOptions {
ignoreCase?: boolean;
matchType?: 'full' | 'partial';
maxDepth?: number;
}
interface LocateOptions {
maxNodeCount?: number;
serializationOptions?: SerializationOptions;
startNodes?: NodeReference[];
}
interface SerializationOptions {
maxDomDepth?: number;
maxObjectDepth?: number;
includeShadowTree?: 'none' | 'open' | 'all';
}Usage Examples:
// BiDi locators
let cssLocator = Locator.css('.button[data-action="submit"]');
let xpathLocator = Locator.xpath('//button[contains(@class, "primary")]');
// Text-based location
let textLocator = Locator.innerText('Submit', {
ignoreCase: true,
matchType: 'partial'
});
// Locate nodes with options
let nodes = await context.locateNodes(cssLocator, {
maxNodeCount: 10,
serializationOptions: {
maxDomDepth: 2,
includeShadowTree: 'open'
}
});
// Convert to WebElements
let element = await context.locateElement(cssLocator);
let elements = await context.locateElements(textLocator);Real-time log monitoring and filtering with BiDi protocol.
/**
* BiDi log inspection and monitoring
*/
class LogInspector {
constructor(driver: WebDriver);
/** Start listening for log entries */
onLog(callback: (logEntry: LogEntry) => void): Promise<void>;
/** Stop listening for log entries */
close(): Promise<void>;
/** Filter logs by level */
filterByLevel(level: string): LogInspector;
/** Filter logs by source */
filterBySource(source: string): LogInspector;
/** Filter logs by text content */
filterByText(pattern: string | RegExp): LogInspector;
}
interface LogEntry {
level: string;
text: string;
timestamp: number;
source: {
realm: string;
context: string;
};
type: string;
method?: string;
args?: any[];
}Usage Examples:
const { LogInspector } = require('selenium-webdriver');
// Create log inspector
let logInspector = new LogInspector(driver);
// Listen to all logs
await logInspector.onLog((logEntry) => {
console.log(`[${logEntry.level}] ${logEntry.text}`);
});
// Filter logs by level
let errorInspector = new LogInspector(driver);
await errorInspector
.filterByLevel('error')
.onLog((errorEntry) => {
console.error('Error detected:', errorEntry.text);
// Handle critical errors
});
// Filter by source
let consoleInspector = new LogInspector(driver);
await consoleInspector
.filterBySource('console-api')
.onLog((consoleEntry) => {
console.log('Console output:', consoleEntry.text);
});
// Filter by text pattern
let apiInspector = new LogInspector(driver);
await apiInspector
.filterByText(/API.*error/i)
.onLog((apiError) => {
console.warn('API error detected:', apiError.text);
});
// Close inspector when done
await logInspector.close();Network request and response monitoring with BiDi protocol.
/**
* BiDi network inspection and monitoring
*/
class NetworkInspector {
constructor(driver: WebDriver);
/** Start network monitoring */
start(): Promise<void>;
/** Stop network monitoring */
stop(): Promise<void>;
/** Listen for request events */
onRequest(callback: (request: NetworkRequest) => void): Promise<void>;
/** Listen for response events */
onResponse(callback: (response: NetworkResponse) => void): Promise<void>;
/** Listen for network errors */
onError(callback: (error: NetworkError) => void): Promise<void>;
/** Add request interception */
addIntercept(pattern: InterceptPattern): Promise<string>;
/** Remove request interception */
removeIntercept(interceptId: string): Promise<void>;
/** Continue intercepted request */
continueRequest(requestId: string, overrides?: RequestOverrides): Promise<void>;
/** Fail intercepted request */
failRequest(requestId: string, errorReason: string): Promise<void>;
/** Provide intercepted response */
provideResponse(requestId: string, response: ResponseData): Promise<void>;
}
interface NetworkRequest {
requestId: string;
url: string;
method: string;
headers: Record<string, string>;
body?: string;
timestamp: number;
}
interface NetworkResponse {
requestId: string;
url: string;
status: number;
headers: Record<string, string>;
body?: string;
timestamp: number;
}Usage Examples:
const { NetworkInspector } = require('selenium-webdriver');
// Create network inspector
let networkInspector = new NetworkInspector(driver);
await networkInspector.start();
// Monitor requests
await networkInspector.onRequest((request) => {
console.log(`Request: ${request.method} ${request.url}`);
if (request.url.includes('/api/')) {
console.log('API request headers:', request.headers);
}
});
// Monitor responses
await networkInspector.onResponse((response) => {
console.log(`Response: ${response.status} ${response.url}`);
if (response.status >= 400) {
console.error('HTTP error response:', response);
}
});
// Monitor network errors
await networkInspector.onError((error) => {
console.error('Network error:', error);
});
// Request interception
let interceptId = await networkInspector.addIntercept({
urlPattern: '*/api/data',
method: 'GET'
});
await networkInspector.onRequest(async (request) => {
if (request.url.includes('/api/data')) {
// Modify request or provide mock response
await networkInspector.provideResponse(request.requestId, {
status: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ mocked: true, data: [] })
});
} else {
// Continue normal request
await networkInspector.continueRequest(request.requestId);
}
});
// Clean up
await networkInspector.removeIntercept(interceptId);
await networkInspector.stop();Script execution and management with BiDi protocol for enhanced JavaScript capabilities.
/**
* BiDi script execution and management
*/
class ScriptManager {
constructor(driver: WebDriver);
/** Evaluate script in browsing context */
evaluate(script: string, options?: EvaluateOptions): Promise<any>;
/** Call function with arguments */
callFunction(functionDeclaration: string, options?: CallFunctionOptions): Promise<any>;
/** Add preload script */
addPreloadScript(script: string, contexts?: string[]): Promise<string>;
/** Remove preload script */
removePreloadScript(scriptId: string): Promise<void>;
/** Get realms (execution contexts) */
getRealms(options?: GetRealmsOptions): Promise<RealmInfo[]>;
/** Disown handles (release object references) */
disown(handles: string[]): Promise<void>;
}
interface EvaluateOptions {
awaitPromise?: boolean;
resultOwnership?: 'root' | 'none';
serializationOptions?: SerializationOptions;
target?: {
context: string;
sandbox?: string;
};
}
interface RealmInfo {
realm: string;
origin: string;
type: 'window' | 'worker' | 'paint-worklet' | 'audio-worklet' | 'service-worker' | 'shared-worker' | 'dedicated-worker';
context?: string;
sandbox?: string;
}Usage Examples:
const { ScriptManager } = require('selenium-webdriver');
// Create script manager
let scriptManager = new ScriptManager(driver);
// Evaluate JavaScript
let result = await scriptManager.evaluate(`
return {
title: document.title,
url: window.location.href,
userAgent: navigator.userAgent
};
`, {
awaitPromise: false,
resultOwnership: 'root'
});
console.log('Page info:', result);
// Call function with arguments
let sum = await scriptManager.callFunction(`
function(a, b) {
return a + b;
}
`, {
arguments: [
{ type: 'number', value: 10 },
{ type: 'number', value: 20 }
],
awaitPromise: false
});
console.log('Sum:', sum); // 30
// Add preload script (runs before page load)
let preloadScriptId = await scriptManager.addPreloadScript(`
window.testMode = true;
window.startTime = Date.now();
// Override console methods for testing
const originalLog = console.log;
console.log = function(...args) {
originalLog('[TEST]', ...args);
};
`);
// Navigate to page (preload script will run)
await driver.get('https://example.com');
// Script is now active on the page
let testMode = await driver.executeScript('return window.testMode');
console.log('Test mode active:', testMode);
// Get execution realms
let realms = await scriptManager.getRealms();
console.log('Available realms:', realms);
// Remove preload script
await scriptManager.removePreloadScript(preloadScriptId);Monitor browsing context lifecycle events and changes.
/**
* BiDi browsing context inspection and monitoring
*/
class BrowsingContextInspector {
constructor(driver: WebDriver);
/** Listen for context created events */
onContextCreated(callback: (context: ContextInfo) => void): Promise<void>;
/** Listen for context destroyed events */
onContextDestroyed(callback: (context: ContextInfo) => void): Promise<void>;
/** Listen for navigation started events */
onNavigationStarted(callback: (navigation: NavigationInfo) => void): Promise<void>;
/** Listen for navigation completed events */
onNavigationCompleted(callback: (navigation: NavigationInfo) => void): Promise<void>;
/** Listen for user prompt events */
onUserPrompt(callback: (prompt: UserPromptInfo) => void): Promise<void>;
/** Stop monitoring */
close(): Promise<void>;
}
interface ContextInfo {
context: string;
url: string;
children: ContextInfo[];
parent?: string;
userContext: string;
}
interface NavigationInfo {
context: string;
navigation: string;
url: string;
timestamp: number;
}
interface UserPromptInfo {
context: string;
type: 'alert' | 'confirm' | 'prompt' | 'beforeunload';
message: string;
defaultValue?: string;
}Usage Examples:
const { BrowsingContextInspector } = require('selenium-webdriver');
// Create context inspector
let contextInspector = new BrowsingContextInspector(driver);
// Monitor new contexts (tabs, iframes)
await contextInspector.onContextCreated((context) => {
console.log('New context created:', context.url);
if (context.url.includes('popup')) {
console.log('Popup detected, may need handling');
}
});
// Monitor context destruction
await contextInspector.onContextDestroyed((context) => {
console.log('Context destroyed:', context.context);
});
// Monitor navigation events
await contextInspector.onNavigationStarted((navigation) => {
console.log('Navigation started to:', navigation.url);
});
await contextInspector.onNavigationCompleted((navigation) => {
console.log('Navigation completed:', navigation.url);
console.log('Load time:', Date.now() - navigation.timestamp, 'ms');
});
// Monitor user prompts
await contextInspector.onUserPrompt((prompt) => {
console.log(`User prompt detected: ${prompt.type} - ${prompt.message}`);
// Auto-handle prompts based on type
if (prompt.type === 'alert') {
// Handle alert automatically
} else if (prompt.type === 'confirm') {
// Handle confirmation
}
});
// Navigate and see events fire
await driver.get('https://example.com');
// Clean up
await contextInspector.close();Enhanced input handling with BiDi protocol for advanced interaction capabilities.
/**
* BiDi input handling for advanced interactions
*/
class Input {
constructor(driver: WebDriver);
/** Perform action sequence in browsing context */
perform(contextId: string, actions: ActionSequence[]): Promise<void>;
/** Release all input sources */
release(contextId: string): Promise<void>;
/** Set files on input element */
setFiles(contextId: string, element: ElementReference, files: string[]): Promise<void>;
}
interface ActionSequence {
type: 'pointer' | 'key' | 'wheel';
id: string;
actions: Action[];
}
interface Action {
type: string;
duration?: number;
x?: number;
y?: number;
button?: number;
key?: string;
value?: string;
deltaX?: number;
deltaY?: number;
}Usage Examples:
const { Input } = require('selenium-webdriver');
// Create BiDi input handler
let input = new Input(driver);
let contextId = await driver.getWindowHandle();
// Complex pointer sequence
await input.perform(contextId, [{
type: 'pointer',
id: 'mouse',
actions: [
{ type: 'pointerMove', x: 100, y: 100, duration: 500 },
{ type: 'pointerDown', button: 0 },
{ type: 'pointerMove', x: 200, y: 200, duration: 1000 },
{ type: 'pointerUp', button: 0 }
]
}]);
// Multi-touch gestures
await input.perform(contextId, [
{
type: 'pointer',
id: 'finger1',
actions: [
{ type: 'pointerMove', x: 100, y: 100 },
{ type: 'pointerDown', button: 0 },
{ type: 'pointerMove', x: 150, y: 150, duration: 1000 },
{ type: 'pointerUp', button: 0 }
]
},
{
type: 'pointer',
id: 'finger2',
actions: [
{ type: 'pointerMove', x: 200, y: 200 },
{ type: 'pointerDown', button: 0 },
{ type: 'pointerMove', x: 150, y: 150, duration: 1000 },
{ type: 'pointerUp', button: 0 }
]
}
]);
// File upload via BiDi
let fileInput = await driver.findElement(By.css('input[type="file"]'));
await input.setFiles(contextId, {
sharedId: await fileInput.getId()
}, ['/path/to/file1.jpg', '/path/to/file2.png']);
// Release all inputs
await input.release(contextId);