or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdcli.mdconfiguration.mderror-handling.mdevents.mdhooks.mdindex.mdtest-definition.mdtest-flavors.mdutilities.md

events.mddocs/

0

# Events

1

2

Event-driven architecture enabling monitoring of test lifecycle, capturing results, building custom reporting solutions, and integrating with external tools.

3

4

## Capabilities

5

6

### Event Registration

7

8

Register callbacks to listen for test lifecycle events.

9

10

```javascript { .api }

11

/**

12

* Register event listener for test lifecycle events

13

* @param {string} eventName - Name of the event to listen for

14

* @param {Function} callback - Function to call when event occurs

15

*/

16

QUnit.on(eventName, callback)

17

```

18

19

**Usage Examples:**

20

21

```javascript

22

import QUnit from "qunit";

23

24

// Listen for test start events

25

QUnit.on("testStart", function(details) {

26

console.log(`Starting test: ${details.name}`);

27

});

28

29

// Listen for assertion events

30

QUnit.on("assertion", function(details) {

31

if (!details.result) {

32

console.error(`Assertion failed: ${details.message}`);

33

}

34

});

35

36

// Listen for test completion

37

QUnit.on("testEnd", function(details) {

38

console.log(`Test completed: ${details.name} (${details.status})`);

39

});

40

```

41

42

### Test Run Events

43

44

Events related to overall test run lifecycle.

45

46

```javascript { .api }

47

/**

48

* Fired when test run begins

49

* @typedef {Object} RunStartEvent

50

* @property {number} totalTests - Total number of tests to run

51

* @property {Array} modules - Array of modules (for legacy callbacks)

52

*/

53

QUnit.on('runStart', function(runSuite) {

54

// runSuite contains test run information

55

console.log('Test run started');

56

});

57

58

/**

59

* Fired when test run completes

60

* @typedef {Object} RunEndEvent

61

* @property {string} status - 'passed' or 'failed'

62

* @property {Object} testCounts - Test result counts

63

* @property {number} runtime - Total runtime in milliseconds

64

*/

65

QUnit.on('runEnd', function(runSuite) {

66

// runSuite contains final test results

67

console.log('Test run completed');

68

});

69

```

70

71

**Usage Examples:**

72

73

```javascript

74

QUnit.on('runStart', function(runSuite) {

75

console.log('Test run started');

76

console.log(`Total tests: ${QUnit.config.stats.testCount}`);

77

});

78

79

QUnit.on('runEnd', function(runSuite) {

80

console.log('Test run completed');

81

console.log(`Results: ${runSuite.testCounts.passed} passed, ${runSuite.testCounts.failed} failed`);

82

console.log(`Runtime: ${runSuite.runtime}ms`);

83

});

84

```

85

86

### Module Events

87

88

Events related to test module execution.

89

90

```javascript { .api }

91

/**

92

* Fired when module execution begins

93

* @typedef {Object} SuiteStartEvent

94

* @property {string} name - Module name

95

* @property {string} moduleId - Module ID

96

*/

97

QUnit.on('suiteStart', function(suite) {

98

console.log(`Starting module: ${suite.name}`);

99

});

100

101

/**

102

* Fired when module execution completes

103

* @typedef {Object} SuiteEndEvent

104

* @property {string} name - Module name

105

* @property {string} moduleId - Module ID

106

* @property {string} status - 'passed' or 'failed'

107

* @property {Object} testCounts - Test counts within module

108

* @property {number} runtime - Module runtime in milliseconds

109

*/

110

QUnit.on('suiteEnd', function(suite) {

111

console.log(`Module completed: ${suite.name}`);

112

});

113

```

114

115

**Usage Examples:**

116

117

```javascript

118

QUnit.on('suiteStart', function(suite) {

119

console.log(`Starting module: ${suite.name}`);

120

console.log(`Tests in module: ${suite.testCounts.total}`);

121

});

122

123

QUnit.on('suiteEnd', function(suite) {

124

console.log(`Module ${suite.name} completed`);

125

console.log(`Status: ${suite.status}`);

126

console.log(`Runtime: ${suite.runtime}ms`);

127

});

128

```

