39

I've been reading articles on this all morning trying to get my environment setup correctly. But for some reason I'm not getting it. My setup-

/app
    ... source (mixed js and ts)
/scripts
    ... copied source (js)
    typescripts.js // transpiled typescript with inline mapping

Tests run fine, and with the mapping debugging in the chrome debugger is mapped correctly. But Istanbul sees the typescripts.js file as one file instead of the concatenation of dozens of other files.

To generate the typescript source I'm using gulp-typescript. The source (excluding tests) are transpiled to the aforementioned typescripts.js, and the tests are transpiled individually and copied to /scripts.

  var ts = require('gulp-typescript');
  var sourcemaps = require('gulp-sourcemaps');
  var concat = require('gulp-concat');

  module.exports = function (gulp, config) {
     'use strict';

     // Runs dot ts files found in `www` through the typescript compiler and copies them as js 
     // files to the scripts directory

     gulp.task('typescript', ['typescript:tests'], function () {
        return gulp.src(config.paths.typescript) // [ './www/app/**/*.ts', '!./www/app/**/*.test.ts', '!./www/app/**/*.mock.ts' ]
           .pipe(sourcemaps.init())
           .pipe(ts(ts.createProject(config.paths.tsConfig))) // './tsconfig.json'
           .js
           .pipe(concat(config.sourcemaps.dest)) // typescripts.js
           .pipe(sourcemaps.write(config.sourcemaps)) // { includeContent: false, sourceRoot: '/app' } - i've also tried absolute local path
           .pipe(gulp.dest(config.paths.tmpScripts)); // ./www/scripts


     });

     gulp.task('typescript:tests', [], function() {
        return gulp.src(config.paths.typescriptTests) // [ './www/app/**/*.test.ts', './www/app/**/*.mock.ts' ]
           .pipe(ts(ts.createProject(config.paths.tsConfig))) // './tsconfig.json'
           .pipe(gulp.dest(config.paths.tmpScripts)); // ./www/scripts
     });
  };

The resulting typescripts.js has the inline sourcemap. With the sourcemap, the dozen or so ts files results in 106kb.

So from here tests and debugging works fine.

Now in an attempt to get Istanbul code coverage working properly i've installed karma-sourcemap-loader and added it to the preprocessors.

preprocessors: {
    'www/scripts/typescripts.js': ['sourcemap'],
    'www/scripts/**/*.js': ['coverage']
},

I'd think this is what I'd need to do. But it does not show code coverage on the source files. I tried the absolute path from C:/ but that didn't work either. I also tried the different options in gulp-sourcemaps like adding source (which pushed the file to 160kb) but no like either.

Has anyone gotten this to work? Any ideas what I could be doing wrong?

aurelius
  • 3,946
  • 7
  • 40
  • 73
micah
  • 7,596
  • 10
  • 49
  • 90

5 Answers5

24

TL;DR: There is a tool: https://github.com/SitePen/remap-istanbul described as A tool for remapping Istanbul coverage via Source Maps

The article on Sitepan describes it in more detail:

Intern as well as other JavaScript testing frameworks utilise Istanbul for their code coverage analysis. As we started to adopt more and more TypeScript for our own projects, we continued to struggle with getting a clear picture of our code coverage as all the reports only included the coverage of our emitted code. We had to try to use the compilers in our minds to try to figure out where we were missing test coverage. We also like to set metrics around our coverage to let us track if we are headed the right direction.

A couple of us started exploring how we might be able to accomplish mapping the coverage report back to its origins and after a bit of work, we created remap-istanbul, a package that allows Istanbul coverage information to be mapped back to its source when there are Source Maps available. While we have been focused on TypeScript, it can be used wherever the coverage is being produced on emitted code, including the tools mentioned above!

How to use the tool with gulp: https://github.com/SitePen/remap-istanbul#gulp-plugin

MartyIX
  • 27,828
  • 29
  • 136
  • 207
4

If you want source map support with Istanbul, you can use the 1.0 alpha release as the current release does not support source maps. I have it set up using ts-node in http://github.com/typings/typings (see https://github.com/typings/typings/blob/bff1abad91dabec1cd8a744e0dd3f54b613830b5/package.json#L19) and source code is being mapped. It looks great and is nice to have my tests and code coverage all running in-process with zero transpilation. Of course, you can use Istanbul 1.0 with the transpiled JavaScript.

