Skip to content

Commit 591d612

Browse files
authored
feat: Add support for the jest.config.ts configuration file (#10564)
1 parent d63f18a commit 591d612

20 files changed

Lines changed: 420 additions & 31 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
### Features
44

5+
- `[jest-cli, jest-config]` Add support for the `jest.config.ts` configuration file ([#10564](https://github.com/facebook/jest/pull/10564))
6+
57
### Fixes
68

79
### Chore & Maintenance

docs/Configuration.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ id: configuration
33
title: Configuring Jest
44
---
55

6-
Jest's configuration can be defined in the `package.json` file of your project, or through a `jest.config.js` file or through the `--config <path/to/file.js|cjs|mjs|json>` option. If you'd like to use your `package.json` to store Jest's config, the `"jest"` key should be used on the top level so Jest will know how to find your settings:
6+
Jest's configuration can be defined in the `package.json` file of your project, or through a `jest.config.js`, or `jest.config.ts` file or through the `--config <path/to/file.js|ts|cjs|mjs|json>` option. If you'd like to use your `package.json` to store Jest's config, the `"jest"` key should be used on the top level so Jest will know how to find your settings:
77

88
```json
99
{
@@ -18,19 +18,39 @@ Or through JavaScript:
1818

1919
```js
2020
// jest.config.js
21-
//Sync object
21+
// Sync object
2222
module.exports = {
2323
verbose: true,
2424
};
2525

26-
//Or async function
26+
// Or async function
2727
module.exports = async () => {
2828
return {
2929
verbose: true,
3030
};
3131
};
3232
```
3333

34+
Or through TypeScript (if `ts-node` is installed):
35+
36+
```ts
37+
// jest.config.ts
38+
import type {Config} from '@jest/types';
39+
40+
// Sync object
41+
const config: Config.InitialOptions = {
42+
verbose: true,
43+
};
44+
export default config;
45+
46+
// Or async function
47+
export default async (): Promise<Config.InitialOptions> => {
48+
return {
49+
verbose: true,
50+
};
51+
};
52+
```
53+
3454
Please keep in mind that the resulting configuration must be JSON-serializable.
3555

3656
When using the `--config` option, the JSON file must not contain a "jest" key:
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`traverses directory tree up until it finds jest.config 1`] = `
4+
console.log
5+
<<REPLACED>>/jest.config.ts/some/nested/directory
6+
7+
at Object.log (__tests__/a-giraffe.js:3:27)
8+
9+
`;
10+
11+
exports[`traverses directory tree up until it finds jest.config 2`] = `
12+
PASS ../../../__tests__/a-giraffe.js
13+
✓ giraffe
14+
✓ abc
15+
`;
16+
17+
exports[`traverses directory tree up until it finds jest.config 3`] = `
18+
Test Suites: 1 passed, 1 total
19+
Tests: 2 passed, 2 total
20+
Snapshots: 0 total
21+
Time: <<REPLACED>>
22+
Ran all test suites.
23+
`;
24+
25+
exports[`works with jest.config.ts 1`] = `
26+
PASS __tests__/a-giraffe.js
27+
✓ giraffe
28+
`;
29+
30+
exports[`works with jest.config.ts 2`] = `
31+
Test Suites: 1 passed, 1 total
32+
Tests: 1 passed, 1 total
33+
Snapshots: 0 total
34+
Time: <<REPLACED>>
35+
Ran all test suites.
36+
`;
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import * as path from 'path';
9+
import {wrap} from 'jest-snapshot-serializer-raw';
10+
import runJest from '../runJest';
11+
import {cleanup, extractSummary, writeFiles} from '../Utils';
12+
13+
const DIR = path.resolve(__dirname, '../jest.config.ts');
14+
15+
beforeEach(() => cleanup(DIR));
16+
afterAll(() => cleanup(DIR));
17+
18+
test('works with jest.config.ts', () => {
19+
writeFiles(DIR, {
20+
'__tests__/a-giraffe.js': `test('giraffe', () => expect(1).toBe(1));`,
21+
'jest.config.ts': `export default {testEnvironment: 'jest-environment-node', testRegex: '.*-giraffe.js'};`,
22+
'package.json': '{}',
23+
});
24+
25+
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false']);
26+
const {rest, summary} = extractSummary(stderr);
27+
expect(exitCode).toBe(0);
28+
expect(wrap(rest)).toMatchSnapshot();
29+
expect(wrap(summary)).toMatchSnapshot();
30+
});
31+
32+
test('traverses directory tree up until it finds jest.config', () => {
33+
writeFiles(DIR, {
34+
'__tests__/a-giraffe.js': `
35+
const slash = require('slash');
36+
test('giraffe', () => expect(1).toBe(1));
37+
test('abc', () => console.log(slash(process.cwd())));
38+
`,
39+
'jest.config.ts': `export default {testEnvironment: 'jest-environment-node', testRegex: '.*-giraffe.js'};`,
40+
'package.json': '{}',
41+
'some/nested/directory/file.js': '// nothing special',
42+
});
43+
44+
const {stderr, exitCode, stdout} = runJest(
45+
path.join(DIR, 'some', 'nested', 'directory'),
46+
['-w=1', '--ci=false'],
47+
{skipPkgJsonCheck: true},
48+
);
49+
50+
// Snapshot the console.loged `process.cwd()` and make sure it stays the same
51+
expect(
52+
wrap(stdout.replace(/^\W+(.*)e2e/gm, '<<REPLACED>>')),
53+
).toMatchSnapshot();
54+
55+
const {rest, summary} = extractSummary(stderr);
56+
expect(exitCode).toBe(0);
57+
expect(wrap(rest)).toMatchSnapshot();
58+
expect(wrap(summary)).toMatchSnapshot();
59+
});
60+
61+
test('it does type check the config', () => {
62+
writeFiles(DIR, {
63+
'__tests__/a-giraffe.js': `test('giraffe', () => expect(1).toBe(1));`,
64+
'jest.config.ts': `export default { testTimeout: "10000" }`,
65+
'package.json': '{}',
66+
});
67+
68+
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false']);
69+
expect(stderr).toMatch('must be of type');
70+
expect(exitCode).toBe(1);
71+
});
72+
73+
test('invalid JS in jest.config.ts', () => {
74+
writeFiles(DIR, {
75+
'__tests__/a-giraffe.js': `test('giraffe', () => expect(1).toBe(1));`,
76+
'jest.config.ts': `export default i'll break this file yo`,
77+
'package.json': '{}',
78+
});
79+
80+
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false']);
81+
expect(stderr).toMatch('TSError: ⨯ Unable to compile TypeScript:');
82+
expect(exitCode).toBe(1);
83+
});

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
"strip-ansi": "^6.0.0",
7878
"tempy": "^0.6.0",
7979
"throat": "^5.0.0",
80+
"ts-node": "^9.0.0",
8081
"type-fest": "^0.16.0",
8182
"typescript": "^4.0.2",
8283
"which": "^2.0.1"

packages/jest-cli/src/__tests__/cli/args.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,13 @@ describe('check', () => {
8282
it('raises an exception if config is not a valid JSON string', () => {
8383
const argv = {config: 'x:1'} as Config.Argv;
8484
expect(() => check(argv)).toThrow(
85-
'The --config option requires a JSON string literal, or a file path with one of these extensions: .js, .mjs, .cjs, .json',
85+
'The --config option requires a JSON string literal, or a file path with one of these extensions: .js, .ts, .mjs, .cjs, .json',
8686
);
8787
});
8888

8989
it('raises an exception if config is not a supported file type', () => {
9090
const message =
91-
'The --config option requires a JSON string literal, or a file path with one of these extensions: .js, .mjs, .cjs, .json';
91+
'The --config option requires a JSON string literal, or a file path with one of these extensions: .js, .ts, .mjs, .cjs, .json';
9292

9393
expect(() => check({config: 'jest.configjs'} as Config.Argv)).toThrow(
9494
message,

packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,81 @@ Object {
4545
}
4646
`;
4747

48+
exports[`init has-jest-config-file-ts ask the user whether to override config or not user answered with "Yes" 1`] = `
49+
Object {
50+
"initial": true,
51+
"message": "It seems that you already have a jest configuration, do you want to override it?",
52+
"name": "continue",
53+
"type": "confirm",
54+
}
55+
`;
56+
57+
exports[`init project using jest.config.ts ask the user whether he wants to use Typescript or not user answered with "Yes" 1`] = `
58+
Array [
59+
Object {
60+
"initial": true,
61+
"message": "Would you like to use Jest when running \\"test\\" script in \\"package.json\\"?",
62+
"name": "scripts",
63+
"type": "confirm",
64+
},
65+
Object {
66+
"initial": false,
67+
"message": "Would you like to use Typescript for the configuration file?",
68+
"name": "useTypescript",
69+
"type": "confirm",
70+
},
71+
Object {
72+
"choices": Array [
73+
Object {
74+
"title": "node",
75+
"value": "node",
76+
},
77+
Object {
78+
"title": "jsdom (browser-like)",
79+
"value": "jsdom",
80+
},
81+
],
82+
"initial": 0,
83+
"message": "Choose the test environment that will be used for testing",
84+
"name": "environment",
85+
"type": "select",
86+
},
87+
Object {
88+
"initial": false,
89+
"message": "Do you want Jest to add coverage reports?",
90+
"name": "coverage",
91+
"type": "confirm",
92+
},
93+
Object {
94+
"choices": Array [
95+
Object {
96+
"title": "v8",
97+
"value": "v8",
98+
},
99+
Object {
100+
"title": "babel",
101+
"value": "babel",
102+
},
103+
],
104+
"initial": 0,
105+
"message": "Which provider should be used to instrument code for coverage?",
106+
"name": "coverageProvider",
107+
"type": "select",
108+
},
109+
Object {
110+
"initial": false,
111+
"message": "Automatically clear mock calls and instances between every test?",
112+
"name": "clearMocks",
113+
"type": "confirm",
114+
},
115+
]
116+
`;
117+
48118
exports[`init project with package.json and no jest config all questions answered with answer: "No" should return the default configuration (an empty config) 1`] = `
49-
"// For a detailed explanation regarding each configuration property, visit:
50-
// https://jestjs.io/docs/en/configuration.html
119+
"/*
120+
* For a detailed explanation regarding each configuration property, visit:
121+
* https://jestjs.io/docs/en/configuration.html
122+
*/
51123
52124
module.exports = {
53125
// All imported modules in your tests should be mocked automatically
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
export default {};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

0 commit comments

Comments
 (0)