or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-wdio--local-runner

A WebdriverIO runner to run tests locally within isolated worker processes

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

To install, run

npx @tessl/cli install tessl/npm-wdio--local-runner@9.19.0

0

# WebdriverIO Local Runner

1

2

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.

3

4

## Package Information

5

6

- **Package Name**: @wdio/local-runner

7

- **Package Type**: npm

8

- **Language**: TypeScript

9

- **Installation**: `npm install --save-dev @wdio/local-runner`

10

11

## Core Imports

12

13

```typescript

14

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

15

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

16

17

// Worker process runner (separate entry point)

18

import { runner } from "@wdio/local-runner/run";

19

```

20

21

For CommonJS:

22

23

```javascript

24

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

25

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

26

```

27

28

## Basic Usage

29

30

```typescript

31

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

32

33

// Initialize the runner with WebdriverIO config

34

const runner = new LocalRunner({} as never, {

35

autoXvfb: true,

36

outputDir: "./logs",

37

runnerEnv: { NODE_ENV: "test" }

38

} as WebdriverIO.Config);

39

40

// Initialize the runner

41

await runner.initialize();

42

43

// Run a test worker

44

const worker = await runner.run({

45

cid: "0-0",

46

command: "run",

47

configFile: "/path/to/wdio.conf.js",

48

args: {},

49

caps: { browserName: "chrome" },

50

specs: ["./test/example.spec.js"],

51

execArgv: [],

52

retries: 0

53

});

54

55

// Shutdown all workers when done

56

await runner.shutdown();

57

```

58

59

## Architecture

60

61

WebdriverIO Local Runner is built around several key components:

62

63

- **LocalRunner**: Main class that manages the worker pool and coordinates test execution

64

- **WorkerInstance**: Individual worker process manager that handles test execution in isolation

65

- **Runner Process**: Worker child process executor that runs the actual test framework

66

- **Process Management**: Each worker runs as a separate Node.js child process for complete isolation

67

- **IPC Message System**: Inter-process communication using Node.js child_process messaging

68

- **Xvfb Integration**: Automatic virtual display setup for headless browser testing with lazy initialization

69

- **Stream Management**: Aggregated output handling with capability ID prefixing and transformation

70

- **REPL Integration**: Interactive debugging support with queue management for multiple workers

71

- **Buffer Management**: Stream buffering for stdout/stderr aggregation with configurable options

72

73

## Capabilities

74

75

### Runner Management

76

77

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

78

79

```typescript { .api }

80

class LocalRunner {

81

workerPool: Record<string, WorkerInstance>;

82

stdout: WritableStreamBuffer;

83

stderr: WritableStreamBuffer;

84

85

constructor(options: never, config: WebdriverIO.Config);

86

initialize(): Promise<void>;

87

getWorkerCount(): number;

88

run(args: RunArgs): Promise<WorkerInstance>;

89

shutdown(): Promise<boolean>;

90

}

91

92

interface RunArgs extends Workers.WorkerRunPayload {

93

command: string;

94

args: Workers.WorkerMessageArgs;

95

cid: string;

96

}

97

```

98

99

[Runner Management](./runner-management.md)

100

101

### Worker Process Management

102

103

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

104

105

```typescript { .api }

106

class WorkerInstance extends EventEmitter implements Workers.Worker {

107

cid: string;

108

config: WebdriverIO.Config;

109

configFile: string;

110

caps: WebdriverIO.Capabilities;

111

capabilities: WebdriverIO.Capabilities;

112

specs: string[];

113

execArgv: string[];

114

retries: number;

115

stdout: WritableStreamBuffer;

116

stderr: WritableStreamBuffer;

117

childProcess?: ChildProcess;

118

sessionId?: string;

119

server?: Record<string, string>;

120

instances?: Record<string, { sessionId: string }>;

121

isMultiremote?: boolean;

122

isBusy: boolean;

123

isKilled: boolean;

124

isReady: Promise<boolean>;

125

isSetup: Promise<boolean>;

126

127

constructor(

128

config: WebdriverIO.Config,

129

payload: Workers.WorkerRunPayload,

130

stdout: WritableStreamBuffer,

131

stderr: WritableStreamBuffer,

132

xvfbManager: XvfbManager

133

);

134

135

startProcess(): Promise<ChildProcess>;

136

postMessage(

137

command: string,

138

args: Workers.WorkerMessageArgs,

139

requiresSetup?: boolean

140

): Promise<void>;

141

}

142

```

