Skip to content

A Jest transformer with source map support that lets you use Jest to test projects written in TypeScript.

License

Notifications You must be signed in to change notification settings

kulshekhar/ts-jest

Repository files navigation

ts-jest npm version NPM downloads Greenkeeper badge Build Status for linux Build Status for Windows

ts-jest is a TypeScript preprocessor with source map support for Jest that lets you use Jest to test projects written in TypeScript.


Before reporting any issue, be sure to check the troubleshooting page

You can also find help on the ts-jest community on Slack

Looking for collaborators. Want to help improve ts-jest?


Table of Contents

Usage

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": {
    "preset": "ts-jest"
  }
}

or create/modify the jest.config.js:

module.exports = {
  preset: 'ts-jest',
};

This setup should allow you to write Jest tests in Typescript and be able to locate errors without any additional gymnastics.

Versioning

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@next; use at your own risk! (And file an issue if you find problems.)

Coverage

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.

Default Setup

ts-jest tries to ship with sensible defaults, to get you on your feet as quickly as possible.

Sourcemap support

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.

Automatically finds tsconfig.json

ts-jest automatically located your tsconfig file. If you want to compile typescript with a special configuration, you can do that too.

Supports synthetic modules

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 does that by using TypeScript 2.7+ esModuleInterop option. More details here.

Supports automatic of jest.mock() calls

Just like Jest ts-jest automatically hoist your jest.mock() calls to the top of their block.

Configuration

If the default setup doesn't address your requirements, you can create a custom setup to suit your project. All ts-jest specific configuration is done in an object with the ts-jest key within jest gobals config:

// package.json
{
  "jest": {
    "globals": {
      "ts-jest": {
        // ts-jest specific configuration
      }
    }
  }
}

OR

// jest.config.js
module.exports = {
  globals: {
    'ts-jest': {
      // ts-jest specific configuration
    }
  }
}

In following documentation we'll show you examples as if you were using a jest.config.js file, but the same applies if you were putting the configuration optons within package.json's jest section of course.

Any configuration options which is a path to some file can make the use of <rootDir>. It'll be replaced with the value of rootDir as in other Jest config options.

TypeScript configuration

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 behavior with the tsConfig option of ts-jest. It can be:

  • the path to a tsconfig JSON file (relative to rootDir):

    // jest.config.js
    module.exports = {
      globals: {
        'ts-jest': {
          tsConfig: 'my-tsconfig.json'
        }
      }
    };
  • a plain object containing the compilerOptions:

    // jest.config.js
    module.exports = {
      globals: {
        'ts-jest': {
          tsConfig: {
            experimentalDecorators: true,
            // ...
          }
        }
      }
    };

For all available tsc options see TypeScript docs.

Note that files are transpiled as isolated modules. Because of that some compiler options have no effect: declaration, declarationDir, esModuleInterop, inlineSourceMaps, inlineSources, lib, module, noEmit, noEmitOnError, out, outFile, paths, rootDirs, sourceMaps and types. See TypeScript transpileModule's function source.

Module path mapping

If you use "baseUrl" and "paths" options for the compiler, see "moduleNameMapper" option on Jest docs.

For example, with the below config in your tsconfig:

// tsconfig.json
{
  "compilerOptions": {
    "paths": {
      "@App/*": ["src/*"],
      "@Shared/*": ["src/Shared/*"]
    }
  }
}

...here's what your jest config should look like:

// jest.config.js
module.exports = {
  moduleNameMapper: {
    '@App/(.*)': '<rootDir>/src/$1',
    '@Shared/(.*)': '<rootDir>/src/Shared/$1'
  }
};

TS Jest provides a helper to automatically create this map from the paths compiler option of your TS config:

// jest.config.js
const { pathsToModuleNameMapper } = require('ts-jest');
const { compilerOptions } = require('./tsconfig'); // replace with the path to your tsconfig.json file

module.exports = {
  // [...]
  moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths /*, { prefix: '<rootDir>/' } */ )
};

Using babel-jest

By default ts-jest does not rely on babel-jest. But you may want to use some babel plugins and stll be able to write TypeScript. This can be achieved using the babelConfig config key. It can be:

  • true, in which case it'll use defaults from babelrc or any other found config file:

    // jest.config.js
    module.exports = {
      globals: {
        'ts-jest': {
          babelConfig: true
        }
      }
    };
  • the path to a babel config file:

    // jest.config.js
    module.exports = {
      globals: {
        'ts-jest': {
          babelConfig: 'babelrc.test.js'
        }
      }
    };
  • a plain object containing babel configuration:

    // jest.config.js
    module.exports = {
      globals: {
        'ts-jest': {
          babelConfig: {
            plugins: [
              // ...
            ]
          }
        }
      }
    };
  • false, in which case it'll disable the use of babel-jest (which is the default):

    // jest.config.js
    module.exports = {
      globals: {
        'ts-jest': {
          babelConfig: false
        }
      }
    };

TS compiler & error reporting

=== To be documented ===

Ignore coverage on decorators

=== To be documented ===

extending

You can extend the defaults shipped with ts-jest in its preset (this is only possible in an external jest.config.js file):

// jest.config.js
const { jestPreset } = require('ts-jest');

module.exports = {
  // ...
  ...jestPreset,
  moduleFileExtensions: ['ts'],
  transform: {
    ...jestPreset.transform,
    // ...
  }
  // ...
};

Use cases

React Native

There is a few additional steps if you want to use it with React Native.

Install babel-preset-react-native modules.

npm install -D babel-preset-react-native

Ensure .babelrc contains:

// .babelrc
{
  "presets": ["react-native"],
}

And your jest config should look like:

// jest.config.js
const { jestPreset } = require('ts-jest');

module.exports = {
  ...jestPreset,
  preset: 'react-native',
  globals: {
    'ts-jest': {
      babelConfig: true
    }
  }
};

Angular 2

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 using the stringifyContentPathRegex config option:

// jest.config.js
const { jestPreset } = require('ts-jest');

module.exports = {
  // ...
  transform: {
    ...jestPreset.transform,
    '^.+\\.html$': 'ts-jest'
  },
  globals: {
    'ts-jest': {
      stringifyContentPathRegex: '\\.html$'
    }
  }
};

Tips

Importing packages written in TypeScript

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/bar)"
  ]
  // ...
}

By default Jest ignores everything in node_modules. This setting prevents Jest from ignoring the package you're interested in, in this case @foo/bar, while continuing to ignore everything else in node_modules.

Logging

This package is using bs-logger.

Use environment variable TS_JEST_LOG=xxx to configure log targets. By default it'll log entries with level warning and above to stderr.

See the examples in there to configure different target(s).

When posting an issue, it's best to join the full log file which you can create in CWD using:

TS_JEST_LOG=ts-jest.log jest
# or
TS_JEST_LOG=ts-jest.log npm run test

Known Limitations

Known limitations for TS compiler options

If you use "baseUrl": "<path_to_your_sources>", you also have to change jest config a little bit (also check Module path mapping section):

"jest": {
  "moduleDirectories": ["node_modules", "<path_to_your_sources>"]
}

const enum is not supported if typeCheck is not enabled

This is due to a limitation in the ts-jest basic processor 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.

How to Contribute

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.

Quickstart to run tests (only if you're working on this package)

git clone https://github.com/kulshekhar/ts-jest
cd ts-jest
npm install
npm test

License

Copyright (c) Authors. This source code is licensed under the MIT license.