129

130

### Test Events

131

132

Events related to individual test execution.

133

134

```javascript { .api }

135

/**

136

* Fired when individual test begins

137

* @typedef {Object} TestStartEvent

138

* @property {string} name - Test name

139

* @property {string} testId - Test ID

140

* @property {string} module - Module name

141

* @property {boolean} [previousFailure] - Whether test failed in previous run

142

*/

143

QUnit.on('testStart', function(test) {

144

console.log(`Starting test: ${test.name}`);

145

});

146

147

/**

148

* Fired when individual test completes

149

* @typedef {Object} TestEndEvent

150

* @property {string} name - Test name

151

* @property {string} testId - Test ID

152

* @property {string} module - Module name

153

* @property {boolean} skipped - Whether test was skipped

154

* @property {boolean} todo - Whether test is a todo test

155

* @property {number} failed - Number of failed assertions

156

* @property {number} passed - Number of passed assertions

157

* @property {number} total - Total number of assertions

158

* @property {number} runtime - Test runtime in milliseconds

159

* @property {Array} assertions - Array of assertion objects (HTML Reporter use)

160

* @property {string} source - Test source location (getter)

161

*/

162

QUnit.on('testEnd', function(test) {

163

const status = test.failed > 0 ? 'failed' : 'passed';

164

console.log(`Test ${status}: ${test.name}`);

165

});

166

```

167

168

**Usage Examples:**

169

170

```javascript

171

QUnit.on('testStart', function(test) {

172

console.log(`Starting test: ${test.name}`);

173

console.log(`Module: ${test.module}`);

174

console.log(`Test ID: ${test.testId}`);

175

});

176

177

QUnit.on('testEnd', function(test) {

178

const status = test.failed > 0 ? 'FAILED' : 'PASSED';

179

console.log(`${status}: ${test.name}`);

180

console.log(` Passed: ${test.passed}, Failed: ${test.failed}, Total: ${test.total}`);

181

console.log(` Runtime: ${test.runtime}ms`);

182

183

if (test.skipped) {

184

console.log(' Status: SKIPPED');

185

} else if (test.todo) {

186

console.log(' Status: TODO');

187

}

188

});

189

```

190

191

### Assertion Events

192

193

Events fired for each individual assertion.

194

195

```javascript { .api }

196

/**

197

* Fired for each assertion

198

* @typedef {Object} AssertionEvent

199

* @property {boolean} passed - Whether assertion passed

200

* @property {any} [actual] - Actual value

201

* @property {any} [expected] - Expected value

202

* @property {string} message - Assertion message

203

* @property {string} [stack] - Stack trace for failed assertions

204

* @property {boolean} todo - Whether assertion is in a todo test

205

*/

206

QUnit.on('assertion', function(assertion) {

207

if (assertion.passed) {

208

console.log(`✓ ${assertion.message}`);

209

} else {

210

console.error(`✗ ${assertion.message}`);

211

if (assertion.stack) {

212

console.error(assertion.stack);

213

}

214

}

215

});

216

```

217

218

**Usage Examples:**

219

220

```javascript

221

QUnit.on('assertion', function(assertion) {

222

if (assertion.passed) {

223

console.log(`✓ ${assertion.message}`);

224

} else {

225

console.error(`✗ ${assertion.message}`);

226

227

if (assertion.actual !== undefined) {

228

console.error(` Expected: ${assertion.expected}`);

229

console.error(` Actual: ${assertion.actual}`);

230

}

231

232

if (assertion.stack) {

233

console.error(` ${assertion.stack}`);

234

}

235

}

236

});

237

```

238

239

### Error Events

240

241

Events fired for uncaught errors and exceptions.

242

243

```javascript { .api }

244

/**

245

* Fired for uncaught errors during test execution

246

* @typedef {Object} ErrorEvent

247

* @property {string} message - Error message

248

* @property {string} [source] - Error source location

249

* @property {string} [testName] - Test name when error occurred

250

* @property {string} [module] - Module name when error occurred

251

*/

252

QUnit.on('error', function(error) {

253

console.error('Uncaught error:', error.message);

254

if (error.source) {

255

console.error('Source:', error.source);

256

}

257

});

258

```

