Overview
Type definitions for worker process communication, messaging protocols, and the socket-based message system used between the main process, test runners, and browser runner environments.
Description
This module defines the inter-process communication types for WebdriverIO's parallel test execution architecture. Job represents a unit of work assigned to a worker including capabilities and specs. WorkerRunPayload carries the data needed to initialize a worker process, while WorkerCommand and WorkerMessage define the command/response protocol between the main process and workers. The Worker interface extends EventEmitter and the Testrunner options to model a running worker with its session, capabilities, and messaging methods. The MESSAGE_TYPES enum and SocketMessage type define the browser runner's WebSocket communication protocol covering console messages, command requests/responses, hook triggers, and expect assertion flow.
Usage
Use these types when building custom runner implementations, extending worker process behavior, or implementing browser runner communication handlers. The Worker interface is referenced by RunnerInstance.run() and the worker pool. MESSAGE_TYPES and SocketMessage are used in the browser runner to handle bidirectional communication between Node.js and browser environments. WorkerPool is used by the test orchestrator to track and manage all active worker processes.
Code Reference
Source Location
Signature
export interface Job {
caps: WebdriverIO.Capabilities
specs: string[]
hasTests: boolean
baseUrl?: string
config?: TestrunnerOptions & { sessionId?: string }
capabilities?: WebdriverIO.Capabilities
}
export interface WorkerRunPayload {
cid: string
configFile: string
caps: WebdriverIO.Capabilities
specs: string[]
execArgv: string[]
retries: number
}
export interface WorkerCommand extends Omit<WorkerRunPayload, 'execArgv'> {
command: string
args: any
}
export interface WorkerMessage {
name: string
specFileRetries?: number
content: {
sessionId?: string
isMultiremote?: boolean
capabilities: WebdriverIO.Capabilities
}
origin: string
params: Record<string, string>
}
export interface Worker
extends Omit<TestrunnerOptions, 'capabilities' | 'specs' | 'rootDir'>,
EventEmitter {
capabilities: WebdriverIO.Capabilities
config: TestrunnerOptions
caps: WebdriverIO.Capabilities
cid: string
isBusy?: boolean
postMessage: (command: string, args: WorkerMessageArgs) => void
specs: string[]
sessionId?: string
logsAggregator: string[]
}
export type WorkerPool = Record<string, Worker>
export enum MESSAGE_TYPES {
consoleMessage = 0,
commandRequestMessage,
commandResponseMessage,
hookTriggerMessage,
hookResultMessage,
expectRequestMessage,
expectResponseMessage,
expectMatchersRequest,
expectMatchersResponse,
coverageMap,
customCommand,
initiateBrowserStateRequest,
initiateBrowserStateResponse,
browserTestResult
}
export type SocketMessage = SocketMessagePayload<MESSAGE_TYPES>
export type SocketMessagePayload<T extends MESSAGE_TYPES> = T extends any
? SocketMessagePayloadType<T>
: never
Import
import type { Workers } from '@wdio/types'
// Access specific types
type WorkerJob = Workers.Job
type Payload = Workers.WorkerRunPayload
type Cmd = Workers.WorkerCommand
type Msg = Workers.WorkerMessage
type WorkerInstance = Workers.Worker
type Pool = Workers.WorkerPool
type MsgTypes = Workers.MESSAGE_TYPES
type SocketMsg = Workers.SocketMessage
I/O Contract
| Key Type Members (Job)
|
| Name |
Type |
Required |
Description
|
caps |
WebdriverIO.Capabilities |
Yes |
Capabilities for the worker session
|
specs |
string[] |
Yes |
Spec file paths to execute
|
hasTests |
boolean |
Yes |
Whether the job has tests to run
|
baseUrl |
string |
No |
Base URL override for the worker
|
config |
TestrunnerOptions |
No |
Worker-specific configuration override
|
| Key Type Members (Worker)
|
| Name |
Type |
Required |
Description
|
cid |
string |
Yes |
Worker capability ID (e.g., '0-0')
|
capabilities |
WebdriverIO.Capabilities |
Yes |
Resolved capabilities for this worker
|
specs |
string[] |
Yes |
Spec files assigned to this worker
|
isBusy |
boolean |
No |
Whether the worker is currently executing
|
postMessage |
(command, args) => void |
Yes |
Send a command to the worker process
|
sessionId |
string |
No |
WebDriver session ID once established
|
logsAggregator |
string[] |
Yes |
Collected log output from the worker
|
| MESSAGE_TYPES Enum Values
|
| Value |
Name |
Description
|
| 0 |
consoleMessage |
Browser console output forwarding
|
| 1 |
commandRequestMessage |
WebDriver command request from browser to Node
|
| 2 |
commandResponseMessage |
WebDriver command response from Node to browser
|
| 3 |
hookTriggerMessage |
Hook execution trigger
|
| 4 |
hookResultMessage |
Hook execution result
|
| 5 |
expectRequestMessage |
Assertion request from browser
|
| 6 |
expectResponseMessage |
Assertion response to browser
|
| 7 |
expectMatchersRequest |
Request available matchers
|
| 8 |
expectMatchersResponse |
Available matchers response
|
| 9 |
coverageMap |
Code coverage data
|
| 10 |
customCommand |
Custom command registration
|
| 11 |
initiateBrowserStateRequest |
Browser state initialization request
|
| 12 |
initiateBrowserStateResponse |
Browser state initialization response
|
| 13 |
browserTestResult |
Test results from browser runner
|
Usage Examples
import type { Workers } from '@wdio/types'
// Define a job for worker execution
const job: Workers.Job = {
caps: { browserName: 'chrome' },
specs: ['./test/specs/login.spec.ts', './test/specs/dashboard.spec.ts'],
hasTests: true,
baseUrl: 'https://staging.example.com'
}
// Create a worker run payload
const payload: Workers.WorkerRunPayload = {
cid: '0-0',
configFile: './wdio.conf.ts',
caps: { browserName: 'chrome' },
specs: ['./test/specs/login.spec.ts'],
execArgv: ['--max-old-space-size=4096'],
retries: 2
}
// Track workers in a pool
const workerPool: Workers.WorkerPool = {}
function assignWork(worker: Workers.Worker, specs: string[]) {
if (!worker.isBusy) {
worker.postMessage('run', {
config: worker.config,
capabilities: worker.capabilities
})
}
}
// Handle socket messages in browser runner
function handleSocketMessage(message: Workers.SocketMessage) {
switch (message.type) {
case Workers.MESSAGE_TYPES.consoleMessage:
const consoleEvent = message.value
console[consoleEvent.type](...consoleEvent.args)
break
case Workers.MESSAGE_TYPES.commandRequestMessage:
const cmdRequest = message.value
processCommand(cmdRequest.commandName, cmdRequest.args)
break
case Workers.MESSAGE_TYPES.browserTestResult:
const testResult = message.value
console.log(`Browser tests: ${testResult.failures} failures`)
break
}
}
// Listen for worker messages
function onWorkerMessage(msg: Workers.WorkerMessage) {
console.log(`Worker ${msg.origin}: ${msg.name}`)
if (msg.content.sessionId) {
console.log(`Session: ${msg.content.sessionId}`)
}
}
Related Pages