From 605cecf92bf080cfbb891c3fdf30b7b11b889b6e Mon Sep 17 00:00:00 2001 From: Doug Luce Date: Fri, 8 Jul 2016 13:24:53 -0700 Subject: [PATCH] Add code coverage stats Electron-mocha makes things like this a little difficult. Luckily, @inukshuk in https://github.com/jprichardson/electron-mocha/issues/19#issuecomment-227868475 figures out a way to get around it. It's a bit of effort but does work in the end. With any luck an npm module will come out with these clues embedded in it and the coverage.js can be removed. --- .gitignore | 1 + package.json | 5 ++++- test/coverage.js | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 test/coverage.js diff --git a/.gitignore b/.gitignore index c2658d7..25fbf5a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules/ +coverage/ diff --git a/package.json b/package.json index 6b5654e..1593645 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "index.js", "scripts": { "test": "electron-mocha", - "testmon": "nodemon --exec '(electron-mocha && growlnotify -n nodemon --image ~/green.png -m good) || (growlnotify -n nodemon --image ~/red.png -m crash && exit 1)'" + "testmon": "nodemon --exec '(electron-mocha && growlnotify -n nodemon --image ~/green.png -m good) || (growlnotify -n nodemon --image ~/red.png -m crash && exit 1)'", + "coverage": "electron-mocha --require test/coverage && istanbul report lcov" }, "bin": { "scan": "./bin/scan" @@ -14,8 +15,10 @@ "license": "ISC", "devDependencies": { "chai": "^3.5.0", + "coveralls": "^2.11.9", "electron-mocha": "^2.3.0", "express": "^4.14.0", + "istanbul": "^0.4.4", "mocha": "^2.5.3", "nodemon": "^1.9.2" }, diff --git a/test/coverage.js b/test/coverage.js new file mode 100644 index 0000000..b267f4e --- /dev/null +++ b/test/coverage.js @@ -0,0 +1,57 @@ +'use strict' + +// Largely cribbed from +// https://raw.githubusercontent.com/tropy/tropy/master/test/support/coverage.js + +const glob = require('glob') +const { readFileSync: read, realpathSync } = require('fs') +const { Reporter, Instrumenter, Collector, hook } = require('istanbul') +const { keys } = Object + +function match () { + const map = {} + const fn = function (file) { return map[file] } + fn.files = [] + + for (let file of glob.sync(pattern)) { + let fullpath = realpathSync(file) + fn.files.push(fullpath) + map[fullpath] = true + } + + return fn +} + +function report () { + const cov = global.__coverage__ + for (let file of matched.files) { + if (!cov[file]) { + // Add uncovered files to the report. + transformer(read(file, 'utf-8'), file) + for (let key of keys(instrumenter.coverState.s)) { + instrumenter.coverState.s[key] = 0 + } + cov[file] = instrumenter.coverState + } + } + + const collector = new Collector() + collector.add(cov) + + const reporter = new Reporter() + reporter.addAll(['text-summary', 'json']) + reporter.write(collector, true, () => {}) +} + +// The source files to cover. Avoid node_modules/, coverage/, and +// */coverage.js (supposed to be test/coverage.js) + +const pattern = '{!(node_modules|coverage)/**,.}/!(coverage).js' +const matched = match() + +const instrumenter = new Instrumenter() +const transformer = instrumenter.instrumentSync.bind(instrumenter) + +hook.hookRequire(matched, transformer, {}) + +process.on('exit', report)