259

260

**Usage Examples:**

261

262

```javascript

263

QUnit.on("error", function(details) {

264

console.error("Uncaught error during test execution:");

265

console.error(`Message: ${details.message}`);

266

console.error(`Source: ${details.source}`);

267

268

if (details.testName) {

269

console.error(`Test: ${details.testName}`);

270

}

271

272

if (details.module) {

273

console.error(`Module: ${details.module}`);

274

}

275

});

276

```

277

278

### Custom Reporter Implementation

279

280

Build custom reporters using the event system.

281

282

**Usage Examples:**

283

284

```javascript

285

// Custom JSON reporter

286

class JSONReporter {

287

constructor() {

288

this.results = {

289

tests: [],

290

modules: [],

291

summary: null

292

};

293

294

this.bindEvents();

295

}

296

297

bindEvents() {

298

QUnit.on("testEnd", (details) => {

299

this.results.tests.push({

300

name: details.name,

301

module: details.module,

302

status: details.status,

303

assertions: details.assertions.total,

304

runtime: details.runtime,

305

errors: details.errors

306

});

307

});

308

309

QUnit.on("suiteEnd", (details) => {

310

this.results.modules.push({

311

name: details.name,

312

status: details.status,

313

testCounts: details.testCounts,

314

runtime: details.runtime

315

});

316

});

317

318

QUnit.on("runEnd", (details) => {

319

this.results.summary = {

320

status: details.status,

321

testCounts: details.testCounts,

322

runtime: details.runtime

323

};

324

325

this.output();

326

});

327

}

328

329

output() {

330

console.log(JSON.stringify(this.results, null, 2));

331

}

332

}

333

334

// Initialize custom reporter

335

new JSONReporter();

336

```

337

338

### Event-based Test Monitoring

339

340

Monitor test progress and performance.

341

342

**Usage Examples:**

343

344

```javascript

345

// Performance monitoring

346

const performanceMonitor = {

347

slowTests: [],

348

threshold: 1000, // 1 second

349

350

init() {

351

QUnit.on("testEnd", (details) => {

352

if (details.runtime > this.threshold) {

353

this.slowTests.push({

354

name: details.name,

355

module: details.module,

356

runtime: details.runtime

357

});

358

}

359

});

360

361

QUnit.on("runEnd", () => {

362

if (this.slowTests.length > 0) {

363

console.warn("Slow tests detected:");

364

this.slowTests.forEach(test => {

365

console.warn(` ${test.module} > ${test.name}: ${test.runtime}ms`);

366

});

367

}

368

});

369

}

370

};

371

372

performanceMonitor.init();

373

```

374

375

## Supported Events

376

377

QUnit supports the following events (defined in src/events.js):

378

379

```javascript { .api }

380

/**

381

* Available event names:

382

* - 'error' - Uncaught errors (memory event)

383

* - 'runStart' - Test run begins

384

* - 'suiteStart' - Module execution begins

385

* - 'testStart' - Individual test begins

386

* - 'assertion' - Each assertion result

387

* - 'testEnd' - Individual test completes

388

* - 'suiteEnd' - Module execution completes

389

* - 'runEnd' - Test run completes (memory event)

390

*/

391

392

/**

393

* Memory events are replayed for late-registered listeners

394

* Events: 'error', 'runEnd'

395

*/

396

```

397

398

## Legacy Callback API

399

400

QUnit also supports legacy callbacks for backwards compatibility:

401

402

```javascript { .api }

403

/**

404

* Legacy callback functions (still supported but events preferred)

405

*/

406

QUnit.begin(callback) // Called before tests start

407

QUnit.testStart(callback) // Called when test starts

408

QUnit.log(callback) // Called for each assertion

409

QUnit.testDone(callback) // Called when test completes

410

QUnit.moduleStart(callback)// Called when module starts

411

QUnit.moduleDone(callback) // Called when module completes

412

QUnit.done(callback) // Called when all tests complete

413

```