diff --git a/.gitignore b/.gitignore
index 282b4dc1..2b037d24 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,7 @@ node_modules
build/
sftp-config.json
coverage/
-temp/
+instrumented/
.idea
/nbproject/private/
.directory
diff --git a/Gruntfile.js b/Gruntfile.js
index b9757de5..bedec6b1 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -1,6 +1,7 @@
/* global module */
module.exports = function(grunt) {
+ var dateFormat = require('dateformat');
// ----------
grunt.loadNpmTasks("grunt-contrib-compress");
@@ -13,6 +14,7 @@ module.exports = function(grunt) {
grunt.loadNpmTasks("grunt-eslint");
grunt.loadNpmTasks("grunt-git-describe");
grunt.loadNpmTasks('grunt-text-replace');
+ grunt.loadNpmTasks('grunt-istanbul');
// ----------
var packageJson = grunt.file.readJSON("package.json"),
@@ -21,6 +23,7 @@ module.exports = function(grunt) {
packageDirName = "openseadragon-bin-" + packageJson.version,
packageDir = "build/" + packageDirName + "/",
releaseRoot = "../site-build/built-openseadragon/",
+ coverageDir = 'coverage/' + dateFormat(new Date(), 'yyyymmdd-HHMMss'),
sources = [
"src/openseadragon.js",
"src/fullscreen.js",
@@ -83,7 +86,7 @@ module.exports = function(grunt) {
clean: {
build: ["build"],
package: [packageDir],
- coverage: ["coverage"],
+ coverage: ["instrumented"],
release: {
src: [releaseRoot],
options: {
@@ -154,7 +157,8 @@ module.exports = function(grunt) {
qunit: {
normal: {
options: {
- urls: [ "http://localhost:8000/test/test.html" ]
+ urls: [ "http://localhost:8000/test/test.html" ],
+ timeout: 500000
}
},
coverage: {
@@ -162,11 +166,13 @@ module.exports = function(grunt) {
urls: [ "http://localhost:8000/test/coverage.html" ],
coverage: {
src: ['src/*.js'],
- htmlReport: 'coverage/html/',
- instrumentedFiles: 'temp/',
+ htmlReport: coverageDir + '/html/',
+ instrumentedFiles: 'instrumented/src/',
baseUrl: '.',
disposeCollector: true
- }
+ },
+ inject: 'test/helpers/phantom-bridge.js',
+ timeout: 500000
}
},
all: {
@@ -199,7 +205,38 @@ module.exports = function(grunt) {
},
build: {}
},
- gitInfo: "unknown"
+ gitInfo: "unknown",
+ instrument: {
+ files: sources,
+ options: {
+ lazy: false,
+ basePath: 'instrumented/'
+ }
+ },
+ reloadTasks: {
+ rootPath: "instrumented/src/"
+ },
+ storeCoverage: {
+ options: {
+ dir: coverageDir,
+ 'include-all-sources': true
+ }
+ },
+ makeReport: {
+ src: "coverage/**/*.json",
+ options: {
+ type: [ "lcov", "html" ],
+ dir: coverageDir,
+ print: "detail"
+ }
+ }
+ });
+
+ grunt.event.on("qunit.coverage", function(coverage) {
+ var reportPath = coverageDir + "/coverage.json";
+
+ // Create the coverage file
+ grunt.file.write(reportPath, JSON.stringify(coverage));
});
// ----------
@@ -287,7 +324,7 @@ module.exports = function(grunt) {
// ----------
// Coverage task.
// Outputs unit test code coverage report.
- grunt.registerTask("coverage", ["clean:coverage", "connect", "qunit:coverage"]);
+ grunt.registerTask("coverage", ["clean:coverage", "instrument", "connect", "qunit:coverage", "makeReport"]);
// ----------
// Package task.
diff --git a/package.json b/package.json
index dc36ae73..efc0ed5f 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
"grunt-contrib-watch": "^1.0.0",
"grunt-eslint": "^19.0.0",
"grunt-git-describe": "^2.3.2",
+ "grunt-istanbul": "^0.8.0",
"grunt-text-replace": "^0.4.0",
"qunitjs": "2.4.1"
},
diff --git a/test/coverage.html b/test/coverage.html
index 36e2e056..e2abc706 100644
--- a/test/coverage.html
+++ b/test/coverage.html
@@ -21,40 +21,40 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/helpers/phantom-bridge.js b/test/helpers/phantom-bridge.js
new file mode 100644
index 00000000..ed5b84ad
--- /dev/null
+++ b/test/helpers/phantom-bridge.js
@@ -0,0 +1,73 @@
+/*
+ * grunt-contrib-qunit
+ * http://gruntjs.com/
+ *
+ * Copyright (c) 2016 "Cowboy" Ben Alman, contributors
+ * Licensed under the MIT license.
+ */
+
+/*global QUnit:true, alert:true*/
+(function (factory) {
+ if (typeof define === 'function' && define.amd) {
+ require(['qunit'], factory);
+ } else {
+ factory(QUnit);
+ }
+}(function(QUnit) {
+ 'use strict';
+
+ // Don't re-order tests.
+ QUnit.config.reorder = false;
+
+ // Send messages to the parent PhantomJS process via alert! Good times!!
+ function sendMessage() {
+ var args = [].slice.call(arguments);
+ alert(JSON.stringify(args));
+ }
+
+ // These methods connect QUnit to PhantomJS.
+ QUnit.log(function(obj) {
+ // What is this I don’t even
+ if (obj.message === '[object Object], undefined:undefined') { return; }
+
+ // Parse some stuff before sending it.
+ var actual, expected;
+ if (!obj.result) {
+ // Dumping large objects can be very slow, and the dump isn't used for
+ // passing tests, so only dump if the test failed.
+ actual = QUnit.dump.parse(obj.actual);
+ expected = QUnit.dump.parse(obj.expected);
+ }
+ // Send it.
+ sendMessage('qunit.log', obj.result, actual, expected, obj.message, obj.source, obj.todo);
+ });
+
+ QUnit.testStart(function(obj) {
+ sendMessage('qunit.testStart', obj.name);
+ });
+
+ QUnit.testDone(function(obj) {
+ sendMessage('qunit.testDone', obj.name, obj.failed, obj.passed, obj.total, obj.runtime, obj.skipped, obj.todo);
+ });
+
+ QUnit.moduleStart(function(obj) {
+ sendMessage('qunit.moduleStart', obj.name);
+ });
+
+ QUnit.moduleDone(function(obj) {
+ sendMessage('qunit.moduleDone', obj.name, obj.failed, obj.passed, obj.total);
+ });
+
+ QUnit.begin(function() {
+ sendMessage('qunit.begin');
+ });
+
+ QUnit.done(function(obj) {
+ // send coverage data if available
+ if ( window.__coverage__ ) {
+ sendMessage( "qunit.coverage", window.__coverage__ );
+ }
+
+ sendMessage('qunit.done', obj.failed, obj.passed, obj.total, obj.runtime);
+ });
+}));