0
# Jest Circus
1
2
Jest Circus is a flux-based test runner for Jest that provides test framework globals and event-driven test execution. It serves as the default test execution engine for Jest, offering a highly maintainable and extensible architecture with comprehensive test orchestration capabilities.
3
4
## Package Information
5
6
- **Package Name**: jest-circus
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install jest-circus` (included with Jest 27+)
10
11
## Core Imports
12
13
```typescript
14
import { describe, it, test, beforeAll, afterAll, beforeEach, afterEach } from "jest-circus";
15
```
16
17
For state management and execution:
18
19
```typescript
20
import { getState, setState, resetState, run } from "jest-circus";
21
```
22
23
For type definitions:
24
25
```typescript
26
import { type Event, type State } from "jest-circus";
27
```
28
29
For Jest integration (runner):
30
31
```typescript
32
// Used in Jest configuration
33
import runner from "jest-circus/runner";
34
// or
35
const runner = require("jest-circus/runner");
36
```
37
38
## Basic Usage
39
40
```typescript
41
import { describe, it, test, beforeAll, afterAll, beforeEach, afterEach } from "jest-circus";
42
43
describe("Calculator", () => {
44
let calculator;
45
46
beforeAll(() => {
47
// Setup before all tests
48
calculator = new Calculator();
49
});
50
51
beforeEach(() => {
52
// Setup before each test
53
calculator.reset();
54
});
55
56
afterEach(() => {
57
// Cleanup after each test
58
calculator.clearMemory();
59
});
60
61
afterAll(() => {
62
// Cleanup after all tests
63
calculator = null;
64
});
65
66
it("should add numbers correctly", () => {
67
expect(calculator.add(2, 3)).toBe(5);
68
});
69
70
test("should multiply numbers correctly", () => {
71
expect(calculator.multiply(4, 5)).toBe(20);
72
});
73
74
test.concurrent("should handle concurrent tests", async () => {
75
const result = await calculator.asyncCalculation(10);
76
expect(result).toBe(100);
77
});
78
});
79
```
80
81
## Architecture
82
83
Jest Circus is built around several key components:
84
85
- **Test Framework Globals**: Standard Jest testing functions (`describe`, `it`, `test`) with support for lifecycle hooks
86
- **Flux-based Architecture**: Event-driven system where test execution triggers events that can be handled by custom environments
87
- **State Management**: Centralized state system tracking test execution progress and results
88
- **Concurrent Execution**: Built-in support for running tests concurrently with configurable concurrency limits
89
- **Event System**: Comprehensive event lifecycle for hooking into test execution phases
90
91
## Capabilities
92
93
### Test Framework Globals
94
95
Core testing functions for organizing and defining tests. Provides the standard Jest API with support for skipping, focusing, concurrent execution, and parameterized tests.
96
97
```typescript { .api }
98
function describe(blockName: BlockNameLike, blockFn: BlockFn): void;
99
function it(testName: TestNameLike, fn: TestFn, timeout?: number): void;
100
function test(testName: TestNameLike, fn: TestFn, timeout?: number): void;
101
102
function beforeAll(fn: HookFn, timeout?: number): void;
103
function afterAll(fn: HookFn, timeout?: number): void;
104
function beforeEach(fn: HookFn, timeout?: number): void;
105
function afterEach(fn: HookFn, timeout?: number): void;
106
```
107
108
[Test Framework Globals](./test-globals.md)
109
110
### State Management
111
112
Low-level state management for controlling test execution state and accessing runtime information.
113
114
```typescript { .api }
115
function getState(): State;
116
function setState(state: State): State;
117
function resetState(): void;
118
119
interface State {
120
currentDescribeBlock: DescribeBlock;
121
currentlyRunningTest?: TestEntry | null;
122
rootDescribeBlock: DescribeBlock;
123
hasStarted: boolean;
124
hasFocusedTests: boolean;
125
testTimeout: number;
126
maxConcurrency: number;
127
unhandledErrors: Array<Exception>;
128
includeTestLocationInResult: boolean;
129
parentProcess: NodeJS.Process | null;
130
seed: number;
131
testNamePattern?: RegExp | null;
132
expand?: boolean;
133
randomize?: boolean;
134
}
135
```
136
137
[State Management](./state-management.md)
138
139
### Test Execution
140
141
Core test execution engine that runs tests and produces results.
142
143
```typescript { .api }
144
function run(): Promise<RunResult>;
145
146
interface RunResult {
147
unhandledErrors: Array<FormattedError>;
148
testResults: TestResults;
149
}
150
```
151
152
[Test Execution](./test-execution.md)
153
154
### Jest Runner Integration
155
156
Jest test runner adapter for integrating circus with Jest's infrastructure.
157
158
```typescript { .api }
159
// Export from jest-circus/runner
160
function jestAdapter(
161
globalConfig: any,
162
config: any,
163
environment: any,
164
runtime: any,
165
testPath: string,
166
sendMessageToJest?: any
167
): Promise<any>;
168
```
169
170
The runner is automatically used when jest-circus is configured as the test runner.
171
172
## Types
173
174
```typescript { .api }
175
type BlockNameLike = string | Function;
176
type TestNameLike = string | Function;
177
type BlockName = string;
178
type TestName = string;
179
type BlockFn = () => void;
180
type TestFn = (done?: DoneFn) => void | Promise<void>;
181
type HookFn = (done?: DoneFn) => void | Promise<void>;
182
type DoneFn = (reason?: string | Error) => void;
183
type Exception = any;
184
type FormattedError = string;
185
186
type BlockMode = void | 'skip' | 'only' | 'todo';
187
type TestMode = BlockMode;
188
type HookType = 'beforeAll' | 'afterAll' | 'beforeEach' | 'afterEach';
189
190
interface DescribeBlock {
191
type: 'describeBlock';
192
children: Array<DescribeBlock | TestEntry>;
193
name: BlockName;
194
parent?: DescribeBlock;
195
mode: BlockMode;
196
hooks: Array<Hook>;
197
/** @deprecated Please get from children array instead */
198
tests: Array<TestEntry>;
199
}
200
201
interface TestEntry {
202
type: 'test';
203
asyncError: Exception;
204
concurrent: boolean;
205
errors: Array<Exception>;
206
retryReasons: Array<Exception>;
207
fn: TestFn;
208
mode: TestMode;
209
name: TestName;
210
parent: DescribeBlock;
211
seenDone: boolean;
212
timeout?: number;
213
failing: boolean;
214
invocations: number;
215
numPassingAsserts: number;
216
startedAt?: number | null;
217
duration?: number | null;
218
status?: 'skip' | 'done' | 'todo' | null;
219
}
220
221
interface Hook {
222
asyncError: Error;
223
fn: HookFn;
224
type: HookType;
225
parent: DescribeBlock;
226
seenDone: boolean;
227
timeout: number | undefined | null;
228
}
229
230
interface RunResult {
231
unhandledErrors: Array<FormattedError>;
232
testResults: Array<TestResult>;
233
}
234
235
interface TestResult {
236
duration?: number | null;
237
errors: Array<FormattedError>;
238
errorsDetailed: Array<unknown>;
239
invocations: number;
240
status: 'skip' | 'done' | 'todo';
241
location?: {column: number; line: number} | null;
242
numPassingAsserts: number;
243
retryReasons: Array<FormattedError>;
244
testPath: Array<TestName | BlockName>;
245
}
246
247
// Event types (re-exported from @jest/types)
248
type Event = SyncEvent | AsyncEvent;
249
type SyncEvent = {name: string; [key: string]: any};
250
type AsyncEvent = {name: string; [key: string]: any};
251
```