or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

browser-environment.mdbuild-tools.mdcli.mdconfiguration.mdindex.mdplugin-system.mdtest-runner.md

test-runner.mddocs/

0

# Test Runner

1

2

The Web Component Tester programmatic API provides full control over test execution with event-based progress tracking and comprehensive configuration options.

3

4

## Capabilities

5

6

### Main Test Function

7

8

Runs a suite of web component tests with lifecycle events and comprehensive error handling.

9

10

```typescript { .api }

11

/**

12

* Runs a suite of web component tests

13

* @param options - Configuration object or Context instance

14

* @returns Promise that resolves when all tests complete

15

*/

16

function test(options: Config | Context): Promise<void>;

17

```

18

19

**Usage Examples:**

20

21

```javascript

22

const wct = require('web-component-tester');

23

24

// Basic test run

25

await wct.test({

26

suites: ['test/**/*.html'],

27

verbose: true

28

});

29

30

// Advanced configuration

31

await wct.test({

32

suites: ['test/unit/*.html', 'test/integration/*.js'],

33

root: './app',

34

testTimeout: 30000,

35

persistent: false,

36

plugins: {

37

local: {

38

browsers: ['chrome', 'firefox']

39

}

40

}

41

});

42

43

// Using Context for advanced control

44

const { Context } = wct;

45

const context = new Context({

46

verbose: true,

47

suites: ['test/*.html']

48

});

49

50

context.on('test-end', (browser, test, stats) => {

51

console.log(`Test "${test.title}" ${test.state}`);

52

});

53

54

await wct.test(context);

55

```

56

57

### Configuration Interface

58

59

Main configuration object for controlling test execution behavior.

60

61

```typescript { .api }

62

interface Config {

63

/** Array of test file patterns to run */

64

suites?: string[];

65

/** Output stream for test results */

66

output?: NodeJS.WritableStream;

67

/** Enable TTY-specific output formatting */

68

ttyOutput?: boolean;

69

/** Enable verbose logging */

70

verbose?: boolean;

71

/** Suppress output */

72

quiet?: boolean;

73

/** Show expanded test results */

74

expanded?: boolean;

75

/** Root directory for test files */

76

root?: string;

77

/** Test timeout in milliseconds */

78

testTimeout?: number;

79

/** Keep browsers open after tests complete */

80

persistent?: boolean;

81

/** Additional scripts to load in browser */

82

extraScripts?: string[];

83

/** Package name for client-side WCT code */

84

wctPackageName?: string;

85

/** Browser-side configuration options */

86

clientOptions?: {

87

root?: string;

88

verbose?: boolean;

89

environmentScripts?: string[];

90

};

91

/** Active browser configurations */

92

activeBrowsers?: BrowserDef[];

93

/** Plugin configurations */

94

plugins?: {[key: string]: any};

95

/** Browser-specific options */

96

browserOptions?: any;

97

/** Skip cleanup after tests */

98

skipCleanup?: boolean;

99

}

100

```

101

102

### Browser Definition

103

104

Configuration for individual browser instances.

105

106

```typescript { .api }

107

interface BrowserDef {

108

/** Browser name (chrome, firefox, safari, etc.) */

109

browserName?: string;

110

/** Platform/OS name */

111

platform?: string;

112

/** Browser version */

113

version?: string;

114

/** Unique browser ID (assigned automatically) */

115

id?: number;

116

/** Variant name for dependency testing */

117

variant?: string;

118

/** Additional browser-specific capabilities */

119

[key: string]: any;

120

}

121

122

type Browser = string | BrowserDef;

123

```

124

125

## Test Lifecycle Events

126

127

The test runner emits comprehensive lifecycle events for monitoring test progress:

128

129

### Event Types

130

131

```typescript { .api }

132

// Lifecycle Events

133

interface TestEvents {

134

'run-start': (options: Config) => void;

135

'browser-init': (browser: BrowserDef, stats: TestStats) => void;

136

'browser-start': (browser: BrowserDef, metadata: any, stats: TestStats) => void;

137

'sub-suite-start': (browser: BrowserDef, sharedState: any, stats: TestStats) => void;

138

'test-start': (browser: BrowserDef, test: TestCase, stats: TestStats) => void;

139

'test-end': (browser: BrowserDef, test: TestCase, stats: TestStats) => void;

140

'sub-suite-end': (browser: BrowserDef, sharedState: any, stats: TestStats) => void;

141

'browser-end': (browser: BrowserDef, error: any, stats: TestStats) => void;

142

'run-end': (error: any) => void;

143

144

// Log Events

145

'log:debug': (message: string, ...args: any[]) => void;

146

'log:info': (message: string, ...args: any[]) => void;

147

'log:warn': (message: string, ...args: any[]) => void;

148

'log:error': (message: string, ...args: any[]) => void;

149

}

150

```

