mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2024-12-29 09:22:22 -05:00
Start cleaning up unit tests by introducing new class/type-based comparators lookup table.
This commit is contained in:
parent
28538d8a43
commit
e95e17826e
7 changed files with 122 additions and 106 deletions
|
@ -27,42 +27,70 @@ QUnit.jsDump.setParser('object', function (obj, stack) {
|
|||
: objectParser).call(this, obj, stack);
|
||||
});
|
||||
|
||||
function getFunctionBody(func) {
|
||||
return func.toString().match(
|
||||
var comparators = {
|
||||
Number: function(actual, expected, message, options) {
|
||||
// Compare with a default tolerance of Numerical.TOLERANCE:
|
||||
var ok = Math.abs(actual - expected)
|
||||
<= Base.pick(options && options.tolerance, Numerical.TOLERANCE);
|
||||
QUnit.push(ok, ok ? expected : actual, expected, message);
|
||||
},
|
||||
|
||||
Array: function(actual, expected, message, options) {
|
||||
equals(actual.length, expected.length, (message || '') + ' length',
|
||||
options);
|
||||
for (var i = 0, l = actual.length; i < l; i++) {
|
||||
equals(actual[i], expected[i], (message || '') + ' [' + i + ']',
|
||||
options);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function getClass(object) {
|
||||
return typeof object === 'number' && 'Number'
|
||||
|| Array.isArray(object) && 'Array'
|
||||
|| object && object._class;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Override equals to convert functions to message and execute them as tests()
|
||||
function equals(actual, expected, message, tolerance) {
|
||||
function equals(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') {
|
||||
if (!message) {
|
||||
message = getFunctionBody(actual);
|
||||
if (/^return /.test(message)) {
|
||||
message = message
|
||||
.replace(/^return /, '')
|
||||
.replace(/;$/, '');
|
||||
}
|
||||
}
|
||||
if (!message)
|
||||
message = getFunctionMessage(actual);
|
||||
actual = actual();
|
||||
}
|
||||
if (typeof expected === 'number') {
|
||||
// Compare with a default tolerance of Numerical.TOLERANCE:
|
||||
var ok = Math.abs(actual - expected)
|
||||
<= Base.pick(tolerance, Numerical.TOLERANCE);
|
||||
return QUnit.push(ok, ok ? expected : actual, expected, message);
|
||||
} else if (actual && actual.equals) {
|
||||
// Support calling of #equals() on the actual or expected value, and
|
||||
// automatically convert displayed values to strings.
|
||||
return QUnit.push(actual.equals(expected), actual, expected, message);
|
||||
} else if (expected && expected.equals) {
|
||||
return QUnit.push(expected.equals(actual), actual, expected, message);
|
||||
if (actual != null) {
|
||||
var comparator = comparators[getClass(actual)];
|
||||
if (comparator)
|
||||
return comparator(actual, expected, message, options);
|
||||
// Support calling of #equals() on the actual or expected value.
|
||||
if (actual.equals)
|
||||
return QUnit.push(actual.equals(expected),
|
||||
actual, expected, message);
|
||||
}
|
||||
// Let's be strict
|
||||
return strictEqual(actual, expected, message);
|
||||
if (expected != null) {
|
||||
var comparator = comparators[getClass(expected)];
|
||||
if (comparator)
|
||||
return comparator(actual, expected, message, options);
|
||||
if (expected.equals)
|
||||
return QUnit.push(expected.equals(actual),
|
||||
actual, expected, message);
|
||||
}
|
||||
QUnit.push(actual === expected, actual, expected, message);
|
||||
}
|
||||
|
||||
function test(testName, expected) {
|
||||
|
@ -83,42 +111,36 @@ function asyncTest(testName, expected) {
|
|||
});
|
||||
}
|
||||
|
||||
function compareArrays(array1, array2, message, tolerance) {
|
||||
equals(array1.length, array2.length, (message || '') + ' length');
|
||||
for (var i = 0, l = array1.length; i < l; i++) {
|
||||
equals(array1[i], array2[i], (message || '') + ' [' + i + ']',
|
||||
tolerance);
|
||||
}
|
||||
function comparePoints(point1, point2, message, options) {
|
||||
equals(point1.x, point2.x, (message || '') + ' x', options);
|
||||
equals(point1.y, point2.y, (message || '') + ' y', options);
|
||||
}
|
||||
|
||||
function comparePoints(point1, point2, message, tolerance) {
|
||||
equals(point1.x, point2.x, (message || '') + ' x', tolerance);
|
||||
equals(point1.y, point2.y, (message || '') + ' y', tolerance);
|
||||
function compareSize(size1, size2, message, options) {
|
||||
equals(size1.width, size2.width, (message || '') + ' width', options);
|
||||
equals(size1.height, size2.height, (message || '') + ' height', options);
|
||||
}
|
||||
|
||||
function compareSize(size1, size2, message, tolerance) {
|
||||
equals(size1.width, size2.width, (message || '') + ' width', tolerance);
|
||||
equals(size1.height, size2.height, (message || '') + ' height', tolerance);
|
||||
function compareRectangles(rect1, rect2, message, options) {
|
||||
comparePoints(rect1, rect2, message, options);
|
||||
compareSize(rect1, rect2, message, options);
|
||||
}
|
||||
|
||||
function compareRectangles(rect1, rect2, message, tolerance) {
|
||||
comparePoints(rect1, rect2, message, tolerance);
|
||||
compareSize(rect1, rect2, message, tolerance);
|
||||
}
|
||||
|
||||
function compareColors(color1, color2, message, tolerance) {
|
||||
function compareColors(color1, color2, message, options) {
|
||||
color1 = color1 && new Color(color1);
|
||||
color2 = color2 && new Color(color2);
|
||||
if (color1 && color2) {
|
||||
equals(color1.type, color2.type, (message || '') + ' type');
|
||||
compareArrays(color1.components, color2.components,
|
||||
(message || '') + ' components', tolerance);
|
||||
equals(color1.type, color2.type,
|
||||
(message || '') + ' type', options);
|
||||
equals(color1.components, color2.components,
|
||||
(message || '') + ' components', options);
|
||||
} else {
|
||||
equals(color1, color2, message, tolerance);
|
||||
equals(color1, color2, message, options);
|
||||
}
|
||||
}
|
||||
|
||||
function compareStyles(style, style2, checkIdentity) {
|
||||
function compareStyles(style, style2, options) {
|
||||
var checkIdentity = options && options.checkIdentity;
|
||||
if (checkIdentity) {
|
||||
equals(function() {
|
||||
return style !== style2;
|
||||
|
@ -150,38 +172,30 @@ function compareStyles(style, style2, checkIdentity) {
|
|||
}
|
||||
});
|
||||
|
||||
compareObjects('Style', ['strokeCap', 'strokeJoin', 'dashArray',
|
||||
'dashOffset', 'miterLimit', 'strokeOverprint', 'fillOverprint',
|
||||
compareObjects(['strokeCap', 'strokeJoin', 'dashArray', 'dashOffset',
|
||||
'miterLimit', 'strokeOverprint', 'fillOverprint',
|
||||
'fontSize', 'font', 'leading', 'justification'],
|
||||
style, style2, checkIdentity);
|
||||
style, style2, 'Compare Style', options);
|
||||
}
|
||||
|
||||
function compareObjects(name, keys, obj, obj2, checkIdentity) {
|
||||
if (checkIdentity) {
|
||||
function compareObjects(keys, obj, obj2, message, options) {
|
||||
if (options && options.checkIdentity) {
|
||||
equals(function() {
|
||||
return obj !== obj2;
|
||||
}, true);
|
||||
}
|
||||
Base.each(keys, function(key) {
|
||||
var val = obj[key], val2 = obj2[key],
|
||||
message = 'Compare ' + name + '#' + key;
|
||||
if (typeof val === 'number') {
|
||||
equals(val, val2, message);
|
||||
} else if (Array.isArray(val)) {
|
||||
compareArrays(val, val2, message);
|
||||
} else {
|
||||
equals(val, val2, message);
|
||||
}
|
||||
equals(obj[key], obj2[key], message + '#' + key, options);
|
||||
});
|
||||
}
|
||||
|
||||
function compareSegmentPoints(segmentPoint, segmentPoint2, checkIdentity) {
|
||||
compareObjects('SegmentPoint', ['x', 'y', 'selected'],
|
||||
segmentPoint, segmentPoint2, checkIdentity);
|
||||
function compareSegmentPoints(segmentPoint, segmentPoint2, options) {
|
||||
compareObjects(['x', 'y', 'selected'], segmentPoint, segmentPoint2,
|
||||
'Compare SegmentPoint', options);
|
||||
}
|
||||
|
||||
function compareSegments(segment, segment2, checkIdentity) {
|
||||
if (checkIdentity) {
|
||||
function compareSegments(segment, segment2, options) {
|
||||
if (options.checkIdentity) {
|
||||
equals(function() {
|
||||
return segment !== segment2;
|
||||
}, true);
|
||||
|
@ -194,7 +208,8 @@ function compareSegments(segment, segment2, checkIdentity) {
|
|||
});
|
||||
}
|
||||
|
||||
function compareSegmentLists(segmentList, segmentList2, checkIdentity) {
|
||||
function compareSegmentLists(segmentList, segmentList2, options) {
|
||||
var checkIdentity = options && options.checkIdentity;
|
||||
if (checkIdentity) {
|
||||
equals(function() {
|
||||
return segmentList !== segmentList2;
|
||||
|
@ -206,12 +221,13 @@ function compareSegmentLists(segmentList, segmentList2, checkIdentity) {
|
|||
for (var i = 0, l = segmentList.length; i < l; i++) {
|
||||
var segment = segmentList[i],
|
||||
segment2 = segmentList2[i];
|
||||
compareSegments(segment, segment2, checkIdentity);
|
||||
compareSegments(segment, segment2, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function compareItems(item, item2, cloned, checkIdentity, dontShareProject) {
|
||||
function compareItems(item, item2, options) {
|
||||
var checkIdentity = options && options.checkIdentity;
|
||||
if (checkIdentity) {
|
||||
equals(function() {
|
||||
return item !== item2;
|
||||
|
@ -232,7 +248,7 @@ function compareItems(item, item2, cloned, checkIdentity, dontShareProject) {
|
|||
var value = item[key];
|
||||
// When item was cloned and had a name, the name will be versioned
|
||||
equals(
|
||||
key == 'name' && cloned && value
|
||||
key == 'name' && options && options.cloned && value
|
||||
? value + ' 1'
|
||||
: value,
|
||||
item2[key],
|
||||
|
@ -279,7 +295,7 @@ function compareItems(item, item2, cloned, checkIdentity, dontShareProject) {
|
|||
equals(item[key], item2[key], 'Compare Path#' + key);
|
||||
}
|
||||
equals(item.length, item2.length, 'Compare Path#length');
|
||||
compareSegmentLists(item.segments, item2.segments, checkIdentity);
|
||||
compareSegmentLists(item.segments, item2.segments, options);
|
||||
}
|
||||
|
||||
// Shape specific
|
||||
|
@ -301,7 +317,7 @@ function compareItems(item, item2, cloned, checkIdentity, dontShareProject) {
|
|||
// Layer specific
|
||||
if (item instanceof Layer) {
|
||||
equals(function() {
|
||||
return dontShareProject
|
||||
return options && options.dontShareProject
|
||||
? item.project != item2.project
|
||||
: item.project == item2.project;
|
||||
}, true);
|
||||
|
@ -309,9 +325,9 @@ function compareItems(item, item2, cloned, checkIdentity, dontShareProject) {
|
|||
|
||||
// PlacedSymbol specific
|
||||
if (item instanceof PlacedSymbol) {
|
||||
if (dontShareProject) {
|
||||
if (options.dontShareProject) {
|
||||
compareItems(item.symbol.definition, item2.symbol.definition,
|
||||
cloned, checkIdentity, dontShareProject,
|
||||
options,
|
||||
'Compare Symbol#definition');
|
||||
} else {
|
||||
equals(function() {
|
||||
|
@ -331,7 +347,7 @@ function compareItems(item, item2, cloned, checkIdentity, dontShareProject) {
|
|||
'Compare Raster#ppi');
|
||||
|
||||
equals(item.source, item2.source, 'Compare Raster#source');
|
||||
if (checkIdentity) {
|
||||
if (options.checkIdentity) {
|
||||
equals(item.image, item2.image, 'Compare Raster#image');
|
||||
}
|
||||
equals(item.size.toString(), item2.size.toString(),
|
||||
|
@ -347,7 +363,7 @@ function compareItems(item, item2, cloned, checkIdentity, dontShareProject) {
|
|||
|
||||
// PointText specific:
|
||||
if (item instanceof PointText) {
|
||||
if (checkIdentity) {
|
||||
if (options.checkIdentity) {
|
||||
equals(function() {
|
||||
return item.point !== item2.point;
|
||||
}, true);
|
||||
|
@ -358,7 +374,7 @@ function compareItems(item, item2, cloned, checkIdentity, dontShareProject) {
|
|||
|
||||
if (item.style) {
|
||||
// Style
|
||||
compareStyles(item.style, item2.style, checkIdentity);
|
||||
compareStyles(item.style, item2.style, options);
|
||||
}
|
||||
|
||||
// Check length of children and recursively compare them:
|
||||
|
@ -367,8 +383,7 @@ function compareItems(item, item2, cloned, checkIdentity, dontShareProject) {
|
|||
return item.children.length == item2.children.length;
|
||||
}, true);
|
||||
for (var i = 0, l = item.children.length; i < l; i++) {
|
||||
compareItems(item.children[i], item2.children[i], cloned,
|
||||
checkIdentity, dontShareProject);
|
||||
compareItems(item.children[i], item2.children[i], options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -381,7 +396,7 @@ function compareProjects(project, project2) {
|
|||
for (var i = 0, l = project.symbols.length; i < l; i++) {
|
||||
var definition1 = project.symbols[i].definition;
|
||||
var definition2 = project2.symbols[i].definition;
|
||||
compareItems(definition1, definition2, false, false, true,
|
||||
compareItems(definition1, definition2, { dontShareProject: true },
|
||||
'Compare Symbol#definition');
|
||||
}
|
||||
|
||||
|
@ -390,7 +405,8 @@ function compareProjects(project, project2) {
|
|||
return project.layers.length == project2.layers.length;
|
||||
}, true);
|
||||
for (var i = 0, l = project.layers.length; i < l; i++) {
|
||||
compareItems(project.layers[i], project2.layers[i], false, false, true);
|
||||
compareItems(project.layers[i], project2.layers[i],
|
||||
{ dontShareProject: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,5 +71,5 @@ test('text.bounds', function() {
|
|||
var text = new PointText(new Point(50, 100));
|
||||
text.fillColor = 'black';
|
||||
text.content = 'This is a test';
|
||||
compareRectangles(text.bounds, { x: 50, y: 89.2, width: 67, height: 14.4 } , 'text.bounds', 0.5);
|
||||
compareRectangles(text.bounds, { x: 50, y: 89.2, width: 67, height: 14.4 } , 'text.bounds', { tolerance: 0.5 });
|
||||
});
|
||||
|
|
|
@ -24,7 +24,7 @@ function cloneAndCompare(item) {
|
|||
return copy.parent.children[copy.name] == copy;
|
||||
}, true);
|
||||
}
|
||||
compareItems(item, copy, true, true);
|
||||
compareItems(item, copy, { cloned: true, checkIdentity: true });
|
||||
// Remove the cloned item to restore the document:
|
||||
copy.remove();
|
||||
}
|
||||
|
|
|
@ -64,30 +64,30 @@ test('Item#insertAbove(item) / Item#insertBelow(item)', function() {
|
|||
item1 = new Group();
|
||||
item2 = new Group();
|
||||
command();
|
||||
var str = getFunctionBody(command);
|
||||
var str = getFunctionMessage(command);
|
||||
equals(item0.index, indexes[0], str + ': item0.index');
|
||||
equals(item1.index, indexes[1], str + ': item1.index');
|
||||
equals(item2.index, indexes[2], str + ': item2.index');
|
||||
}
|
||||
|
||||
testMove(function() { item0.insertBelow(item0) }, [0,1,2]);
|
||||
testMove(function() { item0.insertBelow(item1) }, [0,1,2]);
|
||||
testMove(function() { item0.insertBelow(item2) }, [1,0,2]);
|
||||
testMove(function() { item1.insertBelow(item0) }, [1,0,2]);
|
||||
testMove(function() { item1.insertBelow(item1) }, [0,1,2]);
|
||||
testMove(function() { item1.insertBelow(item2) }, [0,1,2]);
|
||||
testMove(function() { item0.insertBelow(item0); }, [0,1,2]);
|
||||
testMove(function() { item0.insertBelow(item1); }, [0,1,2]);
|
||||
testMove(function() { item0.insertBelow(item2); }, [1,0,2]);
|
||||
testMove(function() { item1.insertBelow(item0); }, [1,0,2]);
|
||||
testMove(function() { item1.insertBelow(item1); }, [0,1,2]);
|
||||
testMove(function() { item1.insertBelow(item2); }, [0,1,2]);
|
||||
|
||||
testMove(function() { item2.insertBelow(item0) }, [1,2,0]);
|
||||
testMove(function() { item2.insertBelow(item1) }, [0,2,1]);
|
||||
testMove(function() { item2.insertBelow(item2) }, [0,1,2]);
|
||||
testMove(function() { item2.insertBelow(item0); }, [1,2,0]);
|
||||
testMove(function() { item2.insertBelow(item1); }, [0,2,1]);
|
||||
testMove(function() { item2.insertBelow(item2); }, [0,1,2]);
|
||||
|
||||
testMove(function() { item0.insertAbove(item0) }, [0,1,2]);
|
||||
testMove(function() { item0.insertAbove(item1) }, [1,0,2]);
|
||||
testMove(function() { item0.insertAbove(item2) }, [2,0,1]);
|
||||
testMove(function() { item1.insertAbove(item0) }, [0,1,2]);
|
||||
testMove(function() { item1.insertAbove(item1) }, [0,1,2]);
|
||||
testMove(function() { item1.insertAbove(item2) }, [0,2,1]);
|
||||
testMove(function() { item2.insertAbove(item0) }, [0,2,1]);
|
||||
testMove(function() { item2.insertAbove(item1) }, [0,1,2]);
|
||||
testMove(function() { item2.insertAbove(item2) }, [0,1,2]);
|
||||
testMove(function() { item0.insertAbove(item0); }, [0,1,2]);
|
||||
testMove(function() { item0.insertAbove(item1); }, [1,0,2]);
|
||||
testMove(function() { item0.insertAbove(item2); }, [2,0,1]);
|
||||
testMove(function() { item1.insertAbove(item0); }, [0,1,2]);
|
||||
testMove(function() { item1.insertAbove(item1); }, [0,1,2]);
|
||||
testMove(function() { item1.insertAbove(item2); }, [0,2,1]);
|
||||
testMove(function() { item2.insertAbove(item0); }, [0,2,1]);
|
||||
testMove(function() { item2.insertAbove(item1); }, [0,1,2]);
|
||||
testMove(function() { item2.insertAbove(item2); }, [0,1,2]);
|
||||
});
|
||||
|
|
|
@ -131,7 +131,7 @@ test('Raster#getAverageColor(path)', function() {
|
|||
});
|
||||
var raster = paper.project.activeLayer.rasterize(72);
|
||||
circle.scale(0.9);
|
||||
compareColors(raster.getAverageColor(circle), circle.fillColor, null, 3);
|
||||
compareColors(raster.getAverageColor(circle), circle.fillColor);
|
||||
});
|
||||
|
||||
test('Raster#getAverageColor(path) with compound path', function() {
|
||||
|
@ -153,5 +153,5 @@ test('Raster#getAverageColor(path) with compound path', function() {
|
|||
var raster = paper.project.activeLayer.rasterize(72);
|
||||
path.scale(0.9);
|
||||
path2.scale(1.1);
|
||||
compareColors(raster.getAverageColor(compoundPath), new Color(1, 0, 0), null, 3);
|
||||
compareColors(raster.getAverageColor(compoundPath), new Color(1, 0, 0), null, { tolerance: 10e-4 });
|
||||
});
|
||||
|
|
|
@ -15,7 +15,7 @@ module('SVGImport');
|
|||
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'));
|
||||
compareItems(item, item.clone(), true, true);
|
||||
compareItems(item, item.clone(), { cloned: true, checkIdentity: true });
|
||||
});
|
||||
|
||||
test('make an svg line', function() {
|
||||
|
|
|
@ -22,7 +22,7 @@ test('PointText', function() {
|
|||
compareColors(text.fillColor, new Color(0, 0, 0), 'text.fillColor should be black by default');
|
||||
comparePoints(text.point, { x: 100, y: 100 }, 'text.point');
|
||||
comparePoints(text.bounds.point, { x: 100, y: 87.4 }, 'text.bounds.point');
|
||||
compareSize(text.bounds.size, { width: 77, height: 16.8 }, 'text.bounds.size', 1.0);
|
||||
compareSize(text.bounds.size, { width: 77, height: 16.8 }, 'text.bounds.size', { tolerance: 1.0 });
|
||||
equals(function() {
|
||||
return text.hitTest(text.bounds.center) != null;
|
||||
}, true);
|
||||
|
|
Loading…
Reference in a new issue