Tests: Start getting QUnit tests to work on Node.js

Work in progress…
This commit is contained in:
Jürg Lehni 2016-01-27 19:57:07 +01:00
parent 0c1b4376d3
commit 4c84c3dad5
44 changed files with 322 additions and 176 deletions

View file

@ -18,4 +18,5 @@ addons:
script:
- npm run lint
- gulp minify
- gulp test
- gulp test:browser
- gulp test:node

View file

@ -11,9 +11,68 @@
*/
var gulp = require('gulp'),
qunit = require('gulp-qunit');
gulp_qunit = require('gulp-qunit'),
node_qunit = require('qunit'),
gutil = require('gulp-util'),
extend = require('extend'),
minimist = require('minimist');
gulp.task('test', function() {
return gulp.src('test/index.html')
.pipe(qunit({ timeout: 20, noGlobals: true }));
// Support simple command line options to pass on to test:node, to display
// errors selectively, e.g.:
// gulp test:node --assertions
var options = minimist(process.argv.slice(2), {
boolean: true
});
gulp.task('test', ['test:browser']);
gulp.task('test:browser', ['minify:acorn'], function() {
return gulp.src('test/index.html')
.pipe(gulp_qunit({ timeout: 20, noGlobals: true }));
});
gulp.task('test:node', ['minify:acorn'], function(callback) {
var name = 'node-qunit';
node_qunit.setup({
log: extend({ errors: true }, options)
});
// Use the correct working directory for tests:
process.chdir('./test');
node_qunit.run({
maxBlockDuration: 100 * 1000,
deps: [
// To dynamically load the tests files from the sources, we need to
// require Prepro.js first. Since we need a sub-module, we have to
// use relative addresses: require('prepro/lib/node') does not work
// because of the way node-qunit handles relative addresses.
'../node_modules/prepro/lib/node.js',
// 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) {
var result;
if (err) {
result = new gutil.PluginError(name, err);
} else {
// Imitate the way gulp-qunit formats results and errors.
var color = gutil.colors[stats.failed > 0 ? 'red' : 'green'];
gutil.log('Took ' + stats.runtime + ' ms to run ' +
gutil.colors.blue(stats.assertions) + ' tests. ' +
color(stats.passed + ' passed, ' + stats.failed + ' failed.'));
if (stats.failed > 0) {
err = 'QUnit assertions failed';
gutil.log(name + ': ' + gutil.colors.red('✖ ') + err);
result = new gutil.PluginError(name, err);
} else {
gutil.log(name + ': ' + gutil.colors.green('✔ ') +
'QUnit assertions all passed');
}
}
callback(result);
});
});

View file

@ -18,7 +18,7 @@ gulp.on('error', function(err) {
var msg = err.toString();
if (msg === '[object Object]')
msg = err;
gutil.log(ERROR, err);
gutil.log(ERROR, msg);
if (err.stack)
gutil.log(ERROR, err.stack);
this.emit('end');

View file

@ -25,7 +25,7 @@
"README.md"
],
"engines": {
"node": ">=0.8.0 <5.0.0"
"node": ">=0.8.0 <6.0.0"
},
"dependencies": {
"jsdom": "git://github.com/lehni/jsdom.git#3d55789d0f4d55392721b1e22890837fde472375",
@ -42,7 +42,7 @@
"gulp": "^3.9.0",
"gulp-cached": "^1.1.0",
"gulp-jshint": "^2.0.0",
"gulp-prepro": "^2.0.0",
"gulp-prepro": "^2.1.0",
"gulp-qunit": "git://github.com/lehni/gulp-qunit.git#459c5603ceac460327a40dc89df6f19c786dc61b",
"gulp-rename": "^1.2.2",
"gulp-rimraf": "^0.2.0",
@ -56,7 +56,9 @@
"jshint": "2.8.x",
"jshint-summary": "^0.4.0",
"merge-stream": "^1.0.0",
"prepro": "^2.0.0",
"minimist": "^1.2.0",
"prepro": "^2.1.0",
"qunit": "^0.7.7",
"qunitjs": "^1.20.0",
"require-dir": "^0.3.0",
"resemblejs": "^2.1.0",

View file

@ -45,7 +45,7 @@ if (typeof window === 'object') {
}
} else {
// Node.js based loading through Prepro.js:
var prepro = require('prepro/lib/node.js'),
var prepro = require('prepro/lib/node'),
// Load the default browser-based options for further amendments.
// Step out and back into src, in case this is loaded from
// dist/paper-node.js

View file

@ -10,8 +10,19 @@
* All rights reserved.
*/
// Until window.history.pushState() works when running locally, we need to trick
// qunit into thinking that the feature is not present. This appears to work...
var isNode = typeof global === 'object',
root;
if (isNode) {
root = global;
// Resemble.js needs the Image constructor this global.
global.Image = paper.window.Image;
} else {
root = window;
// This is only required when running in the browser:
// Until window.history.pushState() works when running locally, we need to
// trick qunit into thinking that the feature is not present. This appears
// to work...
// TODO: Ideally we should fix this in QUnit instead.
delete window.history;
window.history = {};
@ -30,6 +41,11 @@ QUnit.begin(function() {
transparency: 1
});
});
}
// The unit-tests expect the paper classes to be global.
if (!('Base' in root))
paper.install(root);
var errorHandler = console.error;
console.error = function() {
@ -37,8 +53,48 @@ console.error = function() {
errorHandler.apply(this, arguments);
};
// NOTE: In order to "export" all methods into the shared Prepro.js scope when
// using node-qunit, we need to define global functions as:
// `var name = function() {}`. `function name() {}` does not work!
var currentProject;
var test = function(testName, expected) {
var parameters = expected.toString().match(/^\s*function[^\(]*\(([^\)]*)/)[1];
// If this is running on an older version of QUnit (e.g. node-qunit is stuck
// with v1.10 for now), emulate the new assert.async() syntax through
// QUnit.asyncTest() and QUnit.start();
if (!QUnit.async && parameters === 'assert') {
return QUnit.asyncTest(testName, function() {
// Since tests may be asynchronous, remove the old project before
// running the next test.
if (currentProject)
currentProject.remove();
currentProject = new Project();
// Pass a fake assert object with just the functions that we need,
// so far a async() function returning a done() function:
expected({
async: function() {
return function() {
QUnit.start();
};
}
});
});
} else {
return QUnit.test(testName, function(assert) {
// Since tests may be asynchronous, remove the old project before
// running the next test.
if (currentProject)
currentProject.remove();
currentProject = new Project();
expected(assert);
});
}
};
// Override equals to convert functions to message and execute them as tests()
function equals(actual, expected, message, options) {
var equals = function(actual, expected, message, options) {
// Allow the use of functions for actual, which will get called and their
// source content extracted for readable reports.
if (typeof actual === 'function') {
@ -55,7 +111,7 @@ function equals(actual, expected, message, options) {
|| type === 'boolean' && 'Boolean'
|| type === 'undefined' && 'Undefined'
|| Array.isArray(expected) && 'Array'
|| expected instanceof Element && 'Element' // handle DOM Elements
|| expected instanceof window.Element && 'Element' // handle DOM Elements
|| (cls = expected && expected._class) // check _class 2nd last
|| type === 'object' && 'Object'; // Object as catch-all
var comparator = type && comparators[type];
@ -76,7 +132,40 @@ function equals(actual, expected, message, options) {
actual, identical ? expected : 'not ' + expected,
message + ': identical after cloning');
}
};
// A list of classes that should be identical after their owners were cloned.
var identicalAfterCloning = {
Gradient: true,
Symbol: true
};
var getFunctionMessage = function(func) {
var message = func.toString().match(
/^\s*function[^\{]*\{([\s\S]*)\}\s*$/)[1]
.replace(/ /g, '')
.replace(/^\s+|\s+$/g, '');
if (/^return /.test(message)) {
message = message
.replace(/^return /, '')
.replace(/;$/, '');
}
return message;
};
var createSVG = function(str, attrs) {
if (attrs) {
// Similar to SVGExport's createElement / setAttributes.
var node = document.createElementNS('http://www.w3.org/2000/svg', str);
for (var key in attrs)
node.setAttribute(key, attrs[key]);
return node;
} else {
return new window.DOMParser().parseFromString(
'<svg xmlns="http://www.w3.org/2000/svg">' + str + '</svg>',
'text/xml');
}
};
// Register a jsDump parser for Base.
QUnit.jsDump.setParser('Base', function (obj, stack) {
@ -95,14 +184,15 @@ QUnit.jsDump.setParser('object', function (obj, stack) {
: objectParser).call(this, obj, stack);
});
function compareProperties(actual, expected, properties, message, options) {
var compareProperties = function(actual, expected, properties, message, options) {
for (var i = 0, l = properties.length; i < l; i++) {
var key = properties[i];
equals(actual[key], expected[key], message + '.' + key, options);
}
}
};
function compareItem(actual, expected, message, options, properties) {
var compareItem = function(actual, expected, message, options, properties) {
options = options || {};
function rasterize(item, group, resolution) {
var raster = null;
@ -119,7 +209,7 @@ function compareItem(actual, expected, message, options, properties) {
+ '" src="' + raster.source + '">';
}
if (options && options.rasterize) {
if (options.rasterize) {
// In order to properly compare pixel by pixel, we need to put each item
// into a group with a white background of the united dimensions of the
// bounds of both items before rasterizing.
@ -159,11 +249,15 @@ function compareItem(actual, expected, message, options, properties) {
.compareTo(expected.getImageData())
// When working with imageData, this call is synchronous:
.onComplete(function(data) { result = data; });
var identical = result ? 100 - result.misMatchPercentage : 0,
ok = identical == 100,
text = identical.toFixed(2) + '% identical';
QUnit.push(ok, text, '100.00% identical', message);
if (!ok && result) {
var tolerance = (options.tolerance || 1e-4) * 100, // percentages...
fixed = ((1 / tolerance) + '').length - 1,
identical = result ? 100 - result.misMatchPercentage : 0,
reached = identical.toFixed(fixed),
hundred = (100).toFixed(fixed),
ok = reached == hundred;
QUnit.push(ok, reached + '% identical', hundred + '% identical',
message);
if (!ok && result && !isNode) {
// Get the right entry for this unit test and assertion, and
// replace the results with images
var entry = document.getElementById('qunit-test-output-' + id)
@ -179,14 +273,14 @@ function compareItem(actual, expected, message, options, properties) {
}
}
} else {
if (options && options.cloned)
if (options.cloned)
QUnit.notStrictEqual(actual.id, expected.id,
'not ' + message + '.id');
QUnit.strictEqual(actual.constructor, expected.constructor,
message + '.constructor');
// When item is cloned and has a name, the name will be versioned:
equals(actual.name,
options && options.cloned && expected.name
options.cloned && expected.name
? expected.name + ' 1' : expected.name,
message + '.name');
compareProperties(actual, expected, ['children', 'bounds', 'position',
@ -201,7 +295,7 @@ function compareItem(actual, expected, message, options, properties) {
'dashOffset', 'miterLimit', 'fontSize', 'font', 'leading',
'justification'], message + '.style', options);
}
}
};
// A list of comparator functions, based on `expected` type. See equals() for
// an explanation of how the type is determined.
@ -359,56 +453,3 @@ var comparators = {
message, options);
}
};
// A list of classes that should be identical after their owners were cloned.
var identicalAfterCloning = {
Gradient: true,
Symbol: true
};
function getFunctionMessage(func) {
var message = func.toString().match(
/^\s*function[^\{]*\{([\s\S]*)\}\s*$/)[1]
.replace(/ /g, '')
.replace(/^\s+|\s+$/g, '');
if (/^return /.test(message)) {
message = message
.replace(/^return /, '')
.replace(/;$/, '');
}
return message;
}
function test(testName, expected) {
return QUnit.test(testName, function() {
var project = new Project();
expected();
project.remove();
});
}
function asyncTest(testName, expected) {
return QUnit.asyncTest(testName, function() {
var project = new Project();
expected(function() {
project.remove();
QUnit.start();
});
});
}
// SVG
function createSVG(str, attrs) {
if (attrs) {
// Similar to SVGExport's createElement / setAttributes.
var node = document.createElementNS('http://www.w3.org/2000/svg', str);
for (var key in attrs)
node.setAttribute(key, attrs[key]);
return node;
} else {
return new window.DOMParser().parseFromString(
'<svg xmlns="http://www.w3.org/2000/svg">' + str + '</svg>',
'text/xml');
}
}

View file

@ -3,11 +3,10 @@
<head>
<title>Paper.js Tests</title>
<link rel="stylesheet" href="../node_modules/qunitjs/qunit/qunit.css">
<script type="text/javascript" src="../node_modules/qunitjs/qunit/qunit.js"></script>
<script type="text/javascript" src="../node_modules/resemblejs/resemble.js"></script>
<script type="text/javascript" src="js/helpers.js"></script>
<script type="text/javascript" src="../src/load.js"></script>
<script type="text/javascript" src="tests/load.js"></script>
<script src="../node_modules/qunitjs/qunit/qunit.js"></script>
<script src="../dist/paper-full.js"></script>
<script src="../node_modules/prepro/lib/browser.js"></script>
<script src="load.js"></script>
</head>
<body>
<h1 id="qunit-header">QUnit Test Suite</h1>

15
test/load.js Normal file
View file

@ -0,0 +1,15 @@
/*
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
* http://paperjs.org/
*
* Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
* http://scratchdisk.com/ & http://jonathanpuckey.com/
*
* Distributed under the MIT license. See LICENSE file for details.
*
* All rights reserved.
*/
/*#*/ include('helpers.js');
/*#*/ include('../node_modules/resemblejs/resemble.js', { namespace: 'resemble' });
/*#*/ include('tests/load.js');

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Color');
QUnit.module('Color');
test('Set named color', function() {
var path = new Path();
@ -222,6 +222,3 @@ test('Color#divide', function() {
var color = new Color(1, 1, 1);
equals(color.divide(4), new Color([0.25, 0.25, 0.25]));
});

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Compound Path');
QUnit.module('Compound Path');
test('moveTo / lineTo', function() {
var path = new CompoundPath();

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Curve');
QUnit.module('Curve');
test('Curve#getParameterOf()', function() {
// For issue #708:

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('CurveLocation');
QUnit.module('CurveLocation');
test('CurveLocation#offset', function() {
var path = new Path();

View file

@ -10,10 +10,10 @@
* All rights reserved.
*/
module('Emitter');
QUnit.module('Emitter');
test('on()', function() {
var emitter = new Base(Emitter),
var emitter = new Item(),
installed;
// fake event type registration
emitter._eventTypes = {mousemove: {install: function(){ installed = true;} } };
@ -37,7 +37,7 @@ test('on()', function() {
});
test('off()', function() {
var emitter = new Base(Emitter),
var emitter = new Item(),
uninstalled, called = 0,
handler = function () {called++},
handler2 = function () {};
@ -68,7 +68,7 @@ test('off()', function() {
});
test('emit()', function() {
var emitter = new Base(Emitter),
var emitter = new Item(),
called,
handler = function (e) {called = e};
// fake event type registration

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Group');
QUnit.module('Group');
test('new Group()', function() {
var group = new Group();

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('HitResult');
QUnit.module('HitResult');
test('Hit-testing options', function() {
var defaultOptions = {

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Item');
QUnit.module('Item');
test('copyTo(project)', function() {
var project = paper.project;

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Item Bounds');
QUnit.module('Item Bounds');
test('item.bounds caching', function() {
var circle = new Path.Circle(new Point(100, 100), 50);
@ -94,5 +94,5 @@ test('text.bounds', function() {
var text = new PointText(new Point(50, 100));
text.fillColor = 'black';
text.content = 'This is a test';
equals(text.bounds, new Rectangle(50, 89.2, 67, 14.4), 'text.bounds', { tolerance: 0.5 });
equals(text.bounds, new Rectangle(50, 89.2, 67, 14.4), 'text.bounds', { tolerance: 1 });
});

View file

@ -10,6 +10,8 @@
* All rights reserved.
*/
QUnit.module('Item Cloning');
function cloneAndCompare(item) {
var copy = item.clone();
equals(function() {

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Getting and Matching Items');
QUnit.module('Getting and Matching Items');
test('Item#getItems()', function() {
var group = new Group([new Path({ selected: true }), new Raster()]);
@ -72,14 +72,14 @@ test('Project#getItems()', function() {
className: 'Group'
});
equals(function() {
return matches.length == 1 && matches[0] === group
return matches.length == 1 && matches[0] === group;
}, true);
var matches = paper.project.getItems({
type: 'group'
});
equals(function() {
return matches.length == 1 && matches[0] === group
return matches.length == 1 && matches[0] === group;
}, true);
var raster = new Raster();
@ -87,7 +87,7 @@ test('Project#getItems()', function() {
class: Raster
});
equals(function() {
return matches.length == 1 && matches[0] === raster
return matches.length == 1 && matches[0] === raster;
}, true);
equals(function() {
@ -120,7 +120,7 @@ test('Project#getItems() with compare function', function() {
var items = paper.project.getItems({
opacity: function(value) {
return value < 1
return value < 1;
}
});
equals(function() {
@ -162,23 +162,26 @@ test('Project#getItems() with color', function() {
});
test('Project#getItems() with regex function', function() {
var decoyPath = new Path({
var layer = paper.project.activeLayer;
var stopPath = new Path({
name: 'stop'
});
var decoyPath2 = new Path({
var pausePath = new Path({
name: 'pause'
});
var path = new Path({
var startPath = new Path({
name: 'starting'
});
var items = paper.project.getItems({
name: /^start/g
});
// console.log(paper.project.activeLayer);
equals(function() {
return items.length == 1 && items[0] == path;
return items.length == 1 && items[0] == startPath;
}, true);
equals(function() {

View file

@ -10,6 +10,8 @@
* All rights reserved.
*/
QUnit.module('Item Order');
test('Item Order', function() {
var line = new Path();
line.add([0, 0], [100, 100]);

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('JSON');
QUnit.module('JSON');
function testExportImportJSON(project) {
// Use higher precision than in comparissons, for bounds

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Layer');
QUnit.module('Layer');
test('previousSibling / nextSibling', function() {
var project = paper.project;

View file

@ -10,7 +10,8 @@
* All rights reserved.
*/
module('Matrix');
QUnit.module('Matrix');
test('Decomposition: rotate()', function() {
function testAngle(a, ea) {
var m = new Matrix().rotate(a),

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Path');
QUnit.module('Path');
test('path.join(path)', function() {
var path = new Path();

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('PathItem Contains');
QUnit.module('PathItem Contains');
function testPoint(item, point, inside, message) {
equals(item.contains(point), inside, message || ('The point ' + point

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Path Boolean Operations');
QUnit.module('Path Boolean Operations');
function createPath(str) {
var ctor = (str.match(/z/gi) || []).length > 1 ? CompoundPath : Path;
@ -30,7 +30,7 @@ function compareBoolean(actual, expected, message, options) {
strokeColor: 'black',
fillColor: expected.closed ? 'yellow' : null
};
equals(actual, expected, message, options || { rasterize: true });
equals(actual, expected, message, Base.set({ rasterize: true }, options));
}
test('#541', function() {
@ -884,7 +884,8 @@ test('Isolated edge-cases from @iconexperience\'s boolean-test suite', function(
closed: true
});
compareBoolean(function() { return path1.unite(); },
'M428.65987,123.24313c0,0 18.24445,159.97772 20.21157,166.76806c-3.05664,-6.18082 -73.53131,-139.25432 -73.53131,-139.25432z M448.97323,290.23336c0,0 0,0 0,0c0.22704,0.04317 -0.06896,-0.00471 0,0c-0.02659,-0.00506 -0.06063,-0.08007 -0.1018,-0.22217c0.07286,0.14733 0.10741,0.22256 0.1018,0.22217z');
'M428.65987,123.24313c0,0 18.24445,159.97772 20.21157,166.76806c-3.05664,-6.18082 -73.53131,-139.25432 -73.53131,-139.25432z M448.97323,290.23336c0,0 0,0 0,0c0.22704,0.04317 -0.06896,-0.00471 0,0c-0.02659,-0.00506 -0.06063,-0.08007 -0.1018,-0.22217c0.07286,0.14733 0.10741,0.22256 0.1018,0.22217z',
null, { tolerance: 1e-3 });
// #784#issuecomment-168605018
var path1 = new CompoundPath();

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Path Bounds');
QUnit.module('Path Bounds');
test('path.bounds', function() {
var path = new Path([

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Path Curves');
QUnit.module('Path Curves');
test('path.curves synchronisation', function() {
var path = new Path();

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Path Drawing Commands');
QUnit.module('Path Drawing Commands');
test('path.lineTo(point);', function() {
var path = new Path();

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Path Intersections');
QUnit.module('Path Intersections');
function testIntersection(intersections, results) {
equals(intersections.length, results.length, 'intersections.length');

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Path Length');
QUnit.module('Path Length');
test('path.length', function() {
var path = new Path([

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Predefined Path Shapes');
QUnit.module('Predefined Path Shapes');
test('new Path.Rectangle([50, 50], [100, 100])', function() {
var path = new Path.Rectangle([50, 50], [100, 100]);

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Symbol & Placed Symbol');
QUnit.module('Symbol & Placed Symbol');
test('placedSymbol bounds', function() {
var path = new Path.Circle([50, 50], 50);

View file

@ -10,7 +10,8 @@
* All rights reserved.
*/
module('Point');
QUnit.module('Point');
test('new Point(10, 20)', function() {
var point = new Point(10, 20);
equals(point.x, 10, 'point.x');
@ -44,8 +45,6 @@ test('new Point({ angle: 45, length: 20})', function() {
equals(point, new Point(15.32089, 12.85575));
});
module('Point vector operations');
test('normalize(length)', function() {
var point = new Point(0, 10).normalize(20);
equals(point, new Point(0, 20));

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Project');
QUnit.module('Project');
test('activate()', function() {
var project = new Project();

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Raster');
QUnit.module('Raster');
test('Create a raster without a source and check its size', function() {
var raster = new Raster();
@ -23,23 +23,34 @@ test('Create a raster without a source and set its size', function() {
equals(raster.size, new Size(640, 480), true);
});
asyncTest('Create a raster from a url', function(callback) {
test('Create a raster from a url', function(assert) {
var done = assert.async();
var raster = new Raster('assets/paper-js.gif');
raster.onLoad = function() {
equals(raster.size, new Size(146, 146), true);
callback();
done();
};
raster.onError = function(event) {
pushFailure(event.event);
done();
};
});
asyncTest('Create a raster from a data url', function(callback) {
test('Create a raster from a data url', function(assert) {
var done = assert.async();
var raster = new Raster('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABlJREFUeNpi+s/AwPCfgYmR4f9/hv8AAQYAHiAFAS8Lwy8AAAAASUVORK5CYII=');
raster.onLoad = function() {
equals(raster.size, new Size(2, 2), true);
callback();
done();
};
raster.onError = function(event) {
pushFailure(event.event);
done();
};
});
asyncTest('Create a raster from a dom image', function(callback) {
test('Create a raster from a dom image', function(assert) {
var done = assert.async();
var img = document.createElement('img');
img.src = 'assets/paper-js.gif';
document.body.appendChild(img);
@ -48,19 +59,19 @@ asyncTest('Create a raster from a dom image', function(callback) {
var raster = new Raster(img);
equals(raster.size, new Size(146, 146), true);
document.body.removeChild(img);
callback();
done();
}
});
});
test('Create a raster from a canvas', function(callback) {
var canvas = CanvasProvider.getCanvas(30, 20);
test('Create a raster from a canvas', function() {
var canvas = paper.createCanvas(30, 20);
var raster = new Raster(canvas);
equals(raster.size, new Size(30, 20), true);
CanvasProvider.release(canvas);
});
asyncTest('Create a raster from a dom id', function(callback) {
test('Create a raster from a dom id', function(assert) {
var done = assert.async();
var img = document.createElement('img');
img.src = 'assets/paper-js.gif';
img.id = 'testimage';
@ -70,12 +81,13 @@ asyncTest('Create a raster from a dom id', function(callback) {
var raster = new Raster('testimage');
equals(raster.size, new Size(146, 146), true);
document.body.removeChild(img);
callback();
done();
}
});
});
asyncTest('Raster#getPixel / setPixel', function(callback) {
test('Raster#getPixel / setPixel', function(assert) {
var done = assert.async();
var raster = new Raster('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABlJREFUeNpi+s/AwPCfgYmR4f9/hv8AAQYAHiAFAS8Lwy8AAAAASUVORK5CYII=');
raster.onLoad = function() {
equals(raster.getPixel(0, 0), new Color(1, 0, 0, 1));
@ -86,12 +98,17 @@ asyncTest('Raster#getPixel / setPixel', function(callback) {
// Alpha
var color = new Color(1, 1, 0, 0.50196);
raster.setPixel([0, 0], color);
equals(raster.getPixel([0, 0]), color, 'alpha');
callback();
equals(raster.getPixel([0, 0]), color, 'alpha', { tolerance: 1e-2 });
done();
};
raster.onError = function(event) {
pushFailure(event.event);
done();
};
});
asyncTest('Raster#getSubCanvas', function(callback) {
test('Raster#getSubCanvas', function(assert) {
var done = assert.async();
var raster = new Raster('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABlJREFUeNpi+s/AwPCfgYmR4f9/hv8AAQYAHiAFAS8Lwy8AAAAASUVORK5CYII=');
raster.onLoad = function() {
var canvas = raster.getSubCanvas(new Rectangle({
@ -114,7 +131,11 @@ asyncTest('Raster#getSubCanvas', function(callback) {
equals(function() {
return Base.equals(Array.prototype.slice.call(ctx.getImageData(0, 0, 1, 2).data), expected);
}, true);
callback();
done();
};
raster.onError = function(event) {
pushFailure(event.event);
done();
};
});
@ -132,7 +153,7 @@ test('Raster#getAverageColor(path)', function() {
var raster = paper.project.activeLayer.rasterize(72);
circle.scale(0.8);
equals(raster.getAverageColor(circle), circle.fillColor, null,
{ tolerance: 10e-4 });
{ tolerance: 1e-3 });
});
test('Raster#getAverageColor(path) with compound path', function() {
@ -155,5 +176,5 @@ test('Raster#getAverageColor(path) with compound path', function() {
path.scale(0.8);
path2.scale(1.2);
equals(raster.getAverageColor(compoundPath), new Color(1, 0, 0), null,
{ tolerance: 10e-4 });
{ tolerance: 1e-3 });
});

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Rectangle');
QUnit.module('Rectangle');
test('new Rectangle(new Point(10, 20), new Size(30, 40));', function() {
var rect = new Rectangle(new Point(10, 20), new Size(30, 40));

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('SVGExport');
QUnit.module('SVGExport');
test('Export SVG line', function() {
var attrs = {

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('SVGImport');
QUnit.module('SVGImport');
test('Import SVG line', function() {
var attrs = {
@ -59,7 +59,7 @@ test('Import SVG ellipse', function() {
cy: 80,
rx: 100,
ry: 50
}
};
var imported = paper.project.importSVG(createSVG('ellipse', attrs),
{ expandShapes: true });
var path = new Path.Ellipse({
@ -74,7 +74,7 @@ test('Import SVG circle', function() {
cx: 100,
cy: 80,
r: 50
}
};
var imported = paper.project.importSVG(createSVG('circle', attrs),
{ expandShapes: true });
var path = new Path.Circle({
@ -115,7 +115,8 @@ test('Import SVG polyline', function() {
});
test('Import complex CompoundPath and clone', function() {
var svg = createSVG('<path id="path" fill="red" d="M4,14h20v-2H4V14z M15,26h7v-2h-7V26z M15,22h9v-2h-9V22z M15,18h9v-2h-9V18z M4,26h9V16H4V26z M28,10V6H0v22c0,0,0,4,4,4 h25c0,0,3-0.062,3-4V10H28z M4,30c-2,0-2-2-2-2V8h24v20c0,0.921,0.284,1.558,0.676,2H4z"/>;');
var item = paper.project.importSVG(svg.getElementById('path'));
var svg = createSVG('<path fill="red" d="M4,14h20v-2H4V14z M15,26h7v-2h-7V26z M15,22h9v-2h-9V22z M15,18h9v-2h-9V18z M4,26h9V16H4V26z M28,10V6H0v22c0,0,0,4,4,4 h25c0,0,3-0.062,3-4V10H28z M4,30c-2,0-2-2-2-2V8h24v20c0,0.921,0.284,1.558,0.676,2H4z"/>;');
var item = paper.project.importSVG(svg.firstChild);
equals(item.clone(), item, null, { cloned: true });
return;
});

View file

@ -10,7 +10,8 @@
* All rights reserved.
*/
module('Segment');
QUnit.module('Segment');
test('new Segment(point)', function() {
var segment = new Segment(new Point(10, 10));
equals(segment.toString(), '{ point: { x: 10, y: 10 } }');

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Shape');
QUnit.module('Shape');
test('shape.toPath().toShape()', function() {
var shapes = {

View file

@ -10,7 +10,8 @@
* All rights reserved.
*/
module('Size');
QUnit.module('Size');
test('new Size(10, 20)', function() {
var size = new Size(10, 20);
equals(size.toString(), '{ width: 10, height: 20 }');

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('Style');
QUnit.module('Style');
test('style defaults', function() {
var path = new Path();

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
module('TextItem');
QUnit.module('TextItem');
test('PointText', function() {
var text = new PointText({