Continuous Testing of TypeScript Code

After taking a closer look at continuous testing of JavaScript code, I'm moving on to other languages that transpile to JavaScript. I'll mostly be focusing on TypeScript, but there aren't many differences with other languages. I'll mention some of them at the end of this post.

Karma Configuration

I'm assuming you already have a valid Karma configuration setup for JavaScript. You can find instructions on how to set it up in my previous post.

To take full advantage of TypeScript, you'll want to use type definitions for the libraries you're using. To make downloading them easier, you can use Typings TypeScript Definition Manager. It can be installed globally just like any other npm package:

npm install -g typings

Now we can download the type definitions for Jasmine:

typings install dt~jasmine --SG

The --SG option will add the type definition to typings.json configuration file as a global dependency, so that you can easily restore the packages by calling typings install after you get the project from source control without the type definitions committed. Installing the package also creates or updates the bundle index.d.ts file which you can reference from your source code instead of individual type definitions to import all the type definitions with a single call.

For Karma to support tests and code in TypeScript a preprocessor is required. As always, it is distributed as a npm package:

npm install --save-dev karma-typescript-preprocessor
npm install --save-dev typescript

Now, it's time to add the preprocessor configuration to karma.conf.js:

preprocessors: {
  '**/*.ts': ['typescript']
},

typescriptPreprocessor: {
  options: {
    sourceMap: true, // generate source maps
    noResolve: false // enforce type resolution
  },
  transformPath: function(path) {
    return path.replace(/\.ts$/, '.js');
  }
},

Also, patterns for *.ts files must be added to karma.conf.js:

files: [
    './src/*.ts',
    './test/*.ts'
],

Herewith, everything is ready to write some TypeScript code:

function subtract(a: number, b: number) : number {
    return a - b;
}

And tests:

///<reference path="../typings/index.d.ts"/>
///<reference path="../src/subtract.ts"/>

describe('subtract method', () => {
    it('subtracts 2 numbers', () => {
        expect(subtract(2, 4)).toBe(-3);
    });
});

Notice the references at the top pointing to the source code being tested and the type definition bundle file to get the type information for the compiler.

Running the tests is no different than for JavaScript code, now:

node node_modules/karma/bin/karma start .\karma.conf.js

Because of source maps any errors will point back to the original TypeScript source code, not only the transpiled JavaScript code:

Chrome 47.0.2526 (Windows 10 0.0.0) subtract method subtracts 2 numbers FAILED
        Expected -2 to be -3.
            at Object.<anonymous> (D:/Users/Damir/Temp/Karma/test/test-subtract.js:8:32 <- test-subtract.ts.ktp.ts:6:31)
Chrome 47.0.2526 (Windows 10 0.0.0): Executed 3 of 3 (1 FAILED) (0.024 secs / 0.004 secs)

IDE Specifics

With WebStorm configured as described in my previous post and the Karma configuration from the above, continuous testing will just work... With one unfortunate exception: breakpoints will not get hit. Again, hopefully the bug will get fixed soon.

ReSharper's support for TypeScript is at JavaScript level as well. Debugging doesn't work even JavaScript already; TypeScript is no different.

Other languages

As long as there is a corresponding preprocessor for Karma available, other languages (e.g. CoffeeScript) can be used in a similar manner. Support in IDEs is a different matter, though. With ReSharper you're pretty much out of luck. I couldn't get tests in any other language to work. WebStorm is better in this field. As soon as everything is setup in Karma, the tests are just run. With a dedicated WebStorm plugin, you can get proper support in the editor and potentially even debugging support.

Copyright
Creative Commons License