From f7bdf6be18fcab94cfb62f835cef9f4906be3313 Mon Sep 17 00:00:00 2001 From: Brett Zamir Date: Tue, 15 May 2018 23:16:28 +0800 Subject: [PATCH] - Testing (math_test): Fix undeclared variables - Testing: Move JavaScript out of HTML to own files - Linting: ESLint; unfinished: editor/extensions/, editor/ (root); some of test --- test/all_tests.html | 10 +- test/all_tests.js | 8 + test/contextmenu_test.html | 62 +-- test/contextmenu_test.js | 62 +++ test/coords_test.html | 336 +----------- test/coords_test.js | 336 ++++++++++++ test/draw_test.html | 797 +--------------------------- test/draw_test.js | 793 +++++++++++++++++++++++++++ test/history_test.html | 566 +------------------- test/history_test.js | 565 ++++++++++++++++++++ test/jquery-svg_test.html | 12 +- test/jquery-svg_test.js | 10 + test/math_test.html | 122 +---- test/math_test.js | 122 +++++ test/path_test.html | 140 +---- test/path_test.js | 140 +++++ test/recalculate_test.html | 131 +---- test/recalculate_test.js | 130 +++++ test/sanitize_test.html | 27 +- test/sanitize_test.js | 26 + test/select_test.html | 132 +---- test/select_test.js | 132 +++++ test/svgtransformlist_test.html | 393 +------------- test/svgtransformlist_test.js | 391 ++++++++++++++ test/svgutils_bbox_test.html | 499 +---------------- test/svgutils_bbox_test.js | 499 +++++++++++++++++ test/svgutils_performance_test.html | 174 +----- test/svgutils_performance_test.js | 164 ++++++ test/svgutils_test.html | 344 +----------- test/svgutils_test.js | 337 ++++++++++++ test/test1.html | 247 +-------- test/test1.js | 247 +++++++++ test/units_test.html | 83 +-- test/units_test.js | 83 +++ 34 files changed, 4062 insertions(+), 4058 deletions(-) create mode 100644 test/all_tests.js create mode 100644 test/contextmenu_test.js create mode 100644 test/coords_test.js create mode 100644 test/draw_test.js create mode 100644 test/history_test.js create mode 100644 test/jquery-svg_test.js create mode 100644 test/math_test.js create mode 100644 test/path_test.js create mode 100644 test/recalculate_test.js create mode 100644 test/sanitize_test.js create mode 100644 test/select_test.js create mode 100644 test/svgtransformlist_test.js create mode 100644 test/svgutils_bbox_test.js create mode 100644 test/svgutils_performance_test.js create mode 100644 test/svgutils_test.js create mode 100644 test/test1.js create mode 100644 test/units_test.js diff --git a/test/all_tests.html b/test/all_tests.html index c4b19f3f..32ce315c 100644 --- a/test/all_tests.html +++ b/test/all_tests.html @@ -22,13 +22,5 @@ - + diff --git a/test/all_tests.js b/test/all_tests.js new file mode 100644 index 00000000..918d0f36 --- /dev/null +++ b/test/all_tests.js @@ -0,0 +1,8 @@ +/* eslint-disable no-var */ +window.setTimeout(function () { + var iframes = document.getElementsByTagName('iframe'); + for (var i = 0, len = iframes.length; i < len; ++i) { + var f = iframes[i]; + f.style.height = (f.contentDocument.body.scrollHeight + 20) + 'px'; + } +}, 5000); diff --git a/test/contextmenu_test.html b/test/contextmenu_test.html index 7fca59e3..76a65a09 100644 --- a/test/contextmenu_test.html +++ b/test/contextmenu_test.html @@ -11,67 +11,7 @@ - +

Unit Tests for contextmenu.js

diff --git a/test/contextmenu_test.js b/test/contextmenu_test.js new file mode 100644 index 00000000..3612176d --- /dev/null +++ b/test/contextmenu_test.js @@ -0,0 +1,62 @@ +/* eslint-disable no-var */ +/* eslint-env qunit */ +/* globals svgedit, $, equals */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + + function tearDown () { + svgedit.contextmenu.resetCustomMenus(); + } + + module('svgedit.contextmenu'); + + test('Test svgedit.contextmenu package', function () { + expect(4); + + ok(svgedit.contextmenu, 'contextmenu registered correctly'); + ok(svgedit.contextmenu.add, 'contextmenu.add registered correctly'); + ok(svgedit.contextmenu.hasCustomHandler, 'contextmenu hasCustomHandler registered correctly'); + ok(svgedit.contextmenu.getCustomHandler, 'contextmenu getCustomHandler registered correctly'); + }); + + test('Test svgedit.contextmenu does not add invalid menu item', function () { + expect(3); + + svgedit.contextmenu.add({id: 'justanid'}); + ok(!svgedit.contextmenu.hasCustomHandler('justanid'), 'menu item with just an id is invalid'); + + svgedit.contextmenu.add({id: 'idandlabel', label: 'anicelabel'}); + ok(!svgedit.contextmenu.hasCustomHandler('idandlabel'), 'menu item with just an id and label is invalid'); + + svgedit.contextmenu.add({id: 'idandlabel', label: 'anicelabel', action: 'notafunction'}); + ok(!svgedit.contextmenu.hasCustomHandler('idandlabel'), 'menu item with action that is not a function is invalid'); + }); + + test('Test svgedit.contextmenu adds valid menu item', function () { + expect(2); + + var validItem = {id: 'valid', label: 'anicelabel', action: function () { alert('testing'); }}; + svgedit.contextmenu.add(validItem); + + ok(svgedit.contextmenu.hasCustomHandler('valid'), 'Valid menu item is added.'); + equals(svgedit.contextmenu.getCustomHandler('valid'), validItem.action, 'Valid menu action is added.'); + tearDown(); + }); + + test('Test svgedit.contextmenu rejects valid duplicate menu item id', function () { + expect(1); + + var validItem1 = {id: 'valid', label: 'anicelabel', action: function () { alert('testing'); }}; + var validItem2 = {id: 'valid', label: 'anicelabel', action: function () { alert('testingtwice'); }}; + svgedit.contextmenu.add(validItem1); + svgedit.contextmenu.add(validItem2); + + equals(svgedit.contextmenu.getCustomHandler('valid'), validItem1.action, 'duplicate menu item is rejected.'); + tearDown(); + }); +}); diff --git a/test/coords_test.html b/test/coords_test.html index 7ff981a8..5183aa66 100644 --- a/test/coords_test.html +++ b/test/coords_test.html @@ -15,341 +15,7 @@ - +

Unit Tests for svgedit.coords

