Skip to content

Commit

Permalink
handle typescript by default (#7533)
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB authored Dec 19, 2018
1 parent c1d3de5 commit c7caa7b
Show file tree
Hide file tree
Showing 19 changed files with 57 additions and 154 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- `[jest-haste-map]` [**BREAKING**] Remove name from hash in `HasteMap.getCacheFilePath` ([#7218](https://github.com/facebook/jest/pull/7218))
- `[babel-preset-jest]` [**BREAKING**] Export a function instead of an object for Babel 7 compatibility ([#7203](https://github.com/facebook/jest/pull/7203))
- `[jest-haste-map]` [**BREAKING**] Expose relative paths when getting the file iterator ([#7321](https://github.com/facebook/jest/pull/7321))
- `[jest-config]` Handle typescript (`ts` and `tsx`) by default ([#7533](https://github.com/facebook/jest/pull/7533))
- `[jest-validate]` Add support for comments in `package.json` using a `"//"` key ([#7295](https://github.com/facebook/jest/pull/7295))
- `[jest-config]` Add shorthand for watch plugins and runners ([#7213](https://github.com/facebook/jest/pull/7213))
- `[jest-jasmine2/jest-circus/jest-cli]` Add test.todo ([#6996](https://github.com/facebook/jest/pull/6996))
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ Jest can be used in projects that use [webpack](https://webpack.js.org/) to mana

### Using TypeScript

To use TypeScript in your tests you can use [ts-jest](https://github.com/kulshekhar/ts-jest).
To use TypeScript in your tests install `@babel/preset-typescript` and add it to your Babel config.

<!-- generated_getting_started_end -->

Expand Down
12 changes: 5 additions & 7 deletions docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,12 +367,10 @@ An array of directory names to be searched recursively up from the requiring mod

### `moduleFileExtensions` [array<string>]

Default: `["js", "json", "jsx", "node"]`
Default: `["js", "json", "jsx", "ts", "tsx", "node"]`

An array of file extensions your modules use. If you require modules without specifying a file extension, these are the extensions Jest will look for.

If you are using TypeScript this should be `["js", "jsx", "json", "ts", "tsx"]`, check [ts-jest's documentation](https://github.com/kulshekhar/ts-jest).

### `moduleNameMapper` [object<string, string>]

Default: `null`
Expand Down Expand Up @@ -832,9 +830,9 @@ Test environment options that will be passed to the `testEnvironment`. The relev

### `testMatch` [array<string>]

(default: `[ "**/__tests__/**/*.js?(x)", "**/?(*.)+(spec|test).js?(x)" ]`)
(default: `[ "**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[jt]s?(x)" ]`)

The glob patterns Jest uses to detect test files. By default it looks for `.js` and `.jsx` files inside of `__tests__` folders, as well as any files with a suffix of `.test` or `.spec` (e.g. `Component.test.js` or `Component.spec.js`). It will also find files called `test.js` or `spec.js`.
The glob patterns Jest uses to detect test files. By default it looks for `.js`, `.jsx`, `.ts` and `.tsx` files inside of `__tests__` folders, as well as any files with a suffix of `.test` or `.spec` (e.g. `Component.test.js` or `Component.spec.js`). It will also find files called `test.js` or `spec.js`.

See the [micromatch](https://github.com/jonschlinkert/micromatch) package for details of the patterns you can specify.

Expand All @@ -850,9 +848,9 @@ These pattern strings match against the full path. Use the `<rootDir>` string to

### `testRegex` [string | Array<string>]

Default: `(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$`
Default: `(/__tests__/.*|(\\.|/)(test|spec))\\.[jt]sx?$`

The pattern or patterns Jest uses to detect test files. By default it looks for `.js` and `.jsx` files inside of `__tests__` folders, as well as any files with a suffix of `.test` or `.spec` (e.g. `Component.test.js` or `Component.spec.js`). It will also find files called `test.js` or `spec.js`. See also [`testMatch` [array<string>]](#testmatch-array-string), but note that you cannot specify both options.
The pattern or patterns Jest uses to detect test files. By default it looks for `.js`, `.jsx`, `.ts` and `.tsx` files inside of `__tests__` folders, as well as any files with a suffix of `.test` or `.spec` (e.g. `Component.test.js` or `Component.spec.js`). It will also find files called `test.js` or `spec.js`. See also [`testMatch` [array<string>]](#testmatch-array-string), but note that you cannot specify both options.

The following is a visualization of the default regex:

Expand Down
4 changes: 3 additions & 1 deletion docs/GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,6 @@ Jest can be used in projects that use [webpack](https://webpack.github.io/) to m

### Using TypeScript

To use TypeScript in your tests you can use [ts-jest](https://github.com/kulshekhar/ts-jest).
Jest supports TypeScript out of the box, via Babel.

However, there are some caveats to using Typescript with Babel, see http://artsy.github.io/blog/2017/11/27/Babel-7-and-TypeScript/. Another caveat is that Jest will not typecheck your tests. If you want that, you can use [ts-jest](https://github.com/kulshekhar/ts-jest).
8 changes: 5 additions & 3 deletions e2e/__tests__/__snapshots__/show_config.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ exports[`--showConfig outputs config info and exits 1`] = `
\\"js\\",
\\"json\\",
\\"jsx\\",
\\"ts\\",
\\"tsx\\",
\\"node\\"
],
\\"moduleNameMapper\\": {},
Expand All @@ -54,8 +56,8 @@ exports[`--showConfig outputs config info and exits 1`] = `
\\"testEnvironmentOptions\\": {},
\\"testLocationInResults\\": false,
\\"testMatch\\": [
\\"**/__tests__/**/*.js?(x)\\",
\\"**/?(*.)+(spec|test).js?(x)\\"
\\"**/__tests__/**/*.[jt]s?(x)\\",
\\"**/?(*.)+(spec|test).[tj]s?(x)\\"
],
\\"testPathIgnorePatterns\\": [
\\"/node_modules/\\"
Expand All @@ -66,7 +68,7 @@ exports[`--showConfig outputs config info and exits 1`] = `
\\"timers\\": \\"real\\",
\\"transform\\": [
[
\\"^.+\\\\\\\\.jsx?$\\",
\\"^.+\\\\\\\\.[jt]sx?$\\",
\\"<<REPLACED_JEST_PACKAGES_DIR>>/babel-jest/build/index.js\\"
]
],
Expand Down
13 changes: 0 additions & 13 deletions examples/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,5 @@
},
"scripts": {
"test": "jest"
},
"jest": {
"moduleFileExtensions": [
"ts",
"tsx",
"js"
],
"transform": {
"^.+\\.(ts|tsx)$": "babel-jest"
},
"testMatch": [
"**/__tests__/*.+(ts|tsx|js)"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ module.exports = {
// \\"js\\",
// \\"json\\",
// \\"jsx\\",
// \\"ts\\",
// \\"tsx\\",
// \\"node\\"
// ],
Expand Down Expand Up @@ -158,8 +160,8 @@ module.exports = {
// The glob patterns Jest uses to detect test files
// testMatch: [
// \\"**/__tests__/**/*.js?(x)\\",
// \\"**/?(*.)+(spec|test).js?(x)\\"
// \\"**/__tests__/**/*.[jt]s?(x)\\",
// \\"**/?(*.)+(spec|test).[tj]s?(x)\\"
// ],
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
Expand Down Expand Up @@ -214,42 +216,3 @@ exports[`init project with package.json and no jest config some questions answer
}
"
`;

exports[`init typescript project should ask "typescript question" when has typescript in dependencies 1`] = `
Object {
"initial": true,
"message": "Typescript detected, would you like to setup Jest for Typescript?",
"name": "typescript",
"type": "confirm",
}
`;

exports[`init typescript project should ask "typescript question" when has typescript in devDependencies 1`] = `
Object {
"initial": true,
"message": "Typescript detected, would you like to setup Jest for Typescript?",
"name": "typescript",
"type": "confirm",
}
`;

exports[`init typescript project should create configuration for {typescript: true} 1`] = `
Object {
"globals": Object {
"ts-jest": Object {
"tsConfigFile": "tsconfig.json",
},
},
"moduleFileExtensions": Array [
"ts",
"tsx",
"js",
],
"testMatch": Array [
"**/__tests__/*.+(ts|tsx|js)",
],
"transform": Object {
"^.+\\\\.(ts|tsx)$": "ts-jest",
},
}
`;
33 changes: 0 additions & 33 deletions packages/jest-cli/src/lib/__tests__/init.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,37 +181,4 @@ describe('init', () => {
expect(questionsNames).not.toContain('scripts');
});
});

describe('typescript project', () => {
it('should ask "typescript question" when has typescript in dependencies', async () => {
prompts.mockReturnValueOnce({});

await init(resolveFromFixture('typescript_in_dependencies'));

const typescriptQuestion = prompts.mock.calls[0][0][0];

expect(typescriptQuestion).toMatchSnapshot();
});

it('should ask "typescript question" when has typescript in devDependencies', async () => {
prompts.mockReturnValueOnce({});

await init(resolveFromFixture('typescript_in_dev_dependencies'));

const typescriptQuestion = prompts.mock.calls[0][0][0];

expect(typescriptQuestion).toMatchSnapshot();
});

it('should create configuration for {typescript: true}', async () => {
prompts.mockReturnValueOnce({typescript: true});

await init(resolveFromFixture('typescript_in_dev_dependencies'));

const writtenJestConfig = fs.writeFileSync.mock.calls[0][1];
const evaluatedConfig = eval(writtenJestConfig);

expect(evaluatedConfig).toMatchSnapshot();
});
});
});
17 changes: 1 addition & 16 deletions packages/jest-cli/src/lib/init/generate_config_file.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,10 @@ const stringifyOption = (
};

const generateConfigFile = (results: {[string]: boolean}): string => {
const {typescript, coverage, clearMocks, environment} = results;
const {coverage, clearMocks, environment} = results;

const overrides: Object = {};

if (typescript) {
Object.assign(overrides, {
globals: {
'ts-jest': {
tsConfigFile: 'tsconfig.json',
},
},
moduleFileExtensions: ['ts', 'tsx', 'js'],
testMatch: ['**/__tests__/*.+(ts|tsx|js)'],
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
},
});
}

if (coverage) {
Object.assign(overrides, {
coverageDirectory: 'coverage',
Expand Down
19 changes: 1 addition & 18 deletions packages/jest-cli/src/lib/init/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ import chalk from 'chalk';
import fs from 'fs';
import path from 'path';
import prompts from 'prompts';
import defaultQuestions, {
typescriptQuestion,
testScriptQuestion,
} from './questions';
import defaultQuestions, {testScriptQuestion} from './questions';
import {NotFoundPackageJsonError, MalformedPackageJsonError} from './errors';
import {PACKAGE_JSON, JEST_CONFIG} from '../../constants';
import generateConfigFile from './generate_config_file';
Expand All @@ -25,7 +22,6 @@ type PromptsResults = {
coverage: boolean,
environment: boolean,
scripts: boolean,
typescript: boolean,
};

export default async (rootDir: string = process.cwd()) => {
Expand Down Expand Up @@ -82,19 +78,6 @@ export default async (rootDir: string = process.cwd()) => {
questions.unshift(testScriptQuestion);
}

// Try to detect typescript and add a question if needed
const deps: Object = {};

Object.assign(
deps,
projectPackageJson.dependencies,
projectPackageJson.devDependencies,
);

if (Object.keys(deps).includes('typescript')) {
questions.unshift(typescriptQuestion);
}

// Start the init process
console.log();
console.log(
Expand Down
7 changes: 0 additions & 7 deletions packages/jest-cli/src/lib/init/questions.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,3 @@ export const testScriptQuestion: Question = {
name: 'scripts',
type: 'confirm',
};

export const typescriptQuestion: Question = {
initial: true,
message: 'Typescript detected, would you like to setup Jest for Typescript?',
name: 'typescript',
type: 'confirm',
};
4 changes: 2 additions & 2 deletions packages/jest-config/src/Defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default ({
providesModuleNodeModules: [],
},
moduleDirectories: ['node_modules'],
moduleFileExtensions: ['js', 'json', 'jsx', 'node'],
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node'],
moduleNameMapper: {},
modulePathIgnorePatterns: [],
noStackTrace: false,
Expand All @@ -70,7 +70,7 @@ export default ({
testEnvironmentOptions: {},
testFailureExitCode: 1,
testLocationInResults: false,
testMatch: ['**/__tests__/**/*.js?(x)', '**/?(*.)+(spec|test).js?(x)'],
testMatch: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[tj]s?(x)'],
testPathIgnorePatterns: [NODE_MODULES_REGEXP],
testRegex: [],
testResultsProcessor: null,
Expand Down
8 changes: 4 additions & 4 deletions packages/jest-config/src/ValidConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export default ({
lastCommit: false,
logHeapUsage: true,
moduleDirectories: ['node_modules'],
moduleFileExtensions: ['js', 'json', 'jsx', 'node'],
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node'],
moduleLoader: '<rootDir>',
moduleNameMapper: {
'^React$': '<rootDir>/node_modules/react',
Expand Down Expand Up @@ -100,12 +100,12 @@ export default ({
testEnvironmentOptions: {userAgent: 'Agent/007'},
testFailureExitCode: 1,
testLocationInResults: false,
testMatch: ['**/__tests__/**/*.js?(x)', '**/?(*.)+(spec|test).js?(x)'],
testMatch: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)'],
testNamePattern: 'test signature',
testPathIgnorePatterns: [NODE_MODULES_REGEXP],
testRegex: multipleValidOptions(
'(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$',
['/__tests__/\\.test\\.jsx?$', '/__tests__/\\.spec\\.jsx?$'],
'(/__tests__/.*|(\\.|/)(test|spec))\\.[jt]sx?$',
['/__tests__/\\.test\\.[jt]sx?$', '/__tests__/\\.spec\\.[jt]sx?$'],
),
testResultsProcessor: 'processor-node-module',
testRunner: 'jasmine2',
Expand Down
9 changes: 8 additions & 1 deletion packages/jest-config/src/__tests__/normalize.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1456,7 +1456,14 @@ describe('moduleFileExtensions', () => {
it('defaults to something useful', () => {
const {options} = normalize({rootDir: '/root'}, {});

expect(options.moduleFileExtensions).toEqual(['js', 'json', 'jsx', 'node']);
expect(options.moduleFileExtensions).toEqual([
'js',
'json',
'jsx',
'ts',
'tsx',
'node',
]);
});

it('throws if missing `js`', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-config/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import path from 'path';

export const NODE_MODULES = path.sep + 'node_modules' + path.sep;
export const DEFAULT_JS_PATTERN = '^.+\\.jsx?$';
export const DEFAULT_JS_PATTERN = '^.+\\.[jt]sx?$';
export const DEFAULT_REPORTER_LABEL = 'default';
export const PACKAGE_JSON = 'package.json';
export const JEST_CONFIG = 'jest.config.js';
15 changes: 15 additions & 0 deletions packages/jest-config/src/normalize.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ const setupBabelJest = (options: InitialOptions) => {
const regex = new RegExp(pattern);
return regex.test('a.js') || regex.test('a.jsx');
});
const customTSPattern = Object.keys(transform).find(pattern => {
const regex = new RegExp(pattern);
return regex.test('a.ts') || regex.test('a.tsx');
});

if (customJSPattern) {
const customJSTransformer = transform[customJSPattern];
Expand All @@ -148,6 +152,17 @@ const setupBabelJest = (options: InitialOptions) => {
babelJest = customJSTransformer;
}
}

if (customTSPattern) {
const customTSTransformer = transform[customTSPattern];

if (customTSTransformer === 'babel-jest') {
babelJest = require.resolve('babel-jest');
transform[customTSPattern] = babelJest;
} else if (customTSTransformer.includes('babel-jest')) {
babelJest = customTSTransformer;
}
}
} else {
babelJest = require.resolve('babel-jest');
options.transform = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ exports[`Runtime requireModule with no extension throws error pointing out file
However, Jest was able to find:
'./RegularModuleWithWrongExt.txt'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'node'].
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].
See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string"
`;
Loading

0 comments on commit c7caa7b

Please sign in to comment.