summaryrefslogtreecommitdiffstats
path: root/spec
diff options
context:
space:
mode:
authorUlrich-Matthias Schäfer <ulima.ums@googlemail.com>2020-04-29 10:57:14 +1000
committerUlrich-Matthias Schäfer <ulima.ums@googlemail.com>2020-04-29 10:57:14 +1000
commita6dae04f796cbcf878a4cfd98acae7c4645c2b7c (patch)
treedb82cf787e3dcb77be7beba65086316d6b08d54f /spec
parent5a70312f36355f20e7a643e26e1f6bdb597df7be (diff)
downloadsvg.js-a6dae04f796cbcf878a4cfd98acae7c4645c2b7c.tar.gz
svg.js-a6dae04f796cbcf878a4cfd98acae7c4645c2b7c.zip
finished specs for Box.js and made zoom handle level 0 correctly + make it more clear when zoom cannot zoom because it cant get width and height of the element
Diffstat (limited to 'spec')
-rw-r--r--spec/spec/types/Box.js305
1 files changed, 206 insertions, 99 deletions
diff --git a/spec/spec/types/Box.js b/spec/spec/types/Box.js
index 34b1e20..e220cea 100644
--- a/spec/spec/types/Box.js
+++ b/spec/spec/types/Box.js
@@ -1,15 +1,14 @@
-/* globals describe, expect, it, jasmine, container */
+/* globals describe, expect, it, beforeEach, afterEach, spyOn, jasmine, container */
import {
Box,
Matrix,
Rect,
+ G,
makeInstance as SVG
} from '../../../src/main.js'
-import { getMethodsFor } from '../../../src/utils/methods.js'
-import { withWindow } from '../../../src/utils/window.js'
-
-const { zoom, viewbox } = getMethodsFor('viewbox')
+import { withWindow, getWindow } from '../../../src/utils/window.js'
+import { isNulledBox, domContains } from '../../../src/types/Box.js'
const { any, objectContaining } = jasmine
@@ -19,122 +18,181 @@ const { any, objectContaining } = jasmine
// }
describe('Box.js', () => {
- describe('()', () => {
- it('creates a new Box with default attributes', () => {
- const box = new Box()
- expect(box).toEqual(any(Box))
- expect(box).toEqual(objectContaining({
- width: 0, height: 0, x: 0, y: 0, w: 0, h: 0, cx: 0, cy: 0, x2: 0, y2: 0
- }))
+ describe('isNulledBox', () => {
+ it('returns true if x, y, with and height is 0', () => {
+ expect(isNulledBox({ x: 0, y: 0, width: 0, height: 0 })).toBe(true)
})
- })
- describe('init()', () => {
- it('inits or reinits the box according to input', () => {
- expect(new Box().init(1, 2, 3, 4).toArray()).toEqual([ 1, 2, 3, 4 ])
+ it('returns false if one or more of x, y, with and height is not 0', () => {
+ expect(isNulledBox({ x: 0, y: 0, width: 0, height: 1 })).toBe(false)
+ expect(isNulledBox({ x: 0, y: 1, width: 0, height: 1 })).toBe(false)
})
+ })
- it('works with array input', () => {
- expect(new Box().init([ 1, 2, 3, 4 ]).toArray()).toEqual([ 1, 2, 3, 4 ])
- })
+ describe('domContains()', () => {
+ describe('with native function', () => {
+ it('returns true if node is in the dom', () => {
+ expect(domContains(container)).toBe(true)
+ })
- it('works with 3 arguments as input', () => {
- expect(new Box().init(1, 2, 3, 4).toArray()).toEqual([ 1, 2, 3, 4 ])
+ it('returns false if node is not in the dom', () => {
+ const g = new G()
+ const rect = new Rect().addTo(g)
+ expect(domContains(rect.node)).toBe(false)
+ })
})
- it('works with string input', () => {
- expect(new Box().init('1,2,3,4').toArray()).toEqual([ 1, 2, 3, 4 ])
- })
+ describe('with polyfill', () => {
+ let containsBackup
+ beforeEach(() => {
+ containsBackup = getWindow().document.documentElement.contains
+ getWindow().document.documentElement.contains = null
+ })
- it('creates a new box from parsed string with exponential values', function () {
- expect(new Box().init('-1.12e1 1e-2 +2e2 +.3e+4').toArray())
- .toEqual([ -11.2, 0.01, 200, 3000 ])
- })
+ afterEach(() => {
+ getWindow().document.documentElement.contains = containsBackup
+ })
- it('works with object input', () => {
- expect(new Box().init({ x: 1, y: 2, width: 3, height: 4 }).toArray())
- .toEqual([ 1, 2, 3, 4 ])
- })
+ it('returns true if node is in the dom', () => {
+ expect(domContains(container)).toBe(true)
+ })
- it('calculates all derived values correctly', () => {
- expect(new Box().init(2, 4, 6, 8)).toEqual(objectContaining({
- cx: 5, cy: 8, x2: 8, y2: 12, w: 6, h: 8
- }))
+ it('returns false if node is not in the dom', () => {
+ const g = new G()
+ const rect = new Rect().addTo(g)
+ expect(domContains(rect.node)).toBe(false)
+ })
})
+ })
- it('can handle input with left instead of x and top instead of y', () => {
- expect(new Box().init({ left: 1, top: 2, width: 3, height: 4 }).toArray())
- .toEqual([ 1, 2, 3, 4 ])
+ describe('Box', () => {
+ describe('()', () => {
+ it('creates a new Box with default attributes', () => {
+ const box = new Box()
+ expect(box).toEqual(any(Box))
+ expect(box).toEqual(objectContaining({
+ width: 0, height: 0, x: 0, y: 0, w: 0, h: 0, cx: 0, cy: 0, x2: 0, y2: 0
+ }))
+ })
})
- })
- describe('merge()', () => {
- it('merges various bounding boxes', () => {
- var box1 = new Box(50, 50, 100, 100)
- var box2 = new Box(300, 400, 100, 100)
- var box3 = new Box(500, 100, 100, 100)
- var merged = box1.merge(box2).merge(box3)
+ describe('init()', () => {
+ it('inits or reinits the box according to input', () => {
+ expect(new Box().init(1, 2, 3, 4).toArray()).toEqual([ 1, 2, 3, 4 ])
+ })
- expect(merged.toArray()).toEqual([ 50, 50, 550, 450 ])
- })
+ it('works with array input', () => {
+ expect(new Box().init([ 1, 2, 3, 4 ]).toArray()).toEqual([ 1, 2, 3, 4 ])
+ })
+
+ it('works with 3 arguments as input', () => {
+ expect(new Box().init(1, 2, 3, 4).toArray()).toEqual([ 1, 2, 3, 4 ])
+ })
+
+ it('works with string input', () => {
+ expect(new Box().init('1,2,3,4').toArray()).toEqual([ 1, 2, 3, 4 ])
+ })
+
+ it('creates a new box from parsed string with exponential values', function () {
+ expect(new Box().init('-1.12e1 1e-2 +2e2 +.3e+4').toArray())
+ .toEqual([ -11.2, 0.01, 200, 3000 ])
+ })
- it('returns a new instance', () => {
- var box1 = new Box(50, 50, 100, 100)
- var box2 = new Box(300, 400, 100, 100)
- var merged = box1.merge(box2)
+ it('works with object input', () => {
+ expect(new Box().init({ x: 1, y: 2, width: 3, height: 4 }).toArray())
+ .toEqual([ 1, 2, 3, 4 ])
+ })
+
+ it('calculates all derived values correctly', () => {
+ expect(new Box().init(2, 4, 6, 8)).toEqual(objectContaining({
+ cx: 5, cy: 8, x2: 8, y2: 12, w: 6, h: 8
+ }))
+ })
- expect(merged).toEqual(any(Box))
+ it('can handle input with left instead of x and top instead of y', () => {
+ expect(new Box().init({ left: 1, top: 2, width: 3, height: 4 }).toArray())
+ .toEqual([ 1, 2, 3, 4 ])
+ })
})
- })
- describe('transform()', () => {
- it('transforms the box with given matrix', () => {
- var box1 = new Box(50, 50, 100, 100).transform(new Matrix(1, 0, 0, 1, 20, 20))
- var box2 = new Box(50, 50, 100, 100).transform(new Matrix(2, 0, 0, 2, 0, 0))
- var box3 = new Box(-200, -200, 100, 100).transform(new Matrix(1, 0, 0, 1, -20, -20))
+ describe('merge()', () => {
+ it('merges various bounding boxes', () => {
+ var box1 = new Box(50, 50, 100, 100)
+ var box2 = new Box(300, 400, 100, 100)
+ var box3 = new Box(500, 100, 100, 100)
+ var merged = box1.merge(box2).merge(box3)
+
+ expect(merged.toArray()).toEqual([ 50, 50, 550, 450 ])
+ })
+
+ it('returns a new instance', () => {
+ var box1 = new Box(50, 50, 100, 100)
+ var box2 = new Box(300, 400, 100, 100)
+ var merged = box1.merge(box2)
- expect(box1.toArray()).toEqual([ 70, 70, 100, 100 ])
- expect(box2.toArray()).toEqual([ 100, 100, 200, 200 ])
- expect(box3.toArray()).toEqual([ -220, -220, 100, 100 ])
+ expect(merged).toEqual(any(Box))
+ })
})
- })
- describe('addOffset()', () => {
- it('returns a new instance', () => {
- withWindow({ pageXOffset: 50, pageYOffset: 25 }, () => {
- const box = new Box(100, 100, 100, 100)
- const box2 = box.addOffset()
+ describe('transform()', () => {
+ it('transforms the box with given matrix', () => {
+ var box1 = new Box(50, 50, 100, 100).transform(new Matrix(1, 0, 0, 1, 20, 20))
+ var box2 = new Box(50, 50, 100, 100).transform(new Matrix(2, 0, 0, 2, 0, 0))
+ var box3 = new Box(-200, -200, 100, 100).transform(new Matrix(1, 0, 0, 1, -20, -20))
+
+ expect(box1.toArray()).toEqual([ 70, 70, 100, 100 ])
+ expect(box2.toArray()).toEqual([ 100, 100, 200, 200 ])
+ expect(box3.toArray()).toEqual([ -220, -220, 100, 100 ])
+ })
+
+ it('also works with matrix like input', () => {
+ var box1 = new Box(50, 50, 100, 100).transform(new Matrix(1, 0, 0, 1, 20, 20).toArray())
+ var box2 = new Box(50, 50, 100, 100).transform(new Matrix(2, 0, 0, 2, 0, 0).toArray())
+ var box3 = new Box(-200, -200, 100, 100).transform(new Matrix(1, 0, 0, 1, -20, -20).toArray())
- expect(box2).toEqual(any(Box))
- expect(box2).not.toBe(box)
+ expect(box1.toArray()).toEqual([ 70, 70, 100, 100 ])
+ expect(box2.toArray()).toEqual([ 100, 100, 200, 200 ])
+ expect(box3.toArray()).toEqual([ -220, -220, 100, 100 ])
})
})
- it('adds the current page offset to the box', () => {
- withWindow({ pageXOffset: 50, pageYOffset: 25 }, () => {
- const box = new Box(100, 100, 100, 100).addOffset()
+ describe('addOffset()', () => {
+ it('returns a new instance', () => {
+ withWindow({ pageXOffset: 50, pageYOffset: 25 }, () => {
+ const box = new Box(100, 100, 100, 100)
+ const box2 = box.addOffset()
+
+ expect(box2).toEqual(any(Box))
+ expect(box2).not.toBe(box)
+ })
+ })
+
+ it('adds the current page offset to the box', () => {
+ withWindow({ pageXOffset: 50, pageYOffset: 25 }, () => {
+ const box = new Box(100, 100, 100, 100).addOffset()
- expect(box.toArray()).toEqual([ 150, 125, 100, 100 ])
+ expect(box.toArray()).toEqual([ 150, 125, 100, 100 ])
+ })
})
})
- })
- describe('toString()', () => {
- it('returns a string representation of the box', () => {
- expect(new Box(1, 2, 3, 4).toString()).toBe('1 2 3 4')
+ describe('toString()', () => {
+ it('returns a string representation of the box', () => {
+ expect(new Box(1, 2, 3, 4).toString()).toBe('1 2 3 4')
+ })
})
- })
- describe('toArray()', () => {
- it('returns an array representation of the box', () => {
- expect(new Box(1, 2, 3, 4).toArray()).toEqual([ 1, 2, 3, 4 ])
+ describe('toArray()', () => {
+ it('returns an array representation of the box', () => {
+ expect(new Box(1, 2, 3, 4).toArray()).toEqual([ 1, 2, 3, 4 ])
+ })
})
- })
- describe('isNulled()', () => {
- it('checks if the box consists of only zeros', () => {
- expect(new Box().isNulled()).toBe(true)
- expect(new Box(1, 2, 3, 4).isNulled()).toBe(false)
+ describe('isNulled()', () => {
+ it('checks if the box consists of only zeros', () => {
+ expect(new Box().isNulled()).toBe(true)
+ expect(new Box(1, 2, 3, 4).isNulled()).toBe(false)
+ })
})
})
@@ -153,10 +211,13 @@ describe('Box.js', () => {
expect(rect.bbox().toArray()).toEqual([ 20, 30, 100, 200 ])
})
- // it('throws when it is not possible to get a bbox', () => {
- // const gradient = new Gradient('radial')
- // expect(() => gradient.bbox()).toThrow()
- // })
+ it('throws when it is not possible to get a bbox', () => {
+ const spy = spyOn(getWindow().SVGGraphicsElement.prototype, 'getBBox')
+ .and.callFake(() => { throw new Error('No BBox for you') })
+ const rect = new Rect()
+ expect(() => rect.bbox()).toThrow()
+ expect(spy).toHaveBeenCalled()
+ })
})
describe('rbox()', () => {
@@ -169,6 +230,20 @@ describe('Box.js', () => {
expect(rect.rbox().toArray()).toEqual([ 80, 110, 200, 400 ])
})
+ it('returns the rbox box of the element in the coordinate system of the passed element', () => {
+ const canvas = SVG().addTo(container)
+ const group = canvas.group().translate(1, 1)
+ const rect = new Rect().size(100, 200).move(20, 30).addTo(canvas)
+ .attr('transform', new Matrix({ scale: 2, translate: [ 40, 50 ] }))
+
+ expect(rect.rbox(group)).toEqual(any(Box))
+ expect(rect.rbox(group).toArray()).toEqual([ 79, 109, 200, 400 ])
+ })
+
+ // svgdom actually only throws here because a new Rect without dimensions has no bounding box
+ // so in case you would create a rect with with and height this test would fail because
+ // svgdom actually can calculate an rbox for the element
+ // in that case we have to change the test like above so that the getBoundingClientRect call is mocked with a spy
it('throws when element is not in dom', () => {
expect(() => new Rect().rbox()).toThrow()
})
@@ -185,31 +260,63 @@ describe('Box.js', () => {
describe('viewbox()', () => {
it('sets the viewbox of the element', () => {
- const canvas = viewbox.call(SVG().addTo(container), 10, 10, 200, 200)
+ const canvas = SVG().addTo(container).viewbox(10, 10, 200, 200)
expect(canvas.attr('viewBox')).toEqual('10 10 200 200')
})
it('gets the viewbox of the element', () => {
- const canvas = viewbox.call(SVG().addTo(container), 10, 10, 200, 200)
- expect(viewbox.call(canvas)).toEqual(any(Box))
- expect(viewbox.call(canvas).toArray()).toEqual([ 10, 10, 200, 200 ])
+ const canvas = SVG().addTo(container).viewbox(10, 10, 200, 200)
+ expect(canvas.viewbox()).toEqual(any(Box))
+ expect(canvas.viewbox().toArray()).toEqual([ 10, 10, 200, 200 ])
})
})
describe('zoom()', () => {
it('zooms around the center by default', () => {
- const canvas = zoom.call(SVG().size(100, 50).viewbox(0, 0, 100, 50).addTo(container), 2)
+ const canvas = SVG().size(100, 50).viewbox(0, 0, 100, 50).addTo(container).zoom(2)
expect(canvas.attr('viewBox')).toEqual('25 12.5 50 25')
})
it('zooms around a point', () => {
- const canvas = zoom.call(SVG().size(100, 50).viewbox(0, 0, 100, 50).addTo(container), 2, [ 0, 0 ])
+ const canvas = SVG().size(100, 50).viewbox(0, 0, 100, 50).addTo(container).zoom(2, [ 0, 0 ])
expect(canvas.attr('viewBox')).toEqual('0 0 50 25')
})
it('gets the zoom', () => {
- const canvas = zoom.call(SVG().size(100, 50).viewbox(0, 0, 100, 50).addTo(container), 2)
- expect(zoom.call(canvas)).toEqual(2)
+ // We use a nested here because its actually harder to get a width and height for a nested svg because clientHeight
+ // is not available
+ const svg = SVG().size(100, 50).addTo(container).nested().size(100, 50).viewbox(0, 0, 100, 50).zoom(2)
+ expect(svg.zoom()).toEqual(2)
+ })
+
+ it('gets the zoom with clientHeight', () => {
+ const svg = SVG().css({ width: '100px', height: '50px' }).addTo(container).viewbox(25, 12.5, 50, 25)
+
+ const node = svg.node
+
+ // svgdom doesn't support clientHeight
+ // so we mock it here
+ if (typeof node.clientHeight === 'undefined') {
+ node.clientHeight = 50
+ node.clientWidth = 100
+ }
+
+ expect(svg.zoom()).toEqual(2)
+ })
+
+ it('throws an error if it is impossible to get an absolute value', () => {
+ const svg = SVG().size(100, 50).addTo(container).nested().viewbox(0, 0, 100, 50)
+ expect(() => svg.zoom()).toThrowError('Impossible to get absolute width and height. Please provide an absolute width and height attribute on the zooming element')
+ })
+
+ it('handles zoom level 0 which is - which basically sets the viewbox to a very high value', () => {
+ const svg = SVG().size(100, 50).viewbox(0, 0, 100, 50).addTo(container).zoom(0)
+ expect(svg.zoom()).toBeCloseTo(0, 10)
+ })
+
+ it('handles zoom level 0 and can recover from it', () => {
+ const svg = SVG().size(100, 50).viewbox(0, 0, 100, 50).addTo(container).zoom(0).zoom(1)
+ expect(svg.zoom()).toBe(1)
})
})
})