mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2024-12-29 09:22:22 -05:00
Implement unit test comparator for Item & co + Project, and further improve new comparator code.
This commit is contained in:
parent
1de750bc77
commit
644fb71dc1
4 changed files with 132 additions and 168 deletions
|
@ -27,6 +27,34 @@ QUnit.jsDump.setParser('object', function (obj, stack) {
|
|||
: objectParser).call(this, obj, stack);
|
||||
});
|
||||
|
||||
function compareProperties(actual, expected, properties, message, options) {
|
||||
Base.each(properties, function(key) {
|
||||
equals(actual[key], expected[key], message + '.' + key, options);
|
||||
});
|
||||
}
|
||||
|
||||
function compareItem(actual, expected, message, options, properties) {
|
||||
if (options && options.cloned)
|
||||
QUnit.notStrictEqual(actual.id, 'not ' + expected.id, message + '.id');
|
||||
QUnit.strictEqual(actual.constructor, expected.constructor,
|
||||
message + '.constructor');
|
||||
// When item was cloned and had a name, the name will be versioned
|
||||
equals(options && options.cloned && actual.name ? actual.name + ' 1'
|
||||
: actual.name, expected.name,
|
||||
message + '.name');
|
||||
compareProperties(actual, expected, ['children', 'bounds', 'position',
|
||||
'matrix', 'data', 'opacity', 'locked', 'visible', 'blendMode',
|
||||
'selected', 'fullySelected', 'clipMask', 'guide'],
|
||||
message, options);
|
||||
if (properties)
|
||||
compareProperties(actual, expected, properties, message, options);
|
||||
// Style
|
||||
compareProperties(actual.style, expected.style, ['fillColor', 'strokeColor',
|
||||
'strokeCap', 'strokeJoin', 'dashArray', 'dashOffset', 'miterLimit',
|
||||
'fontSize', 'font', 'leading', 'justification'],
|
||||
message + '.style', options);
|
||||
}
|
||||
|
||||
var comparators = {
|
||||
Null: QUnit.strictEqual,
|
||||
Undefined: QUnit.strictEqual,
|
||||
|
@ -48,26 +76,23 @@ var comparators = {
|
|||
},
|
||||
|
||||
Array: function(actual, expected, message, options) {
|
||||
QUnit.strictEqual(actual.length, expected.length,
|
||||
(message || '') + ' length');
|
||||
QUnit.strictEqual(actual.length, expected.length, message + '.length');
|
||||
for (var i = 0, l = actual.length; i < l; i++) {
|
||||
equals(actual[i], expected[i], (message || '') + ' [' + i + ']',
|
||||
equals(actual[i], expected[i], (message || '') + '[' + i + ']',
|
||||
options);
|
||||
}
|
||||
},
|
||||
|
||||
Point: function(actual, expected, message, options) {
|
||||
comparators.Number(actual.x, expected.x, (message || '') + ' x',
|
||||
options);
|
||||
comparators.Number(actual.y, expected.y, (message || '') + ' y',
|
||||
options);
|
||||
comparators.Number(actual.x, expected.x, message + '.x', options);
|
||||
comparators.Number(actual.y, expected.y, message + '.y', options);
|
||||
},
|
||||
|
||||
Size: function(actual, expected, message, options) {
|
||||
comparators.Number(actual.width, expected.width,
|
||||
(message || '') + ' width', options);
|
||||
comparators.Number(actual.height, expected.height,
|
||||
(message || '') + ' height', options);
|
||||
comparators.Number(actual.width, expected.width, message + '.width',
|
||||
options);
|
||||
comparators.Number(actual.height, expected.height, message + '.height',
|
||||
options);
|
||||
},
|
||||
|
||||
Rectangle: function(actual, expected, message, options) {
|
||||
|
@ -81,20 +106,24 @@ var comparators = {
|
|||
|
||||
Color: function(actual, expected, message, options) {
|
||||
if (actual && expected) {
|
||||
equals(actual.type, expected.type,
|
||||
(message || '') + ' type', options);
|
||||
equals(actual.type, expected.type, message + '.type', options);
|
||||
// NOTE: This also compares gradients, with identity checks and all.
|
||||
equals(actual.components, expected.components,
|
||||
(message || '') + ' components', options);
|
||||
message + '.components', options);
|
||||
} else {
|
||||
equals(actual, expected, message, options);
|
||||
QUnit.strictEqual(actual, expected, message);
|
||||
}
|
||||
},
|
||||
|
||||
Symbol: function(actual, expected, message, options) {
|
||||
equals(actual.definition, expected.definition, message + '.definition',
|
||||
options);
|
||||
},
|
||||
|
||||
Segment: function(actual, expected, message, options) {
|
||||
Base.each(['handleIn', 'handleOut', 'point', 'selected'],
|
||||
function(key) {
|
||||
equals(actual[key], expected[key], (message || '') + ' ' + key);
|
||||
equals(actual[key], expected[key], message + '.' + key);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
@ -102,11 +131,67 @@ var comparators = {
|
|||
SegmentPoint: function(actual, expected, message, options) {
|
||||
comparators.Point(actual, expected, message, options);
|
||||
comparators.Boolean(actual.selected, expected.selected,
|
||||
(message || '') + ' selected', options);
|
||||
message + '.selected', options);
|
||||
},
|
||||
|
||||
Item: compareItem,
|
||||
|
||||
Group: function(actual, expected, message, options) {
|
||||
compareItem(actual, expected, message, options,
|
||||
['clipped']);
|
||||
},
|
||||
|
||||
Layer: function(actual, expected, message, options) {
|
||||
compareItem(actual, expected, message, options);
|
||||
equals(function() {
|
||||
return options && options.dontShareProject
|
||||
? actual.project !== expected.project
|
||||
: actual.project === expected.project;
|
||||
}, true);
|
||||
},
|
||||
|
||||
Path: function(actual, expected, message, options) {
|
||||
compareItem(actual, expected, message, options,
|
||||
['segments', 'closed', 'clockwise', 'length']);
|
||||
},
|
||||
|
||||
CompoundPath: function(actual, expected, message, options) {
|
||||
compareItem(actual, expected, message, options);
|
||||
},
|
||||
|
||||
Raster: function(actual, expected, message, options) {
|
||||
compareItem(actual, expected, message, options,
|
||||
['size', 'width', 'height', 'ppi', 'source', 'image']);
|
||||
equals(actual.toDataURL(), expected.toDataURL(),
|
||||
message + '.toDataUrl()');
|
||||
},
|
||||
|
||||
Shape: function(actual, expected, message, options) {
|
||||
compareItem(actual, expected, message, options,
|
||||
['shape', 'size', 'radius']);
|
||||
},
|
||||
|
||||
PlacedSymbol: function(actual, expected, message, options) {
|
||||
compareItem(actual, expected, message,
|
||||
// Cloning PlacedSymbols does not result in cloned Symbols
|
||||
options && options.cloned
|
||||
? new Base(options, { cloned: false })
|
||||
: options,
|
||||
['symbol']);
|
||||
},
|
||||
|
||||
PointText: function(actual, expected, message, options) {
|
||||
compareItem(actual, expected, message, options,
|
||||
['content', 'point']);
|
||||
},
|
||||
|
||||
Project: function(actual, expected, message, options) {
|
||||
compareProperties(actual, expected, ['symbols', 'layers'],
|
||||
message, options);
|
||||
}
|
||||
};
|
||||
|
||||
var identicalAfterClone = {
|
||||
var strictIdenticalAfterCloning = {
|
||||
Gradient: true,
|
||||
Symbol: true
|
||||
};
|
||||
|
@ -145,6 +230,11 @@ function equals(actual, expected, message, options) {
|
|||
|| (cls = expected && expected._class)
|
||||
|| type === 'object' && 'Object';
|
||||
var comparator = type && comparators[type];
|
||||
if (!message) {
|
||||
message = type
|
||||
? type.charAt(0).toLowerCase() + type.substring(1)
|
||||
: 'value';
|
||||
}
|
||||
if (comparator) {
|
||||
comparator(actual, expected, message, options);
|
||||
} else if (expected && expected.equals) {
|
||||
|
@ -155,10 +245,10 @@ function equals(actual, expected, message, options) {
|
|||
QUnit.push(actual === expected, actual, expected, message);
|
||||
}
|
||||
if (options && options.cloned && cls) {
|
||||
var identical = identicalAfterClone[cls];
|
||||
var identical = strictIdenticalAfterCloning[cls];
|
||||
QUnit.push(identical ? actual === expected : actual !== expected,
|
||||
actual, identical ? expected : 'not ' + expected,
|
||||
(message || '') + ' identity');
|
||||
message + ': identical after cloning');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,132 +270,6 @@ function asyncTest(testName, expected) {
|
|||
});
|
||||
}
|
||||
|
||||
function compareItems(item, item2, options) {
|
||||
if (options && options.cloned)
|
||||
QUnit.notStrictEqual(item.id, item2.id, 'Compare Item#id');
|
||||
|
||||
QUnit.strictEqual(item.constructor, item2.constructor,
|
||||
'Compare Item#constructor');
|
||||
// When item was cloned and had a name, the name will be versioned
|
||||
equals(options && options.cloned && item.name ? item.name + ' 1'
|
||||
: item.name, item2.name, 'Compare Item#name');
|
||||
Base.each(['bounds', 'position', 'data', 'matrix', 'opacity', 'locked',
|
||||
'visible', 'blendMode', 'selected', 'fullySelected', 'clipMask',
|
||||
'guide'],
|
||||
function(key) {
|
||||
equals(item[key], item2[key], 'Compare Item#' + key, options);
|
||||
}
|
||||
);
|
||||
|
||||
// Style
|
||||
Base.each(['fillColor', 'strokeColor', 'strokeCap', 'strokeJoin',
|
||||
'dashArray', 'dashOffset', 'miterLimit',
|
||||
'fontSize', 'font', 'leading', 'justification'],
|
||||
function(key) {
|
||||
equals(item.style[key], item2.style[key], 'Compare Style#' + key,
|
||||
options);
|
||||
}
|
||||
);
|
||||
|
||||
// Path specific
|
||||
if (item instanceof Path) {
|
||||
Base.each(['segments', 'closed', 'clockwise', 'length'],
|
||||
function(key) {
|
||||
equals(item[key], item2[key], 'Compare Path#' + key, options);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Shape specific
|
||||
if (item instanceof Shape) {
|
||||
Base.each(['shape', 'size', 'radius'],
|
||||
function(key) {
|
||||
equals(item[key], item2[key], 'Compare Shape#' + key, options);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Group specific
|
||||
if (item instanceof Group) {
|
||||
equals(item.clipped, item2.clipped, 'Compare Group#clipped', options);
|
||||
}
|
||||
|
||||
// Layer specific
|
||||
if (item instanceof Layer) {
|
||||
equals(function() {
|
||||
return options && options.dontShareProject
|
||||
? item.project != item2.project
|
||||
: item.project == item2.project;
|
||||
}, true);
|
||||
}
|
||||
|
||||
// PlacedSymbol specific
|
||||
if (item instanceof PlacedSymbol) {
|
||||
if (options.dontShareProject) {
|
||||
compareItems(item.symbol.definition, item2.symbol.definition,
|
||||
options,
|
||||
'Compare Symbol#definition');
|
||||
} else {
|
||||
equals(item.symbol, item2.symbol, 'Compare PlacedSymbol#symbol',
|
||||
options);
|
||||
}
|
||||
}
|
||||
|
||||
// Raster specific
|
||||
if (item instanceof Raster) {
|
||||
equals(item.size, item2.size, 'Compare Raster#size');
|
||||
equals(item.width, item2.width, 'Compare Raster#width');
|
||||
equals(item.height, item2.height, 'Compare Raster#height');
|
||||
equals(item.ppi, item2.ppi, 'Compare Raster#ppi');
|
||||
equals(item.source, item2.source, 'Compare Raster#source');
|
||||
equals(item.image, item2.image, 'Compare Raster#image');
|
||||
equals(item.toDataURL(), item2.toDataURL(),
|
||||
'Compare Raster#toDataUrl()');
|
||||
}
|
||||
|
||||
// TextItem specific:
|
||||
if (item instanceof TextItem) {
|
||||
equals(item.content, item2.content, 'Compare Item#content');
|
||||
}
|
||||
|
||||
// PointText specific:
|
||||
if (item instanceof PointText) {
|
||||
equals(item.point, item2.point, 'Compare Item#point');
|
||||
}
|
||||
|
||||
// Check length of children and recursively compare them:
|
||||
if (item.children) {
|
||||
equals(function() {
|
||||
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], options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function compareProjects(project, project2) {
|
||||
// Compare Project#symbols:
|
||||
equals(function() {
|
||||
return project.symbols.length == project2.symbols.length;
|
||||
}, true);
|
||||
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, { dontShareProject: true },
|
||||
'Compare Symbol#definition');
|
||||
}
|
||||
|
||||
// Compare Project#layers:
|
||||
equals(function() {
|
||||
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],
|
||||
{ dontShareProject: true });
|
||||
}
|
||||
}
|
||||
|
||||
// SVG
|
||||
|
||||
function createSVG(xml) {
|
||||
|
|
|
@ -24,7 +24,7 @@ function cloneAndCompare(item) {
|
|||
return copy.parent.children[copy.name] == copy;
|
||||
}, true);
|
||||
}
|
||||
compareItems(item, copy, { cloned: true });
|
||||
equals(item, copy, 'item.clone()', { cloned: true });
|
||||
// Remove the cloned item to restore the document:
|
||||
copy.remove();
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ test('Symbol#clone()', function() {
|
|||
path.selected = true;
|
||||
var symbol = new Symbol(path);
|
||||
var copy = symbol.clone();
|
||||
compareItems(symbol.definition, copy.definition);
|
||||
equals(symbol.definition, copy.definition, 'symbol.definition');
|
||||
equals(function() {
|
||||
return symbol.project == copy.project;
|
||||
}, true);
|
||||
|
|
|
@ -17,7 +17,7 @@ function testExportImportJSON(project) {
|
|||
var json = project.exportJSON({ precision: 8 });
|
||||
var project2 = new Project();
|
||||
project2.importJSON(json);
|
||||
compareProjects(project2, project);
|
||||
equals(project, project2, null, { dontShareProject: true });
|
||||
}
|
||||
|
||||
test('Circles', function() {
|
||||
|
|
|
@ -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(), { cloned: true });
|
||||
equals(item, item.clone(), null, { cloned: true });
|
||||
});
|
||||
|
||||
test('make an svg line', function() {
|
||||
|
@ -34,7 +34,7 @@ test('make an svg line', function() {
|
|||
|
||||
var line = new Path.Line([x1, y1], [x2, y2]);
|
||||
|
||||
compareItems(importedLine, line);
|
||||
equals(importedLine, line);
|
||||
});
|
||||
|
||||
test('make an svg line with invalid values', function() {
|
||||
|
@ -49,7 +49,7 @@ test('make an svg line with invalid values', function() {
|
|||
|
||||
var line = new Path.Line([0, 0], [0, 0]);
|
||||
|
||||
compareItems(importedLine, line);
|
||||
equals(importedLine, line);
|
||||
});
|
||||
|
||||
test('compare rectangle values', function() {
|
||||
|
@ -71,7 +71,7 @@ test('compare rectangle values', function() {
|
|||
var rectangle = new Rectangle(topLeft, size);
|
||||
var realRectangle = new Shape.Rectangle(rectangle);
|
||||
|
||||
compareItems(importedRectangle, realRectangle);
|
||||
equals(importedRectangle, realRectangle);
|
||||
});
|
||||
|
||||
|
||||
|
@ -93,7 +93,7 @@ test('compare negative rectangle values', function() {
|
|||
var rectangle = new Rectangle(topLeft, size);
|
||||
var realRectangle = new Shape.Rectangle(rectangle);
|
||||
|
||||
compareItems(importedRectangle, realRectangle);
|
||||
equals(importedRectangle, realRectangle);
|
||||
});
|
||||
|
||||
|
||||
|
@ -113,7 +113,7 @@ test('compare invalid rectangle values', function() {
|
|||
var rectangle = new Rectangle(topLeft, size);
|
||||
var realRectangle = new Shape.Rectangle(rectangle);
|
||||
|
||||
compareItems(importedRectangle, realRectangle);
|
||||
equals(importedRectangle, realRectangle);
|
||||
});
|
||||
|
||||
test('compare round rectangle values', function() {
|
||||
|
@ -140,7 +140,7 @@ test('compare round rectangle values', function() {
|
|||
var rectangle = new Rectangle(topLeft, size);
|
||||
var roundRect = new Shape.Rectangle(rectangle, cornerSize);
|
||||
|
||||
compareItems(importedRectangle, roundRect);
|
||||
equals(importedRectangle, roundRect);
|
||||
});
|
||||
|
||||
test('compare negative round rectangle values', function() {
|
||||
|
@ -167,7 +167,7 @@ test('compare negative round rectangle values', function() {
|
|||
var rectangle = new Rectangle(topLeft, size);
|
||||
var roundRect = new Shape.Rectangle(rectangle, cornerSize);
|
||||
|
||||
compareItems(importedRectangle, roundRect);
|
||||
equals(importedRectangle, roundRect);
|
||||
});
|
||||
|
||||
test('compare invalid round rectangle values', function() {
|
||||
|
@ -194,7 +194,7 @@ test('compare invalid round rectangle values', function() {
|
|||
var rectangle = new Rectangle(topLeft, size);
|
||||
var roundRect = new Shape.Rectangle(rectangle, cornerSize);
|
||||
|
||||
compareItems(importedRectangle, roundRect);
|
||||
equals(importedRectangle, roundRect);
|
||||
});
|
||||
|
||||
test('compare ellipse values', function() {
|
||||
|
@ -216,7 +216,7 @@ test('compare ellipse values', function() {
|
|||
radius: new Point(rx, ry)
|
||||
});
|
||||
|
||||
compareItems(importedEllipse, ellipse);
|
||||
equals(importedEllipse, ellipse);
|
||||
});
|
||||
|
||||
test('compare negative ellipse values', function() {
|
||||
|
@ -238,7 +238,7 @@ test('compare negative ellipse values', function() {
|
|||
radius: new Point(rx, ry)
|
||||
});
|
||||
|
||||
compareItems(importedEllipse, ellipse);
|
||||
equals(importedEllipse, ellipse);
|
||||
});
|
||||
|
||||
test('compare invalid ellipse values', function() {
|
||||
|
@ -256,7 +256,7 @@ test('compare invalid ellipse values', function() {
|
|||
radius: new Point(0, 0)
|
||||
});
|
||||
|
||||
compareItems(importedEllipse, ellipse);
|
||||
equals(importedEllipse, ellipse);
|
||||
});
|
||||
|
||||
test('compare circle values', function() {
|
||||
|
@ -274,7 +274,7 @@ test('compare circle values', function() {
|
|||
var center = new Point(cx, cy);
|
||||
var circle = new Shape.Circle(center, r);
|
||||
|
||||
compareItems(importedCircle, circle);
|
||||
equals(importedCircle, circle);
|
||||
});
|
||||
|
||||
test('compare negative circle values', function() {
|
||||
|
@ -292,7 +292,7 @@ test('compare negative circle values', function() {
|
|||
var center = new Point(cx, cy);
|
||||
var circle = new Shape.Circle(center, r);
|
||||
|
||||
compareItems(importedCircle, circle);
|
||||
equals(importedCircle, circle);
|
||||
});
|
||||
|
||||
|
||||
|
@ -308,7 +308,7 @@ test('compare invalid circle values', function() {
|
|||
var center = new Point(0, 0);
|
||||
var circle = new Shape.Circle(center, 0);
|
||||
|
||||
compareItems(importedCircle, circle);
|
||||
equals(importedCircle, circle);
|
||||
|
||||
});
|
||||
|
||||
|
@ -330,7 +330,7 @@ test('compare polygon values', function() {
|
|||
poly.closePath();
|
||||
}
|
||||
|
||||
compareItems(importedPolygon, poly);
|
||||
equals(importedPolygon, poly);
|
||||
});
|
||||
|
||||
test('compare negative polygon values', function() {
|
||||
|
@ -351,7 +351,7 @@ test('compare negative polygon values', function() {
|
|||
poly.closePath();
|
||||
}
|
||||
|
||||
compareItems(importedPolygon, poly);
|
||||
equals(importedPolygon, poly);
|
||||
});
|
||||
|
||||
test('compare polyline values', function() {
|
||||
|
@ -372,7 +372,7 @@ test('compare polyline values', function() {
|
|||
poly.closePath();
|
||||
}
|
||||
|
||||
compareItems(importedPolyline, poly);
|
||||
equals(importedPolyline, poly);
|
||||
});
|
||||
|
||||
test('compare negative polyline values', function() {
|
||||
|
@ -393,5 +393,5 @@ test('compare negative polyline values', function() {
|
|||
poly.closePath();
|
||||
}
|
||||
|
||||
compareItems(importedPolyline, poly);
|
||||
equals(importedPolyline, poly);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue