Supported technologies: TypeScript

Wallaby.js supports continuous testing and real-time code coverage for TypeScript via a built-in TypeScript compiler, for browser and node.js.

No special configuration is required, unless you need to override TypeScript compiler settings defined in your tsconfig.json, or use some special TypeScript version (different from the one installed in your project node_modules).

module.exports = function (w) {

  return {
    files: [
      'src/**/*.ts'
    ],

    tests: [
      'test/**/*Spec.ts'
    ]
  };
};

You may find the working sample of wallaby.js configuration for TypeScript in this repository.

If you’re writing tests for a browser application, and using Webpack plus compiling TypeScript to CommonJs, you may also find this sample useful.

typescript

TypeScript compiler settings

If your project root has a tsconfig.json file, wallaby.js will automatically use TypeScript compiler options configured in that file. Wallaby does not read nested tsconfig.json files that may exist in sub-directories. Please note that to perform TypeScript compilation faster, wallaby.js changes some TypeScript compiler options (see the details below).

You may also override some of the compiler options by passing their values in wallaby TypeScript compiler options.

module.exports = function (wallaby) {
  return {
    files: [
      'src/**/*.ts*'
    ],

    tests: ['test/**/*Spec.ts*'],

    compilers: {
      '**/*.ts?(x)': wallaby.compilers.typeScript({
        module: 'commonjs',
        jsx: 'React'
      })
    },

    ...
  };
};

Wallaby also sets few default compiler settings that are not replaced by tsconfig.json compiler settings (to perform TypeScript compilation faster).

        noLib: true,
        noResolve: true,
        declaration: false,
        noEmitOnError: false,
        composite: false

If you want wallaby to stop overriding them, then you may to do it in your wallaby.js config by adding the useStandardDefaults: true setting. For example, if you have noEmitOnError set to true in your tsconfig.json and would like wallaby apply that value, you may do this:

module.exports = function (wallaby) {
  return {
    ...

    compilers: {
      '**/*.ts?(x)': wallaby.compilers.typeScript({ useStandardDefaults: true })
    },

    ...
  };
};

It may be useful if you want to stop running tests when TypeScript compilation fails (for any reason).

TypeScript compiler version

By default, wallaby.js is using your project local TypeScript compiler version (from the project node_modules/typescript), if there’s no local version, then wallaby falls back to the embedded TypeScript compiler version which is v2.0.7.

If you want to use a different version, you may pass TypeScript compiler via typescript options property. For example, the following config will make wallaby.js use TypeScript compiler from your installed node modules (which is the default option when you don’t specify the setting at all):

  module.exports = function (w) {

    return {
      files: [
        'src/**/*.ts'
      ],

      tests: [
        'test/**/*Spec.ts'
      ],

      compilers: {
        '**/*.ts?(x)': w.compilers.typeScript({
            typescript: require('typescript')
        })
      }
    };
  };

Isolated modules

By default, Wallaby TypeScript compiler works as a post-processor (using stateful TypeScript Language Service).

If you are using Jest with ts-jest, or any other node based testing framework that compiles TypeScript files independently using ts.transpileModule, you may use the isolatedModules setting to make Wallaby do the same. Using the setting may improve your project’s initial compilation time.

Please note that preprocessor file patterns behave differently when using the Isolated Modules compiler setting. Any preprocessor file patterns must match on the .ts or .tsx file extension (this is in contrast to using .js or .jsx when not using Isolated Modules).

  module.exports = function (w) {

    return {
      ...

      compilers: {
        '**/*.ts?(x)': w.compilers.typeScript({ isolatedModules: true })
      }
    };
  };

External modules

By default, when compiling to ES3/ES5, TypeScript compiler compiles modules to CommonJs.

If you’d like to use a different module system, such as AMD (for require.js), UMD or SystemJs, you need to specify the module setting in the compiler config (or your tsconfig.json file):

module.exports = function (w) {

  return {
    files: [
      'src/**/*.ts'
    ],

    tests: [
      'test/**/*Spec.ts'
    ],

    compilers: {

      '**/*.ts': w.compilers.typeScript({ module: 'amd' })
    }

  };
};

You may find the working sample of wallaby.js configuration for TypeScript with AMD and require.js in this repository.

Ordering source files with reference comments

If you are using reference comments in your source files (and not using an enforced module dependency mechanism, such as CommonJs with node.js/webpack/browserify), wallaby.js may still automatically sort your source files so you don’t need to list them in a correct order in your files list, but use broader patterns instead.

To make wallaby sort the files based on reference comments, you need to pass orderFilesByReferenceComments option to your TypeScript compiler settings:

  module.exports = function (w) {

    return {
      files: [
        'src/**/*.ts'
      ],

      tests: [
        'test/**/*Spec.ts'
      ],

      compilers: {
        '**/*.ts?(x)': w.compilers.typeScript({ orderFilesByReferenceComments: true })
      }
    };
  };

In this case, if you have a file a.ts that looks like

///<reference path="./b.ts"/>
///<reference path="./c.ts"/>
...

wallaby.js will order your files to load b.ts and c.ts files before loading a.ts.

Using with Babel

