Important note: When using React 16 with Node version 8, you might see wrong line numbers for errors originating from tsx files. There's an issue with more details on this
Note: Looking for collaborators. Want to help improve ts-jest?
ts-jest is a TypeScript preprocessor with source map support for Jest that lets you use Jest to test projects written in TypeScript.
- Usage
- Default Setup
- Configuration
- Use cases
- Angular 2
- Using ES2015+ features in Javascript files
- Tips
- Known Limitations
- How to Contribute
- License
To use this in your project, run:
npm install --save-dev ts-jest @types/jest
If you don't already have jest installed,
npm install --save-dev jest ts-jest @types/jest
Modify your project's package.json
so that the jest
section looks something like:
{
"jest": {
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
]
}
}
This setup should allow you to write Jest tests in Typescript and be able to locate errors without any additional gymnastics.
From version "jest": "17.0.0"
we are using same MAJOR.MINOR as Jest
.
For "jest": "< 17.0.0"
use "ts-jest": "0.1.13"
. Docs for it see here.
You can try using ts-jest with jest@test
; use at your own risk! (And file an issue if you find problems.)
Prior to version 20.0.0
, coverage reports could be obtained using the inbuilt coverage processor in ts-jest. Starting with version 20.0.0
, ts-jest delegates coverage processing to jest and no longer includes a coverage processor.
Please note that the
outDir
property in thejest
configuration section is removed in coverage mode, due to #201.
ts-jest tries to ship with sensible defaults, to get you on your feet as quickly as possible.
Sourcemaps should work out of the box. That means your stack traces should have the correct line numbers, and you should be able to step through the TypeScript code using a debugger.
ts-jest automatically located your tsconfig
file.
If you want to compile typescript with a special configuration, you can do that too
If you're on a codebase where you're using synthetic default imports, e.g.
//Regular imports
import * as React from 'react';
//Synthetic default imports:
import React from 'react';
ts-jest tries to support that. If allowSyntheticDefaultImports
is set to true in your tsconfig
file, it uses babel
to automatically create the synthetic default exports for you - nothing else needed.
You can opt-out of this behaviour with the skipBabel flag
Typescript 2.7 has built-in support for this feature via the esModuleInterop
flag. We're looking to deprecate this feature.
Please use esModuleInterop
instead. More details here
Just like Jest ts-jest
automatically uses babel to hoist your jest.mock()
calls to the top of your file.
You can opt-out of this behaviour with the skipBabel flag
If the default setup doesn't address your requirements, you can create a custom setup to suit your project.
By default this package will try to locate tsconfig.json
and use its compiler options for your .ts
and .tsx
files.
You can override this behaviour by pointing ts-jest to a custom TypeScript configuration file.
You can do this by setting the tsConfigFile
option in your global variables under the ts-jest
key to path of the
custom configuration file (relative to the project's root directory)
{
"jest": {
"globals": {
"ts-jest": {
"tsConfigFile": "my-tsconfig.json"
}
}
}
}
Warning: In the past, a __TS_CONFIG__
section could be used to provide an inline TypeScript configuration. Going forward, all custom configurations should be in a different file and the tsConfigFile
key in the ts-jest
section (under globals
) should point to this file (as shown above). You can ignore this if the configuration you want is identical to the main tsconfig.json
.
For all available tsc
options see TypeScript docs.
Note that if you haven't explicitly set the module
property through a separate configuration file with tsConfigFile
, it will be overwritten to commonjs
(regardless of the value in tsconfig.json
) since that is the format Jest expects. This only happens during testing.
If you have explicitly set the module
property but to a different value than commonjs
, Jest may throw errors. In that case, a practical workaround is to make a tsconfig.jest.json
file which extends
your real tsconfig.json
but sets module
to commonjs
:
// tsconfig.jest.json
{
"extends": "./tsconfig",
"compilerOptions": {
"module": "commonjs"
}
}
If you use "baseUrl" and "paths" options for the compiler, see "moduleNameMapper" option on Jest docs.
If you don't use mocks, or synthetic default imports you can skip the babel-transpilation step.
This means jest.mock()
calls will not be hoisted to the top,
and synthetic default exports will never be created.
Simply add skipBabel to your global variables under the ts-jest
key:
//This will skip babel transpilation
{
"jest": {
"globals": {
"ts-jest": {
"skipBabel": true
}
}
}
}
When using Babel, ts-jest, by default, doesn't use the .babelrc
file. If you want ts-jest to use .babelrc
, you should set the globals > ts-jest > useBabelrc
flag to true
in your jest
configuration.
{
"jest": {
"globals": {
"ts-jest": {
"useBabelrc": true
}
}
}
}
In some cases, projects may not want to have a .babelrc
file, but still need to provide custom Babel configuration. In these cases, you can provide a Babel config directly to ts-jest
using the globals > ts-jest > babelConfig
option in your jest
configuration.
{
"jest": {
"globals": {
"ts-jest": {
"babelConfig": {
"presets": ["env"]
}
}
}
}
}
Note that if you also set the useBabelrc
option to true
, any configuration passed using this method will be overwritten by corresponding keys in .babelrc
files.
If you want to enable Syntactic & Semantic TypeScript error reporting you can enable this through enableTsDiagnostics
flag;
{
"jest": {
"globals": {
"ts-jest": {
"enableTsDiagnostics": true
}
}
}
}
Note: This is an experimental feature, comes with no guarantees and could be removed if it causes more problems than it solves. Testing is not the place to look for type errors. That should be done separately. Moreover, ts-jest only processes the files that are passed in by jest. It doesn't read files off the disk by default which is why enableTsDiagnostics
will hurt performance compared to the normal use case.
Note: This is an experimental feature, comes with no guarantees and could be removed if it causes more problems than it solves
If you want to ignore coverage on decorators you can enable this through ignoreCoverageForDecorators
and ignoreCoverageForAllDecorators
flags. If you enable the first option you have to add the /* istanbul ignore decorator */
comment after the decorator. If you choose the second option all decorators will be ignored.
{
"jest": {
"globals": {
"ts-jest": {
"ignoreCoverageForDecorators": true,
"ignoreCoverageForAllDecorators": true
}
}
}
}
There is a few additional steps if you want to use it with React Native.
Install babel-jest
and babel-preset-react-native
modules.
npm install -D babel-jest babel-preset-react-native
Ensure .babelrc
contains:
{
"presets": ["react-native"],
"sourceMaps": "inline"
}
In package.json
, inside jest
section, the transform
should be like this:
"transform": {
"^.+\\.jsx?$": "<rootDir>/node_modules/babel-jest",
"^.+\\.tsx?$": "ts-jest"
}
Fully completed jest section should look like this:
"jest": {
"preset": "react-native",
"transform": {
"^.+\\.jsx?$": "<rootDir>/node_modules/babel-jest",
"^.+\\.tsx?$": "ts-jest"
},
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
],
"globals": {
"ts-jest": {
"useBabelrc": true
}
}
}
If only testing typescript files then remove the js
option in the testRegex.
When using Jest with Angular (a.k.a Angular 2) apps you will likely need to parse HTML templates. If you're unable to add html-loader
to webpack config (e.g. because you don't want to eject from angular-cli
) you can do so by defining __TRANSFORM_HTML__
key in globals
for jest
.
{
"jest": {
"globals": {
"__TRANSFORM_HTML__": true
}
}
}
You'll also need to extend your transform
regex with html
extension:
{
"jest": {
"transform": {
"^.+\\.(tsx?|html)$": "ts-jest"
}
}
}
The default setup shown here picks up only .ts
and .tsx
files. However, if there are javascript files in your project that use ES2015+ features (spread operator, import, etc), you probably want them processed. There are two ways you can do this:
- use ts-jest to process js files
"transform": {
"^.+\\.(t|j)sx?$": "ts-jest"
}
- use another transformer to process js files
"transform": {
"^.+\\.jsx?$": "<rootDir>/node_modules/babel-jest",
"^.+\\.tsx?$": "ts-jest"
}
If you have dependencies on npm packages that are written in TypeScript but are
not published in ES5 you have to tweak your configuration. For example
you depend on a private scoped package @foo/bar
you have to add following to
your Jest configuration:
{
// ...
"transformIgnorePatterns": [
"<rootDir>/node_modules/(?!@foo)"
]
// ...
}
By default Jest ignores everything in node_modules
. This setting prevents Jest from ignoring the package you're interested in, in this case @foo
, while continuing to ignore everything else in node_modules
.
- You can't use
"target": "ES6"
while usingnode v4
in your test environment; - You can't use
"jsx": "preserve"
for now (see progress of this issue); - If you use
"baseUrl": "<path_to_your_sources>"
, you also have to changejest config
a little bit (also check Module path mapping section):
"jest": {
"moduleDirectories": ["node_modules", "<path_to_your_sources>"]
}
If the jest.mock()
calls is placed after actual code, (e.g. after functions or classes) and skipBabel
is not set,
the line numbers in stacktraces will be off.
We suggest placing the jest.mock()
calls after the imports, but before any actual code.
This is due to a limitation in the ts-jest preprocessor which compiles each test file individually, therefore ignoring implementations of ambient declarations. The TypeScript team currently have no plan to support const enum inlining for this particular compiler method. See #112 and #281 for more information.
One possible workaround is to manually inline usage of const enum values - i.e. in your code, use let x: Enum = 1 as Enum
as opposed to let x: Enum = Enum.FirstValue
. This allows you to keep the type checking on enums without running into this issue.
If you have any suggestions/pull requests to turn this into a useful package, just open an issue and I'll be happy to work with you to improve this.
git clone https://github.com/kulshekhar/ts-jest
cd ts-jest
npm install
npm test
Copyright (c) Authors. This source code is licensed under the MIT license.