Tests: Switch to our own gulp-qunits module.

Since it handles PhantomJS as well as Node.js execution, and formats errors identically and quickly.
This commit is contained in:
Jürg Lehni 2016-01-28 14:39:40 +01:00
parent e02e9f4643
commit 567f286774
6 changed files with 35 additions and 111 deletions

View file

@ -2,6 +2,8 @@ Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
http://scratchdisk.com/ & http://jonathanpuckey.com/ http://scratchdisk.com/ & http://jonathanpuckey.com/
All rights reserved. All rights reserved.
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights

View file

@ -11,41 +11,32 @@
*/ */
var gulp = require('gulp'), var gulp = require('gulp'),
gulp_qunit = require('gulp-qunit'), qunits = require('gulp-qunits'),
node_qunit = require('qunit'),
gutil = require('gulp-util'); gutil = require('gulp-util');
gulp.task('test', ['test:browser', 'test:node']); gulp.task('test', ['test:browser', 'test:node']);
gulp.task('test:browser', ['minify:acorn'], function() { gulp.task('test:browser', ['minify:acorn'], function() {
return gulp.src('test/index.html') return gulp.src('index.html', { cwd: 'test' })
.pipe(gulp_qunit({ timeout: 20, noGlobals: true })); .pipe(qunits({
noGlobals: true,
timeout: 20
}));
}); });
gulp.task('test:node', ['minify:acorn'], function(callback) { gulp.task('test:node', ['minify:acorn'], function(callback) {
// Use the correct working directory for tests: return gulp.src('load.js', { cwd: 'test' })
process.chdir('./test'); .pipe(qunits({
// Deactivate all logging since we're doing our own directly to gutil.log() require: [
// from helpers.js // To dynamically load the tests files from the sources, we need
node_qunit.setup({ log: {} }); // to require Prepro.js first.
node_qunit.run({ 'prepro/lib/node.js',
maxBlockDuration: 100 * 1000, // Note that loading dist/paper-full.js also works in
deps: [ // combination with `gulp load`, in which case Prepro.js is
// To dynamically load the tests files from the sources, we need to // present and handles the loading transparently.
// require Prepro.js first. Since we need a sub-module, we have to { path: '../dist/paper-full.js', namespace: 'paper' }
// use relative addresses: require('prepro/lib/node') does not work ],
// because of the way node-qunit handles relative addresses. noGlobals: true,
'../node_modules/prepro/lib/node.js', timeout: 20
// Note that loading dist/paper-full.js also works in combination }));
// with `gulp load`, in which case Prepro.js is present and handles
// the loading transparently.
{ path: '../dist/paper-full.js', namespace: 'paper' }
],
// Now load the actual test files through test/load.js, using Prepro.js
// for the loading, which was requested above.
code: 'load.js'
}, function(err, stats) {
err = err || stats.failed > 0 && 'QUnit assertions failed';
callback(err && new gutil.PluginError('node-qunit', err));
});
}); });

View file

@ -18,8 +18,10 @@ gulp.on('error', function(err) {
var msg = err.toString(); var msg = err.toString();
if (msg === '[object Object]') if (msg === '[object Object]')
msg = err; msg = err;
gutil.log(ERROR, msg);
if (err.stack) if (err.stack)
gutil.log(ERROR, err.stack); msg += err.stack;
msg.split(/\r\n|\n|\r/mg).forEach(function(line) {
gutil.log(ERROR, line);
});
this.emit('end'); this.emit('end');
}); });

View file

@ -25,7 +25,7 @@
"README.md" "README.md"
], ],
"engines": { "engines": {
"node": ">=0.8.0 <6.0.0" "node": ">=0.10.0 <6.0.0"
}, },
"dependencies": { "dependencies": {
"jsdom": "git://github.com/lehni/jsdom.git#3d55789d0f4d55392721b1e22890837fde472375", "jsdom": "git://github.com/lehni/jsdom.git#3d55789d0f4d55392721b1e22890837fde472375",
@ -43,7 +43,7 @@
"gulp-cached": "^1.1.0", "gulp-cached": "^1.1.0",
"gulp-jshint": "^2.0.0", "gulp-jshint": "^2.0.0",
"gulp-prepro": "^2.2.0", "gulp-prepro": "^2.2.0",
"gulp-qunit": "git://github.com/lehni/gulp-qunit.git#459c5603ceac460327a40dc89df6f19c786dc61b", "gulp-qunits": "^1.5.1",
"gulp-rename": "^1.2.2", "gulp-rename": "^1.2.2",
"gulp-rimraf": "^0.2.0", "gulp-rimraf": "^0.2.0",
"gulp-shell": "^0.5.1", "gulp-shell": "^0.5.1",
@ -57,7 +57,6 @@
"jshint-summary": "^0.4.0", "jshint-summary": "^0.4.0",
"merge-stream": "^1.0.0", "merge-stream": "^1.0.0",
"prepro": "^2.2.0", "prepro": "^2.2.0",
"qunit": "^0.7.7",
"qunitjs": "^1.20.0", "qunitjs": "^1.20.0",
"require-dir": "^0.3.0", "require-dir": "^0.3.0",
"resemblejs": "^2.1.0", "resemblejs": "^2.1.0",

View file

@ -17,50 +17,6 @@ if (isNode) {
root = global; root = global;
// Resemble.js needs the Image constructor global. // Resemble.js needs the Image constructor global.
global.Image = paper.window.Image; global.Image = paper.window.Image;
// Handle logging to gulp directly from here, imitating the way gulp-qunit
// logs and formats results and errors:
var gutil = require('gulp-util'),
colors = gutil.colors,
done = false;
QUnit.log(function(details) {
if (!details.result) {
var lines = [
colors.red('Test failed') + ': ' + details.module + ': '
+ details.name
];
var line = 'Failed assertion: ' + (details.message || '');
if (details.expected !== undefined) {
line += ', expected: ' + details.expected + ', but was: '
+ details.actual;
}
lines.push(line);
if (details.source) {
lines = lines.concat(details.source.split(/\r\n|\n|\r/mg));
}
lines.forEach(function(line) {
gutil.log(line);
});
} else if (false) {
gutil.log(colors.green('Test succeeded') + ': ' + details.module
+ ': ' + details.name +': ' + (details.message || ''));
}
});
QUnit.done(function(details) {
if (done)
return;
var color = colors[details.failed > 0 ? 'red' : 'green'];
gutil.log('Took ' + details.runtime + 'ms to run '
+ colors.blue(details.total) + ' tests. ' + color(details.passed
+ ' passed, ' + details.failed + ' failed.'));
if (details.failed > 0) {
gutil.log('node-qunit: ' + gutil.colors.red('✖')
+ ' QUnit assertions failed');
} else {
gutil.log('node-qunit: ' + gutil.colors.green('✔')
+ ' QUnit assertions all passed');
}
done = true;
});
} else { } else {
root = window; root = window;
// This is only required when running in the browser: // This is only required when running in the browser:
@ -93,37 +49,19 @@ QUnit.done(function(details) {
console.error = errorHandler; console.error = errorHandler;
}); });
var currentProject, var currentProject;
// In case we're stuck with an old QUnit, use a fake assert object with just
// the functions that we need:
// For now, a async() function returning a done() function:
fakeAssert = {
async: function() {
return function() {
QUnit.start();
};
}
};
// NOTE: In order to "export" all methods into the shared Prepro.js scope when // NOTE: In order to "export" all methods into the shared Prepro.js scope when
// using node-qunit, we need to define global functions as: // using node-qunit, we need to define global functions as:
// `var name = function() {}`. `function name() {}` does not work! // `var name = function() {}`. `function name() {}` does not work!
var test = function(testName, expected) { var test = function(testName, expected) {
// If this is running on an older version of QUnit (e.g. node-qunit is stuck return QUnit.test(testName, function(assert) {
// with v1.10 for now), emulate the new assert.async() syntax through
// QUnit.asyncTest() and QUnit.start();
var emulate = !QUnit.async && 'assert' ===
// Get the parameter list from the passed function to see if we're
// expecting the assert object to do async...
expected.toString().match(/^\s*function[^\(]*\(([^\)]*)/)[1];
return QUnit[emulate ? 'asyncTest' : 'test'](testName, function(assert) {
// Since tests can be asynchronous, remove the old project before // Since tests can be asynchronous, remove the old project before
// running the next test. // running the next test.
if (currentProject) if (currentProject)
currentProject.remove(); currentProject.remove();
currentProject = new Project(); currentProject = new Project();
expected(emulate ? fakeAssert : assert); expected(assert);
}); });
}; };

