0
# Circus Test Runner Types
1
2
Types for Jest's Circus test runner including event handling, test execution state, and test organization structures. Essential for developing custom test runners, reporters, and Jest plugins.
3
4
## Capabilities
5
6
### External Type Dependencies
7
8
Types from external modules used in Circus.
9
10
```typescript { .api }
11
/**
12
* Node.js Process type
13
*/
14
type Process = typeof process;
15
```
16
17
### Re-exported Global Types
18
19
Types imported from the Global module and used throughout Circus.
20
21
```typescript { .api }
22
/**
23
* Re-exported from Global module
24
*/
25
type DoneFn = (reason?: string | Error) => void;
26
type BlockFn = () => void;
27
type BlockName = string;
28
type BlockNameLike = BlockName | number | Function;
29
type TestName = string;
30
type TestNameLike = TestName | number | Function;
31
type TestFn = ((this: Record<string, unknown>) => void | undefined | Promise<unknown>) | ((this: Record<string, unknown>) => Generator<void, unknown, void>) | ((this: Record<string, unknown>, done: DoneFn) => void | undefined);
32
type ConcurrentTestFn = () => Promise<unknown>;
33
type HookFn = TestFn;
34
type TestContext = Record<string, unknown>;
35
```
36
37
### Core Circus Types
38
39
Basic types used throughout the Circus test runner system.
40
41
```typescript { .api }
42
/**
43
* Block execution modes
44
*/
45
type BlockMode = void | 'skip' | 'only' | 'todo';
46
47
/**
48
* Test execution modes (same as BlockMode)
49
*/
50
type TestMode = BlockMode;
51
52
/**
53
* Async function types (test or hook functions)
54
*/
55
type AsyncFn = TestFn | HookFn;
56
57
/**
58
* Shared hook types (apply to all tests in suite)
59
*/
60
type SharedHookType = 'afterAll' | 'beforeAll';
61
62
/**
63
* All hook types including per-test hooks
64
*/
65
type HookType = SharedHookType | 'afterEach' | 'beforeEach';
66
67
/**
68
* Exception type (anything can be thrown in JavaScript)
69
*/
70
type Exception = any;
71
72
/**
73
* String representation of an error
74
*/
75
type FormattedError = string;
76
77
/**
78
* Test execution status
79
*/
80
type TestStatus = 'skip' | 'done' | 'todo';
81
82
/**
83
* Path of test names from root to specific test
84
*/
85
type TestNamesPath = Array<TestName | BlockName>;
86
```
87
88
### Hook Interface
89
90
Interface representing a test hook with execution context and error handling.
91
92
```typescript { .api }
93
/**
94
* Test hook representation
95
*/
96
interface Hook {
97
/** Error object for async error tracking */
98
asyncError: Error;
99
/** Hook function to execute */
100
fn: HookFn;
101
/** Type of hook (beforeAll, beforeEach, etc.) */
102
type: HookType;
103
/** Parent describe block */
104
parent: DescribeBlock;
105
/** Whether done callback has been seen */
106
seenDone: boolean;
107
/** Hook timeout in milliseconds */
108
timeout: number | undefined | null;
109
}
110
```
111
112
### Event Handling Types
113
114
Types for Circus event system enabling custom reporters and plugins.
115
116
```typescript { .api }
117
/**
118
* Event handler function signature
119
*/
120
interface EventHandler {
121
(event: AsyncEvent, state: State): void | Promise<void>;
122
(event: SyncEvent, state: State): void;
123
}
124
125
/**
126
* Union of all event types
127
*/
128
type Event = SyncEvent | AsyncEvent;
129
130
/**
131
* Jest globals interface for Circus
132
*/
133
interface JestGlobals extends Global.TestFrameworkGlobals {
134
// expect is untyped to avoid circular dependencies
135
expect: unknown;
136
}
137
```
138
139
### Synchronous Events
140
141
Events that are dispatched synchronously during test definition phase.
142
143
```typescript { .api }
144
/**
145
* Synchronous events during test definition
146
*/
147
type SyncEvent =
148
| {
149
asyncError: Error;
150
mode: BlockMode;
151
name: 'start_describe_definition';
152
blockName: BlockName;
153
}
154
| {
155
mode: BlockMode;
156
name: 'finish_describe_definition';
157
blockName: BlockName;
158
}
159
| {
160
asyncError: Error;
161
name: 'add_hook';
162
hookType: HookType;
163
fn: HookFn;
164
timeout: number | undefined;
165
}
166
| {
167
asyncError: Error;
168
name: 'add_test';
169
testName: TestName;
170
fn: TestFn;
171
mode?: TestMode;
172
concurrent: boolean;
173
timeout: number | undefined;
174
failing: boolean;
175
}
176
| {
177
// Unhandled error outside of test/hooks
178
name: 'error';
179
error: Exception;
180
promise?: Promise<unknown>;
181
}
182
| {
183
name: 'error_handled';
184
promise: Promise<unknown>;
185
};
186
```
187
188
### Asynchronous Events
189
190
Events that are dispatched during test execution phase.
191
192
```typescript { .api }
193
/**
194
* Asynchronous events during test execution
195
*/
196
type AsyncEvent =
197
| {
198
// First action to dispatch - good time to initialize
199
name: 'setup';
200
testNamePattern?: string;
201
runtimeGlobals: JestGlobals;
202
parentProcess: Process;
203
}
204
| {
205
name: 'include_test_location_in_result';
206
}
207
| {
208
name: 'hook_start';
209
hook: Hook;
210
}
211
| {
212
name: 'hook_success';
213
describeBlock?: DescribeBlock;
214
test?: TestEntry;
215
hook: Hook;
216
}
217
| {
218
name: 'hook_failure';
219
error: string | Exception;
220
describeBlock?: DescribeBlock;
221
test?: TestEntry;
222
hook: Hook;
223
}
224
| {
225
name: 'test_fn_start';
226
test: TestEntry;
227
}
228
| {
229
name: 'test_fn_success';
230
test: TestEntry;
231
}
232
| {
233
name: 'test_fn_failure';
234
error: Exception;
235
test: TestEntry;
236
}
237
| {
238
name: 'test_retry';
239
test: TestEntry;
240
}
241
| {
242
// The test includes all hooks + test function
243
name: 'test_start';
244
test: TestEntry;
245
}
246
| {
247
name: 'test_skip';
248
test: TestEntry;
249
}
250
| {
251
name: 'test_todo';
252
test: TestEntry;
253
}
254
| {
255
name: 'test_started';
256
test: TestEntry;
257
}
258
| {
259
// Test is complete, nothing else will change its state
260
name: 'test_done';
261
test: TestEntry;
262
}
263
| {
264
name: 'run_describe_start';
265
describeBlock: DescribeBlock;
266
}
267
| {
268
name: 'run_describe_finish';
269
describeBlock: DescribeBlock;
270
}
271
| {
272
name: 'run_start';
273
}
274
| {
275
name: 'run_finish';
276
}
277
| {
278
// Final cleanup and result preparation
279
name: 'teardown';
280
};
281
```
282
283
### Test Execution Results
284
285
Types for test execution results and matcher outcomes.
286
287
```typescript { .api }
288
/**
289
* Results from matcher execution
290
*/
291
interface MatcherResults {
292
actual: unknown;
293
expected: unknown;
294
name: string;
295
pass: boolean;
296
}
297
298
/**
299
* Test case start information
300
*/
301
interface TestCaseStartInfo {
302
ancestorTitles: Array<string>;
303
fullName: string;
304
mode: TestMode;
305
title: string;
306
startedAt?: number | null;
307
}
308
309
/**
310
* Individual test result
311
*/
312
interface TestResult {
313
duration?: number | null;
314
errors: Array<FormattedError>;
315
errorsDetailed: Array<MatcherResults | unknown>;
316
/** Whether test.failing() was used */
317
failing?: boolean;
318
invocations: number;
319
startedAt?: number | null;
320
status: TestStatus;
321
location?: { column: number; line: number } | null;
322
numPassingAsserts: number;
323
retryReasons: Array<FormattedError>;
324
testPath: TestNamesPath;
325
}
326
327
/**
328
* Overall test run result
329
*/
330
interface RunResult {
331
unhandledErrors: Array<FormattedError>;
332
testResults: TestResults;
333
}
334
335
/**
336
* Array of test results
337
*/
338
type TestResults = Array<TestResult>;
339
```
340
341
### State Management
342
343
Types for managing Circus test runner state and global error handling.
344
345
```typescript { .api }
346
/**
347
* Global error handlers for different error types
348
*/
349
interface GlobalErrorHandlers {
350
rejectionHandled: Array<(promise: Promise<unknown>) => void>;
351
uncaughtException: Array<NodeJS.UncaughtExceptionListener>;
352
unhandledRejection: Array<NodeJS.UnhandledRejectionListener>;
353
}
354
355
/**
356
* Complete Circus test runner state
357
*/
358
interface State {
359
/** Current describe block being processed */
360
currentDescribeBlock: DescribeBlock;
361
/** Currently running test (includes when hooks are executing) */
362
currentlyRunningTest?: TestEntry | null;
363
/** Whether to expand error messages */
364
expand?: boolean;
365
/** Whether there are focused tests (test.only) */
366
hasFocusedTests: boolean;
367
/** Whether the root describe block has started running */
368
hasStarted: boolean;
369
/** Original global error handlers (restored after run) */
370
originalGlobalErrorHandlers?: GlobalErrorHandlers;
371
/** Process object from outer scope */
372
parentProcess: Process | null;
373
/** Whether to randomize test order */
374
randomize?: boolean;
375
/** Root describe block containing all tests */
376
rootDescribeBlock: DescribeBlock;
377
/** Random seed for test ordering */
378
seed: number;
379
/** Pattern for filtering test names */
380
testNamePattern?: RegExp | null;
381
/** Default test timeout */
382
testTimeout: number;
383
/** Unhandled errors during test run */
384
unhandledErrors: Array<Exception>;
385
/** Whether to include test location in results */
386
includeTestLocationInResult: boolean;
387
/** Maximum number of concurrent tests */
388
maxConcurrency: number;
389
/** Map of unhandled rejection errors by promise */
390
unhandledRejectionErrorByPromise: Map<Promise<unknown>, Exception>;
391
}
392
```
393
394
### Test Organization Structures
395
396
Interfaces representing test suite organization and individual tests.
397
398
```typescript { .api }
399
/**
400
* Describe block (test suite) representation
401
*/
402
interface DescribeBlock {
403
type: 'describeBlock';
404
/** Child describe blocks and tests */
405
children: Array<DescribeBlock | TestEntry>;
406
/** Hooks attached to this describe block */
407
hooks: Array<Hook>;
408
/** Execution mode of this block */
409
mode: BlockMode;
410
/** Name of the describe block */
411
name: BlockName;
412
/** Parent describe block (undefined for root) */
413
parent?: DescribeBlock;
414
/** @deprecated Use children array instead */
415
tests: Array<TestEntry>;
416
}
417
418
/**
419
* Test error types (can be single error or error pair for async)
420
*/
421
type TestError = Exception | [Exception | undefined, Exception];
422
423
/**
424
* Individual test entry representation
425
*/
426
interface TestEntry {
427
type: 'test';
428
/** Error for cases with no usable stack trace */
429
asyncError: Exception;
430
/** Test execution errors */
431
errors: Array<TestError>;
432
/** Errors from test retries */
433
retryReasons: Array<TestError>;
434
/** Test function to execute */
435
fn: TestFn;
436
/** Number of times test has been invoked */
437
invocations: number;
438
/** Test execution mode */
439
mode: TestMode;
440
/** Whether test runs concurrently */
441
concurrent: boolean;
442
/** Test name */
443
name: TestName;
444
/** Number of passing assertions */
445
numPassingAsserts: number;
446
/** Parent describe block */
447
parent: DescribeBlock;
448
/** Test start timestamp */
449
startedAt?: number | null;
450
/** Test duration in milliseconds */
451
duration?: number | null;
452
/** Whether done callback has been seen */
453
seenDone: boolean;
454
/** Test execution status */
455
status?: TestStatus | null;
456
/** Test timeout in milliseconds */
457
timeout?: number;
458
/** Whether this is a failing test (test.failing) */
459
failing: boolean;
460
/** Map of unhandled rejection errors by promise */
461
unhandledRejectionErrorByPromise: Map<Promise<unknown>, Exception>;
462
}
463
```
464
465
**Usage Examples:**
466
467
```typescript
468
import type { Circus } from "@jest/types";
469
470
// Custom event handler
471
const myEventHandler: Circus.EventHandler = (event, state) => {
472
if (event.name === 'test_start') {
473
console.log(`Starting test: ${event.test.name}`);
474
}
475
};
476
477
// Check test status
478
const checkTestStatus = (test: Circus.TestEntry) => {
479
if (test.status === 'done' && test.errors.length === 0) {
480
console.log(`Test ${test.name} passed`);
481
}
482
};
483
484
// Process test results
485
const processResults = (runResult: Circus.RunResult) => {
486
runResult.testResults.forEach((result) => {
487
console.log(`${result.testPath.join(' > ')}: ${result.status}`);
488
});
489
};
490
```