151

152

### Event Usage Examples

153

154

```javascript

155

const wct = require('web-component-tester');

156

const { Context } = wct;

157

158

const context = new Context({

159

suites: ['test/*.html'],

160

verbose: true

161

});

162

163

// Track test progress

164

context.on('run-start', (options) => {

165

console.log('Starting test run with', options.activeBrowsers.length, 'browsers');

166

});

167

168

context.on('browser-start', (browser, metadata, stats) => {

169

console.log(`Browser ${browser.browserName} started`);

170

});

171

172

context.on('test-end', (browser, test, stats) => {

173

const status = test.state === 'passed' ? '✓' : '✗';

174

console.log(`${status} ${test.title} (${browser.browserName})`);

175

});

176

177

context.on('browser-end', (browser, error, stats) => {

178

if (error) {

179

console.error(`Browser ${browser.browserName} failed:`, error);

180

} else {

181

console.log(`Browser ${browser.browserName} completed: ${stats.passed}/${stats.total} passed`);

182

}

183

});

184

185

context.on('run-end', (error) => {

186

if (error) {

187

console.error('Test run failed:', error);

188

} else {

189

console.log('All tests completed successfully');

190

}

191

});

192

193

await wct.test(context);

194

```

195

196

## Advanced Usage

197

198

### Custom Reporting

199

200

```javascript

201

const wct = require('web-component-tester');

202

const fs = require('fs');

203

204

class CustomReporter {

205

constructor() {

206

this.results = [];

207

}

208

209

onTestEnd(browser, test, stats) {

210

this.results.push({

211

browser: browser.browserName,

212

test: test.title,

213

state: test.state,

214

duration: test.duration,

215

timestamp: new Date().toISOString()

216

});

217

}

218

219

onRunEnd() {

220

fs.writeFileSync('test-results.json', JSON.stringify(this.results, null, 2));

221

}

222

}

223

224

const context = new wct.Context({ suites: ['test/*.html'] });

225

const reporter = new CustomReporter();

226

227

context.on('test-end', reporter.onTestEnd.bind(reporter));

228

context.on('run-end', reporter.onRunEnd.bind(reporter));

229

230

await wct.test(context);

231

```

232

233

### Error Handling

234

235

```javascript

236

const wct = require('web-component-tester');

237

238

try {

239

await wct.test({

240

suites: ['test/*.html'],

241

testTimeout: 10000

242

});

243

console.log('All tests passed!');

244

} catch (error) {

245

console.error('Test run failed:', error.message);

246

247

// Check if it's a test failure vs system error

248

if (error.message.includes('failed')) {

249

process.exit(1); // Test failures

250

} else {

251

console.error('System error occurred');

252

process.exit(2); // System errors

253

}

254

}

255

```

256

257

### Plugin Integration

258

259

```javascript

260

const wct = require('web-component-tester');

261

262

await wct.test({

263

suites: ['test/*.html'],

264

plugins: {

265

// Local browser testing

266

local: {

267

browsers: ['chrome', 'firefox'],

268

browserOptions: {

269

chrome: ['--headless', '--disable-gpu'],

270

firefox: ['-headless']

271

}

272

},

273

// Sauce Labs testing

274

sauce: {

275

username: process.env.SAUCE_USERNAME,

276

accessKey: process.env.SAUCE_ACCESS_KEY,

277

browsers: [

278

{ browserName: 'chrome', platform: 'Windows 10' },

279

{ browserName: 'firefox', platform: 'macOS 10.15' }

280

]

281

}

282

}

283

});

284

```

285

286

## Types

287

288

```typescript { .api }

289

interface TestCase {

290

title: string;

291

state: 'passed' | 'failed' | 'pending';

292

duration?: number;

293

error?: Error;

294

}

295

296

interface TestStats {

297

passed: number;

298

pending: number;

299

failed: number;

300

total: number;

301

}

302

303

interface Context extends EventEmitter {

304

options: Config;

305

emitHook(name: string): Promise<void>;

306

plugins(): Promise<Plugin[]>;

307

}

308

```