For the browser implementation you're using, I'd have to see more of code of what you're doing to see this'll just work for you, but try the 1.0.0-alpha.2 and see what happens.

mejdev
  • 3,509
  • 4
  • 24
  • 38
blakeembrey
  • 424
  • 3
  • 8
  • There are no tests in the linked repository. – Shaun Luttin Aug 21 '16 at 01:59
  • There are at the commit hash if you navigate through the repo instead of `master`. If you're after the latest tests, you can look at http://github.com/typings/core. For example, https://github.com/typings/typings/blob/bff1abad91dabec1cd8a744e0dd3f54b613830b5/src/lib/dependencies.spec.ts. – blakeembrey Aug 23 '16 at 08:51
3

As blakeembrey mentioned. Istanbul 1.x handles it well.

Below an example of pure npm script that does it with Jasmine.

See https://github.com/Izhaki/Typescript-Jasmine-Istanbul-Boilerplate.

package.json (the relevant stuff)

{
  "scripts": {
    "postinstall": "typings install dt~jasmine --save --global",
    "test": "ts-node node_modules/.bin/jasmine JASMINE_CONFIG_PATH=jasmine.json",
    "test:coverage": "ts-node node_modules/istanbul/lib/cli.js cover -e .ts  -x \"*.d.ts\" -x \"*.spec.ts\" node_modules/jasmine/bin/jasmine.js -- JASMINE_CONFIG_PATH=jasmine.json"
  },
  "devDependencies": {
    "istanbul": "^1.1.0-alpha.1",
    "jasmine": "^2.4.1",
    "ts-node": "^0.9.3",
    "typescript": "^1.8.10",
    "typings": "^1.3.1"
  },
}

Output

image

Izhaki
  • 23,372
  • 9
  • 69
  • 107
  • The sample at the linked repository does not work. It throws an error: `SyntaxError: missing ) after argument list`. – Shaun Luttin Aug 21 '16 at 01:53
  • @ShaunLuttin open a github issue? Which node version are you using? – Izhaki Aug 21 '16 at 08:34
  • @ShaunLuttin It suppose to work (and the error seems like an obvious issue). Could you open a github issue and provide more details? – Izhaki Aug 21 '16 at 23:32
  • @ShaunLuttin, the windows code works on linux as well, so I've removed your note and just change the code to the version working on both windows/linux. – Izhaki Aug 23 '16 at 09:03
0

This is repo works. I ran the repo and can see the tests running. Html view is also generated. https://github.com/Izhaki/Typescript-Jasmine-Istanbul-Boilerplate

Laksh
  • 41
  • 2
0

None of the examples provided worked for my Node.JS project (written in TypeScript). I wanted to run unit tests in Jasmine, and covered by Istanbul.

I ended up getting it working with the following.

package.json:

{
  "scripts": {
    "lint": "tslint 'src/**/*.ts'",
    "remap": "./node_modules/.bin/remap-istanbul -i ./coverage/coverage-final.json -t html -o ./coverage && rimraf ./coverage/dist",
    "test": "npm run lint && rimraf dist coverage && tsc --project tsconfig-test.json && ./node_modules/.bin/istanbul cover ./node_modules/.bin/jasmine JASMINE_CONFIG_PATH=jasmine.json && npm run remap"
  },
  "devDependencies": {
    "@types/jasmine": "2.8.6",
    "@types/node": "9.6.6",
    "istanbul": "0.4.5",
    "jasmine": "3.1.0",
    "remap-istanbul": "0.11.1",
    "rimraf": "2.6.2",
    "tslint": "5.9.1",
    "typescript": "2.8.1"
  }
}

jasmine.json

{
  "spec_dir": "dist",
  "spec_files": [
    "**/*.spec.js"
  ],
  "stopSpecOnExpectationFailure": false,
  "random": false
}

.istanbul.yml

instrumentation:
  root: ./dist
  excludes: ['**/*.spec.js', '**/fixtures/*.js']
  include-all-sources: true
reporting:
  reports:
    - html
    - json
    - text-summary
  dir: ./coverage

tsconfig-test.json

{
  "compilerOptions": {
    "declaration": true,
    "lib": [
      "dom",
      "es6"
    ],
    "module": "commonjs",
    "noImplicitAny": true,
    "outDir": "dist",
    "sourceMap": true,
    "target": "es5"
  },
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}
Steve Brush
  • 2,911
  • 1
  • 23
  • 15