diff --git a/test/coords_test.js b/test/coords_test.js new file mode 100644 index 00000000..b139b0ff --- /dev/null +++ b/test/coords_test.js @@ -0,0 +1,336 @@ +/* eslint-env qunit */ +/* globals $, svgedit, equals */ +/* eslint-disable no-var */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + + var root = document.getElementById('root'); + var svgroot = document.createElementNS(svgedit.NS.SVG, 'svg'); + svgroot.id = 'svgroot'; + root.appendChild(svgroot); + var svg = document.createElementNS(svgedit.NS.SVG, 'svg'); + svgroot.appendChild(svg); + var elemId = 1; + + function setUp () { + // Mock out editor context. + svgedit.utilities.init({ + getSVGRoot: function () { return svg; }, + getDOMDocument: function () { return null; }, + getDOMContainer: function () { return null; } + }); + svgedit.coords.init({ + getGridSnapping: function () { return false; }, + getDrawing: function () { + return { + getNextId: function () { return '' + elemId++; } + }; + } + }); + } + + function tearDown () { + while (svg.hasChildNodes()) { + svg.removeChild(svg.firstChild); + } + } + + test('Test remapElement(translate) for rect', function () { + expect(4); + + setUp(); + + var rect = document.createElementNS(svgedit.NS.SVG, 'rect'); + rect.setAttribute('x', '200'); + rect.setAttribute('y', '150'); + rect.setAttribute('width', '250'); + rect.setAttribute('height', '120'); + svg.appendChild(rect); + + var attrs = { + x: '200', + y: '150', + width: '125', + height: '75' + }; + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 1; m.b = 0; + m.c = 0; m.d = 1; + m.e = 100; m.f = -50; + + svgedit.coords.remapElement(rect, attrs, m); + + equals(rect.getAttribute('x'), '300'); + equals(rect.getAttribute('y'), '100'); + equals(rect.getAttribute('width'), '125'); + equals(rect.getAttribute('height'), '75'); + + tearDown(); + }); + + test('Test remapElement(scale) for rect', function () { + expect(4); + setUp(); + + var rect = document.createElementNS(svgedit.NS.SVG, 'rect'); + rect.setAttribute('width', '250'); + rect.setAttribute('height', '120'); + svg.appendChild(rect); + + var attrs = { + x: '0', + y: '0', + width: '250', + height: '120' + }; + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 2; m.b = 0; + m.c = 0; m.d = 0.5; + m.e = 0; m.f = 0; + + svgedit.coords.remapElement(rect, attrs, m); + + equals(rect.getAttribute('x'), '0'); + equals(rect.getAttribute('y'), '0'); + equals(rect.getAttribute('width'), '500'); + equals(rect.getAttribute('height'), '60'); + + tearDown(); + }); + + test('Test remapElement(translate) for circle', function () { + expect(3); + setUp(); + + var circle = document.createElementNS(svgedit.NS.SVG, 'circle'); + circle.setAttribute('cx', '200'); + circle.setAttribute('cy', '150'); + circle.setAttribute('r', '125'); + svg.appendChild(circle); + + var attrs = { + cx: '200', + cy: '150', + r: '125' + }; + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 1; m.b = 0; + m.c = 0; m.d = 1; + m.e = 100; m.f = -50; + + svgedit.coords.remapElement(circle, attrs, m); + + equals(circle.getAttribute('cx'), '300'); + equals(circle.getAttribute('cy'), '100'); + equals(circle.getAttribute('r'), '125'); + + tearDown(); + }); + + test('Test remapElement(scale) for circle', function () { + expect(3); + setUp(); + + var circle = document.createElementNS(svgedit.NS.SVG, 'circle'); + circle.setAttribute('cx', '200'); + circle.setAttribute('cy', '150'); + circle.setAttribute('r', '250'); + svg.appendChild(circle); + + var attrs = { + cx: '200', + cy: '150', + r: '250' + }; + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 2; m.b = 0; + m.c = 0; m.d = 0.5; + m.e = 0; m.f = 0; + + svgedit.coords.remapElement(circle, attrs, m); + + equals(circle.getAttribute('cx'), '400'); + equals(circle.getAttribute('cy'), '75'); + // Radius is the minimum that fits in the new bounding box. + equals(circle.getAttribute('r'), '125'); + + tearDown(); + }); + + test('Test remapElement(translate) for ellipse', function () { + expect(4); + setUp(); + + var ellipse = document.createElementNS(svgedit.NS.SVG, 'ellipse'); + ellipse.setAttribute('cx', '200'); + ellipse.setAttribute('cy', '150'); + ellipse.setAttribute('rx', '125'); + ellipse.setAttribute('ry', '75'); + svg.appendChild(ellipse); + + var attrs = { + cx: '200', + cy: '150', + rx: '125', + ry: '75' + }; + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 1; m.b = 0; + m.c = 0; m.d = 1; + m.e = 100; m.f = -50; + + svgedit.coords.remapElement(ellipse, attrs, m); + + equals(ellipse.getAttribute('cx'), '300'); + equals(ellipse.getAttribute('cy'), '100'); + equals(ellipse.getAttribute('rx'), '125'); + equals(ellipse.getAttribute('ry'), '75'); + + tearDown(); + }); + + test('Test remapElement(scale) for ellipse', function () { + expect(4); + setUp(); + + var ellipse = document.createElementNS(svgedit.NS.SVG, 'ellipse'); + ellipse.setAttribute('cx', '200'); + ellipse.setAttribute('cy', '150'); + ellipse.setAttribute('rx', '250'); + ellipse.setAttribute('ry', '120'); + svg.appendChild(ellipse); + + var attrs = { + cx: '200', + cy: '150', + rx: '250', + ry: '120' + }; + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 2; m.b = 0; + m.c = 0; m.d = 0.5; + m.e = 0; m.f = 0; + + svgedit.coords.remapElement(ellipse, attrs, m); + + equals(ellipse.getAttribute('cx'), '400'); + equals(ellipse.getAttribute('cy'), '75'); + equals(ellipse.getAttribute('rx'), '500'); + equals(ellipse.getAttribute('ry'), '60'); + + tearDown(); + }); + + test('Test remapElement(translate) for line', function () { + expect(4); + setUp(); + + var line = document.createElementNS(svgedit.NS.SVG, 'line'); + line.setAttribute('x1', '50'); + line.setAttribute('y1', '100'); + line.setAttribute('x2', '120'); + line.setAttribute('y2', '200'); + svg.appendChild(line); + + var attrs = { + x1: '50', + y1: '100', + x2: '120', + y2: '200' + }; + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 1; m.b = 0; + m.c = 0; m.d = 1; + m.e = 100; m.f = -50; + + svgedit.coords.remapElement(line, attrs, m); + + equals(line.getAttribute('x1'), '150'); + equals(line.getAttribute('y1'), '50'); + equals(line.getAttribute('x2'), '220'); + equals(line.getAttribute('y2'), '150'); + + tearDown(); + }); + + test('Test remapElement(scale) for line', function () { + expect(4); + setUp(); + + var line = document.createElementNS(svgedit.NS.SVG, 'line'); + line.setAttribute('x1', '50'); + line.setAttribute('y1', '100'); + line.setAttribute('x2', '120'); + line.setAttribute('y2', '200'); + svg.appendChild(line); + + var attrs = { + x1: '50', + y1: '100', + x2: '120', + y2: '200' + }; + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 2; m.b = 0; + m.c = 0; m.d = 0.5; + m.e = 0; m.f = 0; + + svgedit.coords.remapElement(line, attrs, m); + + equals(line.getAttribute('x1'), '100'); + equals(line.getAttribute('y1'), '50'); + equals(line.getAttribute('x2'), '240'); + equals(line.getAttribute('y2'), '100'); + + tearDown(); + }); + + test('Test remapElement(translate) for text', function () { + expect(2); + setUp(); + + var text = document.createElementNS(svgedit.NS.SVG, 'text'); + text.setAttribute('x', '50'); + text.setAttribute('y', '100'); + svg.appendChild(text); + + var attrs = { + x: '50', + y: '100' + }; + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 1; m.b = 0; + m.c = 0; m.d = 1; + m.e = 100; m.f = -50; + + svgedit.coords.remapElement(text, attrs, m); + + equals(text.getAttribute('x'), '150'); + equals(text.getAttribute('y'), '50'); + + tearDown(); + }); +}); diff --git a/test/draw_test.html b/test/draw_test.html index c886bb61..1014a90a 100644 --- a/test/draw_test.html +++ b/test/draw_test.html @@ -15,802 +15,7 @@ - +

Unit Tests for draw.js

diff --git a/test/draw_test.js b/test/draw_test.js new file mode 100644 index 00000000..13078084 --- /dev/null +++ b/test/draw_test.js @@ -0,0 +1,793 @@ +/* eslint-env qunit */ +/* globals $, svgedit, equals */ +/* eslint-disable no-var, no-redeclare */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + var NS = svgedit.NS; + var LAYER_CLASS = svgedit.draw.Layer.CLASS_NAME; + var NONCE = 'foo'; + var LAYER1 = 'Layer 1'; + var LAYER2 = 'Layer 2'; + var LAYER3 = 'Layer 3'; + var PATH_ATTR = { + // clone will convert relative to absolute, so the test for equality fails. + // 'd': 'm7.38867,57.38867c0,-27.62431 22.37569,-50 50,-50c27.62431,0 50,22.37569 50,50c0,27.62431 -22.37569,50 -50,50c-27.62431,0 -50,-22.37569 -50,-50z', + 'd': 'M7.389,57.389C7.389,29.764 29.764,7.389 57.389,7.389C85.013,7.389 107.389,29.764 107.389,57.389C107.389,85.013 85.013,107.389 57.389,107.389C29.764,107.389 7.389,85.013 7.389,57.389z', + 'transform': 'rotate(45 57.388671875000036,57.388671874999986) ', + 'stroke-width': '5', + 'stroke': '#660000', + 'fill': '#ff0000' + }; + + var svg = document.createElementNS(NS.SVG, 'svg'); + var sandbox = document.getElementById('sandbox'); + // Firefox throws exception in getBBox() when svg is not attached to DOM. + sandbox.appendChild(svg); + + // Set up with nonce. + var svgN = document.createElementNS(NS.SVG, 'svg'); + svgN.setAttributeNS(NS.XMLNS, 'xmlns:se', NS.SE); + svgN.setAttributeNS(NS.SE, 'se:nonce', NONCE); + + svgedit.units.init({ + // used by svgedit.units.shortFloat - call path: cloneLayer -> copyElem -> convertPath -> pathDSegment -> shortFloat + getRoundDigits: function () { return 3; } + }); + + function createSVGElement (jsonMap) { + var elem = document.createElementNS(svgedit.NS.SVG, jsonMap['element']); + for (var attr in jsonMap['attr']) { + elem.setAttribute(attr, jsonMap['attr'][attr]); + } + return elem; + } + + var setupSvgWith3Layers = function (svgElem) { + var layer1 = document.createElementNS(NS.SVG, 'g'); + var layer1Title = document.createElementNS(NS.SVG, 'title'); + layer1Title.appendChild(document.createTextNode(LAYER1)); + layer1.appendChild(layer1Title); + svgElem.appendChild(layer1); + + var layer2 = document.createElementNS(NS.SVG, 'g'); + var layer2Title = document.createElementNS(NS.SVG, 'title'); + layer2Title.appendChild(document.createTextNode(LAYER2)); + layer2.appendChild(layer2Title); + svgElem.appendChild(layer2); + + var layer3 = document.createElementNS(NS.SVG, 'g'); + var layer3Title = document.createElementNS(NS.SVG, 'title'); + layer3Title.appendChild(document.createTextNode(LAYER3)); + layer3.appendChild(layer3Title); + svgElem.appendChild(layer3); + + return [layer1, layer2, layer3]; + }; + + var createSomeElementsInGroup = function (group) { + group.appendChild(createSVGElement({ + 'element': 'path', + 'attr': PATH_ATTR + })); + // group.appendChild(createSVGElement({ + // 'element': 'path', + // 'attr': {'d': 'M0,1L2,3'} + // })); + group.appendChild(createSVGElement({ + 'element': 'rect', + 'attr': {'x': '0', 'y': '1', 'width': '5', 'height': '10'} + })); + group.appendChild(createSVGElement({ + 'element': 'line', + 'attr': {'x1': '0', 'y1': '1', 'x2': '5', 'y2': '6'} + })); + + var g = createSVGElement({ + 'element': 'g', + 'attr': {} + }); + g.appendChild(createSVGElement({ + 'element': 'rect', + 'attr': {'x': '0', 'y': '1', 'width': '5', 'height': '10'} + })); + group.appendChild(g); + return 4; + }; + + var cleanupSvg = function (svgElem) { + while (svgElem.firstChild) { svgElem.removeChild(svgElem.firstChild); } + }; + + module('svgedit.draw.Drawing', { + setup: function () { + }, + teardown: function () { + } + }); + + test('Test draw module', function () { + expect(4); + + ok(svgedit.draw); + equals(typeof svgedit.draw, typeof {}); + + ok(svgedit.draw.Drawing); + equals(typeof svgedit.draw.Drawing, typeof function () {}); + }); + + test('Test document creation', function () { + expect(3); + + try { + var doc = new svgedit.draw.Drawing(); + ok(false, 'Created drawing without a valid element'); + } catch (e) { + ok(true); + } + + try { + var doc = new svgedit.draw.Drawing(svg); + ok(doc); + equals(typeof doc, typeof {}); + } catch (e) { + ok(false, 'Could not create document from valid element: ' + e); + } + }); + + test('Test nonce', function () { + expect(7); + + var doc = new svgedit.draw.Drawing(svg); + equals(doc.getNonce(), ''); + + doc = new svgedit.draw.Drawing(svgN); + equals(doc.getNonce(), NONCE); + equals(doc.getSvgElem().getAttributeNS(NS.SE, 'nonce'), NONCE); + + doc.clearNonce(); + ok(!doc.getNonce()); + ok(!doc.getSvgElem().getAttributeNS(NS.SE, 'se:nonce')); + + doc.setNonce(NONCE); + equals(doc.getNonce(), NONCE); + equals(doc.getSvgElem().getAttributeNS(NS.SE, 'nonce'), NONCE); + }); + + test('Test getId() and getNextId() without nonce', function () { + expect(7); + + var elem2 = document.createElementNS(NS.SVG, 'circle'); + elem2.id = 'svg_2'; + svg.appendChild(elem2); + + var doc = new svgedit.draw.Drawing(svg); + + equals(doc.getId(), 'svg_0'); + + equals(doc.getNextId(), 'svg_1'); + equals(doc.getId(), 'svg_1'); + + equals(doc.getNextId(), 'svg_3'); + equals(doc.getId(), 'svg_3'); + + equals(doc.getNextId(), 'svg_4'); + equals(doc.getId(), 'svg_4'); + // clean out svg document + cleanupSvg(svg); + }); + + test('Test getId() and getNextId() with prefix without nonce', function () { + expect(7); + + var prefix = 'Bar-'; + var doc = new svgedit.draw.Drawing(svg, prefix); + + equals(doc.getId(), prefix + '0'); + + equals(doc.getNextId(), prefix + '1'); + equals(doc.getId(), prefix + '1'); + + equals(doc.getNextId(), prefix + '2'); + equals(doc.getId(), prefix + '2'); + + equals(doc.getNextId(), prefix + '3'); + equals(doc.getId(), prefix + '3'); + + cleanupSvg(svg); + }); + + test('Test getId() and getNextId() with nonce', function () { + expect(7); + + var prefix = 'svg_' + NONCE; + + var elem2 = document.createElementNS(NS.SVG, 'circle'); + elem2.id = prefix + '_2'; + svgN.appendChild(elem2); + + var doc = new svgedit.draw.Drawing(svgN); + + equals(doc.getId(), prefix + '_0'); + + equals(doc.getNextId(), prefix + '_1'); + equals(doc.getId(), prefix + '_1'); + + equals(doc.getNextId(), prefix + '_3'); + equals(doc.getId(), prefix + '_3'); + + equals(doc.getNextId(), prefix + '_4'); + equals(doc.getId(), prefix + '_4'); + + cleanupSvg(svgN); + }); + + test('Test getId() and getNextId() with prefix with nonce', function () { + expect(7); + + var PREFIX = 'Bar-'; + var doc = new svgedit.draw.Drawing(svgN, PREFIX); + + var prefix = PREFIX + NONCE + '_'; + equals(doc.getId(), prefix + '0'); + + equals(doc.getNextId(), prefix + '1'); + equals(doc.getId(), prefix + '1'); + + equals(doc.getNextId(), prefix + '2'); + equals(doc.getId(), prefix + '2'); + + equals(doc.getNextId(), prefix + '3'); + equals(doc.getId(), prefix + '3'); + + cleanupSvg(svgN); + }); + + test('Test releaseId()', function () { + expect(6); + + var doc = new svgedit.draw.Drawing(svg); + + var firstId = doc.getNextId(); + // var secondId = doc.getNextId(); + + var result = doc.releaseId(firstId); + ok(result); + equals(doc.getNextId(), firstId); + equals(doc.getNextId(), 'svg_3'); + + ok(!doc.releaseId('bad-id')); + ok(doc.releaseId(firstId)); + ok(!doc.releaseId(firstId)); + + cleanupSvg(svg); + }); + + test('Test getNumLayers', function () { + expect(3); + var drawing = new svgedit.draw.Drawing(svg); + equals(typeof drawing.getNumLayers, typeof function () {}); + equals(drawing.getNumLayers(), 0); + + setupSvgWith3Layers(svg); + drawing.identifyLayers(); + + equals(drawing.getNumLayers(), 3); + + cleanupSvg(svg); + }); + + test('Test hasLayer', function () { + expect(5); + + setupSvgWith3Layers(svg); + var drawing = new svgedit.draw.Drawing(svg); + drawing.identifyLayers(); + + equals(typeof drawing.hasLayer, typeof function () {}); + ok(!drawing.hasLayer('invalid-layer')); + + ok(drawing.hasLayer(LAYER3)); + ok(drawing.hasLayer(LAYER2)); + ok(drawing.hasLayer(LAYER1)); + + cleanupSvg(svg); + }); + + test('Test identifyLayers() with empty document', function () { + expect(11); + + var drawing = new svgedit.draw.Drawing(svg); + equals(drawing.getCurrentLayer(), null); + // By default, an empty document gets an empty group created. + drawing.identifyLayers(); + + // Check that element now has one child node + ok(drawing.getSvgElem().hasChildNodes()); + equals(drawing.getSvgElem().childNodes.length, 1); + + // Check that all_layers are correctly set up. + equals(drawing.getNumLayers(), 1); + var emptyLayer = drawing.all_layers[0]; + ok(emptyLayer); + var layerGroup = emptyLayer.getGroup(); + equals(layerGroup, drawing.getSvgElem().firstChild); + equals(layerGroup.tagName, 'g'); + equals(layerGroup.getAttribute('class'), LAYER_CLASS); + ok(layerGroup.hasChildNodes()); + equals(layerGroup.childNodes.length, 1); + var firstChild = layerGroup.childNodes.item(0); + equals(firstChild.tagName, 'title'); + + cleanupSvg(svg); + }); + + test('Test identifyLayers() with some layers', function () { + expect(8); + + var drawing = new svgedit.draw.Drawing(svg); + setupSvgWith3Layers(svg); + + equals(svg.childNodes.length, 3); + + drawing.identifyLayers(); + + equals(drawing.getNumLayers(), 3); + equals(drawing.all_layers[0].getGroup(), svg.childNodes.item(0)); + equals(drawing.all_layers[1].getGroup(), svg.childNodes.item(1)); + equals(drawing.all_layers[2].getGroup(), svg.childNodes.item(2)); + + equals(drawing.all_layers[0].getGroup().getAttribute('class'), LAYER_CLASS); + equals(drawing.all_layers[1].getGroup().getAttribute('class'), LAYER_CLASS); + equals(drawing.all_layers[2].getGroup().getAttribute('class'), LAYER_CLASS); + + cleanupSvg(svg); + }); + + test('Test identifyLayers() with some layers and orphans', function () { + expect(14); + + setupSvgWith3Layers(svg); + + var orphan1 = document.createElementNS(NS.SVG, 'rect'); + var orphan2 = document.createElementNS(NS.SVG, 'rect'); + svg.appendChild(orphan1); + svg.appendChild(orphan2); + + equals(svg.childNodes.length, 5); + + var drawing = new svgedit.draw.Drawing(svg); + drawing.identifyLayers(); + + equals(drawing.getNumLayers(), 4); + equals(drawing.all_layers[0].getGroup(), svg.childNodes.item(0)); + equals(drawing.all_layers[1].getGroup(), svg.childNodes.item(1)); + equals(drawing.all_layers[2].getGroup(), svg.childNodes.item(2)); + equals(drawing.all_layers[3].getGroup(), svg.childNodes.item(3)); + + equals(drawing.all_layers[0].getGroup().getAttribute('class'), LAYER_CLASS); + equals(drawing.all_layers[1].getGroup().getAttribute('class'), LAYER_CLASS); + equals(drawing.all_layers[2].getGroup().getAttribute('class'), LAYER_CLASS); + equals(drawing.all_layers[3].getGroup().getAttribute('class'), LAYER_CLASS); + + var layer4 = drawing.all_layers[3].getGroup(); + equals(layer4.tagName, 'g'); + equals(layer4.childNodes.length, 3); + equals(layer4.childNodes.item(1), orphan1); + equals(layer4.childNodes.item(2), orphan2); + + cleanupSvg(svg); + }); + + test('Test getLayerName()', function () { + expect(4); + + var drawing = new svgedit.draw.Drawing(svg); + setupSvgWith3Layers(svg); + + drawing.identifyLayers(); + + equals(drawing.getNumLayers(), 3); + equals(drawing.getLayerName(0), LAYER1); + equals(drawing.getLayerName(1), LAYER2); + equals(drawing.getLayerName(2), LAYER3); + + cleanupSvg(svg); + }); + + test('Test getCurrentLayer()', function () { + expect(4); + + var drawing = new svgedit.draw.Drawing(svg); + setupSvgWith3Layers(svg); + drawing.identifyLayers(); + + ok(drawing.getCurrentLayer); + equals(typeof drawing.getCurrentLayer, typeof function () {}); + ok(drawing.getCurrentLayer()); + equals(drawing.getCurrentLayer(), drawing.all_layers[2].getGroup()); + + cleanupSvg(svg); + }); + + test('Test setCurrentLayer() and getCurrentLayerName()', function () { + expect(6); + + var drawing = new svgedit.draw.Drawing(svg); + setupSvgWith3Layers(svg); + drawing.identifyLayers(); + + ok(drawing.setCurrentLayer); + equals(typeof drawing.setCurrentLayer, typeof function () {}); + + drawing.setCurrentLayer(LAYER2); + equals(drawing.getCurrentLayerName(), LAYER2); + equals(drawing.getCurrentLayer(), drawing.all_layers[1].getGroup()); + + drawing.setCurrentLayer(LAYER3); + equals(drawing.getCurrentLayerName(), LAYER3); + equals(drawing.getCurrentLayer(), drawing.all_layers[2].getGroup()); + + cleanupSvg(svg); + }); + + test('Test setCurrentLayerName()', function () { + var mockHrService = { + changeElement: this.spy() + }; + + var drawing = new svgedit.draw.Drawing(svg); + setupSvgWith3Layers(svg); + drawing.identifyLayers(); + + ok(drawing.setCurrentLayerName); + equals(typeof drawing.setCurrentLayerName, typeof function () {}); + + var oldName = drawing.getCurrentLayerName(); + var newName = 'New Name'; + ok(drawing.layer_map[oldName]); + equals(drawing.layer_map[newName], undefined); // newName shouldn't exist. + var result = drawing.setCurrentLayerName(newName, mockHrService); + equals(result, newName); + equals(drawing.getCurrentLayerName(), newName); + // Was the map updated? + equals(drawing.layer_map[oldName], undefined); + equals(drawing.layer_map[newName], drawing.current_layer); + // Was mockHrService called? + ok(mockHrService.changeElement.calledOnce); + equals(oldName, mockHrService.changeElement.getCall(0).args[1]['#text']); + equals(newName, mockHrService.changeElement.getCall(0).args[0].textContent); + + cleanupSvg(svg); + }); + + test('Test createLayer()', function () { + expect(10); + + var mockHrService = { + startBatchCommand: this.spy(), + endBatchCommand: this.spy(), + insertElement: this.spy() + }; + + var drawing = new svgedit.draw.Drawing(svg); + setupSvgWith3Layers(svg); + drawing.identifyLayers(); + + ok(drawing.createLayer); + equals(typeof drawing.createLayer, typeof function () {}); + + var NEW_LAYER_NAME = 'Layer A'; + var layerG = drawing.createLayer(NEW_LAYER_NAME, mockHrService); + equals(drawing.getNumLayers(), 4); + equals(layerG, drawing.getCurrentLayer()); + equals(layerG.getAttribute('class'), LAYER_CLASS); + equals(NEW_LAYER_NAME, drawing.getCurrentLayerName()); + equals(NEW_LAYER_NAME, drawing.getLayerName(3)); + + equals(layerG, mockHrService.insertElement.getCall(0).args[0]); + ok(mockHrService.startBatchCommand.calledOnce); + ok(mockHrService.endBatchCommand.calledOnce); + + cleanupSvg(svg); + }); + + test('Test mergeLayer()', function () { + var mockHrService = { + startBatchCommand: this.spy(), + endBatchCommand: this.spy(), + moveElement: this.spy(), + removeElement: this.spy() + }; + + var drawing = new svgedit.draw.Drawing(svg); + var layers = setupSvgWith3Layers(svg); + var elementCount = createSomeElementsInGroup(layers[2]) + 1; // +1 for title element + equals(layers[1].childElementCount, 1); + equals(layers[2].childElementCount, elementCount); + drawing.identifyLayers(); + equals(drawing.getCurrentLayer(), layers[2]); + + ok(drawing.mergeLayer); + equals(typeof drawing.mergeLayer, typeof function () {}); + + drawing.mergeLayer(mockHrService); + + equals(drawing.getNumLayers(), 2); + equals(svg.childElementCount, 2); + equals(drawing.getCurrentLayer(), layers[1]); + equals(layers[1].childElementCount, elementCount); + + // check history record + ok(mockHrService.startBatchCommand.calledOnce); + ok(mockHrService.endBatchCommand.calledOnce); + equals(mockHrService.startBatchCommand.getCall(0).args[0], 'Merge Layer'); + equals(mockHrService.moveElement.callCount, elementCount - 1); // -1 because the title was not moved. + equals(mockHrService.removeElement.callCount, 2); // remove group and title. + + cleanupSvg(svg); + }); + + test('Test mergeLayer() when no previous layer to merge', function () { + var mockHrService = { + startBatchCommand: this.spy(), + endBatchCommand: this.spy(), + moveElement: this.spy(), + removeElement: this.spy() + }; + + var drawing = new svgedit.draw.Drawing(svg); + var layers = setupSvgWith3Layers(svg); + drawing.identifyLayers(); + drawing.setCurrentLayer(LAYER1); + equals(drawing.getCurrentLayer(), layers[0]); + + drawing.mergeLayer(mockHrService); + + equals(drawing.getNumLayers(), 3); + equals(svg.childElementCount, 3); + equals(drawing.getCurrentLayer(), layers[0]); + equals(layers[0].childElementCount, 1); + equals(layers[1].childElementCount, 1); + equals(layers[2].childElementCount, 1); + + // check history record + equals(mockHrService.startBatchCommand.callCount, 0); + equals(mockHrService.endBatchCommand.callCount, 0); + equals(mockHrService.moveElement.callCount, 0); + equals(mockHrService.removeElement.callCount, 0); + + cleanupSvg(svg); + }); + + test('Test mergeAllLayers()', function () { + var mockHrService = { + startBatchCommand: this.spy(), + endBatchCommand: this.spy(), + moveElement: this.spy(), + removeElement: this.spy() + }; + + var drawing = new svgedit.draw.Drawing(svg); + var layers = setupSvgWith3Layers(svg); + var elementCount = createSomeElementsInGroup(layers[0]) + 1; // +1 for title element + createSomeElementsInGroup(layers[1]); + createSomeElementsInGroup(layers[2]); + equals(layers[0].childElementCount, elementCount); + equals(layers[1].childElementCount, elementCount); + equals(layers[2].childElementCount, elementCount); + drawing.identifyLayers(); + + ok(drawing.mergeAllLayers); + equals(typeof drawing.mergeAllLayers, typeof function () {}); + + drawing.mergeAllLayers(mockHrService); + + equals(drawing.getNumLayers(), 1); + equals(svg.childElementCount, 1); + equals(drawing.getCurrentLayer(), layers[0]); + equals(layers[0].childElementCount, elementCount * 3 - 2); // -2 because two titles were deleted. + + // check history record + equals(mockHrService.startBatchCommand.callCount, 3); // mergeAllLayers + 2 * mergeLayer + equals(mockHrService.endBatchCommand.callCount, 3); + equals(mockHrService.startBatchCommand.getCall(0).args[0], 'Merge all Layers'); + equals(mockHrService.startBatchCommand.getCall(1).args[0], 'Merge Layer'); + equals(mockHrService.startBatchCommand.getCall(2).args[0], 'Merge Layer'); + // moveElement count is times 3 instead of 2, because one layer's elements were moved twice. + // moveElement count is minus 3 because the three titles were not moved. + equals(mockHrService.moveElement.callCount, elementCount * 3 - 3); + equals(mockHrService.removeElement.callCount, 2 * 2); // remove group and title twice. + + cleanupSvg(svg); + }); + + test('Test cloneLayer()', function () { + var mockHrService = { + startBatchCommand: this.spy(), + endBatchCommand: this.spy(), + insertElement: this.spy() + }; + + var drawing = new svgedit.draw.Drawing(svg); + var layers = setupSvgWith3Layers(svg); + var layer3 = layers[2]; + var elementCount = createSomeElementsInGroup(layer3) + 1; // +1 for title element + equals(layer3.childElementCount, elementCount); + drawing.identifyLayers(); + + ok(drawing.cloneLayer); + equals(typeof drawing.cloneLayer, typeof function () {}); + + var clone = drawing.cloneLayer('clone', mockHrService); + + equals(drawing.getNumLayers(), 4); + equals(svg.childElementCount, 4); + equals(drawing.getCurrentLayer(), clone); + equals(clone.childElementCount, elementCount); + + // check history record + ok(mockHrService.startBatchCommand.calledOnce); // mergeAllLayers + 2 * mergeLayer + ok(mockHrService.endBatchCommand.calledOnce); + equals(mockHrService.startBatchCommand.getCall(0).args[0], 'Duplicate Layer'); + equals(mockHrService.insertElement.callCount, 1); + equals(mockHrService.insertElement.getCall(0).args[0], clone); + + // check that path is cloned properly + equals(clone.childNodes.length, elementCount); + var path = clone.childNodes[1]; + equals(path.id, 'svg_1'); + equals(path.getAttribute('d'), PATH_ATTR.d); + equals(path.getAttribute('transform'), PATH_ATTR.transform); + equals(path.getAttribute('fill'), PATH_ATTR.fill); + equals(path.getAttribute('stroke'), PATH_ATTR.stroke); + equals(path.getAttribute('stroke-width'), PATH_ATTR['stroke-width']); + + // check that g is cloned properly + var g = clone.childNodes[4]; + equals(g.childNodes.length, 1); + equals(g.id, 'svg_4'); + + cleanupSvg(svg); + }); + + test('Test getLayerVisibility()', function () { + expect(5); + + var drawing = new svgedit.draw.Drawing(svg); + setupSvgWith3Layers(svg); + drawing.identifyLayers(); + + ok(drawing.getLayerVisibility); + equals(typeof drawing.getLayerVisibility, typeof function () {}); + ok(drawing.getLayerVisibility(LAYER1)); + ok(drawing.getLayerVisibility(LAYER2)); + ok(drawing.getLayerVisibility(LAYER3)); + + cleanupSvg(svg); + }); + + test('Test setLayerVisibility()', function () { + expect(6); + + var drawing = new svgedit.draw.Drawing(svg); + setupSvgWith3Layers(svg); + drawing.identifyLayers(); + + ok(drawing.setLayerVisibility); + equals(typeof drawing.setLayerVisibility, typeof function () {}); + + drawing.setLayerVisibility(LAYER3, false); + drawing.setLayerVisibility(LAYER2, true); + drawing.setLayerVisibility(LAYER1, false); + + ok(!drawing.getLayerVisibility(LAYER1)); + ok(drawing.getLayerVisibility(LAYER2)); + ok(!drawing.getLayerVisibility(LAYER3)); + + drawing.setLayerVisibility(LAYER3, 'test-string'); + ok(!drawing.getLayerVisibility(LAYER3)); + + cleanupSvg(svg); + }); + + test('Test getLayerOpacity()', function () { + expect(5); + + var drawing = new svgedit.draw.Drawing(svg); + setupSvgWith3Layers(svg); + drawing.identifyLayers(); + + ok(drawing.getLayerOpacity); + equals(typeof drawing.getLayerOpacity, typeof function () {}); + ok(drawing.getLayerOpacity(LAYER1) === 1.0); + ok(drawing.getLayerOpacity(LAYER2) === 1.0); + ok(drawing.getLayerOpacity(LAYER3) === 1.0); + + cleanupSvg(svg); + }); + + test('Test setLayerOpacity()', function () { + expect(6); + + var drawing = new svgedit.draw.Drawing(svg); + setupSvgWith3Layers(svg); + drawing.identifyLayers(); + + ok(drawing.setLayerOpacity); + equals(typeof drawing.setLayerOpacity, typeof function () {}); + + drawing.setLayerOpacity(LAYER1, 0.4); + drawing.setLayerOpacity(LAYER2, 'invalid-string'); + drawing.setLayerOpacity(LAYER3, -1.4); + + ok(drawing.getLayerOpacity(LAYER1) === 0.4); + QUnit.log({result: 'layer2 opacity', message: drawing.getLayerOpacity(LAYER2)}); + ok(drawing.getLayerOpacity(LAYER2) === 1.0); + ok(drawing.getLayerOpacity(LAYER3) === 1.0); + + drawing.setLayerOpacity(LAYER3, 100); + ok(drawing.getLayerOpacity(LAYER3) === 1.0); + + cleanupSvg(svg); + }); + + test('Test deleteCurrentLayer()', function () { + expect(6); + + var drawing = new svgedit.draw.Drawing(svg); + setupSvgWith3Layers(svg); + drawing.identifyLayers(); + + drawing.setCurrentLayer(LAYER2); + + var curLayer = drawing.getCurrentLayer(); + equals(curLayer, drawing.all_layers[1].getGroup()); + var deletedLayer = drawing.deleteCurrentLayer(); + + equals(curLayer, deletedLayer); + equals(2, drawing.getNumLayers()); + equals(LAYER1, drawing.all_layers[0].getName()); + equals(LAYER3, drawing.all_layers[1].getName()); + equals(drawing.getCurrentLayer(), drawing.all_layers[1].getGroup()); + }); + + test('Test svgedit.draw.randomizeIds()', function () { + expect(9); + + // Confirm in LET_DOCUMENT_DECIDE mode that the document decides + // if there is a nonce. + var drawing = new svgedit.draw.Drawing(svgN.cloneNode(true)); + ok(!!drawing.getNonce()); + + drawing = new svgedit.draw.Drawing(svg.cloneNode(true)); + ok(!drawing.getNonce()); + + // Confirm that a nonce is set once we're in ALWAYS_RANDOMIZE mode. + svgedit.draw.randomizeIds(true, drawing); + ok(!!drawing.getNonce()); + + // Confirm new drawings in ALWAYS_RANDOMIZE mode have a nonce. + drawing = new svgedit.draw.Drawing(svg.cloneNode(true)); + ok(!!drawing.getNonce()); + + drawing.clearNonce(); + ok(!drawing.getNonce()); + + // Confirm new drawings in NEVER_RANDOMIZE mode do not have a nonce + // but that their se:nonce attribute is left alone. + svgedit.draw.randomizeIds(false, drawing); + ok(!drawing.getNonce()); + ok(!!drawing.getSvgElem().getAttributeNS(NS.SE, 'nonce')); + + drawing = new svgedit.draw.Drawing(svg.cloneNode(true)); + ok(!drawing.getNonce()); + + drawing = new svgedit.draw.Drawing(svgN.cloneNode(true)); + ok(!drawing.getNonce()); + }); +}); diff --git a/test/history_test.html b/test/history_test.html index 060fcbe1..c6e64d95 100644 --- a/test/history_test.html +++ b/test/history_test.html @@ -8,571 +8,7 @@ - +

Unit Tests for history.js

diff --git a/test/history_test.js b/test/history_test.js new file mode 100644 index 00000000..5bbec843 --- /dev/null +++ b/test/history_test.js @@ -0,0 +1,565 @@ +/* eslint-env qunit */ +/* globals $, svgedit, equals */ +/* eslint-disable no-var */ +$(function () { + // TODO(codedread): Write tests for handling history events. + + // Mocked out methods. + svgedit.transformlist = {}; + svgedit.transformlist.removeElementFromListMap = function (elem) {}; + svgedit.utilities = {}; + svgedit.utilities.getHref = function (elem) { return '#foo'; }; + svgedit.utilities.setHref = function (elem, val) {}; + svgedit.utilities.getRotationAngle = function (elem) { return 0; }; + + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + + var NS = svgedit.NS; + // var svg = document.createElementNS(NS.SVG, 'svg'); + var undoMgr = null; + var divparent = document.getElementById('divparent'); + var div1 = document.getElementById('div1'); + var div2 = document.getElementById('div2'); + var div3 = document.getElementById('div3'); + var div4 = document.getElementById('div4'); + var div5 = document.getElementById('div5'); + + module('svgedit.history'); + + var MockCommand = function (optText) { this.text_ = optText; }; + MockCommand.prototype.apply = function () {}; + MockCommand.prototype.unapply = function () {}; + MockCommand.prototype.getText = function () { return this.text_; }; + MockCommand.prototype.elements = function () { return []; }; + + var MockHistoryEventHandler = function () {}; + MockHistoryEventHandler.prototype.handleHistoryEvent = function (eventType, command) {}; + + function setUp () { + undoMgr = new svgedit.history.UndoManager(); + } + function tearDown () { + undoMgr = null; + } + + test('Test svgedit.history package', function () { + expect(13); + + ok(svgedit.history); + ok(svgedit.history.MoveElementCommand); + ok(svgedit.history.InsertElementCommand); + ok(svgedit.history.ChangeElementCommand); + ok(svgedit.history.RemoveElementCommand); + ok(svgedit.history.BatchCommand); + ok(svgedit.history.UndoManager); + equals(typeof svgedit.history.MoveElementCommand, typeof function () {}); + equals(typeof svgedit.history.InsertElementCommand, typeof function () {}); + equals(typeof svgedit.history.ChangeElementCommand, typeof function () {}); + equals(typeof svgedit.history.RemoveElementCommand, typeof function () {}); + equals(typeof svgedit.history.BatchCommand, typeof function () {}); + equals(typeof svgedit.history.UndoManager, typeof function () {}); + }); + + test('Test UndoManager methods', function () { + expect(14); + setUp(); + + ok(undoMgr); + ok(undoMgr.addCommandToHistory); + ok(undoMgr.getUndoStackSize); + ok(undoMgr.getRedoStackSize); + ok(undoMgr.resetUndoStack); + ok(undoMgr.getNextUndoCommandText); + ok(undoMgr.getNextRedoCommandText); + + equals(typeof undoMgr, typeof {}); + equals(typeof undoMgr.addCommandToHistory, typeof function () {}); + equals(typeof undoMgr.getUndoStackSize, typeof function () {}); + equals(typeof undoMgr.getRedoStackSize, typeof function () {}); + equals(typeof undoMgr.resetUndoStack, typeof function () {}); + equals(typeof undoMgr.getNextUndoCommandText, typeof function () {}); + equals(typeof undoMgr.getNextRedoCommandText, typeof function () {}); + + tearDown(); + }); + + test('Test UndoManager.addCommandToHistory() function', function () { + expect(3); + + setUp(); + + equals(undoMgr.getUndoStackSize(), 0); + undoMgr.addCommandToHistory(new MockCommand()); + equals(undoMgr.getUndoStackSize(), 1); + undoMgr.addCommandToHistory(new MockCommand()); + equals(undoMgr.getUndoStackSize(), 2); + + tearDown(); + }); + + test('Test UndoManager.getUndoStackSize() and getRedoStackSize() functions', function () { + expect(18); + + setUp(); + + undoMgr.addCommandToHistory(new MockCommand()); + undoMgr.addCommandToHistory(new MockCommand()); + undoMgr.addCommandToHistory(new MockCommand()); + + equals(undoMgr.getUndoStackSize(), 3); + equals(undoMgr.getRedoStackSize(), 0); + + undoMgr.undo(); + equals(undoMgr.getUndoStackSize(), 2); + equals(undoMgr.getRedoStackSize(), 1); + + undoMgr.undo(); + equals(undoMgr.getUndoStackSize(), 1); + equals(undoMgr.getRedoStackSize(), 2); + + undoMgr.undo(); + equals(undoMgr.getUndoStackSize(), 0); + equals(undoMgr.getRedoStackSize(), 3); + + undoMgr.undo(); + equals(undoMgr.getUndoStackSize(), 0); + equals(undoMgr.getRedoStackSize(), 3); + + undoMgr.redo(); + equals(undoMgr.getUndoStackSize(), 1); + equals(undoMgr.getRedoStackSize(), 2); + + undoMgr.redo(); + equals(undoMgr.getUndoStackSize(), 2); + equals(undoMgr.getRedoStackSize(), 1); + + undoMgr.redo(); + equals(undoMgr.getUndoStackSize(), 3); + equals(undoMgr.getRedoStackSize(), 0); + + undoMgr.redo(); + equals(undoMgr.getUndoStackSize(), 3); + equals(undoMgr.getRedoStackSize(), 0); + + tearDown(); + }); + + test('Test UndoManager.resetUndoStackSize() function', function () { + expect(4); + + setUp(); + + undoMgr.addCommandToHistory(new MockCommand()); + undoMgr.addCommandToHistory(new MockCommand()); + undoMgr.addCommandToHistory(new MockCommand()); + undoMgr.undo(); + + equals(undoMgr.getUndoStackSize(), 2); + equals(undoMgr.getRedoStackSize(), 1); + + undoMgr.resetUndoStack(); + + equals(undoMgr.getUndoStackSize(), 0); + equals(undoMgr.getRedoStackSize(), 0); + + tearDown(); + }); + + test('Test UndoManager.getNextUndoCommandText() function', function () { + expect(9); + + setUp(); + + equals(undoMgr.getNextUndoCommandText(), ''); + + undoMgr.addCommandToHistory(new MockCommand('First')); + undoMgr.addCommandToHistory(new MockCommand('Second')); + undoMgr.addCommandToHistory(new MockCommand('Third')); + + equals(undoMgr.getNextUndoCommandText(), 'Third'); + + undoMgr.undo(); + equals(undoMgr.getNextUndoCommandText(), 'Second'); + + undoMgr.undo(); + equals(undoMgr.getNextUndoCommandText(), 'First'); + + undoMgr.undo(); + equals(undoMgr.getNextUndoCommandText(), ''); + + undoMgr.redo(); + equals(undoMgr.getNextUndoCommandText(), 'First'); + + undoMgr.redo(); + equals(undoMgr.getNextUndoCommandText(), 'Second'); + + undoMgr.redo(); + equals(undoMgr.getNextUndoCommandText(), 'Third'); + + undoMgr.redo(); + equals(undoMgr.getNextUndoCommandText(), 'Third'); + + tearDown(); + }); + + test('Test UndoManager.getNextRedoCommandText() function', function () { + expect(8); + + setUp(); + + equals(undoMgr.getNextRedoCommandText(), ''); + + undoMgr.addCommandToHistory(new MockCommand('First')); + undoMgr.addCommandToHistory(new MockCommand('Second')); + undoMgr.addCommandToHistory(new MockCommand('Third')); + + equals(undoMgr.getNextRedoCommandText(), ''); + + undoMgr.undo(); + equals(undoMgr.getNextRedoCommandText(), 'Third'); + + undoMgr.undo(); + equals(undoMgr.getNextRedoCommandText(), 'Second'); + + undoMgr.undo(); + equals(undoMgr.getNextRedoCommandText(), 'First'); + + undoMgr.redo(); + equals(undoMgr.getNextRedoCommandText(), 'Second'); + + undoMgr.redo(); + equals(undoMgr.getNextRedoCommandText(), 'Third'); + + undoMgr.redo(); + equals(undoMgr.getNextRedoCommandText(), ''); + + tearDown(); + }); + + test('Test UndoManager.undo() and redo() functions', function () { + expect(10); + + setUp(); + + var lastCalled = null; + var cmd1 = new MockCommand(); + var cmd2 = new MockCommand(); + var cmd3 = new MockCommand(); + cmd1.apply = function () { lastCalled = 'cmd1.apply'; }; + cmd2.apply = function () { lastCalled = 'cmd2.apply'; }; + cmd3.apply = function () { lastCalled = 'cmd3.apply'; }; + cmd1.unapply = function () { lastCalled = 'cmd1.unapply'; }; + cmd2.unapply = function () { lastCalled = 'cmd2.unapply'; }; + cmd3.unapply = function () { lastCalled = 'cmd3.unapply'; }; + + undoMgr.addCommandToHistory(cmd1); + undoMgr.addCommandToHistory(cmd2); + undoMgr.addCommandToHistory(cmd3); + + ok(!lastCalled); + + undoMgr.undo(); + equals(lastCalled, 'cmd3.unapply'); + + undoMgr.redo(); + equals(lastCalled, 'cmd3.apply'); + + undoMgr.undo(); + undoMgr.undo(); + equals(lastCalled, 'cmd2.unapply'); + + undoMgr.undo(); + equals(lastCalled, 'cmd1.unapply'); + lastCalled = null; + + undoMgr.undo(); + ok(!lastCalled); + + undoMgr.redo(); + equals(lastCalled, 'cmd1.apply'); + + undoMgr.redo(); + equals(lastCalled, 'cmd2.apply'); + + undoMgr.redo(); + equals(lastCalled, 'cmd3.apply'); + lastCalled = null; + + undoMgr.redo(); + ok(!lastCalled); + + tearDown(); + }); + + test('Test MoveElementCommand', function () { + expect(26); + + setUp(); + + var move = new svgedit.history.MoveElementCommand(div3, div1, divparent); + ok(move.unapply); + ok(move.apply); + equals(typeof move.unapply, typeof function () {}); + equals(typeof move.apply, typeof function () {}); + + move.unapply(); + equals(divparent.firstElementChild, div3); + equals(divparent.firstElementChild.nextElementSibling, div1); + equals(divparent.lastElementChild, div2); + + move.apply(); + equals(divparent.firstElementChild, div1); + equals(divparent.firstElementChild.nextElementSibling, div2); + equals(divparent.lastElementChild, div3); + + move = new svgedit.history.MoveElementCommand(div1, null, divparent); + + move.unapply(); + equals(divparent.firstElementChild, div2); + equals(divparent.firstElementChild.nextElementSibling, div3); + equals(divparent.lastElementChild, div1); + + move.apply(); + equals(divparent.firstElementChild, div1); + equals(divparent.firstElementChild.nextElementSibling, div2); + equals(divparent.lastElementChild, div3); + + move = new svgedit.history.MoveElementCommand(div2, div5, div4); + + move.unapply(); + equals(divparent.firstElementChild, div1); + equals(divparent.firstElementChild.nextElementSibling, div3); + equals(divparent.lastElementChild, div3); + equals(div4.firstElementChild, div2); + equals(div4.firstElementChild.nextElementSibling, div5); + + move.apply(); + equals(divparent.firstElementChild, div1); + equals(divparent.firstElementChild.nextElementSibling, div2); + equals(divparent.lastElementChild, div3); + equals(div4.firstElementChild, div5); + equals(div4.lastElementChild, div5); + + tearDown(); + }); + + test('Test InsertElementCommand', function () { + expect(20); + + setUp(); + + var insert = new svgedit.history.InsertElementCommand(div3); + ok(insert.unapply); + ok(insert.apply); + equals(typeof insert.unapply, typeof function () {}); + equals(typeof insert.apply, typeof function () {}); + + insert.unapply(); + equals(divparent.childElementCount, 2); + equals(divparent.firstElementChild, div1); + equals(div1.nextElementSibling, div2); + equals(divparent.lastElementChild, div2); + + insert.apply(); + equals(divparent.childElementCount, 3); + equals(divparent.firstElementChild, div1); + equals(div1.nextElementSibling, div2); + equals(div2.nextElementSibling, div3); + + insert = new svgedit.history.InsertElementCommand(div2); + + insert.unapply(); + equals(divparent.childElementCount, 2); + equals(divparent.firstElementChild, div1); + equals(div1.nextElementSibling, div3); + equals(divparent.lastElementChild, div3); + + insert.apply(); + equals(divparent.childElementCount, 3); + equals(divparent.firstElementChild, div1); + equals(div1.nextElementSibling, div2); + equals(div2.nextElementSibling, div3); + + tearDown(); + }); + + test('Test RemoveElementCommand', function () { + expect(22); + + setUp(); + + var div6 = document.createElement('div'); + div6.id = 'div6'; + + var remove = new svgedit.history.RemoveElementCommand(div6, null, divparent); + ok(remove.unapply); + ok(remove.apply); + equals(typeof remove.unapply, typeof function () {}); + equals(typeof remove.apply, typeof function () {}); + + remove.unapply(); + equals(divparent.childElementCount, 4); + equals(divparent.firstElementChild, div1); + equals(div1.nextElementSibling, div2); + equals(div2.nextElementSibling, div3); + equals(div3.nextElementSibling, div6); + + remove.apply(); + equals(divparent.childElementCount, 3); + equals(divparent.firstElementChild, div1); + equals(div1.nextElementSibling, div2); + equals(div2.nextElementSibling, div3); + + remove = new svgedit.history.RemoveElementCommand(div6, div2, divparent); + + remove.unapply(); + equals(divparent.childElementCount, 4); + equals(divparent.firstElementChild, div1); + equals(div1.nextElementSibling, div6); + equals(div6.nextElementSibling, div2); + equals(div2.nextElementSibling, div3); + + remove.apply(); + equals(divparent.childElementCount, 3); + equals(divparent.firstElementChild, div1); + equals(div1.nextElementSibling, div2); + equals(div2.nextElementSibling, div3); + + tearDown(); + }); + + test('Test ChangeElementCommand', function () { + expect(26); + + setUp(); + + div1.setAttribute('title', 'new title'); + var change = new svgedit.history.ChangeElementCommand(div1, + {'title': 'old title', 'class': 'foo'}); + ok(change.unapply); + ok(change.apply); + equals(typeof change.unapply, typeof function () {}); + equals(typeof change.apply, typeof function () {}); + + change.unapply(); + equals(div1.getAttribute('title'), 'old title'); + equals(div1.getAttribute('class'), 'foo'); + + change.apply(); + equals(div1.getAttribute('title'), 'new title'); + ok(!div1.getAttribute('class')); + + div1.textContent = 'inner text'; + change = new svgedit.history.ChangeElementCommand(div1, + {'#text': null}); + + change.unapply(); + ok(!div1.textContent); + + change.apply(); + equals(div1.textContent, 'inner text'); + + div1.textContent = ''; + change = new svgedit.history.ChangeElementCommand(div1, + {'#text': 'old text'}); + + change.unapply(); + equals(div1.textContent, 'old text'); + + change.apply(); + ok(!div1.textContent); + + // TODO(codedread): Refactor this #href stuff in history.js and svgcanvas.js + var rect = document.createElementNS(NS.SVG, 'rect'); + var justCalled = null; + var gethrefvalue = null; + var sethrefvalue = null; + svgedit.utilities.getHref = function (elem) { + equals(elem, rect); + justCalled = 'getHref'; + return gethrefvalue; + }; + svgedit.utilities.setHref = function (elem, val) { + equals(elem, rect); + equals(val, sethrefvalue); + justCalled = 'setHref'; + }; + + gethrefvalue = '#newhref'; + change = new svgedit.history.ChangeElementCommand(rect, + {'#href': '#oldhref'}); + equals(justCalled, 'getHref'); + + justCalled = null; + sethrefvalue = '#oldhref'; + change.unapply(); + equals(justCalled, 'setHref'); + + justCalled = null; + sethrefvalue = '#newhref'; + change.apply(); + equals(justCalled, 'setHref'); + + var line = document.createElementNS(NS.SVG, 'line'); + line.setAttributeNS(null, 'class', 'newClass'); + change = new svgedit.history.ChangeElementCommand(line, {class: 'oldClass'}); + + ok(change.unapply); + ok(change.apply); + equals(typeof change.unapply, typeof function () {}); + equals(typeof change.apply, typeof function () {}); + + change.unapply(); + equals(line.getAttributeNS(null, 'class'), 'oldClass'); + + change.apply(); + equals(line.getAttributeNS(null, 'class'), 'newClass'); + + tearDown(); + }); + + test('Test BatchCommand', function () { + expect(13); + + setUp(); + + var concatResult = ''; + MockCommand.prototype.apply = function () { concatResult += this.text_; }; + + var batch = new svgedit.history.BatchCommand(); + ok(batch.unapply); + ok(batch.apply); + ok(batch.addSubCommand); + ok(batch.isEmpty); + equals(typeof batch.unapply, typeof function () {}); + equals(typeof batch.apply, typeof function () {}); + equals(typeof batch.addSubCommand, typeof function () {}); + equals(typeof batch.isEmpty, typeof function () {}); + + ok(batch.isEmpty()); + + batch.addSubCommand(new MockCommand('a')); + ok(!batch.isEmpty()); + batch.addSubCommand(new MockCommand('b')); + batch.addSubCommand(new MockCommand('c')); + + ok(!concatResult); + batch.apply(); + equals(concatResult, 'abc'); + + MockCommand.prototype.apply = function () {}; + MockCommand.prototype.unapply = function () { concatResult += this.text_; }; + concatResult = ''; + batch.unapply(); + equals(concatResult, 'cba'); + + MockCommand.prototype.unapply = function () {}; + + tearDown(); + }); +}); diff --git a/test/jquery-svg_test.html b/test/jquery-svg_test.html index 85093e8f..596db970 100644 --- a/test/jquery-svg_test.html +++ b/test/jquery-svg_test.html @@ -6,17 +6,7 @@ - +

Unit Tests for jquery-svg

diff --git a/test/jquery-svg_test.js b/test/jquery-svg_test.js new file mode 100644 index 00000000..e9d5dce4 --- /dev/null +++ b/test/jquery-svg_test.js @@ -0,0 +1,10 @@ +/* eslint-env qunit */ +/* globals $ */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; +}); diff --git a/test/math_test.html b/test/math_test.html index 94e5e343..831ed8f4 100644 --- a/test/math_test.html +++ b/test/math_test.html @@ -8,127 +8,7 @@ - +

Unit Tests for math.js

diff --git a/test/math_test.js b/test/math_test.js new file mode 100644 index 00000000..643bc9ab --- /dev/null +++ b/test/math_test.js @@ -0,0 +1,122 @@ +/* eslint-env qunit */ +/* globals $, svgedit, equals */ +/* eslint-disable no-var */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + + var svg = document.createElementNS(svgedit.NS.SVG, 'svg'); + + module('svgedit.math'); + + test('Test svgedit.math package', function () { + expect(7); + + ok(svgedit.math); + ok(svgedit.math.transformPoint); + ok(svgedit.math.isIdentity); + ok(svgedit.math.matrixMultiply); + equals(typeof svgedit.math.transformPoint, typeof function () {}); + equals(typeof svgedit.math.isIdentity, typeof function () {}); + equals(typeof svgedit.math.matrixMultiply, typeof function () {}); + }); + + test('Test svgedit.math.transformPoint() function', function () { + expect(6); + var transformPoint = svgedit.math.transformPoint; + + var m = svg.createSVGMatrix(); + m.a = 1; m.b = 0; + m.c = 0; m.d = 1; + m.e = 0; m.f = 0; + var pt = transformPoint(100, 200, m); + equals(pt.x, 100); + equals(pt.y, 200); + + m.e = 300; m.f = 400; + pt = transformPoint(100, 200, m); + equals(pt.x, 400); + equals(pt.y, 600); + + m.a = 0.5; m.b = 0.75; + m.c = 1.25; m.d = 2; + pt = transformPoint(100, 200, m); + equals(pt.x, 100 * m.a + 200 * m.c + m.e); + equals(pt.y, 100 * m.b + 200 * m.d + m.f); + }); + + test('Test svgedit.math.isIdentity() function', function () { + expect(2); + + ok(svgedit.math.isIdentity(svg.createSVGMatrix())); + + var m = svg.createSVGMatrix(); + m.a = 1; m.b = 0; + m.c = 0; m.d = 1; + m.e = 0; m.f = 0; + ok(svgedit.math.isIdentity(m)); + }); + + test('Test svgedit.math.matrixMultiply() function', function () { + expect(5); + var mult = svgedit.math.matrixMultiply; + var isIdentity = svgedit.math.isIdentity; + + // translate there and back + var tr1 = svg.createSVGMatrix().translate(100, 50), + tr2 = svg.createSVGMatrix().translate(-90, 0), + tr3 = svg.createSVGMatrix().translate(-10, -50), + I = mult(tr1, tr2, tr3); + ok(isIdentity(I), 'Expected identity matrix when translating there and back'); + + // rotate there and back + // TODO: currently Mozilla fails this when rotating back at -50 and then -40 degrees + // (b and c are *almost* zero, but not zero) + var rotThere = svg.createSVGMatrix().rotate(90), + rotBack = svg.createSVGMatrix().rotate(-90), // TODO: set this to -50 + rotBackMore = svg.createSVGMatrix().rotate(0); // TODO: set this to -40 + I = mult(rotThere, rotBack, rotBackMore); + ok(isIdentity(I), 'Expected identity matrix when rotating there and back'); + + // scale up and down + var scaleUp = svg.createSVGMatrix().scale(4), + scaleDown = svg.createSVGMatrix().scaleNonUniform(0.25, 1), + scaleDownMore = svg.createSVGMatrix().scaleNonUniform(1, 0.25); + I = mult(scaleUp, scaleDown, scaleDownMore); + ok(isIdentity(I), 'Expected identity matrix when scaling up and down'); + + // test multiplication with its inverse + I = mult(rotThere, rotThere.inverse()); + ok(isIdentity(I), 'Expected identity matrix when multiplying a matrix by its inverse'); + I = mult(rotThere.inverse(), rotThere); + ok(isIdentity(I), 'Expected identity matrix when multiplying a matrix by its inverse'); + }); + + test('Test svgedit.math.transformBox() function', function () { + expect(12); + var transformBox = svgedit.math.transformBox; + + var m = svg.createSVGMatrix(); + m.a = 1; m.b = 0; + m.c = 0; m.d = 1; + m.e = 0; m.f = 0; + + var r = transformBox(10, 10, 200, 300, m); + equals(r.tl.x, 10); + equals(r.tl.y, 10); + equals(r.tr.x, 210); + equals(r.tr.y, 10); + equals(r.bl.x, 10); + equals(r.bl.y, 310); + equals(r.br.x, 210); + equals(r.br.y, 310); + equals(r.aabox.x, 10); + equals(r.aabox.y, 10); + equals(r.aabox.width, 200); + equals(r.aabox.height, 300); + }); +}); diff --git a/test/path_test.html b/test/path_test.html index b4d60990..b62c1cea 100644 --- a/test/path_test.html +++ b/test/path_test.html @@ -11,145 +11,7 @@ - +

Unit Tests for path.js

diff --git a/test/path_test.js b/test/path_test.js new file mode 100644 index 00000000..af6d8ea4 --- /dev/null +++ b/test/path_test.js @@ -0,0 +1,140 @@ +/* eslint-env qunit */ +/* globals $, svgedit, equals */ +/* eslint-disable no-var */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + + test('Test svgedit.path.replacePathSeg', function () { + expect(6); + + var path = document.createElementNS(svgedit.NS.SVG, 'path'); + path.setAttribute('d', 'M0,0 L10,11 L20,21Z'); + svgedit.path.init(); + svgedit.path.Path(path); + + equals(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'L'); + equals(path.pathSegList.getItem(1).x, 10); + equals(path.pathSegList.getItem(1).y, 11); + + svgedit.path.replacePathSeg(SVGPathSeg.PATHSEG_LINETO_REL, 1, [30, 31], path); + + equals(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'l'); + equals(path.pathSegList.getItem(1).x, 30); + equals(path.pathSegList.getItem(1).y, 31); + }); + + test('Test svgedit.path.Segment.setType simple', function () { + expect(9); + + var path = document.createElementNS(svgedit.NS.SVG, 'path'); + path.setAttribute('d', 'M0,0 L10,11 L20,21Z'); + svgedit.path.init(); + svgedit.path.Path(path); + + equals(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'L'); + equals(path.pathSegList.getItem(1).x, 10); + equals(path.pathSegList.getItem(1).y, 11); + + var segment = new svgedit.path.Segment(1, path.pathSegList.getItem(1)); + segment.setType(SVGPathSeg.PATHSEG_LINETO_REL, [30, 31]); + equals(segment.item.pathSegTypeAsLetter, 'l'); + equals(segment.item.x, 30); + equals(segment.item.y, 31); + + // Also verify that the actual path changed. + equals(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'l'); + equals(path.pathSegList.getItem(1).x, 30); + equals(path.pathSegList.getItem(1).y, 31); + }); + + test('Test svgedit.path.Segment.setType with control points', function () { + expect(14); + + // Setup the dom for a mock control group. + var svg = document.createElementNS(svgedit.NS.SVG, 'svg'); + var path = document.createElementNS(svgedit.NS.SVG, 'path'); + path.setAttribute('d', 'M0,0 C11,12 13,14 15,16 Z'); + svg.appendChild(path); + var selectorParentGroup = document.createElementNS(svgedit.NS.SVG, 'g'); + selectorParentGroup.setAttribute('id', 'selectorParentGroup'); + svg.appendChild(selectorParentGroup); + var mockContext = { + getDOMDocument: function () { return svg; }, + getDOMContainer: function () { return svg; }, + getSVGRoot: function () { return svg; }, + getCurrentZoom: function () { return 1; } + }; + svgedit.path.init(mockContext); + svgedit.utilities.init(mockContext); + var segment = new svgedit.path.Segment(1, path.pathSegList.getItem(1)); + segment.path = new svgedit.path.Path(path); + + equals(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'C'); + equals(path.pathSegList.getItem(1).x1, 11); + equals(path.pathSegList.getItem(1).y1, 12); + equals(path.pathSegList.getItem(1).x2, 13); + equals(path.pathSegList.getItem(1).y2, 14); + equals(path.pathSegList.getItem(1).x, 15); + equals(path.pathSegList.getItem(1).y, 16); + + segment.setType(SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, [30, 31, 32, 33, 34, 35]); + equals(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'c'); + equals(path.pathSegList.getItem(1).x1, 32); + equals(path.pathSegList.getItem(1).y1, 33); + equals(path.pathSegList.getItem(1).x2, 34); + equals(path.pathSegList.getItem(1).y2, 35); + equals(path.pathSegList.getItem(1).x, 30); + equals(path.pathSegList.getItem(1).y, 31); + }); + + test('Test svgedit.path.Segment.move', function () { + expect(6); + + var path = document.createElementNS(svgedit.NS.SVG, 'path'); + path.setAttribute('d', 'M0,0 L10,11 L20,21Z'); + svgedit.path.init(); + svgedit.path.Path(path); + + equals(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'L'); + equals(path.pathSegList.getItem(1).x, 10); + equals(path.pathSegList.getItem(1).y, 11); + + var segment = new svgedit.path.Segment(1, path.pathSegList.getItem(1)); + segment.move(-3, 4); + equals(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'L'); + equals(path.pathSegList.getItem(1).x, 7); + equals(path.pathSegList.getItem(1).y, 15); + }); + + test('Test svgedit.path.Segment.moveCtrl', function () { + expect(14); + + var path = document.createElementNS(svgedit.NS.SVG, 'path'); + path.setAttribute('d', 'M0,0 C11,12 13,14 15,16 Z'); + svgedit.path.init(); + svgedit.path.Path(path); + + equals(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'C'); + equals(path.pathSegList.getItem(1).x1, 11); + equals(path.pathSegList.getItem(1).y1, 12); + equals(path.pathSegList.getItem(1).x2, 13); + equals(path.pathSegList.getItem(1).y2, 14); + equals(path.pathSegList.getItem(1).x, 15); + equals(path.pathSegList.getItem(1).y, 16); + + var segment = new svgedit.path.Segment(1, path.pathSegList.getItem(1)); + segment.moveCtrl(1, 100, -200); + equals(path.pathSegList.getItem(1).pathSegTypeAsLetter, 'C'); + equals(path.pathSegList.getItem(1).x1, 111); + equals(path.pathSegList.getItem(1).y1, -188); + equals(path.pathSegList.getItem(1).x2, 13); + equals(path.pathSegList.getItem(1).y2, 14); + equals(path.pathSegList.getItem(1).x, 15); + equals(path.pathSegList.getItem(1).y, 16); + }); +}); diff --git a/test/recalculate_test.html b/test/recalculate_test.html index bc6ea627..908695a3 100644 --- a/test/recalculate_test.html +++ b/test/recalculate_test.html @@ -17,136 +17,7 @@ - +

Unit Tests for svgedit.recalculate

diff --git a/test/recalculate_test.js b/test/recalculate_test.js new file mode 100644 index 00000000..a46ba748 --- /dev/null +++ b/test/recalculate_test.js @@ -0,0 +1,130 @@ +/* eslint-env qunit */ +/* globals $, svgedit */ +/* eslint-disable no-var */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + + var root = document.getElementById('root'); + var svgroot = document.createElementNS(svgedit.NS.SVG, 'svg'); + svgroot.id = 'svgroot'; + root.appendChild(svgroot); + var svg = document.createElementNS(svgedit.NS.SVG, 'svg'); + svgroot.appendChild(svg); + var elemId = 1; + var elem; + + function setUp () { + svgedit.utilities.init({ + getSVGRoot: function () { return svg; }, + getDOMDocument: function () { return null; }, + getDOMContainer: function () { return null; } + }); + svgedit.coords.init({ + getGridSnapping: function () { return false; }, + getDrawing: function () { + return { + getNextId: function () { return '' + elemId++; } + }; + } + }); + svgedit.recalculate.init({ + getSVGRoot: function () { return svg; }, + getStartTransform: function () { return ''; }, + setStartTransform: function () {} + }); + } + + function setUpRect () { + setUp(); + elem = document.createElementNS(svgedit.NS.SVG, 'rect'); + elem.setAttribute('x', '200'); + elem.setAttribute('y', '150'); + elem.setAttribute('width', '250'); + elem.setAttribute('height', '120'); + svg.appendChild(elem); + } + + function setUpTextWithTspan () { + setUp(); + elem = document.createElementNS(svgedit.NS.SVG, 'text'); + elem.setAttribute('x', '200'); + elem.setAttribute('y', '150'); + + var tspan = document.createElementNS(svgedit.NS.SVG, 'tspan'); + tspan.setAttribute('x', '200'); + tspan.setAttribute('y', '150'); + + var theText = document.createTextNode('Foo bar'); + tspan.appendChild(theText); + elem.appendChild(tspan); + svg.appendChild(elem); + } + + function tearDown () { + while (svg.hasChildNodes()) { + svg.removeChild(svg.firstChild); + } + } + + test('Test recalculateDimensions() on rect with identity matrix', function () { + expect(1); + + setUpRect(); + elem.setAttribute('transform', 'matrix(1,0,0,1,0,0)'); + + svgedit.recalculate.recalculateDimensions(elem); + + // Ensure that the identity matrix is swallowed and the element has no + // transform on it. + equal(false, elem.hasAttribute('transform')); + + tearDown(); + }); + + test('Test recalculateDimensions() on rect with simple translate', function () { + expect(5); + + setUpRect(); + elem.setAttribute('transform', 'translate(100,50)'); + + svgedit.recalculate.recalculateDimensions(elem); + + equal(false, elem.hasAttribute('transform')); + equal('300', elem.getAttribute('x')); + equal('200', elem.getAttribute('y')); + equal('250', elem.getAttribute('width')); + equal('120', elem.getAttribute('height')); + tearDown(); + }); + + test('Test recalculateDimensions() on text w/tspan with simple translate', function () { + expect(5); + + setUpTextWithTspan(); + elem.setAttribute('transform', 'translate(100,50)'); + + svgedit.recalculate.recalculateDimensions(elem); + + // Ensure that the identity matrix is swallowed and the element has no + // transform on it. + equal(false, elem.hasAttribute('transform')); + equal('300', elem.getAttribute('x')); + equal('200', elem.getAttribute('y')); + + var tspan = elem.firstElementChild; + equal('300', tspan.getAttribute('x')); + equal('200', tspan.getAttribute('y')); + + tearDown(); + }); + + // TODO: Since recalculateDimensions() and surrounding code is + // probably the largest, most complicated and strange piece of + // code in SVG-edit, we need to write a whole lot of unit tests + // for it here. +}); diff --git a/test/sanitize_test.html b/test/sanitize_test.html index 555bd691..4a8a0147 100644 --- a/test/sanitize_test.html +++ b/test/sanitize_test.html @@ -11,32 +11,7 @@ - +

Unit Tests for sanitize.js

diff --git a/test/sanitize_test.js b/test/sanitize_test.js new file mode 100644 index 00000000..a7aee4d5 --- /dev/null +++ b/test/sanitize_test.js @@ -0,0 +1,26 @@ +/* eslint-env qunit */ +/* globals $, svgedit, equals */ +/* eslint-disable no-var */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + + var svg = document.createElementNS(svgedit.NS.SVG, 'svg'); + + test('Test sanitizeSvg() strips ws from style attr', function () { + expect(2); + + var rect = document.createElementNS(svgedit.NS.SVG, 'rect'); + rect.setAttribute('style', 'stroke: blue ; stroke-width : 40;'); + // sanitizeSvg() requires the node to have a parent and a document. + svg.appendChild(rect); + svgedit.sanitize.sanitizeSvg(rect); + + equals(rect.getAttribute('stroke'), 'blue'); + equals(rect.getAttribute('stroke-width'), '40'); + }); +}); diff --git a/test/select_test.html b/test/select_test.html index 230c8ebf..f753bd86 100644 --- a/test/select_test.html +++ b/test/select_test.html @@ -12,137 +12,7 @@ - +

Unit Tests for select.js

diff --git a/test/select_test.js b/test/select_test.js new file mode 100644 index 00000000..fa9f9356 --- /dev/null +++ b/test/select_test.js @@ -0,0 +1,132 @@ +/* eslint-env qunit */ +/* globals $, svgedit, equals */ +/* eslint-disable no-var */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + + module('svgedit.select'); + + var sandbox = document.getElementById('sandbox'); + var svgroot; + var svgcontent; + var mockConfig = { + dimensions: [640, 480] + }; + var mockFactory = { + createSVGElement: function (jsonMap) { + var elem = document.createElementNS(svgedit.NS.SVG, jsonMap['element']); + for (var attr in jsonMap['attr']) { + elem.setAttribute(attr, jsonMap['attr'][attr]); + } + return elem; + }, + svgRoot: function () { return svgroot; }, + svgContent: function () { return svgcontent; } + }; + + function setUp () { + svgroot = mockFactory.createSVGElement({ + 'element': 'svg', + 'attr': {'id': 'svgroot'} + }); + svgcontent = svgroot.appendChild( + mockFactory.createSVGElement({ + 'element': 'svg', + 'attr': {'id': 'svgcontent'} + }) + ); + /* var rect = */ svgcontent.appendChild( + mockFactory.createSVGElement({ + 'element': 'rect', + 'attr': { + 'id': 'rect', + 'x': '50', + 'y': '75', + 'width': '200', + 'height': '100' + } + }) + ); + sandbox.appendChild(svgroot); + } + + /* + function setUpWithInit () { + setUp(); + svgedit.select.init(mockConfig, mockFactory); + } + */ + + function tearDown () { + while (sandbox.hasChildNodes()) { + sandbox.removeChild(sandbox.firstChild); + } + } + + test('Test svgedit.select package', function () { + expect(10); + + ok(svgedit.select); + ok(svgedit.select.Selector); + ok(svgedit.select.SelectorManager); + ok(svgedit.select.init); + ok(svgedit.select.getSelectorManager); + equals(typeof svgedit.select, typeof {}); + equals(typeof svgedit.select.Selector, typeof function () {}); + equals(typeof svgedit.select.SelectorManager, typeof function () {}); + equals(typeof svgedit.select.init, typeof function () {}); + equals(typeof svgedit.select.getSelectorManager, typeof function () {}); + }); + + test('Test Selector DOM structure', function () { + expect(24); + + setUp(); + + ok(svgroot); + ok(svgroot.hasChildNodes()); + + // Verify non-existence of Selector DOM nodes + equals(svgroot.childNodes.length, 1); + equals(svgroot.childNodes.item(0), svgcontent); + ok(!svgroot.querySelector('#selectorParentGroup')); + + svgedit.select.init(mockConfig, mockFactory); + + equals(svgroot.childNodes.length, 3); + + // Verify existence of canvas background. + var cb = svgroot.childNodes.item(0); + ok(cb); + equals(cb.id, 'canvasBackground'); + + ok(svgroot.childNodes.item(1)); + equals(svgroot.childNodes.item(1), svgcontent); + + // Verify existence of selectorParentGroup. + var spg = svgroot.childNodes.item(2); + ok(spg); + equals(svgroot.querySelector('#selectorParentGroup'), spg); + equals(spg.id, 'selectorParentGroup'); + equals(spg.tagName, 'g'); + + // Verify existence of all grip elements. + ok(spg.querySelector('#selectorGrip_resize_nw')); + ok(spg.querySelector('#selectorGrip_resize_n')); + ok(spg.querySelector('#selectorGrip_resize_ne')); + ok(spg.querySelector('#selectorGrip_resize_e')); + ok(spg.querySelector('#selectorGrip_resize_se')); + ok(spg.querySelector('#selectorGrip_resize_s')); + ok(spg.querySelector('#selectorGrip_resize_sw')); + ok(spg.querySelector('#selectorGrip_resize_w')); + ok(spg.querySelector('#selectorGrip_rotateconnector')); + ok(spg.querySelector('#selectorGrip_rotate')); + + tearDown(); + }); +}); diff --git a/test/svgtransformlist_test.html b/test/svgtransformlist_test.html index 94f7501b..82c6a8a8 100644 --- a/test/svgtransformlist_test.html +++ b/test/svgtransformlist_test.html @@ -13,398 +13,7 @@ - +

Unit Tests for svgtransformlist.js

diff --git a/test/svgtransformlist_test.js b/test/svgtransformlist_test.js new file mode 100644 index 00000000..6150a12c --- /dev/null +++ b/test/svgtransformlist_test.js @@ -0,0 +1,391 @@ +/* eslint-env qunit */ +/* globals $, svgedit, equals */ +/* eslint-disable no-var */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + var NS = svgedit.NS; + var svgroot = document.getElementById('svgroot'); + var svgcontent, rect, circle; + + var NEAR_ZERO = 5e-6; // 0.000005, Firefox fails at higher levels of precision. + function almostEquals (a, b, msg) { + msg = msg || (a + ' did not equal ' + b); + ok(Math.abs(a - b) < NEAR_ZERO, msg); + } + + function checkOutOfBoundsException (obj, fn, arg1) { + var caughtException = false; + try { + obj[fn](arg1); + } catch (e) { + if (e.code === 1) { + caughtException = true; + } + } + ok(caughtException, 'Caugh an INDEX_SIZE_ERR exception'); + } + + function setUp () { + svgcontent = svgroot.appendChild(document.createElementNS(NS.SVG, 'svg')); + rect = svgcontent.appendChild(document.createElementNS(NS.SVG, 'rect')); + rect.id = 'r'; + circle = svgcontent.appendChild(document.createElementNS(NS.SVG, 'circle')); + circle.id = 'c'; + } + + function tearDown () { + svgedit.transformlist.resetListMap(); + while (svgroot.hasChildNodes()) { + svgroot.removeChild(svgroot.firstChild); + } + } + + module('svgedit.svgtransformlist'); + + test('Test svgedit.transformlist package', function () { + expect(2); + + ok(svgedit.transformlist); + ok(svgedit.transformlist.getTransformList); + }); + + test('Test svgedit.transformlist.getTransformList() function', function () { + expect(4); + setUp(); + + var rxform = svgedit.transformlist.getTransformList(rect); + var cxform = svgedit.transformlist.getTransformList(circle); + + ok(rxform); + ok(cxform); + equals(typeof rxform, typeof {}); + equals(typeof cxform, typeof {}); + + tearDown(); + }); + + test('Test SVGTransformList.numberOfItems property', function () { + expect(2); + setUp(); + + var rxform = svgedit.transformlist.getTransformList(rect); + + equals(typeof rxform.numberOfItems, typeof 0); + equals(rxform.numberOfItems, 0); + + tearDown(); + }); + + test('Test SVGTransformList.initialize()', function () { + expect(6); + setUp(); + + var rxform = svgedit.transformlist.getTransformList(rect); + var cxform = svgedit.transformlist.getTransformList(circle); + + var t = svgcontent.createSVGTransform(); + ok(t); + ok(rxform.initialize); + equals(typeof rxform.initialize, typeof function () {}); + rxform.initialize(t); + equals(rxform.numberOfItems, 1); + equals(cxform.numberOfItems, 0); + + // If a transform was already in a transform list, this should + // remove it from its old list and add it to this list. + cxform.initialize(t); + // This also fails in Firefox native. + // equals(rxform.numberOfItems, 0, 'Did not remove transform from list before initializing another transformlist'); + equals(cxform.numberOfItems, 1); + + tearDown(); + }); + + test('Test SVGTransformList.appendItem() and getItem()', function () { + expect(12); + setUp(); + + var rxform = svgedit.transformlist.getTransformList(rect); + var cxform = svgedit.transformlist.getTransformList(circle); + + var t1 = svgcontent.createSVGTransform(), + t2 = svgcontent.createSVGTransform(), + t3 = svgcontent.createSVGTransform(); + + ok(rxform.appendItem); + ok(rxform.getItem); + equals(typeof rxform.appendItem, typeof function () {}); + equals(typeof rxform.getItem, typeof function () {}); + + rxform.appendItem(t1); + rxform.appendItem(t2); + rxform.appendItem(t3); + + equals(rxform.numberOfItems, 3); + var rxf = rxform.getItem(0); + equals(rxf, t1); + equals(rxform.getItem(1), t2); + equals(rxform.getItem(2), t3); + + checkOutOfBoundsException(rxform, 'getItem', -1); + checkOutOfBoundsException(rxform, 'getItem', 3); + cxform.appendItem(t1); + // These also fail in Firefox native. + // equals(rxform.numberOfItems, 2, 'Did not remove a transform from a list before appending it to a new transformlist'); + // equals(rxform.getItem(0), t2, 'Found the wrong transform in a transformlist'); + // equals(rxform.getItem(1), t3, 'Found the wrong transform in a transformlist'); + + equals(cxform.numberOfItems, 1); + equals(cxform.getItem(0), t1); + tearDown(); + }); + + test('Test SVGTransformList.removeItem()', function () { + expect(7); + setUp(); + + var rxform = svgedit.transformlist.getTransformList(rect); + + var t1 = svgcontent.createSVGTransform(), + t2 = svgcontent.createSVGTransform(); + ok(rxform.removeItem); + equals(typeof rxform.removeItem, typeof function () {}); + rxform.appendItem(t1); + rxform.appendItem(t2); + + var removedTransform = rxform.removeItem(0); + equals(rxform.numberOfItems, 1); + equals(removedTransform, t1); + equals(rxform.getItem(0), t2); + + checkOutOfBoundsException(rxform, 'removeItem', -1); + checkOutOfBoundsException(rxform, 'removeItem', 1); + + tearDown(); + }); + + test('Test SVGTransformList.replaceItem()', function () { + expect(8); + setUp(); + + var rxform = svgedit.transformlist.getTransformList(rect); + var cxform = svgedit.transformlist.getTransformList(circle); + + ok(rxform.replaceItem); + equals(typeof rxform.replaceItem, typeof function () {}); + + var t1 = svgcontent.createSVGTransform(), + t2 = svgcontent.createSVGTransform(), + t3 = svgcontent.createSVGTransform(); + + rxform.appendItem(t1); + rxform.appendItem(t2); + cxform.appendItem(t3); + + var newItem = rxform.replaceItem(t3, 0); + equals(rxform.numberOfItems, 2); + equals(newItem, t3); + equals(rxform.getItem(0), t3); + equals(rxform.getItem(1), t2); + // Fails in Firefox native + // equals(cxform.numberOfItems, 0); + + // test replaceItem within a list + rxform.appendItem(t1); + rxform.replaceItem(t1, 0); + // Fails in Firefox native + // equals(rxform.numberOfItems, 2); + equals(rxform.getItem(0), t1); + equals(rxform.getItem(1), t2); + + tearDown(); + }); + + test('Test SVGTransformList.insertItemBefore()', function () { + expect(10); + setUp(); + + var rxform = svgedit.transformlist.getTransformList(rect); + var cxform = svgedit.transformlist.getTransformList(circle); + + ok(rxform.insertItemBefore); + equals(typeof rxform.insertItemBefore, typeof function () {}); + + var t1 = svgcontent.createSVGTransform(), + t2 = svgcontent.createSVGTransform(), + t3 = svgcontent.createSVGTransform(); + + rxform.appendItem(t1); + rxform.appendItem(t2); + cxform.appendItem(t3); + + var newItem = rxform.insertItemBefore(t3, 0); + equals(rxform.numberOfItems, 3); + equals(newItem, t3); + equals(rxform.getItem(0), t3); + equals(rxform.getItem(1), t1); + equals(rxform.getItem(2), t2); + // Fails in Firefox native + // equals(cxform.numberOfItems, 0); + + rxform.insertItemBefore(t2, 1); + // Fails in Firefox native (they make copies of the transforms) + // equals(rxform.numberOfItems, 3); + equals(rxform.getItem(0), t3); + equals(rxform.getItem(1), t2); + equals(rxform.getItem(2), t1); + tearDown(); + }); + + test('Test SVGTransformList.init() for translate(200,100)', function () { + expect(8); + setUp(); + rect.setAttribute('transform', 'translate(200,100)'); + + var rxform = svgedit.transformlist.getTransformList(rect); + equals(1, rxform.numberOfItems); + + var translate = rxform.getItem(0); + equals(translate.type, 2); + + var m = translate.matrix; + equals(m.a, 1); + equals(m.b, 0); + equals(m.c, 0); + equals(m.d, 1); + equals(m.e, 200); + equals(m.f, 100); + + tearDown(); + }); + + test('Test SVGTransformList.init() for scale(4)', function () { + expect(8); + setUp(); + rect.setAttribute('transform', 'scale(4)'); + + var rxform = svgedit.transformlist.getTransformList(rect); + equals(1, rxform.numberOfItems); + + var scale = rxform.getItem(0); + equals(3, scale.type); + + var m = scale.matrix; + equals(m.a, 4); + equals(m.b, 0); + equals(m.c, 0); + equals(m.d, 4); + equals(m.e, 0); + equals(m.f, 0); + + tearDown(); + }); + + test('Test SVGTransformList.init() for scale(4,3)', function () { + expect(8); + setUp(); + rect.setAttribute('transform', 'scale(4,3)'); + + var rxform = svgedit.transformlist.getTransformList(rect); + equals(1, rxform.numberOfItems); + + var scale = rxform.getItem(0); + equals(3, scale.type); + + var m = scale.matrix; + equals(m.a, 4); + equals(m.b, 0); + equals(m.c, 0); + equals(m.d, 3); + equals(m.e, 0); + equals(m.f, 0); + + tearDown(); + }); + + test('Test SVGTransformList.init() for rotate(45)', function () { + expect(9); + setUp(); + rect.setAttribute('transform', 'rotate(45)'); + + var rxform = svgedit.transformlist.getTransformList(rect); + equals(1, rxform.numberOfItems); + + var rotate = rxform.getItem(0); + equals(4, rotate.type); + equals(45, rotate.angle); + + var m = rotate.matrix; + almostEquals(m.a, 1 / Math.sqrt(2)); + almostEquals(m.b, 1 / Math.sqrt(2)); + almostEquals(m.c, -1 / Math.sqrt(2)); + almostEquals(m.d, 1 / Math.sqrt(2)); + equals(m.e, 0); + equals(m.f, 0); + + tearDown(); + }); + + test('Test SVGTransformList.init() for rotate(45, 100, 200)', function () { + expect(9); + setUp(); + rect.setAttribute('transform', 'rotate(45, 100, 200)'); + + var rxform = svgedit.transformlist.getTransformList(rect); + equals(1, rxform.numberOfItems); + + var rotate = rxform.getItem(0); + equals(4, rotate.type); + equals(45, rotate.angle); + + var m = rotate.matrix; + almostEquals(m.a, 1 / Math.sqrt(2)); + almostEquals(m.b, 1 / Math.sqrt(2)); + almostEquals(m.c, -1 / Math.sqrt(2)); + almostEquals(m.d, 1 / Math.sqrt(2)); + + var r = svgcontent.createSVGMatrix(); + r.a = 1 / Math.sqrt(2); r.b = 1 / Math.sqrt(2); + r.c = -1 / Math.sqrt(2); r.d = 1 / Math.sqrt(2); + + var t = svgcontent.createSVGMatrix(); + t.e = -100; t.f = -200; + + var t_ = svgcontent.createSVGMatrix(); + t_.e = 100; t_.f = 200; + + var result = t_.multiply(r).multiply(t); + + almostEquals(m.e, result.e); + almostEquals(m.f, result.f); + + tearDown(); + }); + + test('Test SVGTransformList.init() for matrix(1, 2, 3, 4, 5, 6)', function () { + expect(8); + setUp(); + rect.setAttribute('transform', 'matrix(1,2,3,4,5,6)'); + + var rxform = svgedit.transformlist.getTransformList(rect); + equals(1, rxform.numberOfItems); + + var mt = rxform.getItem(0); + equals(1, mt.type); + + var m = mt.matrix; + equals(m.a, 1); + equals(m.b, 2); + equals(m.c, 3); + equals(m.d, 4); + equals(m.e, 5); + equals(m.f, 6); + + tearDown(); + }); +}); diff --git a/test/svgutils_bbox_test.html b/test/svgutils_bbox_test.html index 76b5c3ab..f1677022 100644 --- a/test/svgutils_bbox_test.html +++ b/test/svgutils_bbox_test.html @@ -16,504 +16,7 @@ - +

Unit Tests for svgutils.js BBox functions

diff --git a/test/svgutils_bbox_test.js b/test/svgutils_bbox_test.js new file mode 100644 index 00000000..0f1886a5 --- /dev/null +++ b/test/svgutils_bbox_test.js @@ -0,0 +1,499 @@ +/* eslint-env qunit */ +/* globals $, svgedit */ +/* eslint-disable no-var */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + + function mockCreateSVGElement (jsonMap) { + var elem = document.createElementNS(svgedit.NS.SVG, jsonMap['element']); + for (var attr in jsonMap['attr']) { + elem.setAttribute(attr, jsonMap['attr'][attr]); + } + return elem; + } + var mockAddSvgElementFromJsonCallCount = 0; + function mockAddSvgElementFromJson (json) { + var elem = mockCreateSVGElement(json); + svgroot.appendChild(elem); + mockAddSvgElementFromJsonCallCount++; + return elem; + } + var mockPathActions = { + resetOrientation: function (path) { + if (path == null || path.nodeName !== 'path') { return false; } + var tlist = svgedit.transformlist.getTransformList(path); + var m = svgedit.math.transformListToTransform(tlist).matrix; + tlist.clear(); + path.removeAttribute('transform'); + var segList = path.pathSegList; + + var len = segList.numberOfItems; + var i, last_x, last_y; + + for (i = 0; i < len; ++i) { + var seg = segList.getItem(i); + var type = seg.pathSegType; + if (type == 1) {continue;} + var pts = []; + $.each(['',1,2], function(j, n) { + var x = seg['x'+n], y = seg['y'+n]; + if (x !== undefined && y !== undefined) { + var pt = svgedit.math.transformPoint(x, y, m); + pts.splice(pts.length, 0, pt.x, pt.y); + } + }); + svgedit.path.replacePathSeg(type, i, pts, path); + } + + //svgedit.utilities.reorientGrads(path, m); + } + } + + var EPSILON = 0.001 + var svg = document.createElementNS(svgedit.NS.SVG, 'svg'); + var sandbox = document.getElementById('sandbox'); + var svgroot = mockCreateSVGElement({ + 'element': 'svg', + 'attr': {'id': 'svgroot'} + }); + sandbox.appendChild(svgroot); + + + module('svgedit.utilities_bbox', { + setup: function() { + // We're reusing ID's so we need to do this for transforms. + svgedit.transformlist.resetListMap(); + svgedit.path.init(null); + mockAddSvgElementFromJsonCallCount = 0; + }, + teardown: function() { + } + }); + + + test('Test svgedit.utilities package', function() { + ok(svgedit.utilities); + ok(svgedit.utilities.getBBoxWithTransform); + ok(svgedit.utilities.getStrokedBBox); + ok(svgedit.utilities.getRotationAngleFromTransformList); + ok(svgedit.utilities.getRotationAngle); + }); + + + test("Test getBBoxWithTransform and no transform", function() { + var getBBoxWithTransform = svgedit.utilities.getBBoxWithTransform + + var bbox; + var elem = mockCreateSVGElement({ + 'element': 'path', + 'attr': { 'id': 'path', 'd': 'M0,1 L2,3'} + }); + svgroot.appendChild(elem); + bbox = getBBoxWithTransform(elem, mockAddSvgElementFromJson, mockPathActions); + deepEqual(bbox, {x: 0, y: 1, width: 2, height: 2}); + equal(mockAddSvgElementFromJsonCallCount, 0); + svgroot.removeChild(elem); + + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': {'id': 'rect', 'x': '0', 'y': '1', 'width': '5', 'height': '10'} + }); + svgroot.appendChild(elem); + bbox = getBBoxWithTransform( elem, mockAddSvgElementFromJson, mockPathActions) + deepEqual(bbox, { "x": 0, "y": 1, "width": 5, "height": 10}); + equal(mockAddSvgElementFromJsonCallCount, 0); + svgroot.removeChild(elem); + + elem = mockCreateSVGElement({ + 'element': 'line', + 'attr': {'id': 'line', 'x1': '0', 'y1': '1', 'x2': '5', 'y2': '6'} + }); + svgroot.appendChild(elem); + bbox = getBBoxWithTransform(elem, mockAddSvgElementFromJson, mockPathActions) + deepEqual( bbox, { "x": 0, "y": 1, "width": 5, "height": 5}); + equal( mockAddSvgElementFromJsonCallCount, 0); + svgroot.removeChild( elem); + + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': { 'id': 'rect', 'x': '0', 'y': '1', 'width': '5', 'height': '10'} + }); + var g = mockCreateSVGElement({ + 'element': 'g', + 'attr': {} + }); + g.appendChild( elem); + svgroot.appendChild( g); + bbox = getBBoxWithTransform( elem, mockAddSvgElementFromJson, mockPathActions) + deepEqual( bbox, { "x": 0, "y": 1, "width": 5, "height": 10}); + equal( mockAddSvgElementFromJsonCallCount, 0); + svgroot.removeChild( g); + + }); + + + test("Test getBBoxWithTransform and a rotation transform", function() { + var getBBoxWithTransform = svgedit.utilities.getBBoxWithTransform + + var bbox; + var elem = mockCreateSVGElement({ + 'element': 'path', + 'attr': { 'id': 'path', 'd': 'M10,10 L20,20', 'transform': 'rotate(45 10,10)'} + }); + svgroot.appendChild( elem) + bbox = getBBoxWithTransform(elem, mockAddSvgElementFromJson, mockPathActions); + close( bbox.x, 10, EPSILON); + close( bbox.y, 10, EPSILON); + close( bbox.width, 0, EPSILON); + close( bbox.height, Math.sqrt(100 + 100), EPSILON); + svgroot.removeChild( elem); + + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': { 'id': 'rect', 'x': '10', 'y': '10', 'width': '10', 'height': '20', 'transform': 'rotate(90 15,20)'} + }); + svgroot.appendChild( elem); + bbox = getBBoxWithTransform( elem, mockAddSvgElementFromJson, mockPathActions); + close( bbox.x, 5, EPSILON); + close( bbox.y, 15, EPSILON); + close( bbox.width, 20, EPSILON); + close( bbox.height, 10, EPSILON); + equal( mockAddSvgElementFromJsonCallCount, 1); + svgroot.removeChild( elem); + + var rect = {x: 10, y: 10, width: 10, height: 20}; + var angle = 45; + var origin = { x: 15, y: 20}; + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': { 'id': 'rect2', 'x': rect.x, 'y': rect.y, 'width': rect.width, 'height': rect.height, 'transform': 'rotate(' + angle + ' ' + origin.x + ',' + origin.y + ')'} + }); + svgroot.appendChild( elem); + mockAddSvgElementFromJsonCallCount = 0; + bbox = getBBoxWithTransform( elem, mockAddSvgElementFromJson, mockPathActions); + var r2 = rotateRect( rect, angle, origin); + close( bbox.x, r2.x, EPSILON, 'rect2 x is ' + r2.x); + close( bbox.y, r2.y, EPSILON, 'rect2 y is ' + r2.y); + close( bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width); + close( bbox.height, r2.height, EPSILON, 'rect2 height is ' + r2.height); + equal( mockAddSvgElementFromJsonCallCount, 0); + svgroot.removeChild( elem); + + + // Same as previous but wrapped with g and the transform is with the g. + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': { 'id': 'rect3', 'x': rect.x, 'y': rect.y, 'width': rect.width, 'height': rect.height} + }); + var g = mockCreateSVGElement({ + 'element': 'g', + 'attr': {'transform': 'rotate(' + angle + ' ' + origin.x + ',' + origin.y + ')'} + }); + g.appendChild( elem); + svgroot.appendChild( g); + mockAddSvgElementFromJsonCallCount = 0; + bbox = getBBoxWithTransform( g, mockAddSvgElementFromJson, mockPathActions); + close( bbox.x, r2.x, EPSILON, 'rect2 x is ' + r2.x); + close( bbox.y, r2.y, EPSILON, 'rect2 y is ' + r2.y); + close( bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width); + close( bbox.height, r2.height, EPSILON, 'rect2 height is ' + r2.height); + equal( mockAddSvgElementFromJsonCallCount, 0); + svgroot.removeChild( g); + + + elem = mockCreateSVGElement({ + 'element': 'ellipse', + 'attr': { 'id': 'ellipse1', 'cx': '100', 'cy': '100', 'rx': '50', 'ry': '50', 'transform': 'rotate(45 100,100)'} + }); + svgroot.appendChild( elem); + mockAddSvgElementFromJsonCallCount = 0; + bbox = getBBoxWithTransform( elem, mockAddSvgElementFromJson, mockPathActions); + // TODO: the BBox algorithm is using the bezier control points to calculate the bounding box. Should be 50, 50, 100, 100. + ok( bbox.x > 45 && bbox.x <= 50); + ok( bbox.y > 45 && bbox.y <= 50); + ok( bbox.width >= 100 && bbox.width < 110); + ok( bbox.height >= 100 && bbox.height < 110); + equal( mockAddSvgElementFromJsonCallCount, 1); + svgroot.removeChild( elem); + + }); + + + + test("Test getBBoxWithTransform with rotation and matrix transforms", function() { + var getBBoxWithTransform = svgedit.utilities.getBBoxWithTransform + + var bbox; + var tx = 10; // tx right + var ty = 10; // tx down + var txInRotatedSpace = Math.sqrt(tx*tx + ty*ty); // translate in rotated 45 space. + var tyInRotatedSpace = 0; + var matrix = 'matrix(1,0,0,1,' + txInRotatedSpace + ',' + tyInRotatedSpace + ')' + var elem = mockCreateSVGElement({ + 'element': 'path', + 'attr': { 'id': 'path', 'd': 'M10,10 L20,20', 'transform': 'rotate(45 10,10) ' + matrix} + }); + svgroot.appendChild( elem) + bbox = getBBoxWithTransform(elem, mockAddSvgElementFromJson, mockPathActions) + close( bbox.x, 10 + tx, EPSILON); + close( bbox.y, 10 + ty, EPSILON); + close( bbox.width, 0, EPSILON) + close( bbox.height, Math.sqrt(100 + 100), EPSILON) + svgroot.removeChild( elem); + + txInRotatedSpace = tx; // translate in rotated 90 space. + tyInRotatedSpace = -ty; + matrix = 'matrix(1,0,0,1,' + txInRotatedSpace + ',' + tyInRotatedSpace + ')' + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': { 'id': 'rect', 'x': '10', 'y': '10', 'width': '10', 'height': '20', 'transform': 'rotate(90 15,20) ' + matrix} + }); + svgroot.appendChild( elem); + bbox = getBBoxWithTransform( elem, mockAddSvgElementFromJson, mockPathActions) + close( bbox.x, 5 + tx, EPSILON); + close( bbox.y, 15 + ty, EPSILON); + close( bbox.width, 20, EPSILON); + close( bbox.height, 10, EPSILON); + svgroot.removeChild( elem); + + var rect = {x: 10, y: 10, width: 10, height: 20} + var angle = 45 + var origin = { x: 15, y: 20} + tx = 10; // tx right + ty = 10; // tx down + txInRotatedSpace = Math.sqrt(tx*tx + ty*ty); // translate in rotated 45 space. + tyInRotatedSpace = 0; + matrix = 'matrix(1,0,0,1,' + txInRotatedSpace + ',' + tyInRotatedSpace + ')' + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': { 'id': 'rect2', 'x': rect.x, 'y': rect.y, 'width': rect.width, 'height': rect.height, 'transform': 'rotate(' + angle + ' ' + origin.x + ',' + origin.y + ') ' + matrix} + }); + svgroot.appendChild( elem); + bbox = getBBoxWithTransform( elem, mockAddSvgElementFromJson, mockPathActions) + var r2 = rotateRect( rect, angle, origin) + close( bbox.x, r2.x + tx, EPSILON, 'rect2 x is ' + r2.x); + close( bbox.y, r2.y + ty, EPSILON, 'rect2 y is ' + r2.y); + close( bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width); + close( bbox.height, r2.height, EPSILON, 'rect2 height is ' + r2.height); + svgroot.removeChild( elem); + + + // Same as previous but wrapped with g and the transform is with the g. + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': { 'id': 'rect3', 'x': rect.x, 'y': rect.y, 'width': rect.width, 'height': rect.height} + }); + var g = mockCreateSVGElement({ + 'element': 'g', + 'attr': {'transform': 'rotate(' + angle + ' ' + origin.x + ',' + origin.y + ') ' + matrix} + }); + g.appendChild( elem); + svgroot.appendChild( g); + bbox = getBBoxWithTransform( g, mockAddSvgElementFromJson, mockPathActions) + close( bbox.x, r2.x + tx, EPSILON, 'rect2 x is ' + r2.x); + close( bbox.y, r2.y + ty, EPSILON, 'rect2 y is ' + r2.y); + close( bbox.width, r2.width, EPSILON, 'rect2 width is' + r2.width); + close( bbox.height, r2.height, EPSILON, 'rect2 height is ' + r2.height); + svgroot.removeChild( g); + + + elem = mockCreateSVGElement({ + 'element': 'ellipse', + 'attr': { 'id': 'ellipse1', 'cx': '100', 'cy': '100', 'rx': '50', 'ry': '50', 'transform': 'rotate(45 100,100) ' + matrix} + }); + svgroot.appendChild( elem); + bbox = getBBoxWithTransform( elem, mockAddSvgElementFromJson, mockPathActions) + // TODO: the BBox algorithm is using the bezier control points to calculate the bounding box. Should be 50, 50, 100, 100. + ok( bbox.x > 45 + tx && bbox.x <= 50 + tx); + ok( bbox.y > 45 + ty && bbox.y <= 50 + ty); + ok( bbox.width >= 100 && bbox.width < 110); + ok( bbox.height >= 100 && bbox.height < 110); + svgroot.removeChild( elem); + + }); + + + test("Test getStrokedBBox with stroke-width 10", function() { + var getStrokedBBox = svgedit.utilities.getStrokedBBox + + var bbox; + var strokeWidth = 10 + var elem = mockCreateSVGElement({ + 'element': 'path', + 'attr': { 'id': 'path', 'd': 'M0,1 L2,3', 'stroke-width': strokeWidth} + }); + svgroot.appendChild( elem) + bbox = getStrokedBBox( [elem], mockAddSvgElementFromJson, mockPathActions) + deepEqual(bbox, {"x": 0 - strokeWidth / 2, "y": 1 - strokeWidth / 2, "width": 2 + strokeWidth, "height": 2 + strokeWidth}); + svgroot.removeChild( elem); + + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': { 'id': 'rect', 'x': '0', 'y': '1', 'width': '5', 'height': '10', 'stroke-width': strokeWidth} + }); + svgroot.appendChild( elem); + bbox = getStrokedBBox( [elem], mockAddSvgElementFromJson, mockPathActions) + deepEqual( bbox, { "x": 0 - strokeWidth / 2, "y": 1 - strokeWidth / 2, "width": 5 + strokeWidth, "height": 10 + strokeWidth}); + svgroot.removeChild( elem); + + elem = mockCreateSVGElement({ + 'element': 'line', + 'attr': { 'id': 'line', 'x1': '0', 'y1': '1', 'x2': '5', 'y2': '6', 'stroke-width': strokeWidth} + }); + svgroot.appendChild( elem); + bbox = getStrokedBBox( [elem], mockAddSvgElementFromJson, mockPathActions) + deepEqual( bbox, { "x": 0 - strokeWidth / 2, "y": 1 - strokeWidth / 2, "width": 5 + strokeWidth, "height": 5 + strokeWidth}); + svgroot.removeChild( elem); + + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': { 'id': 'rect', 'x': '0', 'y': '1', 'width': '5', 'height': '10', 'stroke-width': strokeWidth} + }); + var g = mockCreateSVGElement({ + 'element': 'g', + 'attr': {} + }); + g.appendChild( elem); + svgroot.appendChild( g); + bbox = getStrokedBBox( [elem], mockAddSvgElementFromJson, mockPathActions) + deepEqual( bbox, { "x": 0 - strokeWidth / 2, "y": 1 - strokeWidth / 2, "width": 5 + strokeWidth, "height": 10 + strokeWidth}); + svgroot.removeChild( g); + + }); + + + test("Test getStrokedBBox with stroke-width 'none'", function() { + var getStrokedBBox = svgedit.utilities.getStrokedBBox + + var bbox; + var elem = mockCreateSVGElement({ + 'element': 'path', + 'attr': { 'id': 'path', 'd': 'M0,1 L2,3', 'stroke-width': 'none'} + }); + svgroot.appendChild( elem) + bbox = getStrokedBBox( [elem], mockAddSvgElementFromJson, mockPathActions) + deepEqual(bbox, {"x": 0, "y": 1, "width": 2, "height": 2}); + svgroot.removeChild( elem); + + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': { 'id': 'rect', 'x': '0', 'y': '1', 'width': '5', 'height': '10', 'stroke-width': 'none'} + }); + svgroot.appendChild( elem); + bbox = getStrokedBBox( [elem], mockAddSvgElementFromJson, mockPathActions) + deepEqual( bbox, { "x": 0, "y": 1, "width": 5, "height": 10}); + svgroot.removeChild( elem); + + elem = mockCreateSVGElement({ + 'element': 'line', + 'attr': { 'id': 'line', 'x1': '0', 'y1': '1', 'x2': '5', 'y2': '6', 'stroke-width': 'none'} + }); + svgroot.appendChild( elem); + bbox = getStrokedBBox( [elem], mockAddSvgElementFromJson, mockPathActions) + deepEqual( bbox, { "x": 0, "y": 1, "width": 5, "height": 5}); + svgroot.removeChild( elem); + + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': { 'id': 'rect', 'x': '0', 'y': '1', 'width': '5', 'height': '10', 'stroke-width': 'none'} + }); + var g = mockCreateSVGElement({ + 'element': 'g', + 'attr': {} + }); + g.appendChild( elem); + svgroot.appendChild( g); + bbox = getStrokedBBox( [elem], mockAddSvgElementFromJson, mockPathActions) + deepEqual( bbox, { "x": 0, "y": 1, "width": 5, "height": 10}); + svgroot.removeChild( g); + + }); + + + test("Test getStrokedBBox with no stroke-width attribute", function() { + var getStrokedBBox = svgedit.utilities.getStrokedBBox + + var bbox; + var elem = mockCreateSVGElement({ + 'element': 'path', + 'attr': { 'id': 'path', 'd': 'M0,1 L2,3'} + }); + svgroot.appendChild( elem) + bbox = getStrokedBBox( [elem], mockAddSvgElementFromJson, mockPathActions) + deepEqual(bbox, {"x": 0, "y": 1, "width": 2, "height": 2}); + svgroot.removeChild( elem); + + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': { 'id': 'rect', 'x': '0', 'y': '1', 'width': '5', 'height': '10'} + }); + svgroot.appendChild( elem); + bbox = getStrokedBBox( [elem], mockAddSvgElementFromJson, mockPathActions) + deepEqual( bbox, { "x": 0, "y": 1, "width": 5, "height": 10}); + svgroot.removeChild( elem); + + elem = mockCreateSVGElement({ + 'element': 'line', + 'attr': { 'id': 'line', 'x1': '0', 'y1': '1', 'x2': '5', 'y2': '6'} + }); + svgroot.appendChild( elem); + bbox = getStrokedBBox( [elem], mockAddSvgElementFromJson, mockPathActions) + deepEqual( bbox, { "x": 0, "y": 1, "width": 5, "height": 5}); + svgroot.removeChild( elem); + + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': { 'id': 'rect', 'x': '0', 'y': '1', 'width': '5', 'height': '10'} + }); + var g = mockCreateSVGElement({ + 'element': 'g', + 'attr': {} + }); + g.appendChild( elem); + svgroot.appendChild( g); + bbox = getStrokedBBox( [elem], mockAddSvgElementFromJson, mockPathActions) + deepEqual( bbox, { "x": 0, "y": 1, "width": 5, "height": 10}); + svgroot.removeChild( g); + + }); + + + function radians( degrees) { + return degrees * Math.PI / 180; + } + function rotatePoint( point, angle, origin) { + if( !origin) + origin = {x: 0, y: 0}; + var x = point.x - origin.x; + var y = point.y - origin.y; + var theta = radians( angle); + return { + x: x * Math.cos(theta) + y * Math.sin(theta) + origin.x, + y: x * Math.sin(theta) + y * Math.cos(theta) + origin.y + } + } + function rotateRect( rect, angle, origin) { + var tl = rotatePoint( { x: rect.x, y: rect.y}, angle, origin); + var tr = rotatePoint( { x: rect.x + rect.width, y: rect.y}, angle, origin); + var br = rotatePoint( { x: rect.x + rect.width, y: rect.y + rect.height}, angle, origin); + var bl = rotatePoint( { x: rect.x, y: rect.y + rect.height}, angle, origin); + + var minx = Math.min(tl.x, tr.x, bl.x, br.x); + var maxx = Math.max(tl.x, tr.x, bl.x, br.x); + var miny = Math.min(tl.y, tr.y, bl.y, br.y); + var maxy = Math.max(tl.y, tr.y, bl.y, br.y); + + return { + x: minx, + y: miny, + width: (maxx - minx), + height: (maxy - miny) + }; + } + +}); diff --git a/test/svgutils_performance_test.html b/test/svgutils_performance_test.html index e7b94749..26bffb62 100644 --- a/test/svgutils_performance_test.html +++ b/test/svgutils_performance_test.html @@ -18,179 +18,7 @@ - +

Performance Unit Tests for svgutils.js

diff --git a/test/svgutils_performance_test.js b/test/svgutils_performance_test.js new file mode 100644 index 00000000..4ee07bbf --- /dev/null +++ b/test/svgutils_performance_test.js @@ -0,0 +1,164 @@ +/* eslint-env qunit */ +/* globals $, svgedit */ +/* eslint-disable no-var */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + + var currentLayer = document.getElementById('layer1'); + + function mockCreateSVGElement (jsonMap) { + var elem = document.createElementNS(svgedit.NS.SVG, jsonMap['element']); + for (var attr in jsonMap['attr']) { + elem.setAttribute(attr, jsonMap['attr'][attr]); + } + return elem; + } + function mockAddSvgElementFromJson (json) { + var elem = mockCreateSVGElement(json); + currentLayer.appendChild(elem); + return elem; + } + + // var svg = document.createElementNS(svgedit.NS.SVG, 'svg'); + var groupWithMatrixTransform = document.getElementById('svg_group_with_matrix_transform'); + var textWithMatrixTransform = document.getElementById('svg_text_with_matrix_transform'); + + function fillDocumentByCloningElement (elem, count) { + var elemId = elem.getAttribute('id') + '-'; + for (var index = 0; index < count; index++) { + var clone = elem.cloneNode(true); // t: deep clone + // Make sure you set a unique ID like a real document. + clone.setAttribute('id', elemId + index); + var parent = elem.parentNode; + parent.appendChild(clone); + } + } + + module('svgedit.utilities_performance', { + setup: function () { + }, + teardown: function () { + } + }); + + var mockPathActions = { + resetOrientation: function (path) { + if (path == null || path.nodeName !== 'path') { return false; } + var tlist = svgedit.transformlist.getTransformList(path); + var m = svgedit.math.transformListToTransform(tlist).matrix; + tlist.clear(); + path.removeAttribute('transform'); + var segList = path.pathSegList; + + var len = segList.numberOfItems; + var i; // , lastX, lastY; + + for (i = 0; i < len; ++i) { + var seg = segList.getItem(i); + var type = seg.pathSegType; + if (type === 1) { continue; } + var pts = []; + $.each(['', 1, 2], function (j, n) { + var x = seg['x' + n], y = seg['y' + n]; + if (x !== undefined && y !== undefined) { + var pt = svgedit.math.transformPoint(x, y, m); + pts.splice(pts.length, 0, pt.x, pt.y); + } + }); + // svgedit.path.replacePathSeg(type, i, pts, path); + } + + // svgedit.utilities.reorientGrads(path, m); + } + }; + + // ////////////////////////////////////////////////////////// + // Performance times with various browsers on Macbook 2011 8MB RAM OS X El Capitan 10.11.4 + // + // To see 'Before Optimization' performance, making the following two edits. + // 1. svgedit.utilities.getStrokedBBox - change if( elems.length === 1) to if( false && elems.length === 1) + // 2. svgedit.utilities.getBBoxWithTransform - uncomment 'Old technique that was very slow' + + // Chrome + // Before Optimization + // Pass1 svgCanvas.getStrokedBBox total ms 4,218, ave ms 41.0, min/max 37 51 + // Pass2 svgCanvas.getStrokedBBox total ms 4,458, ave ms 43.3, min/max 32 63 + // Optimized Code + // Pass1 svgCanvas.getStrokedBBox total ms 1,112, ave ms 10.8, min/max 9 20 + // Pass2 svgCanvas.getStrokedBBox total ms 34, ave ms 0.3, min/max 0 20 + + // Firefox + // Before Optimization + // Pass1 svgCanvas.getStrokedBBox total ms 3,794, ave ms 36.8, min/max 33 48 + // Pass2 svgCanvas.getStrokedBBox total ms 4,049, ave ms 39.3, min/max 28 53 + // Optimized Code + // Pass1 svgCanvas.getStrokedBBox total ms 104, ave ms 1.0, min/max 0 23 + // Pass2 svgCanvas.getStrokedBBox total ms 71, ave ms 0.7, min/max 0 23 + + // Safari + // Before Optimization + // Pass1 svgCanvas.getStrokedBBox total ms 4,840, ave ms 47.0, min/max 45 62 + // Pass2 svgCanvas.getStrokedBBox total ms 4,849, ave ms 47.1, min/max 34 62 + // Optimized Code + // Pass1 svgCanvas.getStrokedBBox total ms 42, ave ms 0.4, min/max 0 23 + // Pass2 svgCanvas.getStrokedBBox total ms 17, ave ms 0.2, min/max 0 23 + + asyncTest('Test svgCanvas.getStrokedBBox() performance with matrix transforms', function () { + expect(2); + var getStrokedBBox = svgedit.utilities.getStrokedBBox; + var children = currentLayer.children; + + var index, count, child, start, delta, lastTime, now, ave, + min = Number.MAX_VALUE, + max = 0, + total = 0; + + fillDocumentByCloningElement(groupWithMatrixTransform, 50); + fillDocumentByCloningElement(textWithMatrixTransform, 50); + + // The first pass through all elements is slower. + count = children.length; + start = lastTime = now = Date.now(); + // Skip the first child which is the title. + for (index = 1; index < count; index++) { + child = children[index]; + /* var obj = */ getStrokedBBox([child], mockAddSvgElementFromJson, mockPathActions); + now = Date.now(); delta = now - lastTime; lastTime = now; + total += delta; + min = Math.min(min, delta); + max = Math.max(max, delta); + } + total = lastTime - start; + ave = total / count; + ok(ave < 20, 'svgedit.utilities.getStrokedBBox average execution time is less than 20 ms'); + console.log('Pass1 svgCanvas.getStrokedBBox total ms ' + total + ', ave ms ' + ave.toFixed(1) + ', min/max ' + min + ' ' + max); + + // The second pass is two to ten times faster. + setTimeout(function () { + count = children.length; + + start = lastTime = now = Date.now(); + // Skip the first child which is the title. + for (index = 1; index < count; index++) { + child = children[index]; + /* var obj = */ getStrokedBBox([child], mockAddSvgElementFromJson, mockPathActions); + now = Date.now(); delta = now - lastTime; lastTime = now; + total += delta; + min = Math.min(min, delta); + max = Math.max(max, delta); + } + + total = lastTime - start; + ave = total / count; + ok(ave < 2, 'svgedit.utilities.getStrokedBBox average execution time is less than 1 ms'); + console.log('Pass2 svgCanvas.getStrokedBBox total ms ' + total + ', ave ms ' + ave.toFixed(1) + ', min/max ' + min + ' ' + max); + + QUnit.start(); + }); + }); +}); diff --git a/test/svgutils_test.html b/test/svgutils_test.html index afaaaefb..149c5a63 100644 --- a/test/svgutils_test.html +++ b/test/svgutils_test.html @@ -13,349 +13,7 @@ - +

Unit Tests for svgutils.js

diff --git a/test/svgutils_test.js b/test/svgutils_test.js new file mode 100644 index 00000000..6d609f55 --- /dev/null +++ b/test/svgutils_test.js @@ -0,0 +1,337 @@ +/* eslint-env qunit */ +/* globals $, svgedit, equals */ +/* eslint-disable no-var */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + + function mockCreateSVGElement (jsonMap) { + var elem = document.createElementNS(svgedit.NS.SVG, jsonMap['element']); + for (var attr in jsonMap['attr']) { + elem.setAttribute(attr, jsonMap['attr'][attr]); + } + return elem; + } + function mockAddSvgElementFromJson (json) { + var elem = mockCreateSVGElement(json); + svgroot.appendChild(elem); + return elem; + } + var mockPathActions = {resetOrientation: function () {}}; + var mockHistorySubCommands = []; + var mockHistory = { + BatchCommand: function () { + return { + addSubCommand: function (cmd) { mockHistorySubCommands.push(cmd); } + }; + }, + RemoveElementCommand: function (elem, nextSibling, parent) { + this.elem = elem; + this.nextSibling = nextSibling; + this.parent = parent; + }, + InsertElementCommand: function (path) { + this.path = path; + } + }; + var mockCount = { + clearSelection: 0, + addToSelection: 0, + addCommandToHistory: 0 + }; + function mockClearSelection () { mockCount.clearSelection++; } + function mockAddToSelection () { mockCount.addToSelection++; } + function mockAddCommandToHistory () { mockCount.addCommandToHistory++; } + + var svg = document.createElementNS(svgedit.NS.SVG, 'svg'); + var sandbox = document.getElementById('sandbox'); + var svgroot = mockCreateSVGElement({ + 'element': 'svg', + 'attr': {'id': 'svgroot'} + }); + sandbox.appendChild(svgroot); + + module('svgedit.utilities', { + setup: function () { + mockHistorySubCommands = []; + mockCount.clearSelection = 0; + mockCount.addToSelection = 0; + mockCount.addCommandToHistory = 0; + }, + teardown: function () { + } + }); + + test('Test svgedit.utilities package', function () { + expect(3); + + ok(svgedit.utilities); + ok(svgedit.utilities.toXml); + equals(typeof svgedit.utilities.toXml, typeof function () {}); + }); + + test('Test svgedit.utilities.toXml() function', function () { + expect(6); + var toXml = svgedit.utilities.toXml; + + equals(toXml('a'), 'a'); + equals(toXml('ABC_'), 'ABC_'); + equals(toXml('PB&J'), 'PB&J'); + equals(toXml('2 < 5'), '2 < 5'); + equals(toXml('5 > 2'), '5 > 2'); + equals(toXml('\'<&>"'), ''<&>"'); + }); + + test('Test svgedit.utilities.fromXml() function', function () { + expect(6); + var fromXml = svgedit.utilities.fromXml; + + equals(fromXml('a'), 'a'); + equals(fromXml('ABC_'), 'ABC_'); + equals(fromXml('PB&J'), 'PB&J'); + equals(fromXml('2 < 5'), '2 < 5'); + equals(fromXml('5 > 2'), '5 > 2'); + equals(fromXml('<&>'), '<&>'); + }); + + test('Test svgedit.utilities.encode64() function', function () { + expect(4); + var encode64 = svgedit.utilities.encode64; + + equals(encode64('abcdef'), 'YWJjZGVm'); + equals(encode64('12345'), 'MTIzNDU='); + equals(encode64(' '), 'IA=='); + equals(encode64('`~!@#$%^&*()-_=+[{]}\\|;:\'",<.>/?'), 'YH4hQCMkJV4mKigpLV89K1t7XX1cfDs6JyIsPC4+Lz8='); + }); + + test('Test svgedit.utilities.decode64() function', function () { + expect(4); + var decode64 = svgedit.utilities.decode64; + + equals(decode64('YWJjZGVm'), 'abcdef'); + equals(decode64('MTIzNDU='), '12345'); + equals(decode64('IA=='), ' '); + equals(decode64('YH4hQCMkJV4mKigpLV89K1t7XX1cfDs6JyIsPC4+Lz8='), '`~!@#$%^&*()-_=+[{]}\\|;:\'",<.>/?'); + }); + + test('Test svgedit.utilities.convertToXMLReferences() function', function () { + expect(1); + + var convert = svgedit.utilities.convertToXMLReferences; + equals(convert('ABC'), 'ABC'); + // equals(convert('�BC'), 'ÀBC'); + }); + + test('Test svgedit.utilities.bboxToObj() function', function () { + expect(5); + var bboxToObj = svgedit.utilities.bboxToObj; + + var rect = svg.createSVGRect(); + rect.x = 1; + rect.y = 2; + rect.width = 3; + rect.height = 4; + + var obj = bboxToObj(rect); + equals(typeof obj, typeof {}); + equals(obj.x, 1); + equals(obj.y, 2); + equals(obj.width, 3); + equals(obj.height, 4); + }); + + test('Test getUrlFromAttr', function () { + expect(4); + + equal(svgedit.utilities.getUrlFromAttr('url(#foo)'), '#foo'); + equal(svgedit.utilities.getUrlFromAttr('url(somefile.svg#foo)'), 'somefile.svg#foo'); + equal(svgedit.utilities.getUrlFromAttr('url("#foo")'), '#foo'); + equal(svgedit.utilities.getUrlFromAttr('url("#foo")'), '#foo'); + }); + + test('Test getPathBBox', function () { + if (svgedit.browser.supportsPathBBox()) return; + var doc = svgedit.utilities.text2xml(''); + var path = doc.createElementNS(svgedit.NS.SVG, 'path'); + path.setAttributeNS(null, 'd', 'm0,0l5,0l0,5l-5,0l0,-5z'); + var bb = svgedit.utilities.getPathBBox(path); + equals(typeof bb, 'object', 'BBox returned object'); + ok(bb.x && !isNaN(bb.x)); + ok(bb.y && !isNaN(bb.y)); + }); + + test('Test getPathDFromSegments', function () { + var d; + var getPathDFromSegments = svgedit.utilities.getPathDFromSegments; + + var doc = svgedit.utilities.text2xml(''); + var path = doc.createElementNS(svgedit.NS.SVG, 'path'); + path.setAttributeNS(null, 'd', 'm0,0l5,0l0,5l-5,0l0,-5z'); + d = getPathDFromSegments([ + ['M', [1, 2]], + ['Z', []] + ]); + equal(d, 'M1,2 Z'); + + d = getPathDFromSegments([ + ['M', [1, 2]], + ['M', [3, 4]], + ['Z', []] + ]); + equal(d, 'M1,2 M3,4 Z'); + + d = getPathDFromSegments([ + ['M', [1, 2]], + ['C', [3, 4, 5, 6]], + ['Z', []] + ]); + equal(d, 'M1,2 C3,4 5,6 Z'); + }); + + test('Test getPathDFromElement', function () { + var getPathDFromElement = svgedit.utilities.getPathDFromElement; + + var elem = mockCreateSVGElement({ + 'element': 'path', + 'attr': {'id': 'path', 'd': 'M0,1 Z'} + }); + svgroot.appendChild(elem); + equal(getPathDFromElement(elem), 'M0,1 Z'); + svgroot.removeChild(elem); + + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': {'id': 'rect', 'x': '0', 'y': '1', 'width': '5', 'height': '10'} + }); + svgroot.appendChild(elem); + equal(getPathDFromElement(elem), 'M0,1 L5,1 L5,11 L0,11 L0,1 Z'); + svgroot.removeChild(elem); + + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': {'id': 'roundrect', 'x': '0', 'y': '1', 'rx': '2', 'ry': '3', 'width': '10', 'height': '11'} + }); + svgroot.appendChild(elem); + var closeEnough = new RegExp('M0,4 C0,2.3[0-9]* 0.9[0-9]*,1 2,1 L8,1 C9.0[0-9]*,1 10,2.3[0-9]* 10,4 L10,9 C10,10.6[0-9]* 9.08675799086758,12 8,12 L2,12 C0.9[0-9]*,12 0,10.6[0-9]* 0,9 L0,4 Z'); + equal(closeEnough.test(getPathDFromElement(elem)), true); + svgroot.removeChild(elem); + + elem = mockCreateSVGElement({ + 'element': 'line', + 'attr': {'id': 'line', 'x1': '0', 'y1': '1', 'x2': '5', 'y2': '6'} + }); + svgroot.appendChild(elem); + equal(getPathDFromElement(elem), 'M0,1L5,6'); + svgroot.removeChild(elem); + + elem = mockCreateSVGElement({ + 'element': 'circle', + 'attr': {'id': 'circle', 'cx': '10', 'cy': '11', 'rx': '5', 'ry': '10'} + }); + svgroot.appendChild(elem); + equal(getPathDFromElement(elem), 'M10,11 C10,11 10,11 10,11 C10,11 10,11 10,11 C10,11 10,11 10,11 C10,11 10,11 10,11 Z'); + svgroot.removeChild(elem); + + elem = mockCreateSVGElement({ + 'element': 'polyline', + 'attr': {'id': 'polyline', 'points': '0,1 5,1 5,11 0,11'} + }); + svgroot.appendChild(elem); + equal(getPathDFromElement(elem), 'M0,1 5,1 5,11 0,11'); + svgroot.removeChild(elem); + + equal(getPathDFromElement({tagName: 'something unknown'}), undefined); + }); + + test('Test getBBoxOfElementAsPath', function () { + function getBBoxOfElementAsPath (elem, addSvgElementFromJson, pathActions) { + var bbox = svgedit.utilities.getBBoxOfElementAsPath(elem, addSvgElementFromJson, pathActions); + return svgedit.utilities.bboxToObj(bbox); // need this for QUnit equal() to work. + } + + var bbox; + var elem = mockCreateSVGElement({ + 'element': 'path', + 'attr': {'id': 'path', 'd': 'M0,1 Z'} + }); + svgroot.appendChild(elem); + bbox = getBBoxOfElementAsPath(elem, mockAddSvgElementFromJson, mockPathActions); + deepEqual(bbox, {x: 0, y: 1, width: 0, height: 0}); + svgroot.removeChild(elem); + + elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': {'id': 'rect', 'x': '0', 'y': '1', 'width': '5', 'height': '10'} + }); + svgroot.appendChild(elem); + bbox = getBBoxOfElementAsPath(elem, mockAddSvgElementFromJson, mockPathActions); + deepEqual(bbox, {x: 0, y: 1, width: 5, height: 10}); + svgroot.removeChild(elem); + + elem = mockCreateSVGElement({ + 'element': 'line', + 'attr': {'id': 'line', 'x1': '0', 'y1': '1', 'x2': '5', 'y2': '6'} + }); + svgroot.appendChild(elem); + bbox = getBBoxOfElementAsPath(elem, mockAddSvgElementFromJson, mockPathActions); + deepEqual(bbox, {x: 0, y: 1, width: 5, height: 5}); + svgroot.removeChild(elem); + + // TODO: test element with transform. Need resetOrientation above to be working or mock it. + }); + + test('Test convertToPath rect', function () { + var convertToPath = svgedit.utilities.convertToPath; + var attrs = { + 'fill': 'red', + 'stroke': 'white', + 'stroke-width': '1', + 'visibility': 'hidden' + }; + + var elem = mockCreateSVGElement({ + 'element': 'rect', + 'attr': {'id': 'rect', 'x': '0', 'y': '1', 'width': '5', 'height': '10'} + }); + svgroot.appendChild(elem); + var path = convertToPath(elem, attrs, mockAddSvgElementFromJson, mockPathActions, mockClearSelection, mockAddToSelection, mockHistory, mockAddCommandToHistory); + equal(path.getAttribute('d'), 'M0,1 L5,1 L5,11 L0,11 L0,1 Z'); + equal(path.getAttribute('visibilituy'), null); + equal(path.id, 'rect'); + equal(path.parentNode, svgroot); + equal(elem.parentNode, null); + equal(mockHistorySubCommands.length, 2); + equal(mockCount.clearSelection, 1); + equal(mockCount.addToSelection, 1); + equal(mockCount.addCommandToHistory, 1); + svgroot.removeChild(path); + }); + + test('Test convertToPath unknown element', function () { + var convertToPath = svgedit.utilities.convertToPath; + var attrs = { + 'fill': 'red', + 'stroke': 'white', + 'stroke-width': '1', + 'visibility': 'hidden' + }; + + var elem = { + tagName: 'something unknown', + id: 'something-unknown', + getAttribute: function (attr) { return ''; }, + parentNode: svgroot + }; + var path = convertToPath(elem, attrs, mockAddSvgElementFromJson, mockPathActions, mockClearSelection, mockAddToSelection, mockHistory, mockAddCommandToHistory); + equal(path, null); + equal(elem.parentNode, svgroot); + equal(mockHistorySubCommands.length, 0); + equal(mockCount.clearSelection, 0); + equal(mockCount.addToSelection, 0); + equal(mockCount.addCommandToHistory, 0); + }); +}); diff --git a/test/test1.html b/test/test1.html index 89cdfe65..64d12401 100644 --- a/test/test1.html +++ b/test/test1.html @@ -26,252 +26,7 @@ - +

Unit Tests for SvgCanvas

diff --git a/test/test1.js b/test/test1.js new file mode 100644 index 00000000..d3e02c0c --- /dev/null +++ b/test/test1.js @@ -0,0 +1,247 @@ +/* eslint-env qunit */ +/* globals $ */ +/* eslint-disable no-var */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + + // helper functions + var isIdentity = function (m) { + return (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0); + }; + var matrixString = function (m) { + return [m.a, m.b, m.c, m.d, m.e, m.f].join(','); + }; + + var svgCanvas = new $.SvgCanvas( + document.getElementById('svgcanvas'), { + canvas_expansion: 3, + dimensions: [640,480], + initFill: { + color: 'FF0000', // solid red + opacity: 1 + }, + initStroke: { + width: 5, + color: '000000', // solid black + opacity: 1 + }, + initOpacity: 1, + imgPath: 'images/', + langPath: 'locale/', + extPath: 'extensions/', + extensions: ['ext-arrows.js', 'ext-connector.js', 'ext-eyedropper.js'], + initTool: 'select', + wireframe: false + }), + svgroot = document.getElementById("svgroot"), + svgdoc = svgroot.documentElement, + svgns = "http://www.w3.org/2000/svg", + xlinkns = "http://www.w3.org/1999/xlink"; + +module("Basic Module"); + +test("Test existence of SvgCanvas object", function() { + expect(1); + equal(typeof {}, typeof svgCanvas); +}); + +module("Path Module"); + +test("Test path conversion from absolute to relative", function() { + expect(6); + var convert = svgCanvas.pathActions.convertPath; + + // TODO: Test these paths: + // "m400.00491,625.01379a1.78688,1.78688 0 1 1-3.57373,0a1.78688,1.78688 0 1 13.57373,0z" + // "m36.812,15.8566c-28.03099,0 -26.28099,12.15601 -26.28099,12.15601l0.03099,12.59399h26.75v3.781h-37.37399c0,0 -17.938,-2.034 -133.00001,26.25c115.06201,28.284 130.71801,27.281 130.71801,27.281h9.34399v-13.125c0,0 -0.504,-15.656 15.40601,-15.656h26.532c0,0 14.90599,0.241 14.90599,-14.406v-24.219c0,0 2.263,-14.65601 -27.032,-14.65601zm-14.75,8.4684c2.662,0 4.813,2.151 4.813,4.813c0,2.661 -2.151,4.812 -4.813,4.812c-2.661,0 -4.812,-2.151 -4.812,-4.812c0,-2.662 2.151,-4.813 4.812,-4.813z" + // "m 0,0 l 200,0 l 0,100 L 0,100" + + svgCanvas.setSvgString("" + + "" + + "" + + ""); + + var p1 = document.getElementById("p1"), + p2 = document.getElementById("p2"), + d_abs = p1.getAttribute("d"), + seglist = p1.pathSegList, + curseg = null; + + equal(p1.nodeName, "path", "Expected 'path', got"); + + equal(seglist.numberOfItems, 4, "Number of segments before conversion"); + + // verify segments before conversion + curseg = seglist.getItem(0); + equal(curseg.pathSegTypeAsLetter.toUpperCase(), 'M', 'Before conversion, segment #1 type'); + curseg = seglist.getItem(1); + equal(curseg.pathSegTypeAsLetter.toUpperCase(), 'L', 'Before conversion, segment #2 type'); + curseg = seglist.getItem(3); + equal(curseg.pathSegTypeAsLetter.toUpperCase(), 'Z', 'Before conversion, segment #3 type' + d_abs); + + // convert and verify segments + var d = convert(p1, true); + equal(d, 'm100,100l100,0l-100,0z', 'Converted path to relative string'); + + // TODO: see why this isn't working in SVG-edit + d = convert(p2, true); + QUnit.log({result: d}); + d = convert(p2, false); + QUnit.log({result: d}); +}); + +module('Import Module'); + +test('Test import use', function() { + expect(3); + + svgCanvas.setSvgString("" + + "" + + "" + + "" + + "" + + ""); + + var u = document.getElementById("the-use"), + fu = document.getElementById("foreign-use"), + nfu = document.getElementById("no-use"); + + equal((u && u.nodeName == 'use'), true, 'Did not import element'); + equal(fu, null, 'Removed element that had a foreign href'); + equal(nfu, null, 'Removed element that had no href'); +}); + +// This test shows that an element with an invalid attribute is still parsed in properly +// and only the attribute is not imported +test('Test invalid attribute', function() { + expect(2); + + svgCanvas.setSvgString(''+ + 'words' + + ''); + + var t = document.getElementById('the-text'); + + equal(true, (t && t.nodeName === 'text'), 'Did not import element'); + equal(null, t.getAttribute("d"), "Imported a with a d attribute"); +}); + +// This test makes sure import/export properly handles namespaced attributes +test("Test importing/exporting namespaced attributes", function() { + expect(5); + var setStr = svgCanvas.setSvgString(''+ + '' + + '' + + ''); + var attrVal = document.getElementById('se_test_elem').getAttributeNS("http://svg-edit.googlecode.com", "foo"); + + equal(attrVal === "bar", true, "Preserved namespaced attribute on import"); + // + //console.log('getSvgString' in svgCanvas) + + var output = svgCanvas.getSvgString(); + //} catch(e) {console.log(e)} + //console.log('output',output); + var has_xlink = output.indexOf('xmlns:xlink="http://www.w3.org/1999/xlink"') !== -1; + var has_se = output.indexOf('xmlns:se=') !== -1; + var has_foo = output.indexOf('xmlns:foo=') !== -1; + var has_attr = output.indexOf('se:foo="bar"') !== -1; + + equal(has_attr, true, "Preserved namespaced attribute on export"); + equal(has_xlink, true, "Included xlink: xmlns"); + equal(has_se, true, "Included se: xmlns"); + equal(has_foo, false, "Did not include foo: xmlns"); +}); + +test("Test import math elements inside a foreignObject", function() { + expect(4); + var set = svgCanvas.setSvgString(''+ + ''+ + ''+ + 'A'+ + '0'+ + ''+ + ''+ + ''+ + ''); + var fo = document.getElementById('fo'); + // we cannot use getElementById('math') because not all browsers understand MathML and do not know to use the @id attribute + // see Bug https://bugs.webkit.org/show_bug.cgi?id=35042 + var math = fo.firstChild; + + equal(!!math, true, "Math element exists"); + equal(math.nodeName, 'math', "Math element has the proper nodeName"); + equal(math.getAttribute('id'), 'm', "Math element has an id"); + equal(math.namespaceURI, "http://www.w3.org/1998/Math/MathML", "Preserved MathML namespace"); +}); + +test("Test importing SVG into existing drawing", function() { + expect(3); + + var doc = svgCanvas.setSvgString(''+ + 'Layer 1'+ + ''+ + ''+ + ''+ + ''); + + svgCanvas.importSvgString(''+ + ''+ + ''+ + ''); + + var svgcontent = document.getElementById("svgcontent"), + circles = svgcontent.getElementsByTagNameNS(svgns, "circle"), + rects = svgcontent.getElementsByTagNameNS(svgns, "rect"), + ellipses = svgcontent.getElementsByTagNameNS(svgns, "ellipse"); + equal(circles.length, 2, "Found two circles upon importing"); + equal(rects.length, 1, "Found one rectangle upon importing"); + equal(ellipses.length, 1, "Found one ellipse upon importing"); +}); + +test("Test importing SVG remaps IDs", function() { + expect(6); + + var doc = svgCanvas.setSvgString(''+ + 'Layer 1'+ + ''+ + ''+ + ''+ + ''+ + ''); + + svgCanvas.importSvgString(''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''); + + var svgcontent = document.getElementById("svgcontent"), + circles = svgcontent.getElementsByTagNameNS(svgns, "circle"), + rects = svgcontent.getElementsByTagNameNS(svgns, "rect"), + ellipses = svgcontent.getElementsByTagNameNS(svgns, "ellipse"), + defs = svgcontent.getElementsByTagNameNS(svgns, "defs"), + grads = svgcontent.getElementsByTagNameNS(svgns, "linearGradient"), + uses = svgcontent.getElementsByTagNameNS(svgns, "use"); + notEqual(circles.item(0).id, "svg_1", "Circle not re-identified"); + notEqual(rects.item(0).id, "svg_3", "Rectangle not re-identified"); + // TODO: determine why this test fails in WebKit browsers + //equal(grads.length, 1, "Linear gradient imported"); + var grad = defs.item(0).firstChild; + notEqual(grad.id, "svg_2", "Linear gradient not re-identified"); + notEqual(circles.item(0).getAttribute("fill"), "url(#svg_2)", "Circle fill value not remapped"); + notEqual(rects.item(0).getAttribute("stroke"), "url(#svg_2)", "Rectangle stroke value not remapped"); + notEqual(uses.item(0).getAttributeNS(xlinkns, "href"), "#svg_3"); +}); +}); diff --git a/test/units_test.html b/test/units_test.html index efd46be4..44dacbde 100644 --- a/test/units_test.html +++ b/test/units_test.html @@ -8,88 +8,7 @@ - +

Unit Tests for units.js

diff --git a/test/units_test.js b/test/units_test.js new file mode 100644 index 00000000..1eb203c4 --- /dev/null +++ b/test/units_test.js @@ -0,0 +1,83 @@ +/* eslint-env qunit */ +/* globals $, svgedit, equals */ +/* eslint-disable no-var */ +$(function () { + // log function + QUnit.log = function (details) { + if (window.console && window.console.log) { + window.console.log(details.result + ' :: ' + details.message); + } + }; + + function setUp () { + svgedit.units.init({ + getBaseUnit: function () { return 'cm'; }, + getHeight: function () { return 600; }, + getWidth: function () { return 800; }, + getRoundDigits: function () { return 4; }, + getElement: function (elementId) { return document.getElementById(elementId); } + }); + } + + test('Test svgedit.units package', function () { + expect(2); + ok(svgedit.units); + equals(typeof svgedit.units, typeof {}); + }); + + test('Test svgedit.units.shortFloat()', function () { + expect(7); + + setUp(); + + ok(svgedit.units.shortFloat); + equals(typeof svgedit.units.shortFloat, typeof function () {}); + + var shortFloat = svgedit.units.shortFloat; + equals(shortFloat(0.00000001), 0); + equals(shortFloat(1), 1); + equals(shortFloat(3.45678), 3.4568); + equals(shortFloat(1.23443), 1.2344); + equals(shortFloat(1.23455), 1.2346); + }); + + test('Test svgedit.units.isValidUnit()', function () { + expect(18); + + setUp(); + + ok(svgedit.units.isValidUnit); + equals(typeof svgedit.units.isValidUnit, typeof function () {}); + + var isValidUnit = svgedit.units.isValidUnit; + ok(isValidUnit('0')); + ok(isValidUnit('1')); + ok(isValidUnit('1.1')); + ok(isValidUnit('-1.1')); + ok(isValidUnit('.6mm')); + ok(isValidUnit('-.6cm')); + ok(isValidUnit('6000in')); + ok(isValidUnit('6px')); + ok(isValidUnit('6.3pc')); + ok(isValidUnit('-0.4em')); + ok(isValidUnit('-0.ex')); + ok(isValidUnit('40.123%')); + + equals(isValidUnit('id', 'uniqueId', document.getElementById('uniqueId')), true); + equals(isValidUnit('id', 'newId', document.getElementById('uniqueId')), true); + equals(isValidUnit('id', 'uniqueId'), false); + equals(isValidUnit('id', 'uniqueId', document.getElementById('nonUniqueId')), false); + }); + + test('Test svgedit.units.convertUnit()', function () { + expect(4); + + setUp(); + + ok(svgedit.units.convertUnit); + equals(typeof svgedit.units.convertUnit, typeof function () {}); + // cm in default setup + equals(svgedit.units.convertUnit(42), 1.1113); + equals(svgedit.units.convertUnit(42, 'px'), 42); + }); +});