Sometimes you may need to compile your code with Babel after TypeScript compilation. You may use wallaby preprocessor to do it:

  module.exports = function (w) {

    return {
      files: [
        ...
      ],

      tests: [
        ...
      ],

      ...

      preprocessors: {
        '**/*.js': file => require('babel-core').transform(
          file.content,
          {sourceMap: true, compact: false, filename: file.path, presets: ['es2015']})
          /* or
           * {sourceMap: true, compact: false, filename: file.path, babelrc: true}) */
      }
    };
  };

If you hit an issue with missing function names after the double transformation, you may use this solution.

Node.js

If you are using TypeScript with node.js, you will need to configure wallaby TypeScript compiler to use CommonJs modules. You may do it in your tsconfig.json file, or in your wallaby.js config file:

  module.exports = function (w) {

    return {
      files: [
        'src/**/*.ts'
      ],

      tests: [
        'test/**/*Spec.ts'
      ],

      env: {
        type: 'node'
      },

      compilers: {
        '**/*.ts?(x)': w.compilers.typeScript({ module: 'commonjs' })
      }
    };
  };

You may find the working sample of wallaby.js configuration for TypeScript and node.js in this repository (wallaby-node.js configuration file).

TypeScript compilerOptions.paths setting

TypeScript compilerOptions.paths setting doesn’t affect compiled JavaScript, so if you are using the setting to shorten your import paths, then you’ll need to configure your environment to respect the setting.

For example, let’s say you have the src/app folder, and would like to import src/app/myModule.ts module as

import MyModule from 'app/myModule';

from your tests.

Browser environment with Webpack

Wallaby.js provides two different methods to configure projects that use webpack: Wallaby.js built-in postprocessor, and via the open source wallaby-webpack postprocessor.

Wallaby.js built-in postprocessor

If you are running your tests in a browser environment with webpack, then you may use resolve.modules setting as show below:

module.exports = (wallaby) => {
  ...
  postprocessor: wallaby.postprocessors.webpack({
    ...
    resolve: {
      ...
      modules: [
        'src',
        ...
      ]
    }
  })
};

If you are using aliases, such as @ prefix, you may use then you may use resolve.alias setting. For example, to be able to import @domain/* from src/app/domain, you may have the the following configuration:

module.exports = (wallaby) => {
  ...
  postprocessor: wallaby.postprocessors.webpack({
    ...
    resolve: {
      ...
      alias: {
        '@domain': 'src/app/domain',
        ...
      }
    }
  })
};

Wallaby-webpack open source postprocessor

Note if you are using wallaby-webpack postprocessor then you need to use resolve.modules as follows:

const path = require('path');
const wallabyWebpack = require('wallaby-webpack');

module.exports = (wallaby) => {
  const webpackPostprocessor = wallabyWebpack({
    ...
    resolve: {
      modules: [
        path.join(wallaby.projectCacheDir, 'src'),
        ...
      ]
    }
  });
  ...
};

If you are using aliases, such as @ prefix, you may use then you may use resolve.alias setting. For example, to be able to import @domain/* from src/app/domain, you may have the the following configuration:

const path = require('path');
const wallabyWebpack = require('wallaby-webpack');

module.exports = (wallaby) => {
  const webpackPostprocessor = wallabyWebpack({
    ...
    resolve: {
      ...
      alias: {
        '@domain': path.join(wallaby.projectCacheDir, 'src/app/domain'),
        ...
      }
    }
  });
  ...
};

Node environment with Jest

If you are running your tests in node environment with jest, then you may use moduleNameMapper or modulePaths settings.

Node environment with Mocha/Jasmine/Ava/Tape

With any node testing framework other than Jest, you may use NODE_PATH setting or tsconfig-paths module.

module.exports = function(wallaby) {
  var path = require('path');

  process.env.NODE_PATH +=
    path.delimiter + path.join(wallaby.projectCacheDir, 'src');
  ...
}

or

module.exports = function () {

  return {
    files: [
      'tsconfig.json',
      ...
    ],

    ...

    setup: function (wallaby) {
      if (global._tsconfigPathsRegistered) return;
      const tsConfigPaths = require('tsconfig-paths');
      const tsconfig = require('./tsconfig.json');
      tsConfigPaths.register({
        baseUrl: tsconfig.compilerOptions.baseUrl,
        paths: tsconfig.compilerOptions.paths
      });
      global._tsconfigPathsRegistered = true;
    }
  };
};

Type Errors

Wallaby’s default compiler settings disable TypeScript type checking when running your tests. If you want wallaby to check your types, you may to do so in your wallaby.js config by adding the useStandardDefaults: true setting.

However, we do not recommend running Wallaby with type checking in place. Enabling type checking when running Wallaby tests will likely duplicate what your editor is already doing and will create a lot of noise when you’re using Wallaby; this will exhibit as broken coverage indicators breaking whenever type errors are detected (this will happen often). This will also slow down the feedback loop between writing code and running tests, which somewhat reduces the benefit of Wallaby.

Instead, we suggest relying on your editor to catch these which will give you the best user experience in terms of editor feedback + fast wallaby tests. You should of course rely on your build processes, etc. to fail hard on these errors.

create-react-app

To configure Wallaby.js with Jest and TypeScript for create-react-app --typescript generated projects, please use this sample of wallaby.js configuration create-react-app for TypeScript.