143

144

[Worker Process Management](./worker-management.md)

145

146

### Worker Process Execution

147

148

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

149

150

```typescript { .api }

151

// Exported from './run' entry point

152

interface RunnerInterface extends NodeJS.EventEmitter {

153

sigintWasCalled: boolean;

154

[key: string]: unknown;

155

}

156

157

const runner: RunnerInterface;

158

```

159

160

[Worker Process Execution](./worker-process-execution.md)

161

162

### Stream Management and Debugging

163

164

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

165

166

```typescript { .api }

167

function runnerTransformStream(

168

cid: string,

169

inputStream: Readable,

170

aggregator?: string[]

171

): Readable;

172

173

class ReplQueue {

174

isRunning: boolean;

175

add(childProcess: ChildProcess, config: ReplConfig, onStart: () => void, onResult: (ev: unknown) => void): void;

176

next(): void;

177

}

178

179

const SHUTDOWN_TIMEOUT: 5000;

180

const DEBUGGER_MESSAGES: string[];

181

const BUFFER_OPTIONS: { initialSize: number; incrementAmount: number; };

182

```

183

184

[Stream Management and Debugging](./stream-debugging.md)

185

186

## Types

187

188

```typescript { .api }

189

interface Workers.WorkerRunPayload {

190

cid: string;

191

configFile: string;

192

caps: WebdriverIO.Capabilities;

193

specs: string[];

194

execArgv: string[];

195

retries: number;

196

}

197

198

interface Workers.WorkerMessageArgs {

199

[key: string]: any;

200

}

201

202

interface Workers.WorkerMessage {

203

name: string;

204

origin: string;

205

content?: any;

206

params?: any;

207

}

208

209

interface Workers.WorkerCommand {

210

cid: string;

211

command: string;

212

configFile: string;

213

args: Workers.WorkerMessageArgs;

214

caps: WebdriverIO.Capabilities;

215

specs: string[];

216

retries: number;

217

}

218

219

interface Workers.Worker {

220

cid: string;

221

isBusy: boolean;

222

// Additional worker interface properties

223

}

224

225

interface WebdriverIO.Config {

226

autoXvfb?: boolean;

227

xvfbAutoInstall?: string | boolean | object;

228

xvfbAutoInstallMode?: string;

229

xvfbAutoInstallCommand?: string;

230

xvfbMaxRetries?: number;

231

xvfbRetryDelay?: number;

232

outputDir?: string;

233

runnerEnv?: Record<string, any>;

234

watch?: boolean;

235

groupLogsByTestSpec?: boolean;

236

}

237

238

interface WebdriverIO.Capabilities {

239

browserName?: string;

240

[key: string]: any;

241

}

242

243

// External dependency types

244

interface WritableStreamBuffer {

245

// From 'stream-buffers' package

246

getContents(): Buffer;

247

}

248

249

interface XvfbManager {

250

// From '@wdio/xvfb' package

251

init(capabilities: WebdriverIO.Capabilities): Promise<boolean>;

252

shouldRun(): boolean;

253

}

254

255

interface ProcessFactory {

256

// From '@wdio/xvfb' package

257

createWorkerProcess(

258

scriptPath: string,

259

args: string[],

260

options: {

261

cwd: string;

262

env: Record<string, string>;

263

execArgv: string[];

264

stdio: any[];

265

}

266

): Promise<ChildProcess>;

267

}

268

269

interface ReplConfig {

270

// From '@wdio/repl' package

271

prompt?: string;

272

[key: string]: any;

273

}

274

275

interface ChildProcess {

276

// From Node.js 'child_process' module

277

pid?: number;

278

stdout: Readable | null;

279

stderr: Readable | null;

280

send(message: any): boolean;

281

kill(signal?: string): boolean;

282

on(event: string, listener: Function): this;

283

}

284

285

interface Readable {

286

// From Node.js 'stream' module

287

pipe(destination: any): any;

288

on(event: string, listener: Function): this;

289

}

290

291

interface Transform extends Readable {

292

// From Node.js 'stream' module

293

}

294

295

class EventEmitter {

296

// From Node.js 'events' module

297

on(event: string, listener: Function): this;

298

emit(event: string, ...args: any[]): boolean;

299

}

300

```