You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Element.js 10.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /* globals describe, expect, it, beforeEach, spyOn, jasmine, container */
  2. import { Element, create, Rect, G, SVG } from '../../../src/main.js'
  3. const { any, objectContaining } = jasmine
  4. describe('Element.js', function () {
  5. let element
  6. beforeEach(() => {
  7. element = new Element(create('rect'))
  8. })
  9. describe('()', () => {
  10. it('creates a new object of type Element', () => {
  11. expect(element).toEqual(any(Element))
  12. })
  13. it('sets passed attributes on the element', () => {
  14. expect(new Element(create('rect'), { id: 'foo' }).id()).toBe('foo')
  15. })
  16. it('references the instance on the passed node', () => {
  17. expect(element.node.instance).toBe(element)
  18. })
  19. it('sets the dom property to an empty object', () => {
  20. expect(element.dom).toEqual({})
  21. })
  22. it('hydrates the dom property with data found in the dom', () => {
  23. element.dom = { foo: 'bar' }
  24. element.writeDataToDom()
  25. expect(new Element(element.node).dom).toEqual({ foo: 'bar' })
  26. })
  27. it('falls back to empty object when attribute is null', () => {
  28. element.node.setAttribute('svgjs:data', 'null')
  29. expect(new Element(element.node).dom).toEqual({})
  30. })
  31. })
  32. describe('center()', () => {
  33. it('calls cx and cy with passed parameters and returns itself', () => {
  34. const spyCx = spyOn(element, 'cx').and.callThrough()
  35. const spyCy = spyOn(element, 'cy').and.callThrough()
  36. expect(element.center(1, 2)).toBe(element)
  37. expect(spyCx).toHaveBeenCalledWith(1)
  38. expect(spyCy).toHaveBeenCalledWith(2)
  39. })
  40. })
  41. describe('cx()', () => {
  42. it('gets the elements center along the x axis', () => {
  43. element.attr({ x: 10, width: 100 })
  44. expect(element.cx()).toBe(60)
  45. })
  46. it('centers the element along the x axis and returns itself', () => {
  47. element.attr({ x: 10, width: 100 })
  48. expect(element.cx(100)).toBe(element)
  49. expect(element.attr('x')).toBe(50)
  50. })
  51. })
  52. describe('cy()', () => {
  53. it('gets the elements center along the y axis', () => {
  54. element.attr({ y: 10, height: 100 })
  55. expect(element.cy()).toBe(60)
  56. })
  57. it('centers the element along the y axis and returns itself', () => {
  58. element.attr({ y: 10, height: 100 })
  59. expect(element.cy(100)).toBe(element)
  60. expect(element.attr('y')).toBe(50)
  61. })
  62. })
  63. describe('defs()', () => {
  64. it('returns null if detached', () => {
  65. expect(new Rect().defs()).toBe(null)
  66. expect(new G().put(new Rect()).defs()).toBe(null)
  67. })
  68. it('calls defs on root node', () => {
  69. const canvas = SVG()
  70. const rect = canvas.rect(100, 100)
  71. const spy = spyOn(canvas, 'defs').and.callThrough()
  72. expect(rect.defs()).toBe(canvas.defs())
  73. expect(spy.calls.count()).toBe(2)
  74. })
  75. })
  76. describe('dmove()', () => {
  77. it('calls dx and dy with passed parameters and returns itself', () => {
  78. const spyDx = spyOn(element, 'dx').and.callThrough()
  79. const spyDy = spyOn(element, 'dy').and.callThrough()
  80. expect(element.dmove(1, 2)).toBe(element)
  81. expect(spyDx).toHaveBeenCalledWith(1)
  82. expect(spyDy).toHaveBeenCalledWith(2)
  83. })
  84. })
  85. describe('dx()', () => {
  86. it('moves by zero by default', () => {
  87. element.attr({ x: 10, width: 100 })
  88. expect(element.dx().x()).toBe(10)
  89. })
  90. it('moves the element along the x axis relatively and returns itself', () => {
  91. element.attr({ x: 10, width: 100 })
  92. expect(element.dx(100)).toBe(element)
  93. expect(element.attr('x')).toBe(110)
  94. })
  95. })
  96. describe('dy()', () => {
  97. it('moves by zero by default', () => {
  98. element.attr({ y: 10, height: 100 })
  99. expect(element.dy().y()).toBe(10)
  100. })
  101. it('moves the element along the x axis relatively and returns itself', () => {
  102. element.attr({ y: 10, height: 100 })
  103. expect(element.dy(100)).toBe(element)
  104. expect(element.attr('y')).toBe(110)
  105. })
  106. })
  107. describe('root()', () => {
  108. it('returns the root of this element', () => {
  109. const canvas = SVG()
  110. const rect = canvas.rect()
  111. expect(rect.root()).toBe(canvas)
  112. })
  113. it('returns null if element is detached', () => {
  114. expect(new G().put(new Rect()).root()).toBe(null)
  115. })
  116. })
  117. describe('getEventHolder()', () => {
  118. it('returns itself', () => {
  119. expect(element.getEventHolder()).toBe(element)
  120. })
  121. })
  122. describe('height()', () => {
  123. it('calls attr with height', () => {
  124. const spy = spyOn(element, 'attr')
  125. element.height(123)
  126. expect(spy).toHaveBeenCalledWith('height', 123)
  127. })
  128. })
  129. describe('move()', () => {
  130. it('calls x and y with passed parameters and returns itself', () => {
  131. const spyx = spyOn(element, 'x').and.callThrough()
  132. const spyy = spyOn(element, 'y').and.callThrough()
  133. expect(element.move(1, 2)).toBe(element)
  134. expect(spyx).toHaveBeenCalledWith(1)
  135. expect(spyy).toHaveBeenCalledWith(2)
  136. })
  137. })
  138. describe('parents()', () => {
  139. it('returns array of parents until the passed element or root svg', () => {
  140. const canvas = SVG().addTo(container)
  141. const groupA = canvas.group().addClass('test')
  142. const group1 = canvas.group().addClass('test')
  143. const group2 = group1.group()
  144. const group3 = group2.group()
  145. const rect = group3.rect(100, 100)
  146. expect(rect.parents('.test')).toEqual([ group3, group2, group1 ])
  147. expect(rect.parents(group2)).toEqual([ group3, group2 ])
  148. expect(rect.parents(group1).length).toBe(3)
  149. expect(rect.parents()).toEqual([ group3, group2, group1, canvas ])
  150. })
  151. it('returns array of parents until the closest matching parent', () => {
  152. const canvas = SVG().addTo(container)
  153. const groupA = canvas.group().addClass('test')
  154. const group1 = canvas.group().addClass('test')
  155. const group2 = group1.group().addClass('test').addClass('foo')
  156. const group3 = group2.group().addClass('foo')
  157. const rect = group3.rect(100, 100)
  158. expect(rect.parents('.test')).toEqual([ group3, group2 ])
  159. expect(rect.parents('.foo')).toEqual([ group3 ])
  160. expect(rect.parents('.test:not(.foo)')).toEqual([ group3, group2, group1 ])
  161. })
  162. it('returns null if the passed element is not an ancestor', () => {
  163. const canvas = SVG().addTo(container)
  164. const groupA = canvas.group().addClass('test')
  165. const group1 = canvas.group()
  166. const group2 = group1.group()
  167. const group3 = group2.group()
  168. const rect = group3.rect(100, 100)
  169. expect(rect.parents('.does-not-exist')).toEqual(null)
  170. expect(rect.parents('.test')).toEqual(null)
  171. expect(rect.parents(groupA)).toEqual(null)
  172. })
  173. })
  174. describe('reference()', () => {
  175. it('gets a referenced element from a given attribute', () => {
  176. const canvas = SVG().addTo(container)
  177. const rect = canvas.defs().rect(100, 100)
  178. const use = canvas.use(rect)
  179. const mark = canvas.marker(10, 10)
  180. const path = canvas.path('M0 0 50 50').marker('end', mark)
  181. expect(use.reference('href')).toBe(rect)
  182. expect(path.reference('marker-end')).toBe(mark)
  183. expect(rect.reference('width')).toBe(null)
  184. })
  185. })
  186. describe('setData()', () => {
  187. it('sets the given data to the dom property and returns itself', () => {
  188. expect(element.setData({ foo: 'bar' })).toBe(element)
  189. expect(element.dom).toEqual({ foo: 'bar' })
  190. })
  191. })
  192. describe('size()', () => {
  193. it('calls width and height with passed parameters and returns itself', () => {
  194. const spyWidth = spyOn(element, 'width').and.callThrough()
  195. const spyHeight = spyOn(element, 'height').and.callThrough()
  196. expect(element.size(1, 2)).toBe(element)
  197. expect(spyWidth).toHaveBeenCalledWith(objectContaining({ value: 1 }))
  198. expect(spyHeight).toHaveBeenCalledWith(objectContaining({ value: 2 }))
  199. })
  200. it('changes height proportionally if null', () => {
  201. const canvas = SVG().addTo(container)
  202. const element = canvas.rect(100, 100)
  203. const spyWidth = spyOn(element, 'width').and.callThrough()
  204. const spyHeight = spyOn(element, 'height').and.callThrough()
  205. expect(element.size(200, null)).toBe(element)
  206. expect(spyWidth).toHaveBeenCalledWith(objectContaining({ value: 200 }))
  207. expect(spyHeight).toHaveBeenCalledWith(objectContaining({ value: 200 }))
  208. })
  209. it('changes width proportionally if null', () => {
  210. const canvas = SVG().addTo(container)
  211. const element = canvas.rect(100, 100)
  212. const spyWidth = spyOn(element, 'width').and.callThrough()
  213. const spyHeight = spyOn(element, 'height').and.callThrough()
  214. expect(element.size(null, 200)).toBe(element)
  215. expect(spyWidth).toHaveBeenCalledWith(objectContaining({ value: 200 }))
  216. expect(spyHeight).toHaveBeenCalledWith(objectContaining({ value: 200 }))
  217. })
  218. })
  219. describe('width()', () => {
  220. it('calls attr with width', () => {
  221. const spy = spyOn(element, 'attr')
  222. element.width(123)
  223. expect(spy).toHaveBeenCalledWith('width', 123)
  224. })
  225. })
  226. describe('writeDataToDom()', () => {
  227. it('removes previously set data', () => {
  228. element.node.setAttribute('svgjs:data', JSON.stringify({ foo: 'bar' }))
  229. element.writeDataToDom()
  230. expect(element.node.getAttribute('svgjs:data')).toBe(null)
  231. })
  232. it('writes data from the dom property into the dom', () => {
  233. element.dom = { foo: 'bar' }
  234. element.writeDataToDom()
  235. expect(element.node.getAttribute('svgjs:data')).toBe(JSON.stringify({ foo: 'bar' }))
  236. })
  237. it('recursively calls writeDataToDom on all children', () => {
  238. const g = new G()
  239. const rect = g.rect(100, 100)
  240. const spy = spyOn(rect, 'writeDataToDom')
  241. g.writeDataToDom()
  242. expect(spy).toHaveBeenCalled()
  243. })
  244. })
  245. describe('x()', () => {
  246. it('calls attr with x', () => {
  247. const spy = spyOn(element, 'attr')
  248. element.x(123)
  249. expect(spy).toHaveBeenCalledWith('x', 123)
  250. })
  251. })
  252. describe('y()', () => {
  253. it('calls attr with y', () => {
  254. const spy = spyOn(element, 'attr')
  255. element.y(123)
  256. expect(spy).toHaveBeenCalledWith('y', 123)
  257. })
  258. })
  259. })