View file

@ -23,7 +23,7 @@ test('Create a raster without a source and set its size', function() {
equals(raster.size, new Size(640, 480), true); equals(raster.size, new Size(640, 480), true);
}); });
test('Create a raster from a url', function(assert) { test('Create a raster from a URL', function(assert) {
var done = assert.async(); var done = assert.async();
var raster = new Raster('assets/paper-js.gif'); var raster = new Raster('assets/paper-js.gif');
raster.onLoad = function() { raster.onLoad = function() {
@ -31,12 +31,12 @@ test('Create a raster from a url', function(assert) {
done(); done();
}; };
raster.onError = function(event) { raster.onError = function(event) {
pushFailure(event.event); pushFailure('Loading from a valid local URL should not give an error.');
done(); done();
}; };
}); });
test('Create a raster from a data url', function(assert) { test('Create a raster from a data URL', function(assert) {
var done = assert.async(); var done = assert.async();
var raster = new Raster('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABlJREFUeNpi+s/AwPCfgYmR4f9/hv8AAQYAHiAFAS8Lwy8AAAAASUVORK5CYII='); var raster = new Raster('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABlJREFUeNpi+s/AwPCfgYmR4f9/hv8AAQYAHiAFAS8Lwy8AAAAASUVORK5CYII=');
raster.onLoad = function() { raster.onLoad = function() {
@ -44,7 +44,7 @@ test('Create a raster from a data url', function(assert) {
done(); done();
}; };
raster.onError = function(event) { raster.onError = function(event) {
pushFailure(event.event); pushFailure('Loading from a valid data URL should not give an error.');
done(); done();
}; };
}); });
@ -101,10 +101,6 @@ test('Raster#getPixel / setPixel', function(assert) {
equals(raster.getPixel([0, 0]), color, 'alpha', { tolerance: 1e-2 }); equals(raster.getPixel([0, 0]), color, 'alpha', { tolerance: 1e-2 });
done(); done();
}; };
raster.onError = function(event) {
pushFailure(event.event);
done();
};
}); });
test('Raster#getSubCanvas', function(assert) { test('Raster#getSubCanvas', function(assert) {
@ -133,10 +129,6 @@ test('Raster#getSubCanvas', function(assert) {
}, true); }, true);
done(); done();
}; };
raster.onError = function(event) {
pushFailure(event.event);
done();
};
}); });
test('Raster#getAverageColor(path)', function() { test('Raster#getAverageColor(path)', function() {