CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-wdio--local-runner

A WebdriverIO runner to run tests locally within isolated worker processes

Pending
Overview
Eval results
Files

WebdriverIO Local Runner

WebdriverIO Local Runner executes test files locally within isolated worker processes to achieve maximum concurrency and test isolation. It spawns a separate worker process per capability, with each worker maintaining its own browser session for complete test isolation.

Package Information

  • Package Name: @wdio/local-runner
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install --save-dev @wdio/local-runner

Core Imports

import LocalRunner from "@wdio/local-runner";
import type { WorkerInstance, RunArgs } from "@wdio/local-runner";

// Worker process runner (separate entry point)
import { runner } from "@wdio/local-runner/run";

For CommonJS:

const LocalRunner = require("@wdio/local-runner");
const { runner } = require("@wdio/local-runner/run");

Basic Usage

import LocalRunner from "@wdio/local-runner";

// Initialize the runner with WebdriverIO config
const runner = new LocalRunner({} as never, {
  autoXvfb: true,
  outputDir: "./logs",
  runnerEnv: { NODE_ENV: "test" }
} as WebdriverIO.Config);

// Initialize the runner
await runner.initialize();

// Run a test worker
const worker = await runner.run({
  cid: "0-0",
  command: "run",
  configFile: "/path/to/wdio.conf.js",
  args: {},
  caps: { browserName: "chrome" },
  specs: ["./test/example.spec.js"],
  execArgv: [],
  retries: 0
});

// Shutdown all workers when done
await runner.shutdown();

Architecture

WebdriverIO Local Runner is built around several key components:

  • LocalRunner: Main class that manages the worker pool and coordinates test execution
  • WorkerInstance: Individual worker process manager that handles test execution in isolation
  • Runner Process: Worker child process executor that runs the actual test framework
  • Process Management: Each worker runs as a separate Node.js child process for complete isolation
  • IPC Message System: Inter-process communication using Node.js child_process messaging
  • Xvfb Integration: Automatic virtual display setup for headless browser testing with lazy initialization
  • Stream Management: Aggregated output handling with capability ID prefixing and transformation
  • REPL Integration: Interactive debugging support with queue management for multiple workers
  • Buffer Management: Stream buffering for stdout/stderr aggregation with configurable options

Capabilities

Runner Management

Core runner functionality for managing worker processes and coordinating test execution across multiple isolated environments.

class LocalRunner {
  workerPool: Record<string, WorkerInstance>;
  stdout: WritableStreamBuffer;
  stderr: WritableStreamBuffer;
  
  constructor(options: never, config: WebdriverIO.Config);
  initialize(): Promise<void>;
  getWorkerCount(): number;
  run(args: RunArgs): Promise<WorkerInstance>;
  shutdown(): Promise<boolean>;
}

interface RunArgs extends Workers.WorkerRunPayload {
  command: string;
  args: Workers.WorkerMessageArgs;
  cid: string;
}

Runner Management

Worker Process Management

Individual worker process management with lifecycle control, message passing, and browser session handling.

class WorkerInstance extends EventEmitter implements Workers.Worker {
  cid: string;
  config: WebdriverIO.Config;
  configFile: string;
  caps: WebdriverIO.Capabilities;
  capabilities: WebdriverIO.Capabilities;
  specs: string[];
  execArgv: string[];
  retries: number;
  stdout: WritableStreamBuffer;
  stderr: WritableStreamBuffer;
  childProcess?: ChildProcess;
  sessionId?: string;
  server?: Record<string, string>;
  instances?: Record<string, { sessionId: string }>;
  isMultiremote?: boolean;
  isBusy: boolean;
  isKilled: boolean;
  isReady: Promise<boolean>;
  isSetup: Promise<boolean>;
  
  constructor(
    config: WebdriverIO.Config,
    payload: Workers.WorkerRunPayload,
    stdout: WritableStreamBuffer,
    stderr: WritableStreamBuffer,
    xvfbManager: XvfbManager
  );
  
