Add initial code coverage reporting
authorKevin Sawicki <kevinsawicki@gmail.com>
Tue, 2 Aug 2016 17:38:51 +0000 (10:38 -0700)
committerKevin Sawicki <kevinsawicki@gmail.com>
Wed, 3 Aug 2016 23:23:37 +0000 (16:23 -0700)
spec/package.json
spec/static/coverage.js [new file with mode: 0644]
spec/static/index.html
spec/static/main.js

index 32b41b5..d673a81 100644 (file)
@@ -5,9 +5,11 @@
   "version": "0.1.0",
   "devDependencies": {
     "basic-auth": "^1.0.0",
+    "glob": "^7.0.5",
     "graceful-fs": "3.0.5",
-    "mocha": "2.1.0",
+    "istanbul": "^0.4.4",
     "mkdirp": "0.5.1",
+    "mocha": "2.1.0",
     "multiparty": "4.1.2",
     "q": "0.9.7",
     "temp": "0.8.1",
diff --git a/spec/static/coverage.js b/spec/static/coverage.js
new file mode 100644 (file)
index 0000000..3308e26
--- /dev/null
@@ -0,0 +1,45 @@
+const fs = require('fs')
+const glob = require('glob')
+const path = require('path')
+const {ipcRenderer} = require('electron')
+const {Collector, Instrumenter, Reporter} = require('istanbul')
+
+const addUnrequiredFiles = (coverage) => {
+  const instrumenter = new Instrumenter()
+  const transformer = instrumenter.instrumentSync.bind(instrumenter)
+  const libPath = path.join(__dirname, '..', '..', 'lib')
+
+  glob.sync('**/*.js', {cwd: libPath}).map(function (relativePath) {
+    return path.join(libPath, relativePath)
+  }).filter(function (filePath) {
+    return coverage[filePath] == null
+  }).forEach(function (filePath) {
+    transformer(fs.readFileSync(filePath, 'utf8'), filePath)
+
+    // When instrumenting the code, istanbul will give each FunctionDeclaration
+    // a value of 1 in coverState.s,presumably to compensate for function
+    // hoisting. We need to reset this, as the function was not hoisted, as it
+    // was never loaded.
+    Object.keys(instrumenter.coverState.s).forEach(function (key) {
+        instrumenter.coverState.s[key] = 0
+    });
+
+    coverage[filePath] = instrumenter.coverState
+  })
+}
+
+exports.generate = () => {
+  const coverage = window.__coverage__
+  if (coverage == null) return
+
+  addUnrequiredFiles(coverage)
+
+  const collector = new Collector()
+  collector.add(coverage)
+  collector.add(ipcRenderer.sendSync('get-coverage'))
+
+  const outPath = path.join(__dirname, '..', '..', 'out', 'coverage')
+  const reporter = new Reporter(null, outPath)
+  reporter.addAll(['text', 'lcov'])
+  reporter.write(collector, true, function () {})
+}
index 61647c0..faa8f52 100644 (file)
@@ -83,6 +83,7 @@
       Mocha.utils.highlightTags('code');
       if (isCi)
         ipcRenderer.send('process.exit', runner.failures);
+      require('./coverage').generate()
     });
   });
 })();
index 8a43253..8196afd 100644 (file)
@@ -63,6 +63,10 @@ ipcMain.on('echo', function (event, msg) {
   event.returnValue = msg
 })
 
+ipcMain.on('get-coverage', function(event) {
+  event.returnValue = global.__coverage__
+})
+
 global.isCi = !!argv.ci
 if (global.isCi) {
   process.removeAllListeners('uncaughtException')