Skip to content

Commit

Permalink
WIP: Add support for code coverage collection
Browse files Browse the repository at this point in the history
  • Loading branch information
Krinkle committed Jul 24, 2023
1 parent 8e88ec7 commit c254b02
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 7 deletions.
15 changes: 15 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,21 @@ module.exports = function(grunt) {
]
}
},
coverFiles: {
options: {
coverage: true
},
src: 'test/qunit_cover.html'
},
coverUrls: {
options: {
coverage: true,
urls: [
'http://localhost:9000/test/qunit_cover.html',
// 'http://localhost:9000/test/qunit_cover2.html'
]
}
},
circularObject: {
options: {
urls: [
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
"grunt-contrib-internal": "^8.0.2",
"grunt-contrib-jshint": "^3.2.0",
"grunt-shell": "^4.0.0",
"nyc": "^15.1.0",
"puppeteer-to-istanbul": "^1.4.0",
"qunit": "^2.19.4"
},
"keywords": [
Expand Down
25 changes: 18 additions & 7 deletions tasks/qunit.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var EventEmitter = require('eventemitter2');
// NPM libs.
var pEachSeries = require('p-each-series');
var puppeteer = require('puppeteer');
var pti = require('puppeteer-to-istanbul');

var Promise = global.Promise;

Expand Down Expand Up @@ -240,19 +241,20 @@ module.exports = function(grunt) {

grunt.registerMultiTask('qunit', 'Run QUnit tests in Headless Chrome.', function() {
// Chrome sandbox is incompatible with Docker and most CI environments
var defaultChromiumArgs = (
process.env.CHROMIUM_FLAGS || (process.env.CI ? '--no-sandbox' : '')
).split(' ');
var chromiumFlags = process.env.CHROMIUM_FLAGS || (process.env.CI ? '--no-sandbox' : '');
var defaultChromiumArgs = chromiumFlags ? chromiumFlags.split(' '): [];

// Merge task-specific and/or target-specific options with these defaults.
options = this.options({
// Default Chrome timeout.
timeout: 5000,
// QUnit-Chrome bridge file to be injected.
// Bridge file to be injected.
inject: asset('chrome/bridge.js'),
// Explicit non-file URLs to test.
urls: [],
force: false,
coverage: false,
coverageDir: './.nyc_output',
// Connect Chrome console output to Grunt output
console: true,
// Do not use an HTTP base by default
Expand Down Expand Up @@ -353,7 +355,7 @@ module.exports = function(grunt) {
eventBus.emit.apply(eventBus, [].slice.call(arguments));
});
})
.then(function() {
.then(async function() {
// Pass through the console logs if instructed
if (options.console) {
page.on('console', function(msg) {
Expand Down Expand Up @@ -395,12 +397,16 @@ module.exports = function(grunt) {
// injected before any other DOMContentLoaded or window.load event handler.
page.evaluateOnNewDocument('if (window.QUnit) {\n' + bridgContents.join(";") + '\n} else {\n' + 'document.addEventListener("DOMContentLoaded", function() {\n' + bridgContents.join(";") + '\n});\n}\n');

return pEachSeries(urls, function(url) {
if (options.coverage) {
await page.coverage.startJSCoverage();
}

return pEachSeries(urls, async function(url) {
// Reset current module.
grunt.event.emit('qunit.spawn', url);
grunt.verbose.subhead('Testing ' + url + ' ').or.write('Testing ' + url + ' ');

return Promise.all([
await Promise.all([
// Setup listeners for qunit.done / fail events
new Promise(function(resolve, reject) {
eventBus.once('qunit.on.runEnd', function() { resolve(); });
Expand All @@ -410,6 +416,11 @@ module.exports = function(grunt) {
// Navigate to the url to be tested
page.goto(getPath(url), { timeout: options.timeout })
]);

if (options.coverage) {
const jsCoverage = await page.coverage.stopJSCoverage();
pti.write(jsCoverage, { includeHostname: true , storagePath: options.coverageDir });
}
});
})
.then(function() {
Expand Down
15 changes: 15 additions & 0 deletions test/qunit_cover.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test Suite</title>
<link rel="stylesheet" href="../node_modules/qunit/qunit/qunit.css" media="screen">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="../node_modules/qunit/qunit/qunit.js"></script>
<script src="qunit_cover_src.js"></script>
<script src="qunit_cover_test.js"></script>
</body>
</html>
15 changes: 15 additions & 0 deletions test/qunit_cover2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test Suite</title>
<link rel="stylesheet" href="../node_modules/qunit/qunit/qunit.css" media="screen">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="../node_modules/qunit/qunit/qunit.js"></script>
<script src="qunit_cover_src.js"></script>
<script src="qunit_cover_test2.js"></script>
</body>
</html>
22 changes: 22 additions & 0 deletions test/qunit_cover_src.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class Foo {
constructor(id) {
this.id = id;
this.position = 0;
}
reset() {
// Untested
this.position = 0;
}
walk() {
this.position += 1;
}
run() {
this.position += 10;
}
}

globalThis.MyApp = {
makeFoo(id) {
return new Foo(id);
}
};
9 changes: 9 additions & 0 deletions test/qunit_cover_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* global MyApp */

QUnit.test('MyApp.run', function(assert) {
var foo = MyApp.makeFoo(42);
assert.strictEqual(foo.position, 0);

foo.run();
assert.strictEqual(foo.position, 10);
});
9 changes: 9 additions & 0 deletions test/qunit_cover_test2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* global MyApp */

QUnit.test('MyApp.walk', function(assert) {
var foo = MyApp.makeFoo(42);
assert.strictEqual(foo.position, 0);

foo.walk();
assert.strictEqual(foo.position, 1);
});

0 comments on commit c254b02

Please sign in to comment.