  startProcess(): Promise<ChildProcess>;
  postMessage(
    command: string,
    args: Workers.WorkerMessageArgs,
    requiresSetup?: boolean
  ): Promise<void>;
}

Worker Process Management

Worker Process Execution

Worker child process executor that runs the actual test framework in isolated processes.

// Exported from './run' entry point
interface RunnerInterface extends NodeJS.EventEmitter {
  sigintWasCalled: boolean;
  [key: string]: unknown;
}

const runner: RunnerInterface;

Worker Process Execution

Stream Management and Debugging

Advanced stream handling, output transformation, and interactive debugging capabilities.

function runnerTransformStream(
  cid: string,
  inputStream: Readable,
  aggregator?: string[]
): Readable;

class ReplQueue {
  isRunning: boolean;
  add(childProcess: ChildProcess, config: ReplConfig, onStart: () => void, onResult: (ev: unknown) => void): void;
  next(): void;
}

const SHUTDOWN_TIMEOUT: 5000;
const DEBUGGER_MESSAGES: string[];
const BUFFER_OPTIONS: { initialSize: number; incrementAmount: number; };

Stream Management and Debugging

Types

interface Workers.WorkerRunPayload {
  cid: string;
  configFile: string;
  caps: WebdriverIO.Capabilities;
  specs: string[];
  execArgv: string[];
  retries: number;
}

interface Workers.WorkerMessageArgs {
  [key: string]: any;
}

interface Workers.WorkerMessage {
  name: string;
  origin: string;
  content?: any;
  params?: any;
}

interface Workers.WorkerCommand {
  cid: string;
  command: string;
  configFile: string;
  args: Workers.WorkerMessageArgs;
  caps: WebdriverIO.Capabilities;
  specs: string[];
  retries: number;
}

interface Workers.Worker {
  cid: string;
  isBusy: boolean;
  // Additional worker interface properties
}

interface WebdriverIO.Config {
  autoXvfb?: boolean;
  xvfbAutoInstall?: string | boolean | object;
  xvfbAutoInstallMode?: string;
  xvfbAutoInstallCommand?: string;
  xvfbMaxRetries?: number;
  xvfbRetryDelay?: number;
  outputDir?: string;
  runnerEnv?: Record<string, any>;
  watch?: boolean;
  groupLogsByTestSpec?: boolean;
}

interface WebdriverIO.Capabilities {
  browserName?: string;
  [key: string]: any;
}

// External dependency types
interface WritableStreamBuffer {
  // From 'stream-buffers' package
  getContents(): Buffer;
}

interface XvfbManager {
  // From '@wdio/xvfb' package
  init(capabilities: WebdriverIO.Capabilities): Promise<boolean>;
  shouldRun(): boolean;
}

interface ProcessFactory {
  // From '@wdio/xvfb' package
  createWorkerProcess(
    scriptPath: string,
    args: string[],
    options: {
      cwd: string;
      env: Record<string, string>;
      execArgv: string[];
      stdio: any[];
    }
  ): Promise<ChildProcess>;
}

interface ReplConfig {
  // From '@wdio/repl' package
  prompt?: string;
  [key: string]: any;
}

interface ChildProcess {
  // From Node.js 'child_process' module
  pid?: number;
  stdout: Readable | null;
  stderr: Readable | null;
  send(message: any): boolean;
  kill(signal?: string): boolean;
  on(event: string, listener: Function): this;
}

interface Readable {
  // From Node.js 'stream' module
  pipe(destination: any): any;
  on(event: string, listener: Function): this;
}

interface Transform extends Readable {
  // From Node.js 'stream' module
}

class EventEmitter {
  // From Node.js 'events' module
  on(event: string, listener: Function): this;
  emit(event: string, ...args: any[]): boolean;
}

Install with Tessl CLI

npx tessl i tessl/npm-wdio--local-runner
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@wdio/local-runner@9.19.x