0
# CLI Integration
1
2
Programmatic interface to Jest's command-line functionality, supporting all CLI options and returning structured results. The runCLI function provides a complete CLI-compatible interface perfect for build tools, CI systems, and custom test runners.
3
4
## Capabilities
5
6
### CLI Runner Function
7
8
Main function providing complete Jest CLI functionality programmatically.
9
10
```typescript { .api }
11
/**
12
* Runs Jest with command-line arguments and project paths
13
* @param argv - Jest CLI arguments and configuration options
14
* @param projects - Array of project paths to run tests for
15
* @returns Promise resolving to test results and global configuration
16
*/
17
export async function runCLI(
18
argv: Config.Argv,
19
projects: Array<string>
20
): Promise<{
21
results: AggregatedResult;
22
globalConfig: Config.GlobalConfig;
23
}>;
24
```
25
26
**Basic Usage Example:**
27
28
```typescript
29
import { runCLI } from "@jest/core";
30
import { Config } from "@jest/types";
31
32
// Define CLI arguments similar to command line usage
33
const argv: Config.Argv = {
34
// Test discovery
35
testMatch: ["**/__tests__/**/*.test.js"],
36
testPathIgnorePatterns: ["/node_modules/", "/build/"],
37
38
// Output options
39
verbose: true,
40
coverage: true,
41
coverageDirectory: "./coverage",
42
43
// Execution options
44
maxWorkers: 4,
45
runInBand: false,
46
47
// Other options
48
bail: false,
49
forceExit: true,
50
};
51
52
const projects = ["./src", "./packages/utils"];
53
54
try {
55
const { results, globalConfig } = await runCLI(argv, projects);
56
57
console.log(`Tests run: ${results.numTotalTests}`);
58
console.log(`Tests passed: ${results.numPassedTests}`);
59
console.log(`Tests failed: ${results.numFailedTests}`);
60
console.log(`Success: ${results.success}`);
61
62
// Exit with appropriate code
63
process.exit(results.success ? 0 : 1);
64
} catch (error) {
65
console.error("Jest execution failed:", error);
66
process.exit(1);
67
}
68
```
69
70
**Important Note**: When `watch: true` or `watchAll: true` is set in argv, the runCLI function will return a Promise that never resolves, as Jest enters watch mode and monitors for file changes. The function will only complete when the watch process is interrupted (Ctrl+C) or terminated externally.
71
72
## Configuration Options
73
74
### Test Discovery Options
75
76
Configure how Jest finds and filters test files.
77
78
```typescript
79
const discoveryConfig: Partial<Config.Argv> = {
80
// Pattern matching
81
testMatch: ["**/__tests__/**/*.test.{js,ts}"],
82
testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
83
testPathIgnorePatterns: ["/node_modules/", "/dist/"],
84
85
// Root directories
86
rootDir: "./src",
87
roots: ["<rootDir>/src", "<rootDir>/tests"],
88
89
// File extensions
90
moduleFileExtensions: ["js", "ts", "json"],
91
92
// Project selection
93
selectProjects: ["frontend", "backend"],
94
ignoreProjects: ["legacy"],
95
};
96
```
97
98
### Execution Control Options
99
100
Control how tests are executed and scheduled.
101
102
```typescript
103
const executionConfig: Partial<Config.Argv> = {
104
// Parallelization
105
maxWorkers: 4,
106
runInBand: false, // Set to true to disable parallel execution
107
108
// Bail options
109
bail: 1, // Stop after first failure
110
111
// Watch mode
112
watch: false,
113
watchAll: false,
114
115
// Timeout
116
testTimeout: 5000,
117
118
// Cache
119
cache: true,
120
clearCache: false,
121
};
122
```
123
124
### Output and Reporting Options
125
126
Configure test output and reporting formats.
127
128
```typescript
129
const outputConfig: Partial<Config.Argv> = {
130
// Verbosity
131
verbose: true,
132
silent: false,
133
134
// Output formats
135
json: false, // Output results as JSON
136
outputFile: "./test-results.json",
137
138
// Coverage
139
coverage: true,
140
coverageDirectory: "./coverage",
141
collectCoverageFrom: [
142
"src/**/*.{js,ts}",
143
"!src/**/*.test.{js,ts}",
144
"!src/**/*.d.ts",
145
],
146
coverageThreshold: {
147
global: {
148
branches: 80,
149
functions: 80,
150
lines: 80,
151
statements: 80,
152
},
153
},
154
155
// Reporters
156
reporters: [
157
"default",
158
["jest-junit", { outputDirectory: "./test-results" }],
159
],
160
161
// Error output
162
useStderr: false,
163
};
164
```
165
166
## Advanced Usage Patterns
167
168
### CI/CD Integration
169
170
```typescript
171
import { runCLI } from "@jest/core";
172
173
async function runTestsForCI() {
174
const isCI = process.env.CI === "true";
175
176
const argv: Config.Argv = {
177
// Optimize for CI
178
maxWorkers: isCI ? 2 : 4,
179
cache: !isCI, // Disable cache in CI
180
coverage: true,
181
coverageReporters: ["text", "lcov", "json"],
182
183
// CI-specific options
184
forceExit: true,
185
detectOpenHandles: true,
186
verbose: false,
187
silent: false,
188
189
// Output for CI tools
190
json: true,
191
outputFile: "./test-results.json",
192
193
// Reporters for CI
194
reporters: [
195
"default",
196
["jest-junit", {
197
outputDirectory: "./test-results",
198
outputName: "junit.xml",
199
}],
200
],
201
};
202
203
const { results } = await runCLI(argv, [process.cwd()]);
204
205
// Generate additional CI artifacts
206
if (isCI) {
207
await generateCoverageReport(results);
208
await uploadTestResults(results);
209
}
210
211
return results;
212
}
213
```
214
215
### Watch Mode Integration
216
217
```typescript
218
async function runWithCustomWatch() {
219
const argv: Config.Argv = {
220
watch: true,
221
watchman: true,
222
watchPathIgnorePatterns: ["/node_modules/", "/build/"],
223
224
// Watch mode specific options
225
onlyChanged: true,
226
changedFilesWithAncestor: true,
227
228
// Minimal output for watch mode
229
verbose: false,
230
coverage: false,
231
};
232
233
// This will run indefinitely in watch mode
234
const { results } = await runCLI(argv, [process.cwd()]);
235
236
// This code won't be reached in watch mode
237
return results;
238
}
239
```
240
241
### Multi-Project Configuration
242
243
```typescript
244
async function runMultiProjectTests() {
245
const argv: Config.Argv = {
246
// Multi-project configuration
247
projects: [
248
{
249
displayName: "frontend",
250
testMatch: ["<rootDir>/src/frontend/**/*.test.js"],
251
testEnvironment: "jsdom",
252
},
253
{
254
displayName: "backend",
255
testMatch: ["<rootDir>/src/backend/**/*.test.js"],
256
testEnvironment: "node",
257
},
258
{
259
displayName: "integration",
260
testMatch: ["<rootDir>/tests/integration/**/*.test.js"],
261
testEnvironment: "node",
262
testTimeout: 30000,
263
},
264
],
265
266
// Run specific projects
267
selectProjects: ["frontend", "backend"],
268
269
// Coverage across projects
270
coverage: true,
271
collectCoverageFrom: [
272
"src/**/*.js",
273
"!src/**/*.test.js",
274
],
275
};
276
277
const { results } = await runCLI(argv, []);
278
279
// Results will contain data from all selected projects
280
console.log("Project results:");
281
results.testResults.forEach(result => {
282
console.log(`${result.displayName}: ${result.numPassingTests} passed`);
283
});
284
285
return results;
286
}
287
```
288
289
### Custom Configuration Loading
290
291
```typescript
292
import * as path from "path";
293
import { readConfigs } from "jest-config";
294
295
async function runWithCustomConfig() {
296
// Load configuration from custom locations
297
const customArgv: Config.Argv = {
298
config: path.resolve("./custom-jest.config.js"),
299
rootDir: process.cwd(),
300
};
301
302
// Validate configuration before running
303
try {
304
const { globalConfig, configs } = await readConfigs(customArgv, [process.cwd()]);
305
306
console.log(`Loaded configuration for ${configs.length} projects`);
307
console.log(`Test timeout: ${globalConfig.testTimeout}ms`);
308
309
const { results } = await runCLI(customArgv, [process.cwd()]);
310
311
return { results, globalConfig };
312
} catch (configError) {
313
console.error("Configuration error:", configError);
314
throw configError;
315
}
316
}
317
```
318
319
## Types
320
321
```typescript { .api }
322
interface Config.Argv {
323
/** Test discovery patterns */
324
testMatch?: Array<string>;
325
testRegex?: Array<string>;
326
testPathIgnorePatterns?: Array<string>;
327
328
/** Execution options */
329
maxWorkers?: number;
330
runInBand?: boolean;
331
bail?: number | boolean;
332
333
/** Watch mode */
334
watch?: boolean;
335
watchAll?: boolean;
336
onlyChanged?: boolean;
337
338
/** Output options */
339
verbose?: boolean;
340
silent?: boolean;
341
json?: boolean;
342
outputFile?: string;
343
344
/** Coverage options */
345
coverage?: boolean;
346
coverageDirectory?: string;
347
collectCoverageFrom?: Array<string>;
348
coverageThreshold?: CoverageThreshold;
349
350
/** Project selection */
351
selectProjects?: Array<string>;
352
ignoreProjects?: Array<string>;
353
354
/** Configuration */
355
config?: string;
356
rootDir?: string;
357
roots?: Array<string>;
358
359
/** Cache options */
360
cache?: boolean;
361
clearCache?: boolean;
362
363
/** Process options */
364
forceExit?: boolean;
365
detectOpenHandles?: boolean;
366
367
/** Reporters */
368
reporters?: Array<string | [string, Record<string, any>]>;
369
370
/** Environment */
371
testEnvironment?: string;
372
testTimeout?: number;
373
}
374
375
interface CoverageThreshold {
376
global?: {
377
branches?: number;
378
functions?: number;
379
lines?: number;
380
statements?: number;
381
};
382
[key: string]: {
383
branches?: number;
384
functions?: number;
385
lines?: number;
386
statements?: number;
387
} | undefined;
388
}
389
```