* Jasmine RequestAnimationFrame: a set of helpers for testing funcionality
* that uses requestAnimationFrame under the Jasmine BDD framework for JavaScript.
*/
-;(function () {
+function RAFPlugin (jasmine) {
var index = 0
var callbacks = []
- function MockRAF (global) {
- this.realRAF = global.requestAnimationFrame
- this.realCAF = global.cancelAnimationFrame
- this.realPerf = global.performance
+ function MockRAF () {
this.nextTime = 0
var _this = this
/**
- * Mock for window.requestAnimationFrame
- */
+ * Mock for window.requestAnimationFrame
+ */
this.mockRAF = function (fn) {
if (typeof fn !== 'function') {
throw new Error('You should pass a function to requestAnimationFrame')
}
/**
- * Mock for window.cancelAnimationFrame
- */
+ * Mock for window.cancelAnimationFrame
+ */
this.mockCAF = function (requestID) {
callbacks.splice(requestID, 1)
}
}
/**
- * Install request animation frame mocks.
- */
- this.install = function () {
+ * Install request animation frame mocks.
+ */
+ this.install = function (global) {
+ _this.realRAF = global.requestAnimationFrame
+ _this.realCAF = global.cancelAnimationFrame
+ _this.realPerf = global.performance
global.requestAnimationFrame = _this.mockRAF
global.cancelAnimationFrame = _this.mockCAF
global.performance = _this.mockPerf
}
/**
- * Uninstall request animation frame mocks.
- */
- this.uninstall = function () {
+ * Uninstall request animation frame mocks.
+ */
+ this.uninstall = function (global) {
global.requestAnimationFrame = _this.realRAF
global.cancelAnimationFrame = _this.realCAF
global.performance = _this.realPerf
}
/**
- * Simulate animation frame readiness.
- */
+ * Simulate animation frame readiness.
+ */
this.tick = function (dt) {
_this.nextTime += (dt || 1)
}
}
- jasmine.RequestAnimationFrame = new MockRAF(window)
-}())
+ jasmine.RequestAnimationFrame = new MockRAF()
+}
+
+// if (!module) {
+RAFPlugin(jasmine)
+// } else {
+// module.exports.RAFPlugin = RAFPlugin
+
+// }
+import './RAFPlugin.js'
import { createHTMLWindow } from 'svgdom'
/* globals beforeEach, afterEach, jasmine */
--- /dev/null
+/* globals describe, expect, it, beforeEach, afterEach, jasmine */
+
+import { Animator, Queue } from '../../../src/main.js'
+import { getWindow } from '../../../src/utils/window.js'
+
+describe('Animator.js', function () {
+
+ beforeEach(function () {
+ jasmine.RequestAnimationFrame.install(getWindow())
+ Animator.timeouts = new Queue()
+ Animator.frames = new Queue()
+ Animator.nextDraw = null
+ })
+
+ afterEach(function () {
+ jasmine.RequestAnimationFrame.uninstall(getWindow())
+ })
+
+ describe('timeout()', function () {
+ it('calls a function after a specific time', function () {
+
+ var spy = jasmine.createSpy('tester')
+ Animator.timeout(spy, 100)
+
+ jasmine.RequestAnimationFrame.tick(99)
+ expect(spy).not.toHaveBeenCalled()
+ jasmine.RequestAnimationFrame.tick()
+ expect(spy).toHaveBeenCalled()
+ })
+ })
+
+ describe('cancelTimeout()', function () {
+ it('cancels a timeout which was created with timeout()', function () {
+ var spy = jasmine.createSpy('tester')
+ var id = Animator.timeout(spy, 100)
+ Animator.clearTimeout(id)
+
+ expect(spy).not.toHaveBeenCalled()
+ jasmine.RequestAnimationFrame.tick(100)
+ expect(spy).not.toHaveBeenCalled()
+ })
+ })
+
+ describe('frame()', function () {
+ it('calls a function at the next animationFrame', function () {
+ var spy = jasmine.createSpy('tester')
+
+ Animator.frame(spy)
+ expect(spy).not.toHaveBeenCalled()
+ jasmine.RequestAnimationFrame.tick()
+ expect(spy).toHaveBeenCalled()
+ })
+ })
+
+})
--- /dev/null
+/* globals describe, expect, it, jasmine */
+
+import { Morphable, NonMorphable, ObjectBag, Color, Box, Matrix, PointArray, PathArray, TransformBag, Number as SVGNumber, Array as SVGArray } from '../../../src/main.js'
+
+const { objectContaining, arrayContaining, any } = jasmine
+
+describe('Morphable.js', function () {
+ describe('constructors', function () {
+
+ it('Morphable with SVGNumber', function () {
+ var morpher = new Morphable().from(10).to(5)
+
+ expect(morpher).toEqual(any(Morphable))
+ expect(morpher.type()).toBe(SVGNumber)
+ expect(morpher.at(0.5)).toEqual(any(SVGNumber))
+ expect(morpher.at(0.5).valueOf()).toBe(7.5)
+ })
+
+ it('Morphable with String', function () {
+ var morpher = new Morphable().from('foo').to('bar')
+
+ expect(morpher).toEqual(any(Morphable))
+ expect(morpher.type()).toBe(NonMorphable)
+ expect(morpher.at(0.5)).toEqual(any(NonMorphable))
+ expect(morpher.at(0.5).valueOf()).toBe('foo')
+ expect(morpher.at(1).valueOf()).toBe('bar')
+ })
+
+ it('Morphable with Object', function () {
+ var morpher = new Morphable().from({ a: 5, b: 10 }).to({ a: 10, b: 20 })
+
+ expect(morpher).toEqual(any(Morphable))
+ expect(morpher.type()).toBe(ObjectBag)
+ expect(morpher.at(0.5)).toEqual(any(Object))
+ expect(morpher.at(0.5).valueOf()).toEqual(objectContaining({ a: 7.5, b: 15 }))
+ })
+
+ it('Creates a morphable out of an SVGNumber', function () {
+ var morpher = new SVGNumber(5).to(10)
+
+ expect(morpher).toEqual(any(Morphable))
+ expect(morpher.type()).toBe(SVGNumber)
+ expect(morpher.at(0.5)).toEqual(any(SVGNumber))
+ expect(morpher.at(0.5).valueOf()).toBe(7.5)
+ })
+
+ it('Creates a morphable out of an Color', function () {
+ var morpher = new Color('#fff').to('#000')
+
+ expect(morpher).toEqual(any(Morphable))
+ expect(morpher.type()).toBe(Color)
+ expect(morpher.at(0.5)).toEqual(any(Color))
+ expect(morpher.at(0.5).toHex()).toBe('#808080')
+ })
+
+ it('Creates a morphable out of an Box', function () {
+ var morpher = new Box(1, 2, 3, 4).to([ 5, 6, 7, 8 ])
+
+ expect(morpher).toEqual(any(Morphable))
+ expect(morpher.type()).toBe(Box)
+ expect(morpher.at(0.5)).toEqual(any(Box))
+ expect(morpher.at(0.5)).toEqual(objectContaining({ x: 3, y: 4, width: 5, height: 6 }))
+ })
+
+ it('Creates a morphable out of an Matrix', function () {
+ var morpher = new Matrix(1, 2, 3, 4, 5, 6).to([ 3, 4, 5, 6, 7, 8 ])
+
+ expect(morpher).toEqual(any(Morphable))
+ expect(morpher.type()).toBe(Matrix)
+ expect(morpher.at(0.5)).toEqual(any(Matrix))
+ expect(morpher.at(0.5)).toEqual(objectContaining(new Matrix(2, 3, 4, 5, 6, 7)))
+ })
+
+ it('Creates a morphable out of an Array', function () {
+ var morpher = new SVGArray([ 1, 2, 3, 4, 5, 6 ]).to([ 3, 4, 5, 6, 7, 8 ])
+
+ expect(morpher).toEqual(any(Morphable))
+ expect(morpher.type()).toBe(SVGArray)
+ expect(morpher.at(0.5)).toEqual(any(SVGArray))
+ expect(morpher.at(0.5).toArray()).toEqual(arrayContaining([ 2, 3, 4, 5, 6, 7 ]))
+ })
+
+ it('Creates a morphable out of an PointArray', function () {
+ var morpher = new PointArray([ 1, 2, 3, 4, 5, 6 ]).to([ 3, 4, 5, 6, 7, 8 ])
+
+ expect(morpher).toEqual(any(Morphable))
+ expect(morpher.type()).toBe(PointArray)
+ expect(morpher.at(0.5)).toEqual(any(PointArray))
+ expect(morpher.at(0.5).toArray()).toEqual(arrayContaining([ 2, 3, 4, 5, 6, 7 ]))
+ })
+
+ it('Creates a morphable out of an PathArray', function () {
+ var morpher = new PathArray([ 'M', 1, 2, 'L', 3, 4, 'L', 5, 6 ]).to([ 'M', 3, 4, 'L', 5, 6, 'L', 7, 8 ])
+
+ expect(morpher).toEqual(any(Morphable))
+ expect(morpher.type()).toBe(PathArray)
+ expect(morpher.at(0.5)).toEqual(any(PathArray))
+ expect(morpher.at(0.5).toArray()).toEqual(arrayContaining([ 'M', 2, 3, 'L', 4, 5, 'L', 6, 7 ]))
+ })
+
+ it('Creates a morphable out of an NonMorphable', function () {
+ var morpher = new NonMorphable('foo').to('bar')
+
+ expect(morpher).toEqual(any(Morphable))
+ expect(morpher.type()).toBe(NonMorphable)
+ expect(morpher.at(0.5)).toEqual(any(NonMorphable))
+ expect(morpher.at(0.5).valueOf()).toBe('foo')
+ expect(morpher.at(1).valueOf()).toBe('bar')
+ })
+
+ it('Creates a morphable out of an TransformBag', function () {
+ var morpher = new TransformBag({ rotate: 0, translateX: 0 })
+ .to({ rotate: 50, translateX: 20 })
+
+ expect(morpher).toEqual(any(Morphable))
+ expect(morpher.type()).toBe(TransformBag)
+ expect(morpher.at(0.5)).toEqual(any(TransformBag))
+
+ expect(morpher.at(0.5)).toEqual(objectContaining({ rotate: 25, translateX: 10 }))
+ })
+
+ it('Creates a morphable out of an ObjectBag', function () {
+ var morpher = new ObjectBag({ a: 5, b: 10 }).to({ a: 10, b: 20 })
+
+ expect(morpher).toEqual(any(Morphable))
+ expect(morpher.type()).toBe(ObjectBag)
+ expect(morpher.at(0.5)).toEqual(any(Object))
+ expect(morpher.at(0.5).valueOf()).toEqual(objectContaining({ a: 7.5, b: 15 }))
+ })
+ })
+
+ describe('from()', function () {
+ it('sets the type of the runner', function () {
+ var morpher = new Morphable().from(5)
+ expect(morpher.type()).toBe(SVGNumber)
+ })
+
+ it('sets the from attribute to an array representation of the morphable type', function () {
+ var morpher = new Morphable().from(5)
+ expect(morpher.from()).toEqual(arrayContaining([ 5 ]))
+ })
+ })
+
+ describe('type()', function () {
+ it('sets the type of the runner', function () {
+ var morpher = new Morphable().type(SVGNumber)
+ expect(morpher._type).toBe(SVGNumber)
+ })
+
+ it('gets the type of the runner', function () {
+ var morpher = new Morphable().type(SVGNumber)
+ expect(morpher.type()).toBe(SVGNumber)
+ })
+ })
+
+ describe('to()', function () {
+ it('sets the type of the runner', function () {
+ var morpher = new Morphable().to(5)
+ expect(morpher.type()).toBe(SVGNumber)
+ })
+
+ it('sets the from attribute to an array representation of the morphable type', function () {
+ var morpher = new Morphable().to(5)
+ expect(morpher.to()).toEqual(arrayContaining([ 5 ]))
+ })
+ })
+})
--- /dev/null
+/* globals describe, expect, it */
+
+import { Queue } from '../../../src/main.js'
+
+describe('Queue.js', function () {
+
+ describe('first ()', function () {
+
+ it('returns null if no item in the queue', function () {
+ var queue = new Queue()
+ expect(queue.first()).toEqual(null)
+ })
+
+ it('returns the first value in the queue', function () {
+ var queue = new Queue()
+ queue.push(1)
+ expect(queue.first()).toBe(1)
+ queue.push(2)
+ expect(queue.first()).toBe(1)
+ })
+ })
+
+ describe('last ()', function () {
+
+ it('returns null if no item in the queue', function () {
+ var queue = new Queue()
+ expect(queue.last()).toEqual(null)
+ })
+
+ it('returns the last value added', function () {
+ var queue = new Queue()
+ queue.push(1)
+ expect(queue.last()).toBe(1)
+ queue.push(2)
+ expect(queue.last()).toBe(2)
+ })
+ })
+
+ describe('push ()', function () {
+
+ it('adds an element to the end of the queue', function () {
+ var queue = new Queue()
+ queue.push(1)
+ queue.push(2)
+ queue.push(3)
+
+ expect(queue.first()).toBe(1)
+ expect(queue.last()).toBe(3)
+ })
+ })
+
+ describe('remove ()', function () {
+ it('removes the given item from the queue', function () {
+ var queue = new Queue()
+ queue.push(1)
+ queue.push(2)
+ var item = queue.push(3)
+
+ queue.remove(item)
+
+ expect(queue.last()).toBe(2)
+ expect(queue.first()).toBe(1)
+ })
+ })
+
+ describe('shift ()', function () {
+ it('returns nothing if queue is empty', function () {
+ var queue = new Queue()
+ var val = queue.shift()
+ expect(val).toBeFalsy()
+ })
+
+ it('returns the first item of the queue and removes it', function () {
+ var queue = new Queue()
+ queue.push(1)
+ queue.push(2)
+ queue.push(3)
+
+ var val = queue.shift()
+
+ expect(queue.last()).toBe(3)
+ expect(queue.first()).toBe(2)
+
+ expect(val).toBe(1)
+ })
+ })
+})
--- /dev/null
+/* globals describe, expect, it, beforeEach, afterEach, spyOn, jasmine */
+
+import { Runner, defaults, Ease, Controller, SVG, Timeline } from '../../../src/main.js'
+import { getWindow } from '../../../src/utils/window.js'
+
+const { createSpy, objectContaining, arrayContaining } = jasmine
+
+describe('Runner.js', () => {
+
+ var initFn = createSpy('initFn')
+ var runFn = createSpy('runFn')
+
+ beforeEach(() => {
+ jasmine.RequestAnimationFrame.install(getWindow())
+ initFn.calls.reset()
+ runFn.calls.reset()
+ })
+
+ afterEach(() => {
+ jasmine.RequestAnimationFrame.uninstall(getWindow())
+ })
+
+ describe('sanitise()', () => {
+ it('can handle all form of input', () => {
+ var fn = Runner.sanitise
+
+ expect(fn(200, 200, 'now')).toEqual(objectContaining({
+ duration: 200,
+ delay: 200,
+ when: 'now',
+ times: 1,
+ wait: 0,
+ swing: false
+ }))
+
+ expect(fn(200, 200)).toEqual(objectContaining({
+ duration: 200,
+ delay: 200,
+ when: 'last',
+ times: 1,
+ wait: 0,
+ swing: false
+ }))
+
+ expect(fn(200)).toEqual(objectContaining({
+ duration: 200,
+ delay: defaults.timeline.delay,
+ when: 'last',
+ times: 1,
+ wait: 0,
+ swing: false
+ }))
+
+ expect(fn(runFn)).toEqual(objectContaining({
+ duration: runFn,
+ delay: defaults.timeline.delay,
+ when: 'last',
+ times: 1,
+ wait: 0,
+ swing: false
+ }))
+
+ expect(fn({ delay: 200 })).toEqual(objectContaining({
+ duration: defaults.timeline.duration,
+ delay: 200,
+ when: 'last',
+ times: 1,
+ wait: 0,
+ swing: false
+ }))
+
+ expect(fn({ times: 3, delay: 200, when: 'now', swing: true, wait: 200 })).toEqual(objectContaining({
+ duration: defaults.timeline.duration,
+ delay: 200,
+ when: 'now',
+ times: 3,
+ wait: 200,
+ swing: true
+ }))
+ })
+ })
+
+ describe('())', () => {
+ it('creates a runner with defaults', () => {
+ var runner = new Runner()
+ expect(runner instanceof Runner).toBe(true)
+ expect(runner._duration).toBe(defaults.timeline.duration)
+ expect(runner._stepper instanceof Ease).toBe(true)
+ })
+
+ it('creates a runner with duration set', () => {
+ var runner = new Runner(1000)
+ expect(runner instanceof Runner).toBe(true)
+ expect(runner._duration).toBe(1000)
+ expect(runner._stepper instanceof Ease).toBe(true)
+ })
+
+ it('creates a runner with controller set', () => {
+ var runner = new Runner(runFn)
+ expect(runner instanceof Runner).toBe(true)
+ expect(runner._duration).toBeFalsy()
+ expect(runner._stepper instanceof Controller).toBe(true)
+ })
+ })
+
+ describe('constructors', () => {
+ // FIXME: Not possible to spy like this in es6
+ // describe('animate()', () => {
+ // it('creates a runner with the element set and schedules it on the timeline', () => {
+ // var orginalRunner = Runner
+ // spyOn(SVG, 'Runner').and.callFake(() =>{
+ // return new orginalRunner()
+ // })
+ //
+ // var element = SVG('<rect />')
+ // var runner = element.animate()
+ // expect(Runner).toHaveBeenCalled();
+ // expect(runner instanceof Runner)
+ // expect(runner.element()).toBe(element)
+ // expect(runner.timeline()).toBe(element.timeline())
+ // })
+ // })
+
+ describe('delay()', () => {
+ it('calls animate with correct parameters', () => {
+ var element = SVG('<rect />')
+
+ spyOn(element, 'animate')
+ element.delay(100, 'now')
+ expect(element.animate).toHaveBeenCalledWith(0, 100, 'now')
+ })
+ })
+ })
+
+ describe('queue()', () => {
+ it('adds another closure to the runner', () => {
+ var runner = new Runner()
+ runner.queue(initFn, runFn, true)
+
+ expect(runner._queue[0]).toEqual(objectContaining({
+ initialiser: initFn,
+ initialised: false,
+ runner: runFn,
+ finished: false
+ }))
+ })
+ })
+
+ describe('step()', () => {
+
+ it('returns itself', () => {
+ var runner = new Runner()
+ expect(runner.step()).toBe(runner)
+ })
+
+ it('calls initFn once and runFn at every step', () => {
+ var runner = new Runner()
+ runner.queue(initFn, runFn, false)
+
+ runner.step()
+ expect(initFn).toHaveBeenCalled()
+ expect(runFn).toHaveBeenCalled()
+
+ runner.step()
+ expect(initFn.calls.count()).toBe(1)
+ expect(runFn.calls.count()).toBe(2)
+ })
+
+ it('calls initFn on every step if its declaritive', () => {
+ var runner = new Runner(new Controller())
+ runner.queue(initFn, runFn, true)
+
+ runner.step()
+ expect(initFn).toHaveBeenCalled()
+ expect(runFn).toHaveBeenCalled()
+
+ runner.step()
+ expect(initFn.calls.count()).toBe(2)
+ expect(runFn.calls.count()).toBe(2)
+ })
+
+ function getLoop (r) {
+ var loopDuration = r._duration + r._wait
+ var loopsDone = Math.floor(r._time / loopDuration)
+ return loopsDone
+ }
+
+ // step in time
+ it('steps forward a certain time', () => {
+ var spy = createSpy('stepper')
+ var r = new Runner(1000).loop(10, false, 100)
+ r.queue(null, spy)
+
+ r.step(300) // should be 0.3s
+ expect(spy).toHaveBeenCalledWith(0.3)
+ expect(getLoop(r)).toBe(0)
+
+ r.step(300) // should be 0.6s
+ expect(spy).toHaveBeenCalledWith(0.6)
+ expect(getLoop(r)).toBe(0)
+
+ r.step(600) // should be 0.1s
+ expect(spy).toHaveBeenCalledWith(0.1)
+ expect(getLoop(r)).toBe(1)
+
+ r.step(-300) // should be 0.9s
+ expect(spy).toHaveBeenCalledWith(0.9)
+ expect(getLoop(r)).toBe(0)
+
+ r.step(2000) // should be 0.7s
+ expect(spy).toHaveBeenCalledWith(0.7)
+ expect(getLoop(r)).toBe(2)
+
+ r.step(-2000) // should be 0.9s
+ expect(spy).toHaveBeenCalledWith(0.9)
+ expect(getLoop(r)).toBe(0)
+ })
+
+ it('handles dts which are bigger than the animation time', () => {
+ var runner = new Runner(1000)
+ runner.queue(initFn, runFn, true)
+
+ runner.step(1100)
+ expect(initFn).toHaveBeenCalled()
+ expect(runFn).toHaveBeenCalledWith(1)
+ })
+
+ describe('looping', () => {
+ describe('without wait', () => {
+ describe('unreversed', () => {
+ describe('nonswinging', () => {
+ it('does behave correctly at the end of an even loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(6, false)
+ runner.queue(null, spy)
+
+ runner.step(5750)
+ expect(spy).toHaveBeenCalledWith(0.75)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(1)
+ })
+
+ it('does behave correctly at the end of an uneven loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(5, false)
+ runner.queue(null, spy)
+
+ runner.step(4750)
+ expect(spy).toHaveBeenCalledWith(0.75)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(1)
+ })
+ })
+
+ describe('swinging', () => {
+ it('does behave correctly at the end of an even loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(6, true)
+ runner.queue(null, spy)
+
+ runner.step(5750)
+ expect(spy).toHaveBeenCalledWith(0.25)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(0)
+ })
+
+ it('does behave correctly at the end of an uneven loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(5, true)
+ runner.queue(null, spy)
+
+ runner.step(4750)
+ expect(spy).toHaveBeenCalledWith(0.75)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(1)
+ })
+ })
+ })
+
+ describe('reversed', () => {
+ describe('nonswinging', () => {
+ it('does behave correctly at the end of an even loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(6, false).reverse()
+ runner.queue(null, spy)
+
+ runner.step(5750)
+ expect(spy).toHaveBeenCalledWith(0.25)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(0)
+ })
+
+ it('does behave correctly at the end of an uneven loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(5, false).reverse()
+ runner.queue(null, spy)
+
+ runner.step(4750)
+ expect(spy).toHaveBeenCalledWith(0.25)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(0)
+ })
+ })
+
+ describe('swinging', () => {
+ it('does behave correctly at the end of an even loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(6, true).reverse()
+ runner.queue(null, spy)
+
+ runner.step(5750)
+ expect(spy).toHaveBeenCalledWith(0.75)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(1)
+ })
+
+ it('does behave correctly at the end of an uneven loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(5, true).reverse()
+ runner.queue(null, spy)
+
+ runner.step(4750)
+ expect(spy).toHaveBeenCalledWith(0.25)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(0)
+ })
+ })
+ })
+ })
+
+ describe('with wait', () => {
+ describe('unreversed', () => {
+ describe('nonswinging', () => {
+ it('does behave correctly at the end of an even loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(6, false, 100)
+ runner.queue(null, spy)
+
+ runner.step(5450)
+ expect(spy).toHaveBeenCalledWith(1)
+ spy.calls.reset()
+
+ runner.step(800)
+ expect(spy).toHaveBeenCalledWith(0.75)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(1)
+ })
+
+ it('does behave correctly at the end of an uneven loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(5, false, 100)
+ runner.queue(null, spy)
+
+ runner.step(4350)
+ expect(spy).toHaveBeenCalledWith(1)
+ spy.calls.reset()
+
+ runner.step(800)
+ expect(spy).toHaveBeenCalledWith(0.75)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(1)
+ })
+ })
+
+ describe('swinging', () => {
+ it('does behave correctly at the end of an even loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(6, true, 100)
+ runner.queue(null, spy)
+
+ runner.step(5450)
+ expect(spy).toHaveBeenCalledWith(1)
+ spy.calls.reset()
+
+ runner.step(800)
+ expect(spy).toHaveBeenCalledWith(0.25)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(0)
+ })
+
+ it('does behave correctly at the end of an uneven loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(5, true, 100)
+ runner.queue(null, spy)
+
+ runner.step(4350)
+ expect(spy).toHaveBeenCalledWith(0)
+ spy.calls.reset()
+
+ runner.step(800)
+ expect(spy).toHaveBeenCalledWith(0.75)
+
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(1)
+ })
+ })
+ })
+
+ describe('reversed', () => {
+ describe('nonswinging', () => {
+ it('does behave correctly at the end of an even loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(6, false, 100).reverse()
+ runner.queue(null, spy)
+
+ runner.step(5450)
+ expect(spy).toHaveBeenCalledWith(0)
+ spy.calls.reset()
+
+ runner.step(800)
+ expect(spy).toHaveBeenCalledWith(0.25)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(0)
+ })
+
+ it('does behave correctly at the end of an uneven loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(5, false, 100).reverse()
+ runner.queue(null, spy)
+
+ runner.step(4350)
+ expect(spy).toHaveBeenCalledWith(0)
+ spy.calls.reset()
+
+ runner.step(800)
+ expect(spy).toHaveBeenCalledWith(0.25)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(0)
+ })
+ })
+
+ describe('swinging', () => {
+ it('does behave correctly at the end of an even loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(6, true, 100).reverse()
+ runner.queue(null, spy)
+
+ runner.step(5450)
+ expect(spy).toHaveBeenCalledWith(0)
+ spy.calls.reset()
+
+ runner.step(800)
+ expect(spy).toHaveBeenCalledWith(0.75)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(1)
+ })
+
+ it('does behave correctly at the end of an uneven loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(5, true, 100).reverse()
+ runner.queue(null, spy)
+
+ runner.step(4350)
+ expect(spy).toHaveBeenCalledWith(1)
+ spy.calls.reset()
+
+ runner.step(800)
+ expect(spy).toHaveBeenCalledWith(0.25)
+ runner.step(250)
+ expect(spy).toHaveBeenCalledWith(0)
+ })
+ })
+ })
+ })
+ })
+
+ })
+
+ describe('active()', () => {
+ it('acts as a getter without parameters', () => {
+ var runner = new Runner()
+ expect(runner.active()).toBe(true)
+ })
+
+ it('disables the runner when false is passed', () => {
+ var runner = new Runner()
+ expect(runner.active(false)).toBe(runner)
+ expect(runner.active()).toBe(false)
+ })
+
+ it('enables the runner when true is passed', () => {
+ var runner = new Runner()
+ expect(runner.active(false)).toBe(runner)
+ expect(runner.active(true)).toBe(runner)
+ expect(runner.active()).toBe(true)
+ })
+ })
+
+ describe('duration()', () => {
+ it('return the full duration of the runner including all loops and waits', () => {
+ var runner = new Runner(800).loop(10, true, 200)
+ expect(runner.duration()).toBe(9800)
+ })
+ })
+
+ describe('loop()', () => {
+ it('makes this runner looping', () => {
+ var runner = new Runner(1000).loop(5)
+ expect(runner.duration()).toBe(5000)
+ })
+ })
+
+ describe('time()', () => {
+ it('returns itself', () => {
+ var runner = new Runner()
+ expect(runner.time(0)).toBe(runner)
+ })
+
+ it('acts as a getter with no parameter passed', () => {
+ var runner = new Runner()
+ expect(runner.time()).toBe(0)
+ })
+
+ it('reschedules the runner to a new time', () => {
+ var runner = new Runner()
+ runner.time(10)
+
+ expect(runner.time()).toBe(10)
+ })
+
+ it('calls step to reschedule', () => {
+ var runner = new Runner()
+ spyOn(runner, 'step')
+ runner.time(10)
+
+ expect(runner.step).toHaveBeenCalledWith(10)
+ })
+ })
+
+ describe('loops()', () => {
+ it('get the loops of a runner', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).queue(null, spy)
+
+ runner.step(300)
+ expect(spy).toHaveBeenCalledWith(0.3)
+
+ expect(runner.loops()).toBe(0.3)
+ })
+ it('sets the loops of the runner', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).queue(null, spy)
+
+ expect(runner.loops(0.5).loops()).toBe(0.5)
+ expect(spy).toHaveBeenCalledWith(0.5)
+
+ expect(runner.loops(0.1).loops()).toBe(0.1)
+ expect(spy).toHaveBeenCalledWith(0.1)
+
+ expect(runner.loops(1.5).loops()).toBe(1)
+ expect(spy).toHaveBeenCalledWith(1)
+ })
+ it('sets the loops of the runner in a loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(5, true, 500).queue(null, spy)
+
+ expect(runner.loops(1.3).loops()).toBe(1.3)
+ expect(spy).toHaveBeenCalledWith(0.7)
+
+ expect(runner.loops(0.3).loops()).toBe(0.3)
+ })
+ })
+
+ describe('progress()', () => {
+ it('gets the progress of a runner', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).queue(null, spy)
+
+ runner.step(300)
+ expect(spy).toHaveBeenCalledWith(0.3)
+
+ expect(runner.progress()).toBe(0.3)
+ })
+
+ it('gets the progress of a runner when looping', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(800).queue(null, spy).loop(10, false, 200) // duration should be 9800
+
+ // middle of animation, in the middle of wait time
+ runner.step(4900)
+ expect(runner.progress()).toBe(0.5)
+ expect(spy).toHaveBeenCalledWith(1)
+
+ // start of next loop
+ runner.step(100)
+ expect(spy).toHaveBeenCalledWith(0)
+
+ // move 400 into current loop which is 0.5 progress
+ // the progress value is 5400 / 9800
+ runner.step(400)
+ expect(spy).toHaveBeenCalledWith(0.5)
+ expect(runner.progress()).toBe(5400 / 9800)
+ })
+
+ it('sets the progress of a runner', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).queue(null, spy)
+
+ expect(runner.progress(0.5).progress()).toBe(0.5)
+ expect(spy).toHaveBeenCalledWith(0.5)
+ })
+
+ it('sets the progress of a runner when looping', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(800).queue(null, spy).loop(10, false, 200)
+
+ // progress 0.5 somewhere in the middle of wait time
+ expect(runner.progress(0.5).progress()).toBe(0.5)
+ expect(spy).toHaveBeenCalledWith(1)
+
+ // start of next loop
+ runner.step(100)
+ expect(spy).toHaveBeenCalledWith(0)
+
+ // should move 0.5 into the next loop
+ expect(runner.progress(5400 / 9800).progress()).toBe(5400 / 9800)
+ expect(spy.calls.mostRecent().args[0]).toBeCloseTo(0.5)
+ })
+ })
+
+ describe('position()', () => {
+
+ it('gets the position of a runner', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).queue(null, spy)
+
+ runner.step(300)
+ expect(spy).toHaveBeenCalledWith(0.3)
+
+ expect(runner.position()).toBe(0.3)
+ })
+
+ it('gets the position of a runner when looping', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(5, true, 100).queue(null, spy)
+
+ runner.step(1200)
+ expect(spy).toHaveBeenCalledWith(0.9)
+
+ expect(runner.position()).toBe(0.9)
+ })
+
+ it('sets the position of a runner', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).queue(null, spy)
+
+ expect(runner.position(0.5).position()).toBe(0.5)
+ expect(spy).toHaveBeenCalledWith(0.5)
+ })
+
+ it('sets the position of a runner in a loop', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).loop(5, true, 100).queue(null, spy)
+
+ runner.step(1200)
+ expect(runner.position(0.4).position()).toBe(0.4)
+ expect(spy).toHaveBeenCalledWith(0.4)
+
+ expect(runner.position(0).position()).toBe(0)
+ expect(spy).toHaveBeenCalledWith(0)
+
+ expect(runner.position(1).position()).toBe(1)
+ expect(spy).toHaveBeenCalledWith(1)
+ })
+ })
+
+ describe('element()', () => {
+ it('returns the element bound to this runner if any', () => {
+ var runner1 = new Runner()
+ expect(runner1.element()).toBe(null)
+
+ var element = SVG('<rect />')
+ var runner2 = element.animate()
+ expect(runner2.element()).toBe(element)
+ })
+
+ it('sets an element to be bound to the runner', () => {
+ var runner = new Runner()
+ var element = SVG('<rect />')
+ expect(runner.element(element)).toBe(runner)
+ expect(runner.element()).toBe(element)
+ })
+ })
+
+ describe('timeline()', () => {
+ it('returns the timeline bound to this runner if any', () => {
+ var runner1 = new Runner()
+ expect(runner1.element()).toBe(null)
+
+ var element = SVG('<rect />')
+ var runner2 = element.animate()
+ expect(runner2.timeline()).toBe(element.timeline())
+ })
+
+ it('sets a timeline to be bound to the runner', () => {
+ var runner = new Runner()
+ var timeline = new Timeline()
+ expect(runner.timeline(timeline)).toBe(runner)
+ expect(runner.timeline()).toBe(timeline)
+ })
+ })
+
+ describe('schedule()', () => {
+ it('schedules the runner on a timeline', () => {
+ var runner = new Runner()
+ var timeline = new Timeline()
+ var spy = spyOn(timeline, 'schedule').and.callThrough()
+
+ expect(runner.schedule(timeline, 200, 'now')).toBe(runner)
+ expect(runner.timeline()).toBe(timeline)
+ expect(spy).toHaveBeenCalledWith(runner, 200, 'now')
+ })
+
+ it('schedules the runner on its own timeline', () => {
+ var runner = new Runner()
+ var timeline = new Timeline()
+ var spy = spyOn(timeline, 'schedule')
+ runner.timeline(timeline)
+
+ expect(runner.schedule(200, 'now')).toBe(runner)
+ expect(runner.timeline()).toBe(timeline)
+ expect(spy).toHaveBeenCalledWith(runner, 200, 'now')
+ })
+ })
+
+ describe('unschedule()', () => {
+ it('unschedules this runner from its timeline', () => {
+ var runner = new Runner()
+ var timeline = new Timeline()
+ var spy = spyOn(timeline, 'unschedule').and.callThrough()
+
+ expect(runner.schedule(timeline, 200, 'now')).toBe(runner)
+ expect(runner.unschedule()).toBe(runner)
+ expect(spy).toHaveBeenCalledWith(runner)
+ expect(runner.timeline()).toBe(null)
+ })
+ })
+
+ describe('animate()', () => {
+ it('creates a new runner scheduled after the first', () => {
+ var runner = new Runner(1000)
+ var timeline = new Timeline()
+
+ runner.schedule(timeline)
+
+ var runner2 = runner.animate(500, 1000)
+
+ var t = timeline.time()
+
+ expect(runner2.timeline()).toBe(timeline)
+ expect(runner2.time()).toBe(0)
+
+ expect(timeline.schedule()).toEqual(arrayContaining([
+ objectContaining({ start: t, duration: 1000, end: t + 1000, runner: runner }),
+ objectContaining({ start: t + 2000, duration: 500, end: t + 2500, runner: runner2 })
+ ]))
+ })
+ })
+
+ describe('delay()', () => {
+ it('calls animate with delay parameters', () => {
+ var runner = new Runner(1000)
+ spyOn(runner, 'animate')
+
+ runner.delay(500)
+ expect(runner.animate).toHaveBeenCalledWith(0, 500)
+ })
+ })
+
+ describe('during()', () => {
+ it('returns itself', () => {
+ var runner = new Runner()
+ expect(runner.during(runFn)).toBe(runner)
+ })
+
+ it('calls queue passing only a function to call on every step', () => {
+ var runner = new Runner()
+ spyOn(runner, 'queue')
+ runner.during(runFn)
+
+ expect(runner.queue).toHaveBeenCalledWith(null, runFn)
+ })
+ })
+
+ // describe('after()', () => {
+ // it('returns itself', () => {
+ // var runner = new Runner()
+ // expect(runner.after(runFn)).toBe(runner)
+ // })
+ //
+ // it('binds a function to the after event', () => {
+ // var runner = new Runner()
+ // spyOn(runner, 'on')
+ // runner.after(runFn)
+ //
+ // expect(runner.on).toHaveBeenCalledWith('finish', runFn)
+ // })
+ // })
+ //
+ // describe('finish()', () => {
+ // it('returns itself', () => {
+ // var runner = new Runner()
+ // expect(runner.finish()).toBe(runner)
+ // })
+ //
+ // it('calls step with Infinity as argument', () => {
+ // var runner = new Runner()
+ // spyOn(runner, 'step')
+ // runner.finish()
+ //
+ // expect(runner.step).toHaveBeenCalledWith(Infinity)
+ // })
+ // })
+
+ describe('reverse()', () => {
+ it('returns itself', () => {
+ var runner = new Runner()
+ expect(runner.reverse()).toBe(runner)
+ })
+
+ it('reverses the runner', () => {
+ var spy = createSpy('stepper')
+ var runner = new Runner(1000).reverse().queue(null, spy)
+ runner.step(750)
+ expect(spy).toHaveBeenCalledWith(0.25)
+ })
+ })
+
+ describe('ease()', () => {
+ it('returns itself', () => {
+ var runner = new Runner()
+ expect(runner.ease(() => {})).toBe(runner)
+ })
+
+ it('creates an easing Controller from the easing function', () => {
+ var runner = new Runner()
+ runner.ease(() => {})
+
+ expect(runner._stepper instanceof Ease).toBe(true)
+ })
+ })
+})
--- /dev/null
+/* globals describe, expect, it, beforeEach, container */
+
+import { Timeline, SVG } from '../../../src/main.js'
+
+describe('Timeline.js', () => {
+ describe('getEndTimeOfTimeline', () => {
+ it('returns 0 if no runners are scheduled', () => {
+ const timeline = new Timeline()
+ const endTime = timeline.getEndTimeOfTimeline()
+ expect(endTime).toEqual(0)
+ })
+ })
+
+ describe('finish - issue #964', () => {
+ let canvas
+
+ beforeEach(() => {
+ canvas = SVG().addTo(container)
+ })
+
+ it('places all elements at the right position - single runner', () => {
+ const timeline = new Timeline()
+
+ const rect = canvas.rect(20, 20)
+ rect.timeline(timeline)
+ rect.animate().move(100, 200)
+
+ timeline.finish()
+ expect(rect.x()).toEqual(100)
+ expect(rect.y()).toEqual(200)
+ })
+
+ it('places all elements at the right position - runner that finishes latest is in first position', () => {
+ const timeline = new Timeline()
+
+ const rect1 = canvas.rect(10, 10)
+ rect1.timeline(timeline)
+
+ const rect2 = canvas.rect(10, 10)
+ rect2.timeline(timeline)
+
+ const rect3 = canvas.rect(10, 10)
+ rect3.timeline(timeline)
+
+ rect1.animate(2000, 0, 'now').move(100, 200)
+ rect2.animate(1000, 0, 'now').move(100, 200)
+ rect3.animate(1000, 500, 'now').move(100, 200)
+
+ timeline.finish()
+
+ expect(rect1.x()).toEqual(100)
+ expect(rect1.y()).toEqual(200)
+
+ expect(rect2.x()).toEqual(100)
+ expect(rect2.y()).toEqual(200)
+
+ expect(rect3.x()).toEqual(100)
+ expect(rect3.y()).toEqual(200)
+ })
+
+ it('places all elements at the right position - runner that finishes latest is in middle position', () => {
+ const timeline = new Timeline()
+
+ const rect1 = canvas.rect(10, 10)
+ rect1.timeline(timeline)
+
+ const rect2 = canvas.rect(10, 10)
+ rect2.timeline(timeline)
+
+ const rect3 = canvas.rect(10, 10)
+ rect3.timeline(timeline)
+
+ rect2.animate(1000, 0, 'now').move(100, 200)
+ rect1.animate(2000, 0, 'now').move(100, 200)
+ rect3.animate(1000, 500, 'now').move(100, 200)
+
+ timeline.finish()
+
+ expect(rect1.x()).toEqual(100)
+ expect(rect1.y()).toEqual(200)
+
+ expect(rect2.x()).toEqual(100)
+ expect(rect2.y()).toEqual(200)
+
+ expect(rect3.x()).toEqual(100)
+ expect(rect3.y()).toEqual(200)
+ })
+
+ it('places all elements at the right position - runner that finishes latest is in last position', () => {
+ const timeline = new Timeline()
+
+ const rect1 = canvas.rect(10, 10)
+ rect1.timeline(timeline)
+
+ const rect2 = canvas.rect(10, 10)
+ rect2.timeline(timeline)
+
+ const rect3 = canvas.rect(10, 10)
+ rect3.timeline(timeline)
+
+ rect2.animate(1000, 0, 'now').move(100, 200)
+ rect3.animate(1000, 500, 'now').move(100, 200)
+ rect1.animate(2000, 0, 'now').move(100, 200)
+
+ timeline.finish()
+
+ expect(rect1.x()).toEqual(100)
+ expect(rect1.y()).toEqual(200)
+
+ expect(rect2.x()).toEqual(100)
+ expect(rect2.y()).toEqual(200)
+
+ expect(rect3.x()).toEqual(100)
+ expect(rect3.y()).toEqual(200)
+ })
+ })
+})
--- /dev/null
+/* globals describe, expect, it */
+
+import { easing } from '../../../src/main.js'
+
+describe('easing', () => {
+ var easedValues = {
+ '-': 0.5,
+ '<>': 0.5,
+ '>': 0.7071,
+ '<': 0.2929
+ }
+
+ ;[ '-', '<>', '<', '>' ].forEach((el) => {
+ describe(el, () => {
+ it('is 0 at 0', () => {
+ expect(easing[el](0)).toBe(0)
+ })
+ it('is 1 at 1', () => {
+ expect(Math.round(easing[el](1) * 1000) / 1000).toBe(1) // we need to round cause for some reason at some point 1==0.999999999
+ })
+ it('is eased at 0.5', () => {
+ expect(easing[el](0.5)).toBeCloseTo(easedValues[el])
+ })
+ })
+ })
+})
+++ /dev/null
-describe('SVG.Animator', function () {
-
- beforeEach(function () {
- jasmine.RequestAnimationFrame.install()
- SVG.Animator.timeouts = new SVG.Queue()
- SVG.Animator.frames = new SVG.Queue()
- SVG.Animator.nextDraw = null
- })
-
- afterEach(function () {
- jasmine.RequestAnimationFrame.uninstall()
- })
-
- describe('timeout()', function () {
- it('calls a function after a specific time', function () {
-
- var spy = jasmine.createSpy('tester')
- var id = SVG.Animator.timeout(spy, 100)
-
- jasmine.RequestAnimationFrame.tick(99)
- expect(spy).not.toHaveBeenCalled()
- jasmine.RequestAnimationFrame.tick()
- expect(spy).toHaveBeenCalled()
- })
- })
-
- describe('cancelTimeout()', function () {
- it('cancels a timeout which was created with timeout()', function () {
- var spy = jasmine.createSpy('tester')
- var id = SVG.Animator.timeout(spy, 100)
- SVG.Animator.clearTimeout(id)
-
- expect(spy).not.toHaveBeenCalled()
- jasmine.RequestAnimationFrame.tick(100)
- expect(spy).not.toHaveBeenCalled()
- })
- })
-
- describe('frame()', function () {
- it('calls a function at the next animationFrame', function () {
- var spy = jasmine.createSpy('tester')
-
- SVG.Animator.frame(spy)
- expect(spy).not.toHaveBeenCalled()
- jasmine.RequestAnimationFrame.tick()
- expect(spy).toHaveBeenCalled()
- })
- })
-
-})
+++ /dev/null
-
-describe('Color', function() {
- var color
-
- beforeEach(function() {
- color = new SVG.Color({ r: 0, g: 102, b: 255 })
- })
-
- describe ('construct: constructs a color in different formats', () => {
-
- it ('constructs a color from an object in the correct color space', () => {
-
- // Try in rgb
- let color = new SVG.Color({ r: 255, g: 0, b: 128 })
- expect(color.r).toBe(255)
- expect(color.g).toBe(0)
- expect(color.b).toBe(128)
- expect(color.space).toBe('rgb')
-
- // Try in cmyk
- let color2 = new SVG.Color({ c: 20, y: 15, m: 10, k: 5 })
- expect(color2.c).toBe(20)
- expect(color2.m).toBe(10)
- expect(color2.y).toBe(15)
- expect(color2.k).toBe(5)
- expect(color2.space).toBe('cmyk')
- })
-
- it ('constructs a color from an array', () => {
- let color = new SVG.Color([ 30, 24, 50 ])
- expect( color.r ).toBe( 30 )
- expect( color.g ).toBe( 24 )
- expect( color.b ).toBe( 50 )
- expect( color.space ).toBe('rgb')
- })
-
- it ('constructs a color from an array with space in array', () => {
- let color = new SVG.Color([ 50, 50, 5, 'lab' ])
- expect( color.l ).toBe( 50 )
- expect( color.a ).toBe( 50 )
- expect( color.b ).toBe( 5 )
- expect( color.space ).toBe('lab')
- })
-
- it ('constructs a color from an array with space given', () => {
- let color = new SVG.Color([ 50, 50, 5], 'lab' )
- expect( color.l ).toBe( 50 )
- expect( color.a ).toBe( 50 )
- expect( color.b ).toBe( 5 )
- expect( color.space ).toBe('lab')
- })
-
- it('correclty parses an rgb string', () => {
- let color = new SVG.Color('rgb(255,0,128)')
- expect(color.r).toBe(255)
- expect(color.g).toBe(0)
- expect(color.b).toBe(128)
- })
-
- it('correclty parses a 3 digit hex string', () => {
- color = new SVG.Color('#f06')
- expect(color.r).toBe(255)
- expect(color.g).toBe(0)
- expect(color.b).toBe(102)
- })
-
- it('correclty parses a 6 digit hex string', () => {
- color = new SVG.Color('#0066ff')
- expect(color.r).toBe(0)
- expect(color.g).toBe(102)
- expect(color.b).toBe(255)
- })
-
- })
-
- describe ('input and output: Importing and exporting colors', () => {
- describe('toHex()', function() {
- it('returns a hex color', function() {
- expect(color.toHex()).toBe('#0066ff')
- })
- })
-
- describe('toRgb()', function() {
- it('returns a rgb string color', function() {
- expect(color.toRgb()).toBe('rgb(0,102,255)')
- })
- })
- })
-
- describe('color spaces: The color spaces supported by our library', () => {
-
- describe('lab()', () => {
- it ('can convert rgb to lab', () => {
- let color = new SVG.Color( 255, 0, 128 )
- let lab = color.lab()
- expect( lab.l ).toBeCloseTo( 54.88, 1 )
- expect( lab.a ).toBeCloseTo( 84.55, 1 )
- expect( lab.b ).toBeCloseTo( 4.065, 1 )
- expect( lab.space ).toBe('lab')
- })
-
- it ('can convert from lab to rgb', () => {
- let lab = new SVG.Color( 54.88, 84.55, 4.065, 'lab' )
- let rgb = lab.rgb()
- expect( rgb.r ).toBeCloseTo( 255, 0 )
- expect( rgb.g ).toBeCloseTo( 0, 0 )
- expect( rgb.b ).toBeCloseTo( 128, 0 )
- expect( rgb.space ).toBe('rgb')
- })
-
- it ('is invertable', () => {
- let { r, g, b } = new SVG.Color( 255, 0, 128 ).lab().rgb()
- expect ( r ).toBeCloseTo( 255, 0 )
- expect ( g ).toBeCloseTo( 0, 0 )
- expect ( b ).toBeCloseTo( 128, 0 )
- })
-
- it('handles black', () => {
- let color = new SVG.Color(0, 0, 0).lab().rgb()
- expect( color.r ).toBeCloseTo(0, 0)
- expect( color.g ).toBeCloseTo(0, 0)
- expect( color.b ).toBeCloseTo(0, 0)
- expect( color.toHex() ).toBe('#000000')
- })
-
- it('handles white', () => {
- let color = new SVG.Color(255, 255, 255).lab().rgb()
- expect( color.r ).toBeCloseTo(255, 0)
- expect( color.g ).toBeCloseTo(255, 0)
- expect( color.b ).toBeCloseTo(255, 0)
- expect( color.toHex() ).toBe('#ffffff')
- })
- })
-
- describe('lch()', () => {
- it ('can convert rgb to lch', () => {
- let color = new SVG.Color( 255, 0, 128 )
- let lch = color.lch()
- expect( lch.l ).toBeCloseTo( 54.88, 1 )
- expect( lch.c ).toBeCloseTo( 84.65, 1 )
- expect( lch.h ).toBeCloseTo( 2.75, 1 )
- expect( lch.space ).toBe('lch')
- })
-
- it ('can convert from lch to rgb', () => {
- let lch = new SVG.Color( 54.88, 84.65, 2.75, 'lch' )
- let rgb = lch.rgb()
- expect( rgb.r ).toBeCloseTo( 255, 0 )
- expect( rgb.g ).toBeCloseTo( 0, 0 )
- expect( rgb.b ).toBeCloseTo( 128, 0 )
- expect( rgb.space ).toBe('rgb')
- })
-
- it ('is invertable', () => {
- let { r, g, b } = new SVG.Color( 255, 0, 128 ).lch().rgb()
- expect ( r ).toBeCloseTo( 255, 0 )
- expect ( g ).toBeCloseTo( 0, 0 )
- expect ( b ).toBeCloseTo( 128, 0 )
- })
-
- it('handles black', () => {
- let color = new SVG.Color(0, 0, 0).lch().rgb()
- expect( color.r ).toBeCloseTo(0, 0)
- expect( color.g ).toBeCloseTo(0, 0)
- expect( color.b ).toBeCloseTo(0, 0)
- expect( color.toHex() ).toBe('#000000')
- })
-
- it('handles white', () => {
- let color = new SVG.Color(255, 255, 255).lch().rgb()
- expect( color.r ).toBeCloseTo(255, 0)
- expect( color.g ).toBeCloseTo(255, 0)
- expect( color.b ).toBeCloseTo(255, 0)
- expect( color.toHex() ).toBe('#ffffff')
- })
- })
-
- describe('hsl()', () => {
-
- it ('can convert from rgb to hsl', () => {
- let color = new SVG.Color( 255, 0, 128 )
- let hsl = color.hsl()
- expect( hsl.h ).toBeCloseTo( 329.88, 1 )
- expect( hsl.s ).toBeCloseTo( 100, 1 )
- expect( hsl.l ).toBeCloseTo( 50, 1 )
- expect( hsl.space ).toBe('hsl')
- })
-
- it ('can convert from hsl to rgb', () => {
- let hsl = new SVG.Color( 329.88, 100, 50, 'hsl' )
- let rgb = hsl.rgb()
- expect( rgb.r ).toBeCloseTo( 255, 0 )
- expect( rgb.g ).toBeCloseTo( 0, 0 )
- expect( rgb.b ).toBeCloseTo( 128, 0 )
- expect( rgb.space ).toBe('rgb')
- })
-
- it ('is invertable', () => {
- let { r, g, b } = new SVG.Color( 255, 0, 128 ).hsl().rgb()
- expect ( r ).toBeCloseTo( 255, 0 )
- expect ( g ).toBeCloseTo( 0, 0 )
- expect ( b ).toBeCloseTo( 128, 0 )
- })
-
- it('handles black', () => {
- let color = new SVG.Color(0, 0, 0).hsl().rgb()
- expect( color.r ).toBeCloseTo(0, 0)
- expect( color.g ).toBeCloseTo(0, 0)
- expect( color.b ).toBeCloseTo(0, 0)
- expect( color.toHex() ).toBe('#000000')
- })
-
- it('handles white', () => {
- let color = new SVG.Color(255, 255, 255).hsl().rgb()
- expect( color.r ).toBeCloseTo(255, 0)
- expect( color.g ).toBeCloseTo(255, 0)
- expect( color.b ).toBeCloseTo(255, 0)
- expect( color.toHex() ).toBe('#ffffff')
- })
- })
-
- describe('cmyk()', () => {
-
- it ('can convert from rgb to cmyk', () => {
- let color = new SVG.Color( 255, 0, 128 )
- let cmyk = color.cmyk()
- expect( cmyk.c ).toBeCloseTo( 0, 1 )
- expect( cmyk.m ).toBeCloseTo( 1, 1 )
- expect( cmyk.y ).toBeCloseTo( 0.49, 1 )
- expect( cmyk.k ).toBeCloseTo( 0, 1 )
- expect( cmyk.space ).toBe('cmyk')
- })
-
- it ('can convert from cmyk to rgb', () => {
- let color = new SVG.Color( 0, 1, 0.49, 0, 'cmyk' )
- let rgb = color.rgb()
- expect( rgb.r ).toBeCloseTo( 255, -1 )
- expect( rgb.g ).toBeCloseTo( 0, -1 )
- expect( rgb.b ).toBeCloseTo( 128, -1 )
- expect( rgb.space ).toBe('rgb')
- })
-
- it ('is invertable', () => {
- let { r, g, b } = new SVG.Color( 255, 0, 128 ).cmyk().rgb()
- expect ( r ).toBeCloseTo( 255, 0 )
- expect ( g ).toBeCloseTo( 0, 0 )
- expect ( b ).toBeCloseTo( 128, 0 )
- })
-
- it('handles black', () => {
- let color = new SVG.Color(0, 0, 0).cmyk().rgb()
- expect( color.r ).toBeCloseTo(0, 0)
- expect( color.g ).toBeCloseTo(0, 0)
- expect( color.b ).toBeCloseTo(0, 0)
- expect( color.toHex() ).toBe('#000000')
- })
-
- it('handles white', () => {
- let color = new SVG.Color(255, 255, 255).cmyk().rgb()
- expect( color.r ).toBeCloseTo(255, 0)
- expect( color.g ).toBeCloseTo(255, 0)
- expect( color.b ).toBeCloseTo(255, 0)
- expect( color.toHex() ).toBe('#ffffff')
- })
-
- })
-
- })
-
-})
+++ /dev/null
-describe('SVG.easing', function() {
- var easedValues = {
- '-':0.5,
- '<>':0.5,
- '>':0.7071,
- '<':0.2929,
- }
-
- ;['-', '<>', '<', '>'].forEach(function(el) {
- describe(el, function() {
- it('is 0 at 0', function() {
- expect(SVG.easing[el](0)).toBe(0)
- })
- it('is 1 at 1', function() {
- expect(Math.round(SVG.easing[el](1)*1000)/1000).toBe(1) // we need to round cause for some reason at some point 1==0.999999999
- })
- it('is eased at 0.5', function() {
- expect(SVG.easing[el](0.5)).toBeCloseTo(easedValues[el])
- })
- })
- })
-})
--- /dev/null
+/* globals describe, expect, it, spyOn, container */
+
+import { Rect, Matrix, SVG } from '../../../../src/main.js'
+
+describe('transform.js', () => {
+ describe('untransform()', () => {
+ it('returns itself', () => {
+ const rect = new Rect()
+ expect(rect.untransform()).toBe(rect)
+ })
+
+ it('deletes the transform attribute', () => {
+ const rect = new Rect()
+ expect(rect.untransform().attr('transform')).toBe(undefined)
+ })
+ })
+
+ describe('matrixify()', () => {
+ it('reduces all transformations of the transform list into one matrix - 1', () => {
+ const rect = new Rect().attr('transform', 'matrix(1, 0, 1, 1, 0, 1)')
+ expect(rect.matrixify()).toEqual(new Matrix(1, 0, 1, 1, 0, 1))
+ })
+
+ it('reduces all transformations of the transform list into one matrix - 2', () => {
+ const rect = new Rect().attr('transform', 'translate(10, 20) rotate(45)')
+ expect(rect.matrixify()).toEqual(new Matrix().rotate(45).translate(10, 20))
+ })
+
+ it('reduces all transformations of the transform list into one matrix - 3', () => {
+ const rect = new Rect().attr('transform', 'translate(10, 20) rotate(45) skew(1,2) skewX(10) skewY(20)')
+ expect(rect.matrixify()).toEqual(new Matrix().skewY(20).skewX(10).skew(1, 2).rotate(45).translate(10, 20))
+ })
+ })
+
+ describe('toParent()', () => {
+ it('returns itself', () => {
+ const canvas = SVG().addTo(container)
+ const g = canvas.group()
+ const rect = g.rect(100, 100)
+ expect(rect.toParent(canvas)).toBe(rect)
+ })
+
+ it('does nothing if the parent is the the current element', () => {
+ const canvas = SVG().addTo(container)
+ const g = canvas.group()
+ const parent = g.parent()
+ const position = g.position()
+ g.toParent(g)
+ expect(g.parent()).toBe(parent)
+ expect(g.position()).toBe(position)
+ })
+
+ it('moves an element to a different container without changing its visual representation - 1', () => {
+ const canvas = SVG().addTo(container)
+ const g = canvas.group().matrix(1, 0, 1, 1, 0, 1)
+ const rect = g.rect(100, 100)
+ rect.toParent(canvas)
+ expect(rect.matrix()).toEqual(new Matrix(1, 0, 1, 1, 0, 1))
+ expect(rect.parent()).toBe(canvas)
+ })
+
+ it('moves an element to a different container without changing its visual representation - 2', () => {
+ const canvas = SVG().addTo(container)
+ const g = canvas.group().translate(10, 20)
+ const rect = g.rect(100, 100)
+ const g2 = canvas.group().rotate(10)
+ rect.toParent(g2)
+ const actual = rect.matrix()
+ const expected = new Matrix().translate(10, 20).rotate(-10)
+
+ // funny enough the dom seems to shorten the floats and precision gets lost
+ ;[ ...'abcdef' ].forEach(prop => expect(actual[prop]).toBeCloseTo(expected[prop], 5))
+ })
+
+ it('inserts the element at the specified position', () => {
+ const canvas = SVG().addTo(container)
+ const g = canvas.group()
+ const rect = g.rect(100, 100)
+ canvas.rect(100, 100)
+ canvas.rect(100, 100)
+ expect(rect.toParent(canvas, 2).position()).toBe(2)
+ })
+ })
+
+ describe('toRoot()', () => {
+ it('calls toParent() with root node', () => {
+ const canvas = SVG().addTo(container)
+ const g = canvas.group().matrix(1, 0, 1, 1, 0, 1)
+ const rect = g.rect(100, 100)
+ const spy = spyOn(rect, 'toParent')
+ rect.toRoot(3)
+ expect(spy).toHaveBeenCalledWith(canvas, 3)
+ })
+ })
+
+ describe('transform()', () => {
+ it('acts as full getter with no argument', () => {
+ const rect = new Rect().attr('transform', 'translate(10, 20) rotate(45)')
+ const actual = rect.transform()
+ const expected = new Matrix().rotate(45).translate(10, 20).decompose()
+
+ expect(actual).toEqual(expected)
+ })
+
+ it('returns a single transformation value when string was passed', () => {
+ const rect = new Rect().attr('transform', 'translate(10, 20) rotate(45)')
+ expect(rect.transform('rotate')).toBe(45)
+ expect(rect.transform('translateX')).toBe(10)
+ expect(rect.transform('translateY')).toBe(20)
+ })
+
+ it('sets the transformation with an object', () => {
+ const rect = new Rect().transform({ rotate: 45, translate: [ 10, 20 ] })
+ expect(rect.transform('rotate')).toBe(45)
+ expect(rect.transform('translateX')).toBe(10)
+ expect(rect.transform('translateY')).toBe(20)
+ })
+
+ it('performs a relative transformation with flag=true', () => {
+ const rect = new Rect().transform({ rotate: 45, translate: [ 10, 20 ] }).transform({ rotate: 10 }, true)
+ expect(rect.transform('rotate')).toBeCloseTo(55, 5) // rounding errors
+ expect(rect.transform('translateX')).toBe(10)
+ expect(rect.transform('translateY')).toBe(20)
+ })
+
+ it('performs a relative transformation with flag=other matrix', () => {
+ const rect = new Rect().transform({ rotate: 45, translate: [ 10, 20 ] }).transform({ rotate: 10 }, new Matrix().rotate(30))
+ expect(rect.transform('rotate')).toBeCloseTo(40, 5) // rounding errors
+ expect(rect.transform('translateX')).toBe(0)
+ expect(rect.transform('translateY')).toBe(0)
+ })
+
+ it('performs a relative transformation with flag=other element', () => {
+ const referenceElement = new Rect().transform({ rotate: 30 })
+ const rect = new Rect().transform({ rotate: 45, translate: [ 10, 20 ] }).transform({ rotate: 10 }, referenceElement)
+ expect(rect.transform('rotate')).toBeCloseTo(40, 5) // rounding errors
+ expect(rect.transform('translateX')).toBe(0)
+ expect(rect.transform('translateY')).toBe(0)
+ })
+ })
+})
+++ /dev/null
-describe('Morphing', function () {
- describe('constructors', function () {
-
- it('SVG.Morphable with Number', function () {
- var morpher = new SVG.Morphable().from(10).to(5)
-
- expect(morpher instanceof SVG.Morphable).toBe(true)
- expect(morpher.type()).toBe(SVG.Number)
- expect(morpher.at(0.5) instanceof SVG.Number).toBe(true)
- expect(morpher.at(0.5).valueOf()).toBe(7.5)
- })
-
- it('SVG.Morphable with String', function () {
- var morpher = new SVG.Morphable().from('foo').to('bar')
-
- expect(morpher instanceof SVG.Morphable).toBe(true)
- expect(morpher.type()).toBe(SVG.NonMorphable)
- expect(morpher.at(0.5) instanceof SVG.NonMorphable).toBe(true)
- expect(morpher.at(0.5).valueOf()).toBe('foo')
- expect(morpher.at(1).valueOf()).toBe('bar')
- })
-
- it('SVG.Morphable with Object', function () {
- var morpher = new SVG.Morphable().from({a:5, b: 10}).to({a: 10, b: 20})
-
- expect(morpher instanceof SVG.Morphable).toBe(true)
- expect(morpher.type()).toBe(SVG.ObjectBag)
- expect(morpher.at(0.5) instanceof Object).toBe(true)
- expect(morpher.at(0.5).valueOf()).toEqual(jasmine.objectContaining({a: 7.5, b: 15}))
- })
-
- it('Creates a morphable out of an SVG.Number', function () {
- var morpher = new SVG.Number(5).to(10)
-
- expect(morpher instanceof SVG.Morphable).toBe(true)
- expect(morpher.type()).toBe(SVG.Number)
- expect(morpher.at(0.5) instanceof SVG.Number).toBe(true)
- expect(morpher.at(0.5).valueOf()).toBe(7.5)
- })
-
- it('Creates a morphable out of an SVG.Color', function () {
- var morpher = new SVG.Color('#fff').to('#000')
-
- expect(morpher instanceof SVG.Morphable).toBe(true)
- expect(morpher.type()).toBe(SVG.Color)
- expect(morpher.at(0.5) instanceof SVG.Color).toBe(true)
- expect(morpher.at(0.5).toHex()).toBe('#808080')
- })
-
- it('Creates a morphable out of an SVG.Box', function () {
- var morpher = new SVG.Box(1, 2, 3, 4).to([5, 6, 7, 8])
-
- expect(morpher instanceof SVG.Morphable).toBe(true)
- expect(morpher.type()).toBe(SVG.Box)
- expect(morpher.at(0.5) instanceof SVG.Box).toBe(true)
- expect(morpher.at(0.5)).toEqual(jasmine.objectContaining({x: 3, y: 4, width: 5, height: 6}))
- })
-
- it('Creates a morphable out of an SVG.Matrix', function () {
- var morpher = new SVG.Matrix(1, 2, 3, 4, 5, 6).to([3, 4, 5, 6, 7, 8])
-
- expect(morpher instanceof SVG.Morphable).toBe(true)
- expect(morpher.type()).toBe(SVG.Matrix)
- expect(morpher.at(0.5) instanceof SVG.Matrix).toBe(true)
- expect(morpher.at(0.5)).toEqual(jasmine.objectContaining(new SVG.Matrix(2, 3, 4, 5, 6, 7)))
- })
-
- it('Creates a morphable out of an SVG.Array', function () {
- var morpher = new SVG.Array([1,2,3,4,5,6]).to([3,4,5,6,7,8])
-
- expect(morpher instanceof SVG.Morphable).toBe(true)
- expect(morpher.type()).toBe(SVG.Array)
- expect(morpher.at(0.5) instanceof SVG.Array).toBe(true)
- expect(morpher.at(0.5).toArray()).toEqual(jasmine.arrayContaining([2, 3, 4, 5, 6, 7]))
- })
-
- it('Creates a morphable out of an SVG.PointArray', function () {
- var morpher = new SVG.PointArray([1, 2, 3, 4, 5, 6]).to([3, 4, 5, 6, 7, 8])
-
- expect(morpher instanceof SVG.Morphable).toBe(true)
- expect(morpher.type()).toBe(SVG.PointArray)
- expect(morpher.at(0.5) instanceof SVG.PointArray).toBe(true)
- expect(morpher.at(0.5).toArray()).toEqual(jasmine.arrayContaining([2, 3, 4, 5, 6, 7]))
- })
-
- it('Creates a morphable out of an SVG.PathArray', function () {
- var morpher = new SVG.PathArray(['M', 1, 2, 'L', 3, 4, 'L', 5, 6]).to(['M', 3, 4, 'L', 5, 6, 'L', 7, 8])
-
- expect(morpher instanceof SVG.Morphable).toBe(true)
- expect(morpher.type()).toBe(SVG.PathArray)
- expect(morpher.at(0.5) instanceof SVG.PathArray).toBe(true)
- expect(morpher.at(0.5).toArray()).toEqual(jasmine.arrayContaining(['M', 2, 3, 'L', 4, 5, 'L', 6, 7]))
- })
-
- it('Creates a morphable out of an SVG.NonMorphable', function () {
- var morpher = new SVG.NonMorphable('foo').to('bar')
-
- expect(morpher instanceof SVG.Morphable).toBe(true)
- expect(morpher.type()).toBe(SVG.NonMorphable)
- expect(morpher.at(0.5) instanceof SVG.NonMorphable).toBe(true)
- expect(morpher.at(0.5).valueOf()).toBe('foo')
- expect(morpher.at(1).valueOf()).toBe('bar')
- })
-
- it('Creates a morphable out of an SVG.TransformBag', function () {
- var morpher = new SVG.TransformBag({rotate: 0, translateX: 0})
- .to({rotate: 50, translateX: 20})
-
- expect(morpher instanceof SVG.Morphable).toBe(true)
- expect(morpher.type()).toBe(SVG.TransformBag)
- expect(morpher.at(0.5) instanceof SVG.TransformBag).toBe(true)
-
- expect(morpher.at(0.5)).toEqual(jasmine.objectContaining({rotate: 25, translateX: 10}))
- })
-
- it('Creates a morphable out of an SVG.ObjectBag', function () {
- var morpher = new SVG.ObjectBag({a:5, b: 10}).to({a: 10, b: 20})
-
- expect(morpher instanceof SVG.Morphable).toBe(true)
- expect(morpher.type()).toBe(SVG.ObjectBag)
- expect(morpher.at(0.5) instanceof Object).toBe(true)
- expect(morpher.at(0.5).valueOf()).toEqual(jasmine.objectContaining({a: 7.5, b: 15}))
- })
- })
-
- describe('from()', function () {
- it('sets the type of the runner', function () {
- var morpher = new SVG.Morphable().from(5)
- expect(morpher.type()).toBe(SVG.Number)
- })
-
- it('sets the from attribute to an array representation of the morphable type', function () {
- var morpher = new SVG.Morphable().from(5)
- expect(morpher.from()).toEqual(jasmine.arrayContaining([5]))
- })
- })
-
- describe('type()', function () {
- it('sets the type of the runner', function () {
- var morpher = new SVG.Morphable().type(SVG.Number)
- expect(morpher._type).toBe(SVG.Number)
- })
-
- it('gets the type of the runner', function () {
- var morpher = new SVG.Morphable().type(SVG.Number)
- expect(morpher.type()).toBe(SVG.Number)
- })
- })
-
- describe('to()', function () {
- it('sets the type of the runner', function () {
- var morpher = new SVG.Morphable().to(5)
- expect(morpher.type()).toBe(SVG.Number)
- })
-
- it('sets the from attribute to an array representation of the morphable type', function () {
- var morpher = new SVG.Morphable().to(5)
- expect(morpher.to()).toEqual(jasmine.arrayContaining([5]))
- })
- })
-})
+++ /dev/null
-describe('Number', function() {
- var number
-
- beforeEach(function() {
- number = new SVG.Number
- })
-
- describe('new', function() {
- it('is zero', function() {
- expect(number.value).toBe(0)
- })
- it('has a blank unit', function() {
- expect(number.unit).toBe('')
- })
- it('accepts the unit as a second argument', function() {
- number = new SVG.Number(30, '%')
- expect(number.value).toBe(30)
- expect(number.unit).toBe('%')
- })
- it('parses a pixel value', function() {
- number = new SVG.Number('20px')
- expect(number.value).toBe(20)
- expect(number.unit).toBe('px')
- })
- it('parses a percent value', function() {
- number = new SVG.Number('99%')
- expect(number.value).toBe(0.99)
- expect(number.unit).toBe('%')
- })
- it('parses a seconds value', function() {
- number = new SVG.Number('2s')
- expect(number.value).toBe(2000)
- expect(number.unit).toBe('s')
- })
- it('parses a negative percent value', function() {
- number = new SVG.Number('-89%')
- expect(number.value).toBe(-0.89)
- expect(number.unit).toBe('%')
- })
- it('falls back to 0 if given value is NaN', function() {
- number = new SVG.Number(NaN)
- expect(number.value).toBe(0)
- })
- it('falls back to maximum value if given number is positive infinite', function() {
- number = new SVG.Number(1.7976931348623157E+10308)
- expect(number.value).toBe(3.4e+38)
- })
- it('falls back to minimum value if given number is negative infinite', function() {
- number = new SVG.Number(-1.7976931348623157E+10308)
- expect(number.value).toBe(-3.4e+38)
- })
- })
-
- describe('toString()', function() {
- it('converts the number to a string', function() {
- expect(number.toString()).toBe('0')
- })
- it('appends the unit', function() {
- number.value = 1.21
- number.unit = 'px'
- expect(number.toString()).toBe('1.21px')
- })
- it('converts percent values properly', function() {
- number.value = 1.36
- number.unit = '%'
- expect(number.toString()).toBe('136%')
- })
- it('converts second values properly', function() {
- number.value = 2500
- number.unit = 's'
- expect(number.toString()).toBe('2.5s')
- })
- })
-
- describe('valueOf()', function() {
- it('returns a numeric value for default units', function() {
- expect(typeof number.valueOf()).toBe('number')
- number = new SVG.Number('12')
- expect(typeof number.valueOf()).toBe('number')
- number = new SVG.Number(13)
- expect(typeof number.valueOf()).toBe('number')
- })
- it('returns a numeric value for pixel units', function() {
- number = new SVG.Number('10px')
- expect(typeof number.valueOf()).toBe('number')
- })
- it('returns a numeric value for percent units', function() {
- number = new SVG.Number('20%')
- expect(typeof number.valueOf()).toBe('number')
- })
- it('converts to a primitive when multiplying', function() {
- number.value = 80
- expect(number * 4).toBe(320)
- })
- })
-
- describe('plus()', function() {
- it('returns a new instance', function() {
- expect(number.plus(4.5)).not.toBe(number)
- expect(number.plus(4.5) instanceof SVG.Number).toBeTruthy()
- })
- it('adds a given number', function() {
- expect(number.plus(3.5).valueOf()).toBe(3.5)
- })
- it('adds a given percentage value', function() {
- expect(number.plus('225%').valueOf()).toBe(2.25)
- })
- it('adds a given pixel value', function() {
- expect(number.plus('83px').valueOf()).toBe(83)
- })
- it('use the unit of this number as the unit of the returned number by default', function (){
- expect(new SVG.Number('12s').plus('3%').unit).toBe('s')
- })
- it('use the unit of the passed number as the unit of the returned number when this number as no unit', function() {
- expect(number.plus('15%').unit).toBe('%')
- })
- })
-
- describe('minus()', function() {
- it('subtracts a given number', function() {
- expect(number.minus(3.7).valueOf()).toBe(-3.7)
- })
- it('subtracts a given percentage value', function() {
- expect(number.minus('223%').valueOf()).toBe(-2.23)
- })
- it('subtracts a given pixel value', function() {
- expect(number.minus('85px').valueOf()).toBe(-85)
- })
- it('use the unit of this number as the unit of the returned number by default', function (){
- expect(new SVG.Number('12s').minus('3%').unit).toBe('s')
- })
- it('use the unit of the passed number as the unit of the returned number when this number as no unit', function() {
- expect(number.minus('15%').unit).toBe('%')
- })
- })
-
- describe('times()', function() {
- beforeEach(function() {
- number = number.plus(4)
- })
- it('multiplies with a given number', function() {
- expect(number.times(3).valueOf()).toBe(12)
- })
- it('multiplies with a given percentage value', function() {
- expect(number.times('110%').valueOf()).toBe(4.4)
- })
- it('multiplies with a given pixel value', function() {
- expect(number.times('85px').valueOf()).toBe(340)
- })
- it('use the unit of this number as the unit of the returned number by default', function (){
- expect(new SVG.Number('12s').times('3%').unit).toBe('s')
- })
- it('use the unit of the passed number as the unit of the returned number when this number as no unit', function() {
- expect(number.times('15%').unit).toBe('%')
- })
- })
-
- describe('divide()', function() {
- beforeEach(function() {
- number = number.plus(90)
- })
- it('divides by a given number', function() {
- expect(number.divide(3).valueOf()).toBe(30)
- })
- it('divides by a given percentage value', function() {
- expect(number.divide('3000%').valueOf()).toBe(3)
- })
- it('divides by a given pixel value', function() {
- expect(number.divide('45px').valueOf()).toBe(2)
- })
- it('use the unit of this number as the unit of the returned number by default', function (){
- expect(new SVG.Number('12s').divide('3%').unit).toBe('s')
- })
- it('use the unit of the passed number as the unit of the returned number when this number as no unit', function() {
- expect(number.divide('15%').unit).toBe('%')
- })
- })
-})
+++ /dev/null
-describe('Point', function() {
- var point
-
- describe('initialization', function() {
-
- describe('without a source', function() {
-
- beforeEach(function() {
- point = new SVG.Point
- })
-
- it('creates a new point with default values', function() {
- expect(point.x).toBe(0)
- expect(point.y).toBe(0)
- })
-
- })
-
- describe('with x and y given', function() {
- it('creates a point with given values', function() {
- var point = new SVG.Point(2,4)
-
- expect(point.x).toBe(2)
- expect(point.y).toBe(4)
- })
- })
-
- describe('with only x given', function() {
- it('sets the y value to 0', function() {
- var point = new SVG.Point(7)
-
- expect(point.x).toBe(7)
- expect(point.y).toBe(0)
- })
- })
-
- describe('with array given', function() {
- it('creates a point from array', function() {
- var point = new SVG.Point([2,4])
-
- expect(point.x).toBe(2)
- expect(point.y).toBe(4)
- })
- })
-
- describe('with object given', function() {
- it('creates a point from object', function() {
- var point = new SVG.Point({x:2,y:4})
-
- expect(point.x).toBe(2)
- expect(point.y).toBe(4)
- })
- })
-
- describe('with SVG.Point given', function() {
- it('creates a point from SVG.Point', function() {
- var point = new SVG.Point(new SVG.Point(2,4))
-
- expect(point.x).toBe(2)
- expect(point.y).toBe(4)
- })
- })
- })
-
- describe('clone()', function() {
- it('returns cloned point', function() {
- var point1 = new SVG.Point(1,1)
- , point2 = point1.clone()
-
- expect(point1).toEqual(point2)
- expect(point1).not.toBe(point2)
- })
- })
-})
+++ /dev/null
-describe('PointArray', function() {
- const squareString = '0,0 1,0 1,1 0,1';
- const square = new SVG.PointArray(squareString)
-
- describe('toString()', function() {
- it('round trips with string', () => {
- expect(square.toString()).toEqual(squareString)
- })
- })
-
- describe('transform()', function() {
- it('translates correctly', () => {
- const translation = new SVG.Matrix().translate(2,1)
- const newSquare = square.transform(translation)
- expect(newSquare.toString()).toEqual('2,1 3,1 3,2 2,2')
- })
-
- it('transforms like Point', () => {
- const matrix = new SVG.Matrix(1, 2, 3, 4, 5, 6)
- const newSquare = square.transform(matrix)
- for (let i = 0; i < square.length; i++) {
- const squarePoint = new SVG.Point(square[i])
- const newSquarePoint = new SVG.Point(newSquare[i])
- expect(squarePoint.transform(matrix)).toEqual(newSquarePoint)
- }
- })
- })
-})
+++ /dev/null
-
-describe ('SVG.Queue()', function () {
-
- describe('first ()', function () {
-
- it('returns null if no item in the queue', function () {
- var queue = new SVG.Queue()
- expect(queue.first()).toEqual(null)
- })
-
- it ('returns the first value in the queue', function () {
- var queue = new SVG.Queue()
- queue.push(1)
- expect(queue.first()).toBe(1)
- queue.push(2)
- expect(queue.first()).toBe(1)
- })
- })
-
- describe('last ()', function () {
-
- it ('returns null if no item in the queue', function () {
- var queue = new SVG.Queue()
- expect(queue.last()).toEqual(null)
- })
-
- it ('returns the last value added', function () {
- var queue = new SVG.Queue()
- queue.push(1)
- expect(queue.last()).toBe(1)
- queue.push(2)
- expect(queue.last()).toBe(2)
- })
- })
-
- describe('push ()', function () {
-
- it ('adds an element to the end of the queue', function () {
- var queue = new SVG.Queue()
- queue.push(1)
- queue.push(2)
- queue.push(3)
-
- expect(queue.first()).toBe(1)
- expect(queue.last()).toBe(3)
- })
- })
-
- describe('remove ()', function () {
- it('removes the given item from the queue', function () {
- var queue = new SVG.Queue()
- queue.push(1)
- queue.push(2)
- var item = queue.push(3)
-
- queue.remove(item)
-
- expect(queue.last()).toBe(2)
- expect(queue.first()).toBe(1)
- })
- })
-
- describe('shift ()', function () {
- it('returns nothing if queue is empty', function () {
- var queue = new SVG.Queue()
- var val = queue.shift()
- expect(val).toBeFalsy()
- })
-
- it('returns the first item of the queue and removes it', function () {
- var queue = new SVG.Queue()
- queue.push(1)
- queue.push(2)
- queue.push(3)
-
- var val = queue.shift()
-
- expect(queue.last()).toBe(3)
- expect(queue.first()).toBe(2)
-
- expect(val).toBe(1)
- })
- })
-})
+++ /dev/null
-describe('SVG.Runner', function () {
-
- var initFn = jasmine.createSpy('initFn')
- var runFn = jasmine.createSpy('runFn')
-
- beforeEach(function () {
- initFn.calls.reset()
- runFn.calls.reset()
- })
-
- describe('sanitise()', function () {
- it('can handle all form of input', function () {
- var fn = SVG.Runner.sanitise
-
- expect(fn(200, 200, 'now')).toEqual(jasmine.objectContaining({
- duration: 200,
- delay: 200,
- when: 'now',
- times: 1,
- wait: 0,
- swing: false
- }))
-
- expect(fn(200, 200)).toEqual(jasmine.objectContaining({
- duration: 200,
- delay: 200,
- when: 'last',
- times: 1,
- wait: 0,
- swing: false
- }))
-
- expect(fn(200)).toEqual(jasmine.objectContaining({
- duration: 200,
- delay: SVG.defaults.timeline.delay,
- when: 'last',
- times: 1,
- wait: 0,
- swing: false
- }))
-
- expect(fn(runFn)).toEqual(jasmine.objectContaining({
- duration: runFn,
- delay: SVG.defaults.timeline.delay,
- when: 'last',
- times: 1,
- wait: 0,
- swing: false
- }))
-
- expect(fn({delay: 200})).toEqual(jasmine.objectContaining({
- duration: SVG.defaults.timeline.duration,
- delay: 200,
- when: 'last',
- times: 1,
- wait: 0,
- swing: false
- }))
-
- expect(fn({times: 3, delay: 200, when: 'now', swing: true, wait: 200})).toEqual(jasmine.objectContaining({
- duration: SVG.defaults.timeline.duration,
- delay: 200,
- when: 'now',
- times: 3,
- wait: 200,
- swing: true
- }))
- })
- })
-
- describe('())', function () {
- it('creates a runner with defaults', function () {
- var runner = new SVG.Runner()
- expect(runner instanceof SVG.Runner).toBe(true)
- expect(runner._duration).toBe(SVG.defaults.timeline.duration)
- expect(runner._stepper instanceof SVG.Ease).toBe(true)
- })
-
- it('creates a runner with duration set', function () {
- var runner = new SVG.Runner(1000)
- expect(runner instanceof SVG.Runner).toBe(true)
- expect(runner._duration).toBe(1000)
- expect(runner._stepper instanceof SVG.Ease).toBe(true)
- })
-
- it('creates a runner with controller set', function () {
- var runner = new SVG.Runner(runFn)
- expect(runner instanceof SVG.Runner).toBe(true)
- expect(runner._duration).toBeFalsy()
- expect(runner._stepper instanceof SVG.Controller).toBe(true)
- })
- })
-
- describe('constructors', function () {
- // FIXME: Not possible to spy like this in es6
- // describe('animate()', function () {
- // it('creates a runner with the element set and schedules it on the timeline', function () {
- // var orginalRunner = SVG.Runner
- // spyOn(SVG, 'Runner').and.callFake(function() {
- // return new orginalRunner()
- // })
- //
- // var element = SVG('<rect />')
- // var runner = element.animate()
- // expect(SVG.Runner).toHaveBeenCalled();
- // expect(runner instanceof SVG.Runner)
- // expect(runner.element()).toBe(element)
- // expect(runner.timeline()).toBe(element.timeline())
- // })
- // })
-
- describe('delay()', function () {
- it('calls animate with correct parameters', function () {
- var element = SVG('<rect />')
-
- spyOn(element, 'animate')
- element.delay(100, 'now')
- expect(element.animate).toHaveBeenCalledWith(0, 100, 'now')
- })
- })
- })
-
- describe('queue()', function () {
- it('adds another closure to the runner', function () {
- var runner = new SVG.Runner()
- runner.queue(initFn, runFn, true)
-
- expect(runner._queue[0]).toEqual(jasmine.objectContaining({
- initialiser: initFn,
- initialised: false,
- runner: runFn,
- finished: false
- }))
- })
- })
-
-
- describe('step()', function () {
-
- it('returns itself', function () {
- var runner = new SVG.Runner()
- expect(runner.step()).toBe(runner)
- })
-
- it('calls initFn once and runFn at every step', function() {
- var runner = new SVG.Runner()
- runner.queue(initFn, runFn, false)
-
- runner.step()
- expect(initFn).toHaveBeenCalled()
- expect(runFn).toHaveBeenCalled()
-
- runner.step()
- expect(initFn.calls.count()).toBe(1)
- expect(runFn.calls.count()).toBe(2)
- })
-
- it('calls initFn on every step if its declaritive', function() {
- var runner = new SVG.Runner(new SVG.Controller())
- runner.queue(initFn, runFn, true)
-
- runner.step()
- expect(initFn).toHaveBeenCalled()
- expect(runFn).toHaveBeenCalled()
-
- runner.step()
- expect(initFn.calls.count()).toBe(2)
- expect(runFn.calls.count()).toBe(2)
- })
-
- function getLoop(r) {
- var loopDuration = r._duration + r._wait
- var loopsDone = Math.floor(r._time / loopDuration)
- return loopsDone
- }
-
- // step in time
- it('steps forward a certain time', function () {
- var spy = jasmine.createSpy('stepper')
- var r = new SVG.Runner(1000).loop(10, false, 100)
- r.queue(null, spy)
-
- r.step(300) // should be 0.3s
- expect(spy).toHaveBeenCalledWith(0.3)
- expect(getLoop(r)).toBe(0)
-
- r.step(300) // should be 0.6s
- expect(spy).toHaveBeenCalledWith(0.6)
- expect(getLoop(r)).toBe(0)
-
- r.step(600) // should be 0.1s
- expect(spy).toHaveBeenCalledWith(0.1)
- expect(getLoop(r)).toBe(1)
-
- r.step(-300) // should be 0.9s
- expect(spy).toHaveBeenCalledWith(0.9)
- expect(getLoop(r)).toBe(0)
-
- r.step(2000) // should be 0.7s
- expect(spy).toHaveBeenCalledWith(0.7)
- expect(getLoop(r)).toBe(2)
-
- r.step(-2000) // should be 0.9s
- expect(spy).toHaveBeenCalledWith(0.9)
- expect(getLoop(r)).toBe(0)
- })
-
- it('handles dts which are bigger than the animation time', function () {
- var runner = new SVG.Runner(1000)
- runner.queue(initFn, runFn, true)
-
- runner.step(1100)
- expect(initFn).toHaveBeenCalled()
- expect(runFn).toHaveBeenCalledWith(1)
- })
-
-
- describe('looping', function () {
- describe('without wait', function () {
- describe('unreversed', function () {
- describe('nonswinging', function () {
- it('does behave correctly at the end of an even loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(6, false)
- runner.queue(null, spy)
-
- runner.step(5750)
- expect(spy).toHaveBeenCalledWith(0.75)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(1)
- })
-
- it('does behave correctly at the end of an uneven loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(5, false)
- runner.queue(null, spy)
-
- runner.step(4750)
- expect(spy).toHaveBeenCalledWith(0.75)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(1)
- })
- })
-
- describe('swinging', function () {
- it('does behave correctly at the end of an even loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(6, true)
- runner.queue(null, spy)
-
- runner.step(5750)
- expect(spy).toHaveBeenCalledWith(0.25)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(0)
- })
-
- it('does behave correctly at the end of an uneven loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(5, true)
- runner.queue(null, spy)
-
- runner.step(4750)
- expect(spy).toHaveBeenCalledWith(0.75)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(1)
- })
- })
- })
-
- describe('reversed', function () {
- describe('nonswinging', function () {
- it('does behave correctly at the end of an even loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(6, false).reverse()
- runner.queue(null, spy)
-
- runner.step(5750)
- expect(spy).toHaveBeenCalledWith(0.25)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(0)
- })
-
- it('does behave correctly at the end of an uneven loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(5, false).reverse()
- runner.queue(null, spy)
-
- runner.step(4750)
- expect(spy).toHaveBeenCalledWith(0.25)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(0)
- })
- })
-
- describe('swinging', function () {
- it('does behave correctly at the end of an even loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(6, true).reverse()
- runner.queue(null, spy)
-
- runner.step(5750)
- expect(spy).toHaveBeenCalledWith(0.75)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(1)
- })
-
- it('does behave correctly at the end of an uneven loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(5, true).reverse()
- runner.queue(null, spy)
-
- runner.step(4750)
- expect(spy).toHaveBeenCalledWith(0.25)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(0)
- })
- })
- })
- })
-
-
- describe('with wait', function () {
- describe('unreversed', function () {
- describe('nonswinging', function () {
- it('does behave correctly at the end of an even loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(6, false, 100)
- runner.queue(null, spy)
-
- runner.step(5450)
- expect(spy).toHaveBeenCalledWith(1)
- spy.calls.reset()
-
- runner.step(800)
- expect(spy).toHaveBeenCalledWith(0.75)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(1)
- })
-
- it('does behave correctly at the end of an uneven loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(5, false, 100)
- runner.queue(null, spy)
-
- runner.step(4350)
- expect(spy).toHaveBeenCalledWith(1)
- spy.calls.reset()
-
- runner.step(800)
- expect(spy).toHaveBeenCalledWith(0.75)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(1)
- })
- })
-
- describe('swinging', function () {
- it('does behave correctly at the end of an even loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(6, true, 100)
- runner.queue(null, spy)
-
- runner.step(5450)
- expect(spy).toHaveBeenCalledWith(1)
- spy.calls.reset()
-
- runner.step(800)
- expect(spy).toHaveBeenCalledWith(0.25)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(0)
- })
-
- it('does behave correctly at the end of an uneven loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(5, true, 100)
- runner.queue(null, spy)
-
- runner.step(4350)
- expect(spy).toHaveBeenCalledWith(0)
- spy.calls.reset()
-
- runner.step(800)
- expect(spy).toHaveBeenCalledWith(0.75)
-
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(1)
- })
- })
- })
-
- describe('reversed', function () {
- describe('nonswinging', function () {
- it('does behave correctly at the end of an even loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(6, false, 100).reverse()
- runner.queue(null, spy)
-
- runner.step(5450)
- expect(spy).toHaveBeenCalledWith(0)
- spy.calls.reset()
-
- runner.step(800)
- expect(spy).toHaveBeenCalledWith(0.25)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(0)
- })
-
- it('does behave correctly at the end of an uneven loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(5, false, 100).reverse()
- runner.queue(null, spy)
-
- runner.step(4350)
- expect(spy).toHaveBeenCalledWith(0)
- spy.calls.reset()
-
- runner.step(800)
- expect(spy).toHaveBeenCalledWith(0.25)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(0)
- })
- })
-
- describe('swinging', function () {
- it('does behave correctly at the end of an even loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(6, true, 100).reverse()
- runner.queue(null, spy)
-
- runner.step(5450)
- expect(spy).toHaveBeenCalledWith(0)
- spy.calls.reset()
-
- runner.step(800)
- expect(spy).toHaveBeenCalledWith(0.75)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(1)
- })
-
- it('does behave correctly at the end of an uneven loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(5, true, 100).reverse()
- runner.queue(null, spy)
-
- runner.step(4350)
- expect(spy).toHaveBeenCalledWith(1)
- spy.calls.reset()
-
- runner.step(800)
- expect(spy).toHaveBeenCalledWith(0.25)
- runner.step(250)
- expect(spy).toHaveBeenCalledWith(0)
- })
- })
- })
- })
- })
-
-
- })
-
-
- describe('active()', function () {
- it('acts as a getter without parameters', function () {
- var runner = new SVG.Runner()
- expect(runner.active()).toBe(true)
- })
-
- it('disables the runner when false is passed', function () {
- var runner = new SVG.Runner()
- expect(runner.active(false)).toBe(runner)
- expect(runner.active()).toBe(false)
- })
-
- it('enables the runner when true is passed', function () {
- var runner = new SVG.Runner()
- expect(runner.active(false)).toBe(runner)
- expect(runner.active(true)).toBe(runner)
- expect(runner.active()).toBe(true)
- })
- })
-
- describe('duration()', function () {
- it('return the full duration of the runner including all loops and waits', function () {
- var runner = new SVG.Runner(800).loop(10, true, 200)
- expect(runner.duration()).toBe(9800)
- })
- })
-
- describe('loop()', function () {
- it('makes this runner looping', function () {
- var runner = new SVG.Runner(1000).loop(5)
- expect(runner.duration()).toBe(5000)
- })
- })
-
- describe('time()', function () {
- it('returns itself', function () {
- var runner = new SVG.Runner()
- expect(runner.time(0)).toBe(runner)
- })
-
- it('acts as a getter with no parameter passed', function () {
- var runner = new SVG.Runner()
- expect(runner.time()).toBe(0)
- })
-
- it('reschedules the runner to a new time', function () {
- var runner = new SVG.Runner()
- runner.time(10)
-
- expect(runner.time()).toBe(10)
- })
-
- it('calls step to reschedule', function () {
- var runner = new SVG.Runner()
- spyOn(runner, 'step')
- runner.time(10)
-
- expect(runner.step).toHaveBeenCalledWith(10)
- })
- })
-
- describe('loops()', function () {
- it('get the loops of a runner', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).queue(null, spy)
-
- runner.step(300)
- expect(spy).toHaveBeenCalledWith(0.3)
-
- expect(runner.loops()).toBe(0.3)
- })
- it('sets the loops of the runner', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).queue(null, spy)
-
- expect(runner.loops(0.5).loops()).toBe(0.5)
- expect(spy).toHaveBeenCalledWith(0.5)
-
- expect(runner.loops(0.1).loops()).toBe(0.1)
- expect(spy).toHaveBeenCalledWith(0.1)
-
- expect(runner.loops(1.5).loops()).toBe(1)
- expect(spy).toHaveBeenCalledWith(1)
- })
- it('sets the loops of the runner in a loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(5, true, 500).queue(null, spy)
-
- expect(runner.loops(1.3).loops()).toBe(1.3)
- expect(spy).toHaveBeenCalledWith(0.7)
-
- expect(runner.loops(0.3).loops()).toBe(0.3)
- })
- })
-
- describe('progress()', function () {
- it('gets the progress of a runner', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).queue(null, spy)
-
- runner.step(300)
- expect(spy).toHaveBeenCalledWith(0.3)
-
- expect(runner.progress()).toBe(0.3)
- })
-
- it('gets the progress of a runner when looping', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(800).queue(null, spy).loop(10, false, 200) // duration should be 9800
-
- // middle of animation, in the middle of wait time
- runner.step(4900)
- expect(runner.progress()).toBe(0.5)
- expect(spy).toHaveBeenCalledWith(1)
-
- // start of next loop
- runner.step(100)
- expect(spy).toHaveBeenCalledWith(0)
-
- // move 400 into current loop which is 0.5 progress
- // the progress value is 5400 / 9800
- runner.step(400)
- expect(spy).toHaveBeenCalledWith(0.5)
- expect(runner.progress()).toBe(5400 / 9800)
- })
-
- it('sets the progress of a runner', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).queue(null, spy)
-
- expect(runner.progress(0.5).progress()).toBe(0.5)
- expect(spy).toHaveBeenCalledWith(0.5)
- })
-
- it('sets the progress of a runner when looping', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(800).queue(null, spy).loop(10, false, 200)
-
- // progress 0.5 somewhere in the middle of wait time
- expect(runner.progress(0.5).progress()).toBe(0.5)
- expect(spy).toHaveBeenCalledWith(1)
-
- // start of next loop
- runner.step(100)
- expect(spy).toHaveBeenCalledWith(0)
-
- // should move 0.5 into the next loop
- expect(runner.progress(5400 / 9800).progress()).toBe(5400 / 9800)
- expect(spy.calls.mostRecent().args[0]).toBeCloseTo(0.5)
- })
- })
-
- describe('position()', function () {
-
- it('gets the position of a runner', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).queue(null, spy)
-
- runner.step(300)
- expect(spy).toHaveBeenCalledWith(0.3)
-
- expect(runner.position()).toBe(0.3)
- })
-
- it('gets the position of a runner when looping', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(5, true, 100).queue(null, spy)
-
- runner.step(1200)
- expect(spy).toHaveBeenCalledWith(0.9)
-
- expect(runner.position()).toBe(0.9)
- })
-
- it('sets the position of a runner', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).queue(null, spy)
-
- expect(runner.position(0.5).position()).toBe(0.5)
- expect(spy).toHaveBeenCalledWith(0.5)
- })
-
- it('sets the position of a runner in a loop', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).loop(5, true, 100).queue(null, spy)
-
- runner.step(1200)
- expect(runner.position(0.4).position()).toBe(0.4)
- expect(spy).toHaveBeenCalledWith(0.4)
-
- expect(runner.position(0).position()).toBe(0)
- expect(spy).toHaveBeenCalledWith(0)
-
- expect(runner.position(1).position()).toBe(1)
- expect(spy).toHaveBeenCalledWith(1)
- })
- })
-
- describe('element()', function () {
- it('returns the element bound to this runner if any', function () {
- var runner1 = new SVG.Runner()
- expect(runner1.element()).toBe(null)
-
- var element = SVG('<rect />')
- var runner2 = element.animate()
- expect(runner2.element()).toBe(element)
- })
-
- it('sets an element to be bound to the runner', function () {
- var runner = new SVG.Runner()
- var element = SVG('<rect />')
- expect(runner.element(element)).toBe(runner)
- expect(runner.element()).toBe(element)
- })
- })
-
- describe('timeline()', function () {
- it('returns the timeline bound to this runner if any', function () {
- var runner1 = new SVG.Runner()
- expect(runner1.element()).toBe(null)
-
- var element = SVG('<rect />')
- var runner2 = element.animate()
- expect(runner2.timeline()).toBe(element.timeline())
- })
-
- it('sets a timeline to be bound to the runner', function () {
- var runner = new SVG.Runner()
- var timeline = new SVG.Timeline()
- expect(runner.timeline(timeline)).toBe(runner)
- expect(runner.timeline()).toBe(timeline)
- })
- })
-
- describe('schedule()', function () {
- it('schedules the runner on a timeline', function () {
- var runner = new SVG.Runner()
- var timeline = new SVG.Timeline()
- var spy = spyOn(timeline, 'schedule').and.callThrough()
-
- expect(runner.schedule(timeline, 200, 'now')).toBe(runner)
- expect(runner.timeline()).toBe(timeline)
- expect(spy).toHaveBeenCalledWith(runner, 200, 'now')
- })
-
- it('schedules the runner on its own timeline', function () {
- var runner = new SVG.Runner()
- var timeline = new SVG.Timeline()
- var spy = spyOn(timeline, 'schedule')
- runner.timeline(timeline)
-
- expect(runner.schedule(200, 'now')).toBe(runner)
- expect(runner.timeline()).toBe(timeline)
- expect(spy).toHaveBeenCalledWith(runner, 200, 'now')
- })
- })
-
- describe('unschedule()', function () {
- it('unschedules this runner from its timeline', function () {
- var runner = new SVG.Runner()
- var timeline = new SVG.Timeline()
- var spy = spyOn(timeline, 'unschedule').and.callThrough()
-
- expect(runner.schedule(timeline, 200, 'now')).toBe(runner)
- expect(runner.unschedule()).toBe(runner)
- expect(spy).toHaveBeenCalledWith(runner)
- expect(runner.timeline()).toBe(null)
- })
- })
-
-
- describe('animate()', function () {
- it('creates a new runner scheduled after the first', function () {
- var runner = new SVG.Runner(1000)
- var timeline = new SVG.Timeline()
-
- runner.schedule(timeline)
-
- var runner2 = runner.animate(500, 1000)
-
- var t = timeline.time()
-
- expect(runner2.timeline()).toBe(timeline)
- expect(runner2.time()).toBe(0)
-
- expect(timeline.schedule()).toEqual(jasmine.arrayContaining([
- jasmine.objectContaining({start: t, duration: 1000, end: t+1000, runner: runner}),
- jasmine.objectContaining({start: t+2000, duration: 500, end: t+2500, runner: runner2})
- ]))
- })
- })
-
- describe('delay()', function () {
- it('calls animate with delay parameters', function () {
- var runner = new SVG.Runner(1000)
- spyOn(runner, 'animate')
-
- runner.delay(500)
- expect(runner.animate).toHaveBeenCalledWith(0, 500)
- })
- })
-
- describe('during()', function () {
- it('returns itself', function () {
- var runner = new SVG.Runner()
- expect(runner.during(runFn)).toBe(runner)
- })
-
- it('calls queue passing only a function to call on every step', function () {
- var runner = new SVG.Runner()
- spyOn(runner, 'queue')
- runner.during(runFn)
-
- expect(runner.queue).toHaveBeenCalledWith(null, runFn)
- })
- })
-
- // describe('after()', function () {
- // it('returns itself', function () {
- // var runner = new SVG.Runner()
- // expect(runner.after(runFn)).toBe(runner)
- // })
- //
- // it('binds a function to the after event', function () {
- // var runner = new SVG.Runner()
- // spyOn(runner, 'on')
- // runner.after(runFn)
- //
- // expect(runner.on).toHaveBeenCalledWith('finish', runFn)
- // })
- // })
- //
- // describe('finish()', function () {
- // it('returns itself', function () {
- // var runner = new SVG.Runner()
- // expect(runner.finish()).toBe(runner)
- // })
- //
- // it('calls step with Infinity as argument', function () {
- // var runner = new SVG.Runner()
- // spyOn(runner, 'step')
- // runner.finish()
- //
- // expect(runner.step).toHaveBeenCalledWith(Infinity)
- // })
- // })
-
- describe('reverse()', function () {
- it('returns itself', function () {
- var runner = new SVG.Runner()
- expect(runner.reverse()).toBe(runner)
- })
-
- it('reverses the runner', function () {
- var spy = jasmine.createSpy('stepper')
- var runner = new SVG.Runner(1000).reverse().queue(null, spy)
- runner.step(750)
- expect(spy).toHaveBeenCalledWith(0.25)
- })
- })
-
- describe('ease()', function () {
- it('returns itself', function () {
- var runner = new SVG.Runner()
- expect(runner.ease(function () {})).toBe(runner)
- })
-
- it('creates an easing Controller from the easing function', function () {
- var runner = new SVG.Runner()
- runner.ease(function () {})
-
- expect(runner._stepper instanceof SVG.Ease).toBe(true)
- })
- })
-})
+++ /dev/null
-describe('timeline', function() {
- describe('getEndTimeOfTimeline', function() {
- it('returns 0 if no runners are scheduled', function() {
- const timeline = new SVG.Timeline();
- endTime = timeline.getEndTimeOfTimeline();
- expect(endTime).toEqual(0);
- })
- })
-
- describe('finish - issue #964', function() {
- beforeEach(function() {
- draw.clear()
- draw.attr('viewBox', null)
- })
-
- it('places all elements at the right position - single runner', function() {
- const timeline = new SVG.Timeline()
-
- const rect = draw.rect(20,20)
- rect.timeline(timeline)
- rect.animate().move(100, 200)
-
- timeline.finish()
- expect(rect.x()).toEqual(100);
- expect(rect.y()).toEqual(200);
- })
-
- it('places all elements at the right position - runner that finishes latest is in first position', function() {
- const timeline = new SVG.Timeline()
-
- const rect1 = draw.rect(10, 10)
- rect1.timeline(timeline)
-
- const rect2 = draw.rect(10, 10)
- rect2.timeline(timeline);
-
- const rect3 = draw.rect(10, 10)
- rect3.timeline(timeline);
-
- rect1.animate(2000, 0, 'now').move(100, 200)
- rect2.animate(1000, 0, 'now').move(100, 200)
- rect3.animate(1000, 500, 'now').move(100, 200)
-
- timeline.finish()
-
- expect(rect1.x()).toEqual(100);
- expect(rect1.y()).toEqual(200);
-
- expect(rect2.x()).toEqual(100);
- expect(rect2.y()).toEqual(200);
-
- expect(rect3.x()).toEqual(100);
- expect(rect3.y()).toEqual(200);
- })
-
- it('places all elements at the right position - runner that finishes latest is in middle position', function() {
- const timeline = new SVG.Timeline()
-
- const rect1 = draw.rect(10, 10)
- rect1.timeline(timeline)
-
- const rect2 = draw.rect(10, 10)
- rect2.timeline(timeline);
-
- const rect3 = draw.rect(10, 10)
- rect3.timeline(timeline);
-
- rect2.animate(1000, 0, 'now').move(100, 200)
- rect1.animate(2000, 0, 'now').move(100, 200)
- rect3.animate(1000, 500, 'now').move(100, 200)
-
- timeline.finish()
-
- expect(rect1.x()).toEqual(100);
- expect(rect1.y()).toEqual(200);
-
- expect(rect2.x()).toEqual(100);
- expect(rect2.y()).toEqual(200);
-
- expect(rect3.x()).toEqual(100);
- expect(rect3.y()).toEqual(200);
- })
-
- it('places all elements at the right position - runner that finishes latest is in last position', function() {
- const timeline = new SVG.Timeline()
-
- const rect1 = draw.rect(10, 10)
- rect1.timeline(timeline)
-
- const rect2 = draw.rect(10, 10)
- rect2.timeline(timeline);
-
- const rect3 = draw.rect(10, 10)
- rect3.timeline(timeline);
-
- rect2.animate(1000, 0, 'now').move(100, 200)
- rect3.animate(1000, 500, 'now').move(100, 200)
- rect1.animate(2000, 0, 'now').move(100, 200)
-
- timeline.finish()
-
- expect(rect1.x()).toEqual(100);
- expect(rect1.y()).toEqual(200);
-
- expect(rect2.x()).toEqual(100);
- expect(rect2.y()).toEqual(200);
-
- expect(rect3.x()).toEqual(100);
- expect(rect3.y()).toEqual(200);
- })
- })
-})
\ No newline at end of file
--- /dev/null
+/* globals describe, expect, it, beforeEach */
+
+import { Color } from '../../../src/main.js'
+
+describe('Color.js', () => {
+ var color
+
+ beforeEach(() => {
+ color = new Color({ r: 0, g: 102, b: 255 })
+ })
+
+ describe('construct: constructs a color in different formats', () => {
+
+ it('constructs a color from an object in the correct color space', () => {
+
+ // Try in rgb
+ const color = new Color({ r: 255, g: 0, b: 128 })
+ expect(color.r).toBe(255)
+ expect(color.g).toBe(0)
+ expect(color.b).toBe(128)
+ expect(color.space).toBe('rgb')
+
+ // Try in cmyk
+ const color2 = new Color({ c: 20, y: 15, m: 10, k: 5 })
+ expect(color2.c).toBe(20)
+ expect(color2.m).toBe(10)
+ expect(color2.y).toBe(15)
+ expect(color2.k).toBe(5)
+ expect(color2.space).toBe('cmyk')
+ })
+
+ it('constructs a color from an array', () => {
+ const color = new Color([ 30, 24, 50 ])
+ expect(color.r).toBe(30)
+ expect(color.g).toBe(24)
+ expect(color.b).toBe(50)
+ expect(color.space).toBe('rgb')
+ })
+
+ it('constructs a color from an array with space in array', () => {
+ const color = new Color([ 50, 50, 5, 'lab' ])
+ expect(color.l).toBe(50)
+ expect(color.a).toBe(50)
+ expect(color.b).toBe(5)
+ expect(color.space).toBe('lab')
+ })
+
+ it('constructs a color from an array with space given', () => {
+ const color = new Color([ 50, 50, 5 ], 'lab')
+ expect(color.l).toBe(50)
+ expect(color.a).toBe(50)
+ expect(color.b).toBe(5)
+ expect(color.space).toBe('lab')
+ })
+
+ it('correclty parses an rgb string', () => {
+ const color = new Color('rgb(255,0,128)')
+ expect(color.r).toBe(255)
+ expect(color.g).toBe(0)
+ expect(color.b).toBe(128)
+ })
+
+ it('correclty parses a 3 digit hex string', () => {
+ color = new Color('#f06')
+ expect(color.r).toBe(255)
+ expect(color.g).toBe(0)
+ expect(color.b).toBe(102)
+ })
+
+ it('correclty parses a 6 digit hex string', () => {
+ color = new Color('#0066ff')
+ expect(color.r).toBe(0)
+ expect(color.g).toBe(102)
+ expect(color.b).toBe(255)
+ })
+
+ })
+
+ describe('input and output: Importing and exporting colors', () => {
+ describe('toHex()', () => {
+ it('returns a hex color', () => {
+ expect(color.toHex()).toBe('#0066ff')
+ })
+ })
+
+ describe('toRgb()', () => {
+ it('returns a rgb string color', () => {
+ expect(color.toRgb()).toBe('rgb(0,102,255)')
+ })
+ })
+ })
+
+ describe('color spaces: The color spaces supported by our library', () => {
+
+ describe('lab()', () => {
+ it('can convert rgb to lab', () => {
+ const color = new Color(255, 0, 128)
+ const lab = color.lab()
+ expect(lab.l).toBeCloseTo(54.88, 1)
+ expect(lab.a).toBeCloseTo(84.55, 1)
+ expect(lab.b).toBeCloseTo(4.065, 1)
+ expect(lab.space).toBe('lab')
+ })
+
+ it('can convert from lab to rgb', () => {
+ const lab = new Color(54.88, 84.55, 4.065, 'lab')
+ const rgb = lab.rgb()
+ expect(rgb.r).toBeCloseTo(255, 0)
+ expect(rgb.g).toBeCloseTo(0, 0)
+ expect(rgb.b).toBeCloseTo(128, 0)
+ expect(rgb.space).toBe('rgb')
+ })
+
+ it('is invertable', () => {
+ const { r, g, b } = new Color(255, 0, 128).lab().rgb()
+ expect(r).toBeCloseTo(255, 0)
+ expect(g).toBeCloseTo(0, 0)
+ expect(b).toBeCloseTo(128, 0)
+ })
+
+ it('handles black', () => {
+ const color = new Color(0, 0, 0).lab().rgb()
+ expect(color.r).toBeCloseTo(0, 0)
+ expect(color.g).toBeCloseTo(0, 0)
+ expect(color.b).toBeCloseTo(0, 0)
+ expect(color.toHex()).toBe('#000000')
+ })
+
+ it('handles white', () => {
+ const color = new Color(255, 255, 255).lab().rgb()
+ expect(color.r).toBeCloseTo(255, 0)
+ expect(color.g).toBeCloseTo(255, 0)
+ expect(color.b).toBeCloseTo(255, 0)
+ expect(color.toHex()).toBe('#ffffff')
+ })
+ })
+
+ describe('lch()', () => {
+ it('can convert rgb to lch', () => {
+ const color = new Color(255, 0, 128)
+ const lch = color.lch()
+ expect(lch.l).toBeCloseTo(54.88, 1)
+ expect(lch.c).toBeCloseTo(84.65, 1)
+ expect(lch.h).toBeCloseTo(2.75, 1)
+ expect(lch.space).toBe('lch')
+ })
+
+ it('can convert from lch to rgb', () => {
+ const lch = new Color(54.88, 84.65, 2.75, 'lch')
+ const rgb = lch.rgb()
+ expect(rgb.r).toBeCloseTo(255, 0)
+ expect(rgb.g).toBeCloseTo(0, 0)
+ expect(rgb.b).toBeCloseTo(128, 0)
+ expect(rgb.space).toBe('rgb')
+ })
+
+ it('is invertable', () => {
+ const { r, g, b } = new Color(255, 0, 128).lch().rgb()
+ expect(r).toBeCloseTo(255, 0)
+ expect(g).toBeCloseTo(0, 0)
+ expect(b).toBeCloseTo(128, 0)
+ })
+
+ it('handles black', () => {
+ const color = new Color(0, 0, 0).lch().rgb()
+ expect(color.r).toBeCloseTo(0, 0)
+ expect(color.g).toBeCloseTo(0, 0)
+ expect(color.b).toBeCloseTo(0, 0)
+ expect(color.toHex()).toBe('#000000')
+ })
+
+ it('handles white', () => {
+ const color = new Color(255, 255, 255).lch().rgb()
+ expect(color.r).toBeCloseTo(255, 0)
+ expect(color.g).toBeCloseTo(255, 0)
+ expect(color.b).toBeCloseTo(255, 0)
+ expect(color.toHex()).toBe('#ffffff')
+ })
+ })
+
+ describe('hsl()', () => {
+
+ it('can convert from rgb to hsl', () => {
+ const color = new Color(255, 0, 128)
+ const hsl = color.hsl()
+ expect(hsl.h).toBeCloseTo(329.88, 1)
+ expect(hsl.s).toBeCloseTo(100, 1)
+ expect(hsl.l).toBeCloseTo(50, 1)
+ expect(hsl.space).toBe('hsl')
+ })
+
+ it('can convert from hsl to rgb', () => {
+ const hsl = new Color(329.88, 100, 50, 'hsl')
+ const rgb = hsl.rgb()
+ expect(rgb.r).toBeCloseTo(255, 0)
+ expect(rgb.g).toBeCloseTo(0, 0)
+ expect(rgb.b).toBeCloseTo(128, 0)
+ expect(rgb.space).toBe('rgb')
+ })
+
+ it('is invertable', () => {
+ const { r, g, b } = new Color(255, 0, 128).hsl().rgb()
+ expect(r).toBeCloseTo(255, 0)
+ expect(g).toBeCloseTo(0, 0)
+ expect(b).toBeCloseTo(128, 0)
+ })
+
+ it('handles black', () => {
+ const color = new Color(0, 0, 0).hsl().rgb()
+ expect(color.r).toBeCloseTo(0, 0)
+ expect(color.g).toBeCloseTo(0, 0)
+ expect(color.b).toBeCloseTo(0, 0)
+ expect(color.toHex()).toBe('#000000')
+ })
+
+ it('handles white', () => {
+ const color = new Color(255, 255, 255).hsl().rgb()
+ expect(color.r).toBeCloseTo(255, 0)
+ expect(color.g).toBeCloseTo(255, 0)
+ expect(color.b).toBeCloseTo(255, 0)
+ expect(color.toHex()).toBe('#ffffff')
+ })
+ })
+
+ describe('cmyk()', () => {
+
+ it('can convert from rgb to cmyk', () => {
+ const color = new Color(255, 0, 128)
+ const cmyk = color.cmyk()
+ expect(cmyk.c).toBeCloseTo(0, 1)
+ expect(cmyk.m).toBeCloseTo(1, 1)
+ expect(cmyk.y).toBeCloseTo(0.49, 1)
+ expect(cmyk.k).toBeCloseTo(0, 1)
+ expect(cmyk.space).toBe('cmyk')
+ })
+
+ it('can convert from cmyk to rgb', () => {
+ const color = new Color(0, 1, 0.49, 0, 'cmyk')
+ const rgb = color.rgb()
+ expect(rgb.r).toBeCloseTo(255, -1)
+ expect(rgb.g).toBeCloseTo(0, -1)
+ expect(rgb.b).toBeCloseTo(128, -1)
+ expect(rgb.space).toBe('rgb')
+ })
+
+ it('is invertable', () => {
+ const { r, g, b } = new Color(255, 0, 128).cmyk().rgb()
+ expect(r).toBeCloseTo(255, 0)
+ expect(g).toBeCloseTo(0, 0)
+ expect(b).toBeCloseTo(128, 0)
+ })
+
+ it('handles black', () => {
+ const color = new Color(0, 0, 0).cmyk().rgb()
+ expect(color.r).toBeCloseTo(0, 0)
+ expect(color.g).toBeCloseTo(0, 0)
+ expect(color.b).toBeCloseTo(0, 0)
+ expect(color.toHex()).toBe('#000000')
+ })
+
+ it('handles white', () => {
+ const color = new Color(255, 255, 255).cmyk().rgb()
+ expect(color.r).toBeCloseTo(255, 0)
+ expect(color.g).toBeCloseTo(255, 0)
+ expect(color.b).toBeCloseTo(255, 0)
+ expect(color.toHex()).toBe('#ffffff')
+ })
+
+ })
+
+ })
+
+})
/* globals describe, expect, it, spyOn, jasmine */
-import {
- EventTarget
-} from '../../../src/main.js'
+import { EventTarget } from '../../../src/main.js'
import { getWindow } from '../../../src/utils/window.js'
const { any, objectContaining, createSpy } = jasmine
--- /dev/null
+/* globals describe, expect, it, jasmine */
+
+import { Matrix, Rect } from '../../../src/main.js'
+
+const { objectContaining } = jasmine
+
+describe('Matrix.js', () => {
+ const comp = { a: 2, b: 0, c: 0, d: 2, e: 100, f: 50 }
+
+ describe('initialization', () => {
+
+ it('creates a new matrix with default values', () => {
+ const matrix = new Matrix()
+ expect(matrix).toEqual(objectContaining(
+ { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }
+ ))
+ })
+
+ it('parses the current transform matrix from an element', () => {
+ const rect = new Rect().transform(comp)
+ const matrix = new Matrix(rect)
+ expect(matrix).toEqual(objectContaining(comp))
+ })
+
+ it('parses a string value correctly', () => {
+ const matrix = new Matrix('2, 0, 0, 2, 100, 50')
+ expect(matrix).toEqual(objectContaining(comp))
+ })
+
+ it('parses an array correctly', () => {
+ const matrix = new Matrix([ 2, 0, 0, 2, 100, 50 ])
+ expect(matrix).toEqual(objectContaining(comp))
+ })
+
+ it('parses an object correctly', () => {
+ const matrix = new Matrix(comp)
+ expect(matrix).toEqual(objectContaining(comp))
+ })
+
+ it('parses a transform object correctly', () => {
+ const matrix = new Matrix({ scale: 2, translate: [ 100, 50 ] })
+ expect(matrix).toEqual(objectContaining(comp))
+ })
+
+ it('parses 6 arguments correctly', () => {
+ const matrix = new Matrix(2, 0, 0, 2, 100, 50)
+ expect(matrix).toEqual(objectContaining(comp))
+ })
+ })
+
+ describe('toString()', () => {
+ it('exports correctly to a string', () => {
+ expect(new Matrix().toString()).toBe('matrix(1,0,0,1,0,0)')
+ })
+ })
+
+ describe('compose()', () => {
+ it('composes a matrix to form the correct result', () => {
+ const composed = new Matrix().compose({
+ scaleX: 3, scaleY: 20, shear: 4, rotate: 50, translateX: 23, translateY: 52
+ })
+
+ const expected = new Matrix().scale(3, 20).shear(4).rotate(50).translate(23, 52)
+ expect(composed).toEqual(expected)
+ })
+ })
+
+ describe('decompose()', () => {
+ it('decomposes a matrix properly', () => {
+ var matrix = new Matrix().scale(3, 2.5).shear(4).rotate(30).translate(20, 30)
+ var decomposed = matrix.decompose()
+ expect(decomposed.scaleX).toBeCloseTo(3)
+ expect(decomposed.scaleY).toBeCloseTo(2.5)
+ expect(decomposed.shear).toBeCloseTo(4)
+ expect(decomposed.rotate).toBeCloseTo(30)
+ expect(decomposed.translateX).toBeCloseTo(20)
+ expect(decomposed.translateY).toBeCloseTo(30)
+ })
+
+ it('can be recomposed to the same matrix', () => {
+ var matrix = new Matrix().scale(3, 2.5).shear(4).rotate(30).translate(20, 30)
+ var decomposed = matrix.decompose()
+ var composed = new Matrix().compose(decomposed)
+ expect(matrix.a).toBeCloseTo(composed.a)
+ expect(matrix.b).toBeCloseTo(composed.b)
+ expect(matrix.c).toBeCloseTo(composed.c)
+ expect(matrix.d).toBeCloseTo(composed.d)
+ expect(matrix.e).toBeCloseTo(composed.e)
+ expect(matrix.f).toBeCloseTo(composed.f)
+ })
+ })
+
+ describe('clone()', () => {
+ it('returns a clone of the matrix', () => {
+ var matrix = new Matrix(2, 0, 0, 5, 0, 0)
+ var clone = matrix.clone()
+ expect(matrix).not.toBe(clone)
+ for (var i in 'abcdef') {
+ expect(matrix[i]).toEqual(clone[i])
+ }
+ })
+ })
+
+ describe('multiply()', () => {
+ it('multiplies two matrices', () => {
+ var matrix1 = new Matrix(1, 4, 2, 5, 3, 6)
+ var matrix2 = new Matrix(7, 8, 8, 7, 9, 6)
+ var matrix3 = matrix1.multiply(matrix2)
+
+ expect(matrix1.toString()).toBe('matrix(1,4,2,5,3,6)')
+ expect(matrix2.toString()).toBe('matrix(7,8,8,7,9,6)')
+ expect(matrix3.toString()).toBe('matrix(23,68,22,67,24,72)')
+ })
+
+ it('accepts matrices in any form', () => {
+ var matrix1 = new Matrix(1, 4, 2, 5, 3, 6)
+ var matrix2 = matrix1.multiply('7,8,8,7,9,6')
+
+ expect(matrix1.toString()).toBe('matrix(1,4,2,5,3,6)')
+ expect(matrix2.toString()).toBe('matrix(23,68,22,67,24,72)')
+ })
+ })
+
+ describe('inverse()', () => {
+ it('inverses matrix', () => {
+
+ var matrix1 = new Matrix(2, 0, 0, 5, 4, 3)
+ var matrix2 = matrix1.inverse()
+ var abcdef = [ 0.5, 0, 0, 0.2, -2, -0.6 ]
+
+ for (var i in 'abcdef') {
+ expect(matrix2['abcdef'[i]]).toBeCloseTo(abcdef[i])
+ }
+ })
+ })
+
+ describe('translate()', () => {
+ it('translates matrix by given x and y values', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).translate(10, 12.5)
+ expect(matrix.e).toBe(14)
+ expect(matrix.f).toBe(15.5)
+ })
+
+ it('does nothing if you give it no x or y value', () => {
+ var matrix = new Matrix(1, 2, 3, 4, 5, 6).translate()
+ expect(matrix.e).toBe(5)
+ expect(matrix.f).toBe(6)
+ })
+ })
+
+ describe('scale()', () => {
+ it('performs a uniformal scale with one value', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).scale(3)
+
+ expect(matrix.a).toBe(3)
+ expect(matrix.d).toBe(3)
+ expect(matrix.e).toBe(4 * 3)
+ expect(matrix.f).toBe(3 * 3)
+ })
+ it('performs a non-uniformal scale with two values', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).scale(2.5, 3.5)
+
+ expect(matrix.a).toBe(2.5)
+ expect(matrix.d).toBe(3.5)
+ expect(matrix.e).toBe(4 * 2.5)
+ expect(matrix.f).toBe(3 * 3.5)
+ })
+ it('performs a uniformal scale at a given center point with three values', () => {
+ var matrix = new Matrix(1, 3, 2, 3, 4, 3).scale(3, 2, 3)
+
+ expect(matrix.a).toBe(3)
+ expect(matrix.b).toBe(9)
+ expect(matrix.c).toBe(6)
+ expect(matrix.d).toBe(9)
+ expect(matrix.e).toBe(8)
+ expect(matrix.f).toBe(3)
+ })
+ it('performs a non-uniformal scale at a given center point with four values', () => {
+ var matrix = new Matrix(1, 3, 2, 3, 4, 3).scale(3, 2, 2, 3)
+
+ expect(matrix.a).toBe(3)
+ expect(matrix.b).toBe(6)
+ expect(matrix.c).toBe(6)
+ expect(matrix.d).toBe(6)
+ expect(matrix.e).toBe(8)
+ expect(matrix.f).toBe(3)
+ })
+ })
+
+ describe('rotate()', () => {
+ it('performs a rotation with one argument', () => {
+ var matrix = new Matrix(1, 3, 2, 3, 4, 3).rotate(30)
+
+ expect(matrix.a).toBeCloseTo(-0.6339746)
+ expect(matrix.b).toBeCloseTo(3.09807621)
+ expect(matrix.c).toBeCloseTo(0.23205081)
+ expect(matrix.d).toBeCloseTo(3.59807621)
+ expect(matrix.e).toBeCloseTo(1.96410162)
+ expect(matrix.f).toBeCloseTo(4.59807621)
+ })
+ it('performs a rotation around a given point with three arguments', () => {
+ var matrix = new Matrix(1, 3, 2, 3, 4, 3).rotate(30, 2, 3)
+
+ expect(matrix.a).toBeCloseTo(-0.633974596216)
+ expect(matrix.b).toBeCloseTo(3.09807621135)
+ expect(matrix.c).toBeCloseTo(0.232050807569)
+ expect(matrix.d).toBeCloseTo(3.59807621135)
+ expect(matrix.e).toBeCloseTo(3.73205080757)
+ expect(matrix.f).toBeCloseTo(4.0)
+ })
+ })
+
+ describe('flip()', () => {
+ describe('with x given', () => {
+ it('performs a flip over the horizontal axis with one argument', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).flip('x')
+
+ expect(matrix.a).toBe(-1)
+ expect(matrix.d).toBe(1)
+ expect(matrix.e).toBe(-4)
+ expect(matrix.f).toBe(3)
+ })
+ it('performs a flip over the horizontal axis over a given point with two arguments', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).flip('x', 150)
+
+ expect(matrix.a).toBe(-1)
+ expect(matrix.d).toBe(1)
+ expect(matrix.e).toBe(296)
+ expect(matrix.f).toBe(3)
+ })
+ })
+ describe('with y given', () => {
+ it('performs a flip over the vertical axis with one argument', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).flip('y')
+
+ expect(matrix.a).toBe(1)
+ expect(matrix.d).toBe(-1)
+ expect(matrix.e).toBe(4)
+ expect(matrix.f).toBe(-3)
+ })
+ it('performs a flip over the vertical axis over a given point with two arguments', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).flip('y', 100)
+
+ expect(matrix.a).toBe(1)
+ expect(matrix.d).toBe(-1)
+ expect(matrix.e).toBe(4)
+ expect(matrix.f).toBe(197)
+ })
+ })
+ describe('with no axis given', () => {
+ it('performs a flip over the horizontal and vertical axis with no argument', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).flip()
+
+ expect(matrix.a).toBe(-1)
+ expect(matrix.d).toBe(-1)
+ expect(matrix.e).toBe(-4)
+ expect(matrix.f).toBe(-3)
+ })
+ it('performs a flip over the horizontal and vertical axis over a given point with one argument that represent both coordinates', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).flip(100)
+
+ expect(matrix.a).toBe(-1)
+ expect(matrix.d).toBe(-1)
+ expect(matrix.e).toBe(196)
+ expect(matrix.f).toBe(197)
+ })
+ it('performs a flip over the horizontal and vertical axis over a given point with two arguments', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).flip(50, 100)
+
+ expect(matrix.a).toBe(-1)
+ expect(matrix.d).toBe(-1)
+ expect(matrix.e).toBe(96)
+ expect(matrix.f).toBe(197)
+ })
+ })
+ })
+
+ describe('skew()', () => {
+ it('performs a uniformal skew with one value', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).skew(30)
+
+ expect(matrix.a).toBe(1)
+ expect(matrix.b).toBeCloseTo(0.57735026919)
+ expect(matrix.c).toBeCloseTo(0.57735026919)
+ expect(matrix.d).toBe(1)
+ expect(matrix.e).toBeCloseTo(5.73205080757)
+ expect(matrix.f).toBeCloseTo(5.30940107676)
+ })
+
+ it('performs a non-uniformal skew with two values', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).skew(30, 20)
+
+ expect(matrix.a).toBe(1)
+ expect(matrix.b).toBeCloseTo(0.363970234266)
+ expect(matrix.c).toBeCloseTo(0.57735026919)
+ expect(matrix.d).toBe(1)
+ expect(matrix.e).toBeCloseTo(5.73205080757)
+ expect(matrix.f).toBeCloseTo(4.45588093706)
+ })
+
+ it('performs a uniformal skew at a given center point with three values', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).skew(30, 150, 100)
+
+ expect(matrix.a).toBe(1)
+ expect(matrix.b).toBeCloseTo(0.57735026919)
+ expect(matrix.c).toBeCloseTo(0.57735026919)
+ expect(matrix.d).toBe(1)
+ expect(matrix.e).toBeCloseTo(-52.0029761114)
+ expect(matrix.f).toBeCloseTo(-81.2931393017)
+ })
+
+ it('performs a non-uniformal skew at a given center point with four values', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).skew(30, 20, 150, 100)
+
+ expect(matrix.a).toBe(1.0)
+ expect(matrix.b).toBeCloseTo(0.363970234266)
+ expect(matrix.c).toBeCloseTo(0.57735026919)
+ expect(matrix.d).toBe(1.0)
+ expect(matrix.e).toBeCloseTo(-52.0029761114)
+ expect(matrix.f).toBeCloseTo(-50.1396542029)
+ })
+
+ it('can be chained', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).skew(20, 30).skew(30, 20)
+ expect(matrix.a).toBeCloseTo(1.33333333333)
+ expect(matrix.b).toBeCloseTo(0.941320503456)
+ expect(matrix.c).toBeCloseTo(0.941320503456)
+ expect(matrix.d).toBeCloseTo(1.13247433143)
+ expect(matrix.e).toBeCloseTo(8.1572948437)
+ expect(matrix.f).toBeCloseTo(7.16270500812)
+ })
+ })
+
+ describe('skewX', () => {
+ it('performs a skew along the x axis with one value', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).skewX(30)
+
+ expect(matrix.a).toBe(1)
+ expect(matrix.b).toBe(0)
+ expect(matrix.c).toBeCloseTo(0.57735026919)
+ expect(matrix.d).toBe(1)
+ expect(matrix.e).toBeCloseTo(5.73205080757)
+ expect(matrix.f).toBe(3)
+ })
+
+ it('performs a skew along the x axis at a given center point with three values', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).skewX(30, 150, 100)
+
+ expect(matrix.a).toBe(1)
+ expect(matrix.b).toBe(0)
+ expect(matrix.c).toBeCloseTo(0.57735026919)
+ expect(matrix.d).toBe(1)
+ expect(matrix.e).toBeCloseTo(-52.0029761114)
+ expect(matrix.f).toBe(3)
+ })
+ })
+
+ describe('skewY', () => {
+ it('performs a skew along the y axis with one value', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).skewY(30)
+
+ expect(matrix.a).toBe(1)
+ expect(matrix.b).toBeCloseTo(0.57735026919)
+ expect(matrix.c).toBe(0)
+ expect(matrix.d).toBe(1)
+ expect(matrix.e).toBe(4)
+ expect(matrix.f).toBeCloseTo(5.30940107676)
+ })
+
+ it('performs a skew along the y axis at a given center point with three values', () => {
+ var matrix = new Matrix(1, 0, 0, 1, 4, 3).skewY(30, 150, 100)
+
+ expect(matrix.a).toBe(1)
+ expect(matrix.b).toBeCloseTo(0.57735026919)
+ expect(matrix.c).toBe(0)
+ expect(matrix.d).toBe(1)
+ expect(matrix.e).toBe(4)
+ expect(matrix.f).toBeCloseTo(-81.2931393017)
+ })
+ })
+})
--- /dev/null
+/* globals describe, expect, it, beforeEach, jasmine */
+
+import { Number as SVGNumber } from '../../../src/main.js'
+
+const { any } = jasmine
+
+describe('Number.js', () => {
+ var number
+
+ beforeEach(() => {
+ number = new SVGNumber()
+ })
+
+ describe('new', () => {
+ it('is zero', () => {
+ expect(number.value).toBe(0)
+ })
+ it('has a blank unit', () => {
+ expect(number.unit).toBe('')
+ })
+ it('accepts the unit as a second argument', () => {
+ number = new SVGNumber(30, '%')
+ expect(number.value).toBe(30)
+ expect(number.unit).toBe('%')
+ })
+ it('parses a pixel value', () => {
+ number = new SVGNumber('20px')
+ expect(number.value).toBe(20)
+ expect(number.unit).toBe('px')
+ })
+ it('parses a percent value', () => {
+ number = new SVGNumber('99%')
+ expect(number.value).toBe(0.99)
+ expect(number.unit).toBe('%')
+ })
+ it('parses a seconds value', () => {
+ number = new SVGNumber('2s')
+ expect(number.value).toBe(2000)
+ expect(number.unit).toBe('s')
+ })
+ it('parses a negative percent value', () => {
+ number = new SVGNumber('-89%')
+ expect(number.value).toBe(-0.89)
+ expect(number.unit).toBe('%')
+ })
+ it('falls back to 0 if given value is NaN', () => {
+ number = new SVGNumber(NaN)
+ expect(number.value).toBe(0)
+ })
+ it('falls back to maximum value if given number is positive infinite', () => {
+ number = new SVGNumber(1.7976931348623157E+10308)
+ expect(number.value).toBe(3.4e+38)
+ })
+ it('falls back to minimum value if given number is negative infinite', () => {
+ number = new SVGNumber(-1.7976931348623157E+10308)
+ expect(number.value).toBe(-3.4e+38)
+ })
+ })
+
+ describe('toString()', () => {
+ it('converts the number to a string', () => {
+ expect(number.toString()).toBe('0')
+ })
+ it('appends the unit', () => {
+ number.value = 1.21
+ number.unit = 'px'
+ expect(number.toString()).toBe('1.21px')
+ })
+ it('converts percent values properly', () => {
+ number.value = 1.36
+ number.unit = '%'
+ expect(number.toString()).toBe('136%')
+ })
+ it('converts second values properly', () => {
+ number.value = 2500
+ number.unit = 's'
+ expect(number.toString()).toBe('2.5s')
+ })
+ })
+
+ describe('valueOf()', () => {
+ it('returns a numeric value for default units', () => {
+ expect(typeof number.valueOf()).toBe('number')
+ number = new SVGNumber('12')
+ expect(typeof number.valueOf()).toBe('number')
+ number = new SVGNumber(13)
+ expect(typeof number.valueOf()).toBe('number')
+ })
+ it('returns a numeric value for pixel units', () => {
+ number = new SVGNumber('10px')
+ expect(typeof number.valueOf()).toBe('number')
+ })
+ it('returns a numeric value for percent units', () => {
+ number = new SVGNumber('20%')
+ expect(typeof number.valueOf()).toBe('number')
+ })
+ it('converts to a primitive when multiplying', () => {
+ number.value = 80
+ expect(number * 4).toBe(320)
+ })
+ })
+
+ describe('plus()', () => {
+ it('returns a new instance', () => {
+ expect(number.plus(4.5)).not.toBe(number)
+ expect(number.plus(4.5)).toEqual(any(SVGNumber))
+ })
+ it('adds a given number', () => {
+ expect(number.plus(3.5).valueOf()).toBe(3.5)
+ })
+ it('adds a given percentage value', () => {
+ expect(number.plus('225%').valueOf()).toBe(2.25)
+ })
+ it('adds a given pixel value', () => {
+ expect(number.plus('83px').valueOf()).toBe(83)
+ })
+ it('use the unit of this number as the unit of the returned number by default', () => {
+ expect(new SVGNumber('12s').plus('3%').unit).toBe('s')
+ })
+ it('use the unit of the passed number as the unit of the returned number when this number as no unit', () => {
+ expect(number.plus('15%').unit).toBe('%')
+ })
+ })
+
+ describe('minus()', () => {
+ it('subtracts a given number', () => {
+ expect(number.minus(3.7).valueOf()).toBe(-3.7)
+ })
+ it('subtracts a given percentage value', () => {
+ expect(number.minus('223%').valueOf()).toBe(-2.23)
+ })
+ it('subtracts a given pixel value', () => {
+ expect(number.minus('85px').valueOf()).toBe(-85)
+ })
+ it('use the unit of this number as the unit of the returned number by default', () => {
+ expect(new SVGNumber('12s').minus('3%').unit).toBe('s')
+ })
+ it('use the unit of the passed number as the unit of the returned number when this number as no unit', () => {
+ expect(number.minus('15%').unit).toBe('%')
+ })
+ })
+
+ describe('times()', () => {
+ beforeEach(() => {
+ number = number.plus(4)
+ })
+ it('multiplies with a given number', () => {
+ expect(number.times(3).valueOf()).toBe(12)
+ })
+ it('multiplies with a given percentage value', () => {
+ expect(number.times('110%').valueOf()).toBe(4.4)
+ })
+ it('multiplies with a given pixel value', () => {
+ expect(number.times('85px').valueOf()).toBe(340)
+ })
+ it('use the unit of this number as the unit of the returned number by default', () => {
+ expect(new SVGNumber('12s').times('3%').unit).toBe('s')
+ })
+ it('use the unit of the passed number as the unit of the returned number when this number as no unit', () => {
+ expect(number.times('15%').unit).toBe('%')
+ })
+ })
+
+ describe('divide()', () => {
+ beforeEach(() => {
+ number = number.plus(90)
+ })
+ it('divides by a given number', () => {
+ expect(number.divide(3).valueOf()).toBe(30)
+ })
+ it('divides by a given percentage value', () => {
+ expect(number.divide('3000%').valueOf()).toBe(3)
+ })
+ it('divides by a given pixel value', () => {
+ expect(number.divide('45px').valueOf()).toBe(2)
+ })
+ it('use the unit of this number as the unit of the returned number by default', () => {
+ expect(new SVGNumber('12s').divide('3%').unit).toBe('s')
+ })
+ it('use the unit of the passed number as the unit of the returned number when this number as no unit', () => {
+ expect(number.divide('15%').unit).toBe('%')
+ })
+ })
+})
--- /dev/null
+/* globals describe, expect, it, beforeEach */
+
+import { Point } from '../../../src/main.js'
+
+describe('Point.js', () => {
+ var point
+
+ describe('initialization', () => {
+
+ describe('without a source', () => {
+
+ beforeEach(() => {
+ point = new Point()
+ })
+
+ it('creates a new point with default values', () => {
+ expect(point.x).toBe(0)
+ expect(point.y).toBe(0)
+ })
+
+ })
+
+ describe('with x and y given', () => {
+ it('creates a point with given values', () => {
+ var point = new Point(2, 4)
+
+ expect(point.x).toBe(2)
+ expect(point.y).toBe(4)
+ })
+ })
+
+ describe('with only x given', () => {
+ it('sets the y value to 0', () => {
+ var point = new Point(7)
+
+ expect(point.x).toBe(7)
+ expect(point.y).toBe(0)
+ })
+ })
+
+ describe('with array given', () => {
+ it('creates a point from array', () => {
+ var point = new Point([ 2, 4 ])
+
+ expect(point.x).toBe(2)
+ expect(point.y).toBe(4)
+ })
+ })
+
+ describe('with object given', () => {
+ it('creates a point from object', () => {
+ var point = new Point({ x: 2, y: 4 })
+
+ expect(point.x).toBe(2)
+ expect(point.y).toBe(4)
+ })
+ })
+
+ describe('with Point given', () => {
+ it('creates a point from Point', () => {
+ var point = new Point(new Point(2, 4))
+
+ expect(point.x).toBe(2)
+ expect(point.y).toBe(4)
+ })
+ })
+ })
+
+ describe('clone()', () => {
+ it('returns cloned point', () => {
+ var point1 = new Point(1, 1)
+ var point2 = point1.clone()
+
+ expect(point1).toEqual(point2)
+ expect(point1).not.toBe(point2)
+ })
+ })
+})
--- /dev/null
+/* globals describe, expect, it */
+
+import { PointArray, Matrix, Point } from '../../../src/main.js'
+
+describe('PointArray', () => {
+ const squareString = '0,0 1,0 1,1 0,1'
+ const square = new PointArray(squareString)
+
+ describe('toString()', () => {
+ it('round trips with string', () => {
+ expect(square.toString()).toEqual(squareString)
+ })
+ })
+
+ describe('transform()', () => {
+ it('translates correctly', () => {
+ const translation = new Matrix().translate(2, 1)
+ const newSquare = square.transform(translation)
+ expect(newSquare.toString()).toEqual('2,1 3,1 3,2 2,2')
+ })
+
+ it('transforms like Point', () => {
+ const matrix = new Matrix(1, 2, 3, 4, 5, 6)
+ const newSquare = square.transform(matrix)
+ for (let i = 0; i < square.length; i++) {
+ const squarePoint = new Point(square[i])
+ const newSquarePoint = new Point(newSquare[i])
+ expect(squarePoint.transform(matrix)).toEqual(newSquarePoint)
+ }
+ })
+ })
+})