diff options
-rw-r--r-- | spec/spec/modules/optional/sugar.js | 430 | ||||
-rw-r--r-- | src/modules/optional/arrange.js | 14 | ||||
-rw-r--r-- | src/modules/optional/sugar.js | 7 |
3 files changed, 437 insertions, 14 deletions
diff --git a/spec/spec/modules/optional/sugar.js b/spec/spec/modules/optional/sugar.js new file mode 100644 index 0000000..f762ed0 --- /dev/null +++ b/spec/spec/modules/optional/sugar.js @@ -0,0 +1,430 @@ +/* globals describe, expect, it, beforeEach, spyOn, container */ + +import { Rect, SVG, Matrix, Ellipse, Gradient } from '../../../../src/main.js' + +describe('sugar.js', () => { + describe('Element/Runner', () => { + describe('fill()', () => { + describe('as setter', () => { + it('returns itself', () => { + const rect = new Rect() + expect(rect.fill('black')).toBe(rect) + }) + + it('sets a fill color', () => { + const rect = new Rect() + expect(rect.fill('black').attr('fill')).toBe('black') + }) + + it('sets a fill pattern when pattern given', () => { + const canvas = SVG().addTo(container) + const pattern = canvas.pattern() + const rect = canvas.rect(100, 100) + expect(rect.fill(pattern).attr('fill')).toBe(pattern.url()) + }) + + it('sets a fill pattern when image given', () => { + const canvas = SVG().addTo(container) + const image = canvas.image('spec/fictures/pixel.png') + const rect = canvas.rect(100, 100) + expect(rect.fill(image).attr('fill')).toBe(image.parent().url()) + }) + + it('sets an object of fill properties', () => { + const rect = new Rect() + expect(rect.fill({ + color: 'black', + opacity: 0.5, + rule: 'even-odd' + }).attr()).toEqual({ + fill: 'black', + 'fill-opacity': 0.5, + 'fill-rule': + 'even-odd' + }) + }) + }) + + describe('as getter', () => { + it('returns fill color', () => { + const rect = new Rect().fill('black') + expect(rect.fill()).toBe('black') + }) + + it('returns default fill color if nothing is set', () => { + const rect = new Rect() + expect(rect.fill()).toBe('#000000') + }) + }) + }) + + describe('stroke()', () => { + describe('as setter', () => { + it('returns itself', () => { + const rect = new Rect() + expect(rect.stroke('black')).toBe(rect) + }) + + it('sets a stroke color', () => { + const rect = new Rect() + expect(rect.stroke('black').attr('stroke')).toBe('black') + }) + + it('sets a stroke pattern when pattern given', () => { + const canvas = SVG().addTo(container) + const pattern = canvas.pattern() + const rect = canvas.rect(100, 100) + expect(rect.stroke(pattern).attr('stroke')).toBe(pattern.url()) + }) + + it('sets a stroke pattern when image given', () => { + const canvas = SVG().addTo(container) + const image = canvas.image('spec/fictures/pixel.png') + const rect = canvas.rect(100, 100) + expect(rect.stroke(image).attr('stroke')).toBe(image.parent().url()) + }) + + it('sets an object of stroke properties', () => { + const rect = new Rect() + expect(rect.stroke({ + color: 'black', + width: 2, + opacity: 0.5, + linecap: 'butt', + linejoin: 'miter', + miterlimit: 10, + dasharray: '2 2', + dashoffset: 15 + }).attr()).toEqual({ + stroke: 'black', + 'stroke-width': 2, + 'stroke-opacity': 0.5, + 'stroke-linecap': 'butt', + 'stroke-linejoin': 'miter', + 'stroke-miterlimit': 10, + 'stroke-dasharray': '2 2', + 'stroke-dashoffset': 15 + }) + }) + + it('sets stroke dasharray with array passed', () => { + const rect = new Rect().stroke({ dasharray: [ 2, 2 ] }) + expect(rect.attr()).toEqual({ 'stroke-dasharray': '2 2' }) + }) + }) + + describe('as getter', () => { + it('returns stroke color', () => { + const rect = new Rect().stroke('black') + expect(rect.stroke()).toBe('black') + }) + + it('returns default stroke color if nothing is set', () => { + const rect = new Rect() + expect(rect.stroke()).toBe('#000000') + }) + }) + }) + + describe('matrix()', () => { + it('gets the matrix with no argument passed', () => { + const rect = new Rect().transform(new Matrix(1, 0, 1, 1, 1, 0)) + expect(rect.matrix()).toEqual(new Matrix(1, 0, 1, 1, 1, 0)) + }) + + it('sets the matrix if matrix given', () => { + const rect = new Rect().matrix(new Matrix(1, 0, 1, 1, 1, 0)) + expect(rect.matrix()).toEqual(new Matrix(1, 0, 1, 1, 1, 0)) + }) + + it('sets the matrix with 6 arguments given', () => { + const rect = new Rect().matrix(1, 0, 1, 1, 1, 0) + expect(rect.matrix()).toEqual(new Matrix(1, 0, 1, 1, 1, 0)) + }) + }) + + describe('rotate()', function () { + it('redirects to transform()', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.rotate(1, 2, 3) + expect(spy).toHaveBeenCalledWith({ rotate: 1, ox: 2, oy: 3 }, true) + }) + }) + + describe('skew()', function () { + it('redirects to transform() with no argument', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.skew() + expect(spy).toHaveBeenCalledWith({ skew: [ undefined, undefined ], ox: undefined, oy: undefined }, true) + }) + + it('redirects to transform() with one argument', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.skew(5) + expect(spy).toHaveBeenCalledWith({ skew: 5, ox: undefined, oy: undefined }, true) + }) + + it('redirects to transform() with two argument', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.skew(5, 6) + expect(spy).toHaveBeenCalledWith({ skew: [ 5, 6 ], ox: undefined, oy: undefined }, true) + }) + + it('redirects to transform() with three arguments', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.skew(5, 6, 7) + expect(spy).toHaveBeenCalledWith({ skew: 5, ox: 6, oy: 7 }, true) + }) + + it('redirects to transform() with four arguments', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.skew(5, 6, 7, 8) + expect(spy).toHaveBeenCalledWith({ skew: [ 5, 6 ], ox: 7, oy: 8 }, true) + }) + }) + + describe('shear', () => { + it('redirects to transform()', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.shear(1, 2, 3) + expect(spy).toHaveBeenCalledWith({ shear: 1, ox: 2, oy: 3 }, true) + }) + }) + + describe('scale()', function () { + it('redirects to transform() with no argument', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.scale() + expect(spy).toHaveBeenCalledWith({ scale: [ undefined, undefined ], ox: undefined, oy: undefined }, true) + }) + + it('redirects to transform() with one argument', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.scale(5) + expect(spy).toHaveBeenCalledWith({ scale: 5, ox: undefined, oy: undefined }, true) + }) + + it('redirects to transform() with two argument', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.scale(5, 6) + expect(spy).toHaveBeenCalledWith({ scale: [ 5, 6 ], ox: undefined, oy: undefined }, true) + }) + + it('redirects to transform() with three arguments', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.scale(5, 6, 7) + expect(spy).toHaveBeenCalledWith({ scale: 5, ox: 6, oy: 7 }, true) + }) + + it('redirects to transform() with four arguments', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.scale(5, 6, 7, 8) + expect(spy).toHaveBeenCalledWith({ scale: [ 5, 6 ], ox: 7, oy: 8 }, true) + }) + }) + + describe('translate()', function () { + it('redirects to transform()', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.translate(1, 2) + expect(spy).toHaveBeenCalledWith({ translate: [ 1, 2 ] }, true) + }) + }) + + describe('relative()', () => { + it('redirects to transform()', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.relative(1, 2) + expect(spy).toHaveBeenCalledWith({ relative: [ 1, 2 ] }, true) + }) + }) + + describe('flip()', function () { + it('redirects to transform()', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.flip('x', 2) + expect(spy).toHaveBeenCalledWith({ flip: 'x', origin: 2 }, true) + }) + + it('sets flip to "both" when calling without anything', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.flip() + expect(spy).toHaveBeenCalledWith({ flip: 'both', origin: 'center' }, true) + }) + + // this works because only x and y are valid flip values. Evereything else flips on both axis + it('sets flip to both and origin to number when called with origin only', function () { + const rect = new Rect() + const spy = spyOn(rect, 'transform') + rect.flip(5) + expect(spy).toHaveBeenCalledWith({ flip: 'both', origin: 5 }, true) + }) + }) + + describe('opacity()', function () { + it('redirects to attr() directly', function () { + const rect = new Rect() + const spy = spyOn(rect, 'attr') + rect.opacity(0.5) + expect(spy).toHaveBeenCalledWith('opacity', 0.5) + }) + }) + + describe('font()', function () { + const txt = 'Some text' + let canvas, text + + beforeEach(() => { + canvas = SVG().addTo(container) + text = canvas.text(txt) + }) + + it('sets leading when given', function () { + const spy = spyOn(text, 'leading') + text.font({ leading: 3 }) + expect(spy).toHaveBeenCalledWith(3) + }) + + it('sets text-anchor when anchor given', function () { + const spy = spyOn(text, 'attr') + text.font({ anchor: 'start' }) + expect(spy).toHaveBeenCalledWith('text-anchor', 'start') + }) + + it('sets all font properties via attr()', function () { + const spy = spyOn(text, 'attr') + text.font({ + size: 20, + family: 'Verdana', + weight: 'bold', + stretch: 'wider', + variant: 'small-caps', + style: 'italic' + }) + expect(spy).toHaveBeenCalledWith('font-size', 20) + expect(spy).toHaveBeenCalledWith('font-family', 'Verdana') + expect(spy).toHaveBeenCalledWith('font-weight', 'bold') + expect(spy).toHaveBeenCalledWith('font-stretch', 'wider') + expect(spy).toHaveBeenCalledWith('font-variant', 'small-caps') + expect(spy).toHaveBeenCalledWith('font-style', 'italic') + }) + + it('redirects all other stuff directly to attr()', function () { + const spy = spyOn(text, 'attr') + text.font({ + foo: 'bar', + bar: 'baz' + }) + expect(spy).toHaveBeenCalledWith('foo', 'bar') + expect(spy).toHaveBeenCalledWith('bar', 'baz') + }) + + it('sets key value pair when called with 2 parameters', function () { + const spy = spyOn(text, 'attr') + text.font('size', 20) + expect(spy).toHaveBeenCalledWith('font-size', 20) + }) + + it('gets value if called with one parameter', function () { + const spy = spyOn(text, 'attr') + text.font('size') + expect(spy).toHaveBeenCalledWith('font-size', undefined) + }) + }) + + }) + + describe('radius()', () => { + describe('Rect', () => { + it('sets rx and ry on the rectangle', () => { + const rect = new Rect().radius(5, 10) + expect(rect.attr()).toEqual({ rx: 5, ry: 10 }) + }) + }) + + describe('Ellipse', () => { + it('sets rx and ry on the rectangle', () => { + const rect = new Ellipse().radius(5, 10) + expect(rect.attr()).toEqual({ rx: 5, ry: 10 }) + }) + }) + + describe('radialGradient', () => { + it('sets rx and ry on the rectangle', () => { + const rect = new Gradient('radial').radius(5) + expect(rect.attr()).toEqual({ r: 5 }) + }) + }) + }) + + describe('Path', () => { + describe('length', () => { + it('returns the full length of the path', () => { + const canvas = SVG().addTo(container) + const path = canvas.path('M0 0 L 0 5') + expect(path.length()).toBe(5) + }) + }) + + describe('pointAt', () => { + it('returns a point at a specific length', () => { + const canvas = SVG().addTo(container) + const path = canvas.path('M0 0 L 0 5') + const point = path.pointAt(3) + + expect(point.x).toBeCloseTo(0) // chrome has rounding issues -.- + expect(point.y).toBe(3) + }) + }) + }) + + describe('events', () => { + [ 'click', + 'dblclick', + 'mousedown', + 'mouseup', + 'mouseover', + 'mouseout', + 'mousemove', + 'mouseenter', + 'mouseleave', + 'touchstart', + 'touchmove', + 'touchleave', + 'touchend', + 'touchcancel' ].forEach(ev => { + describe(ev, () => { + it('calls on() with the eventname set to ' + ev, () => { + const rect = new Rect() + const spy = spyOn(rect, 'on') + const fn = () => {} + rect[ev](fn) + expect(spy).toHaveBeenCalledWith(ev, fn) + }) + + it('calls off() with the eventname set to ' + ev + ' when null is passed as second argument', () => { + const rect = new Rect() + const spy = spyOn(rect, 'off') + rect[ev](null) + expect(spy).toHaveBeenCalledWith(ev) + }) + }) + }) + }) +}) diff --git a/src/modules/optional/arrange.js b/src/modules/optional/arrange.js index 7db4386..b6c03e0 100644 --- a/src/modules/optional/arrange.js +++ b/src/modules/optional/arrange.js @@ -23,16 +23,11 @@ export function prev () { // Send given element one step forward export function forward () { - var i = this.position() + 1 + var i = this.position() var p = this.parent() // move node one step forward - p.removeElement(this).add(this, i) - - // make sure defs node is always at the top - if (typeof p.isRoot === 'function' && p.isRoot()) { - p.node.appendChild(p.defs().node) - } + p.add(this.remove(), i + 1) return this } @@ -40,10 +35,9 @@ export function forward () { // Send given element one step backward export function backward () { var i = this.position() + var p = this.parent() - if (i > 0) { - this.parent().removeElement(this).add(this, i - 1) - } + p.add(this.remove(), i ? i - 1 : 0) return this } diff --git a/src/modules/optional/sugar.js b/src/modules/optional/sugar.js index 72c02ca..13806f1 100644 --- a/src/modules/optional/sugar.js +++ b/src/modules/optional/sugar.js @@ -1,4 +1,3 @@ -import { on, off } from '../core/event.js' import { registerMethods } from '../../utils/methods.js' import Color from '../../types/Color.js' import Element from '../../elements/Element.js' @@ -106,7 +105,7 @@ registerMethods('radius', { // Add x and y radius radius: function (x, y = x) { var type = (this._element || this).type - return type === 'radialGradient' || type === 'radialGradient' + return type === 'radialGradient' ? this.attr('r', new SVGNumber(x)) : this.rx(x).ry(y) } @@ -159,9 +158,9 @@ const methods = [ 'click', // add event to Element const fn = function (f) { if (f === null) { - off(this, event) + this.off(event) } else { - on(this, event, f) + this.on(event, f) } return this } |