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.

Dom.js 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. /* globals describe, expect, it, beforeEach, spyOn, jasmine, container */
  2. import {
  3. SVG,
  4. G,
  5. Rect,
  6. Svg,
  7. Dom,
  8. List,
  9. Fragment,
  10. Circle,
  11. Tspan,
  12. create,
  13. Text
  14. } from '../../../src/main.js'
  15. import { getWindow } from '../../../src/utils/window.js'
  16. import { svg, html } from '../../../src/modules/core/namespaces.js'
  17. const { any, createSpy, objectContaining } = jasmine
  18. describe('Dom.js', function () {
  19. describe('()', () => {
  20. it('creates a new object of type Dom', () => {
  21. const rect = new Rect()
  22. expect(new Dom(rect.node)).toEqual(any(Dom))
  23. })
  24. it('sets passed attributes on the element', () => {
  25. const rect = new Rect()
  26. expect(new Dom(rect.node, { id: 'foo' }).id()).toBe('foo')
  27. })
  28. it('references the passed node on the instance', () => {
  29. const rect = new Rect()
  30. expect(new Dom(rect.node).node).toBe(rect.node)
  31. })
  32. it('sets the type according to the nodename', () => {
  33. const rect = new Rect()
  34. expect(new Dom(rect.node).type).toBe(rect.node.nodeName)
  35. })
  36. })
  37. describe('add()', () => {
  38. it('adds an element as child to the end with no second argument given', () => {
  39. const g = new G()
  40. g.add(new Rect())
  41. const rect = new Rect()
  42. g.add(rect)
  43. expect(g.children().length).toBe(2)
  44. expect(g.get(1)).toBe(rect)
  45. })
  46. it('adds an element at the specified position with second argument given', () => {
  47. const g = new G()
  48. g.add(new Rect())
  49. g.add(new Rect())
  50. const rect = new Rect()
  51. g.add(rect, 1)
  52. expect(g.children().length).toBe(3)
  53. expect(g.get(1)).toBe(rect)
  54. })
  55. it('does nothing if element is already the element at that position', () => {
  56. const g = new G()
  57. g.rect(100, 100)
  58. const rect = g.rect(100, 100)
  59. g.add(rect, 1)
  60. expect(g.get(1)).toBe(rect)
  61. })
  62. it('handles svg strings', () => {
  63. const g = new G()
  64. g.add('<rect />')
  65. expect(g.children().length).toBe(1)
  66. expect(g.get(0)).toEqual(any(Rect))
  67. })
  68. it('handles query selectors', () => {
  69. const canvas = SVG().addTo(container)
  70. const rect = canvas.rect(100, 100).addClass('test')
  71. const g = canvas.group()
  72. g.add('.test')
  73. expect(g.children().length).toBe(1)
  74. expect(g.get(0)).toBe(rect)
  75. })
  76. it('handles a node', () => {
  77. const g = new G()
  78. const node = create('rect')
  79. g.add(node)
  80. expect(g.children().length).toBe(1)
  81. expect(g.get(0)).toEqual(any(Rect))
  82. })
  83. })
  84. describe('addTo()', () => {
  85. it('returns the current element', () => {
  86. const g = new G()
  87. const rect = new Rect()
  88. expect(rect.addTo(g)).toBe(rect)
  89. })
  90. it('puts an element into another element', () => {
  91. const g = new G()
  92. const rect = new Rect()
  93. const spy = spyOn(g, 'put')
  94. rect.addTo(g, 0)
  95. expect(spy).toHaveBeenCalledWith(rect, 0)
  96. })
  97. it('works with svg strings', () => {
  98. const rect = new Rect()
  99. rect.addTo('<g />')
  100. expect(rect.parent()).toEqual(any(G))
  101. })
  102. it('works with query selector', () => {
  103. const canvas = SVG().addTo(container)
  104. const rect = canvas.rect(100, 100)
  105. const g = canvas.group().addClass('test')
  106. rect.addTo('.test')
  107. expect(g.children().length).toBe(1)
  108. expect(g.get(0)).toBe(rect)
  109. })
  110. })
  111. describe('children()', () => {
  112. it('returns a List of all children', () => {
  113. const g = new G()
  114. const rect = g.rect(100, 100)
  115. const circle = g.circle(100, 100)
  116. const children = g.children()
  117. expect(children).toEqual([rect, circle])
  118. expect(children).toEqual(any(List))
  119. })
  120. })
  121. describe('clear()', () => {
  122. it('returns the current element', () => {
  123. const g = new G()
  124. g.rect(100, 100)
  125. g.circle(100, 100)
  126. expect(g.clear()).toBe(g)
  127. })
  128. it('removes all children from an element', () => {
  129. const g = new G()
  130. g.rect(100, 100)
  131. g.circle(100, 100)
  132. g.clear()
  133. expect(g.children()).toEqual([])
  134. })
  135. })
  136. describe('clone()', () => {
  137. it('clones the current element and returns it', () => {
  138. const rect = new Rect()
  139. const clone = rect.clone()
  140. expect(rect).not.toBe(clone)
  141. expect(clone).toEqual(any(Rect))
  142. expect(clone.type).toBe(rect.type)
  143. })
  144. it('also clones the children by default', () => {
  145. const group = new G()
  146. const rect = group.rect(100, 100)
  147. const clone = group.clone()
  148. expect(clone.get(0)).not.toBe(rect)
  149. expect(clone.get(0)).toEqual(any(Rect))
  150. })
  151. it('does not clone the children when passing false', () => {
  152. const group = new G()
  153. group.rect(100, 100)
  154. const clone = group.clone(false)
  155. expect(clone.children()).toEqual([])
  156. })
  157. it('assigns a new id to the element and to child elements by default', () => {
  158. const group = new G().id('group')
  159. const rect = group.rect(100, 100).id('rect')
  160. const clone = group.clone()
  161. expect(clone.get(0).id()).not.toBe(rect.id())
  162. expect(clone.id()).not.toBe(group.id())
  163. })
  164. it('does not assign a new id to the element and to child elements', () => {
  165. const group = new G().id('group')
  166. const rect = group.rect(100, 100).id('rect')
  167. const clone = group.clone(true, false)
  168. expect(clone.get(0).id()).toBe(rect.id())
  169. expect(clone.id()).toBe(group.id())
  170. })
  171. it('returns an instance of the same class the method was called on', () => {
  172. const rect = new Dom(create('rect'))
  173. expect(rect.constructor).toBe(Dom)
  174. expect(rect.clone().constructor).toBe(Dom)
  175. })
  176. })
  177. describe('each()', () => {
  178. it('iterates over all children and executes the passed function on then', () => {
  179. const group = new G()
  180. const group2 = group.group()
  181. const circle = group.circle(100, 100)
  182. const spy = createSpy('each')
  183. group.each(spy)
  184. expect(spy.calls.all()).toEqual([
  185. objectContaining({ object: group2, args: [0, [group2, circle]] }),
  186. objectContaining({ object: circle, args: [1, [group2, circle]] })
  187. ])
  188. })
  189. it('iterates over all children recursively and executes the passed function on then when deep is true', () => {
  190. const group = new G()
  191. const group2 = group.group()
  192. const rect = group2.rect(100, 100)
  193. const circle = group.circle(100, 100)
  194. const spy = createSpy('each')
  195. group.each(spy, true)
  196. expect(spy.calls.all()).toEqual([
  197. objectContaining({ object: group2, args: [0, [group2, circle]] }),
  198. objectContaining({ object: rect, args: [0, [rect]] }),
  199. objectContaining({ object: circle, args: [1, [group2, circle]] })
  200. ])
  201. })
  202. })
  203. describe('element()', () => {
  204. it('creates an element of given type and appends it to the current element', () => {
  205. const g = new G()
  206. const el = g.element('title')
  207. expect(el).toEqual(any(Dom))
  208. expect(el.type).toBe('title')
  209. })
  210. it('sets the specified attributes passed as second argument', () => {
  211. const g = new G()
  212. const el = g.element('title', { id: 'foo' })
  213. expect(el.id()).toBe('foo')
  214. })
  215. })
  216. describe('first()', () => {
  217. it('returns the first child', () => {
  218. const g = new G()
  219. const rect = g.rect(100, 100)
  220. g.circle(100, 100)
  221. expect(g.first()).toBe(rect)
  222. })
  223. it('returns null if no first child exists', () => {
  224. expect(new G().first()).toBe(null)
  225. })
  226. })
  227. describe('get()', () => {
  228. it('returns the child at the given position', () => {
  229. const g = new G()
  230. const rect = g.rect(100, 100)
  231. const circle = g.circle(100, 100)
  232. expect(g.get(0)).toBe(rect)
  233. expect(g.get(1)).toBe(circle)
  234. })
  235. })
  236. describe('getEventHolder()', () => {
  237. it('returns the node because it holds all events on the object', () => {
  238. const dom = new Dom({})
  239. expect(dom.getEventHolder()).toBe(dom.node)
  240. })
  241. })
  242. describe('getEventTarget()', () => {
  243. it('returns the node because it is the target of the event', () => {
  244. const dom = new Dom({})
  245. expect(dom.getEventTarget()).toBe(dom.node)
  246. })
  247. })
  248. describe('has()', () => {
  249. it('returns true if the element has the passed element as child', () => {
  250. const g = new G()
  251. const rect = g.rect(100, 100)
  252. expect(g.has(rect)).toBe(true)
  253. })
  254. it("returns false if the element hasn't the passed element as child", () => {
  255. const g = new G()
  256. const rect = new Rect()
  257. expect(g.has(rect)).toBe(false)
  258. })
  259. })
  260. describe('html()', () => {
  261. it('calls xml with the html namespace', () => {
  262. const group = new G()
  263. const spy = spyOn(group, 'xml')
  264. group.html('<foo>')
  265. expect(spy).toHaveBeenCalledWith('<foo>', undefined, html)
  266. })
  267. })
  268. describe('id()', () => {
  269. it('returns current element when called as setter', () => {
  270. const g = new G()
  271. expect(g.id('asd')).toBe(g)
  272. })
  273. it('sets the id with argument given', () => {
  274. expect(new G().id('foo').node.id).toBe('foo')
  275. })
  276. it('gets the id when no argument given', () => {
  277. const g = new G({ id: 'foo' })
  278. expect(g.id()).toBe('foo')
  279. })
  280. it('generates an id on getting if none is set', () => {
  281. const g = new G()
  282. expect(g.node.id).toBe('')
  283. g.id()
  284. expect(g.node.id).not.toBe('')
  285. })
  286. })
  287. describe('index()', () => {
  288. it('gets the position of the passed child', () => {
  289. const g = new G()
  290. g.rect(100, 100)
  291. const rect = g.rect(100, 100)
  292. expect(g.index(rect)).toBe(1)
  293. })
  294. it('returns -1 if element is no child', () => {
  295. const g = new G()
  296. const rect = new Rect()
  297. expect(g.index(rect)).toBe(-1)
  298. })
  299. })
  300. describe('last()', () => {
  301. it('gets the last child of the element', () => {
  302. const g = new G()
  303. g.rect(100, 100)
  304. const rect = g.rect(100, 100)
  305. expect(g.last()).toBe(rect)
  306. })
  307. it('returns null if no last child exists', () => {
  308. expect(new G().last()).toBe(null)
  309. })
  310. })
  311. describe('parent()', () => {
  312. var canvas, rect, group1, group2
  313. beforeEach(function () {
  314. canvas = SVG().addTo(container)
  315. group1 = canvas.group().addClass('test')
  316. group2 = group1.group()
  317. rect = group2.rect(100, 100)
  318. })
  319. it('returns the svg parent with no argument given', () => {
  320. expect(rect.parent()).toBe(group2)
  321. })
  322. it('returns the closest parent with the correct type', () => {
  323. expect(rect.parent(Svg)).toBe(canvas)
  324. })
  325. it('returns the closest parent matching the selector', () => {
  326. expect(rect.parent('.test')).toBe(group1)
  327. })
  328. it('returns null if it cannot find a parent matching the argument', () => {
  329. expect(rect.parent('.not-there')).toBe(null)
  330. })
  331. it('returns null if it cannot find a parent matching the argument in a #document-fragment', () => {
  332. const fragment = getWindow().document.createDocumentFragment()
  333. const svg = new Svg().addTo(fragment)
  334. const rect = svg.rect(100, 100)
  335. expect(rect.parent('.not-there')).toBe(null)
  336. })
  337. it('returns Dom if parent is #document-fragment', () => {
  338. const fragment = getWindow().document.createDocumentFragment()
  339. const svg = new Svg().addTo(fragment)
  340. expect(svg.parent()).toEqual(any(Dom))
  341. })
  342. it('returns html parents, too', () => {
  343. expect(canvas.parent().node).toBe(container)
  344. })
  345. })
  346. describe('put()', () => {
  347. it('calls add() but returns the added element instead', () => {
  348. const g = new G()
  349. const rect = new Rect()
  350. const spy = spyOn(g, 'add').and.callThrough()
  351. expect(g.put(rect, 0)).toBe(rect)
  352. expect(spy).toHaveBeenCalledWith(rect, 0)
  353. })
  354. it('creates object from svg string', () => {
  355. const g = new G()
  356. const rect = '<rect />'
  357. const spy = spyOn(g, 'add').and.callThrough()
  358. const ret = g.put(rect, 0)
  359. expect(ret).toEqual(any(Rect))
  360. expect(spy).toHaveBeenCalledWith(ret, 0)
  361. })
  362. it('works with a query selector', () => {
  363. const canvas = SVG().addTo(container)
  364. const rect = canvas.rect().addClass('test')
  365. const g = canvas.group()
  366. const spy = spyOn(g, 'add').and.callThrough()
  367. const ret = g.put('.test', 0)
  368. expect(ret).toEqual(rect)
  369. expect(spy).toHaveBeenCalledWith(rect, 0)
  370. })
  371. })
  372. describe('putIn()', () => {
  373. it('calls add on the given parent', () => {
  374. const g = new G()
  375. const rect = new Rect()
  376. const spy = spyOn(g, 'add')
  377. rect.putIn(g, 0)
  378. expect(spy).toHaveBeenCalledWith(rect, 0)
  379. })
  380. it('returns the passed element', () => {
  381. const g = new G()
  382. const rect = new Rect()
  383. expect(rect.putIn(g, 0)).toBe(g)
  384. })
  385. it('returns an instance when svg string given', () => {
  386. const g = '<g />'
  387. const rect = new Rect()
  388. const ret = rect.putIn(g)
  389. expect(ret).toEqual(any(G))
  390. expect(ret.children()).toEqual([rect])
  391. })
  392. it('works with a query selector', () => {
  393. const canvas = SVG().addTo(container)
  394. const g = canvas.group().addClass('test')
  395. const rect = canvas.rect(100, 100)
  396. const ret = rect.putIn('.test')
  397. expect(ret).toBe(g)
  398. expect(g.children()).toEqual([rect])
  399. })
  400. })
  401. describe('remove()', () => {
  402. it('returns the removed element', () => {
  403. const canvas = SVG().addTo(container)
  404. const rect = canvas.rect(100, 100)
  405. expect(rect.remove()).toBe(rect)
  406. })
  407. it('removes the element from the parent', () => {
  408. const canvas = SVG().addTo(container)
  409. const rect = canvas.rect(100, 100)
  410. expect(canvas.children()).toEqual([rect])
  411. rect.remove()
  412. expect(canvas.children()).toEqual([])
  413. })
  414. it('is a noop when element is not attached to the dom', () => {
  415. const rect = new Rect()
  416. expect(rect.remove()).toBe(rect)
  417. })
  418. it('also works when direct child of document-fragment', () => {
  419. const fragment = new Fragment()
  420. const rect = fragment.rect(100, 100)
  421. expect(fragment.children()).toEqual([rect])
  422. expect(rect.remove()).toBe(rect)
  423. expect(fragment.children()).toEqual([])
  424. })
  425. })
  426. describe('removeElement()', () => {
  427. it('returns itself', () => {
  428. const g = new G()
  429. const rect = g.rect(100, 100)
  430. expect(g.removeElement(rect)).toBe(g)
  431. })
  432. it('removes the given child', () => {
  433. const g = new G()
  434. const rect = g.rect(100, 100)
  435. expect(g.removeElement(rect).children()).toEqual([])
  436. })
  437. it('throws if the given element is not a child', () => {
  438. const g = new G()
  439. const rect = new Rect()
  440. try {
  441. g.removeElement(rect)
  442. } catch (e) {
  443. expect(e).toEqual(objectContaining({ code: 8 }))
  444. }
  445. })
  446. })
  447. describe('replace()', () => {
  448. it('returns the new element', () => {
  449. const g = new G()
  450. const rect = g.rect(100, 100)
  451. const circle = new Circle()
  452. expect(rect.replace(circle)).toBe(circle)
  453. })
  454. it('replaces the child at the correct position', () => {
  455. const g = new G()
  456. const rect1 = g.rect(100, 100)
  457. const rect2 = g.rect(100, 100)
  458. const rect3 = g.rect(100, 100)
  459. const circle = new Circle()
  460. rect2.replace(circle)
  461. expect(g.children()).toEqual([rect1, circle, rect3])
  462. })
  463. it('also works without a parent', () => {
  464. const rect = new Rect()
  465. const circle = new Circle()
  466. expect(rect.replace(circle)).toBe(circle)
  467. })
  468. })
  469. describe('round()', () => {
  470. it('rounds all attributes whose values are numbers to two decimals by default', () => {
  471. const rect = new Rect({ id: 'foo', x: 10.678, y: 3, width: 123.456 })
  472. expect(rect.round().attr()).toEqual({
  473. id: 'foo',
  474. x: 10.68,
  475. y: 3,
  476. width: 123.46
  477. })
  478. })
  479. it('rounds all attributes whose values are numbers to the passed precision', () => {
  480. const rect = new Rect({ id: 'foo', x: 10.678, y: 3, width: 123.456 })
  481. expect(rect.round(1).attr()).toEqual({
  482. id: 'foo',
  483. x: 10.7,
  484. y: 3,
  485. width: 123.5
  486. })
  487. })
  488. it('rounds the given attributes whose values are numbers to the passed precision', () => {
  489. const rect = new Rect({ id: 'foo', x: 10.678, y: 3, width: 123.456 })
  490. expect(rect.round(1, ['id', 'x']).attr()).toEqual({
  491. id: 'foo',
  492. x: 10.7,
  493. y: 3,
  494. width: 123.456
  495. })
  496. })
  497. })
  498. describe('svg()', () => {
  499. it('calls xml with the svg namespace', () => {
  500. const group = new G()
  501. const spy = spyOn(group, 'xml')
  502. group.svg('<foo>')
  503. expect(spy).toHaveBeenCalledWith('<foo>', undefined, svg)
  504. })
  505. })
  506. describe('toString()', () => {
  507. it('calls id() and returns its result', () => {
  508. const rect = new Rect({ id: 'foo' })
  509. const spy = spyOn(rect, 'id').and.callThrough()
  510. expect(rect.toString()).toBe('foo')
  511. expect(spy).toHaveBeenCalled()
  512. })
  513. })
  514. describe('words', () => {
  515. it('sets the nodes textContent to the given value', () => {
  516. const tspan = new Tspan().words('Hello World')
  517. expect(tspan.text()).toBe('Hello World')
  518. })
  519. })
  520. describe('wrap()', function () {
  521. var canvas
  522. var rect
  523. beforeEach(function () {
  524. canvas = SVG()
  525. rect = canvas.rect(100, 100)
  526. })
  527. it('returns the current element', function () {
  528. expect(rect.wrap(new G())).toBe(rect)
  529. })
  530. it('wraps the passed element around the current element', function () {
  531. var g = new G()
  532. expect(rect.wrap(g).parent()).toBe(g)
  533. expect(g.parent()).toBe(canvas)
  534. })
  535. it('wraps also when element is not in the dom', () => {
  536. var g = new G()
  537. var rect = new Rect()
  538. expect(rect.wrap(g).parent()).toBe(g)
  539. expect(g.parent()).toBe(null)
  540. })
  541. it('inserts at the correct position', () => {
  542. canvas.rect(100, 100)
  543. rect = canvas.rect(100, 100)
  544. var position = rect.position()
  545. var g = new G()
  546. expect(rect.wrap(g).parent().position()).toBe(position)
  547. })
  548. it('allows to pass an svg string as element', () => {
  549. rect.wrap('<g />')
  550. expect(rect.parent()).toEqual(any(G))
  551. expect(rect.parent().parent()).toBe(canvas)
  552. })
  553. it('allows to pass an svg string as element', () => {
  554. rect.wrap('<g />')
  555. expect(rect.parent()).toEqual(any(G))
  556. expect(rect.parent().parent()).toBe(canvas)
  557. })
  558. it('allows to pass an svg string as element when element not in the dom', () => {
  559. var rect = new Rect()
  560. rect.wrap(SVG('<g />'))
  561. expect(rect.parent()).toEqual(any(G))
  562. expect(rect.parent().parent()).toBe(null)
  563. })
  564. it('allows to pass an svg node as element', () => {
  565. const node = create('g')
  566. rect.wrap(node)
  567. expect(rect.parent()).toEqual(any(G))
  568. expect(rect.parent().node).toBe(node)
  569. expect(rect.parent().parent()).toBe(canvas)
  570. })
  571. })
  572. describe('writeDataToDom()', () => {
  573. it('writes the data to the dom', () => {
  574. const node = new Rect()
  575. node.setData({ foo: 'bar' })
  576. node.writeDataToDom()
  577. expect(node.node.getAttribute('svgjs:data')).toBe('{"foo":"bar"}')
  578. })
  579. it('filters out default data', () => {
  580. const node1 = new Text()
  581. const node2 = new Text()
  582. node2.dom.foo = 'bar'
  583. node1.writeDataToDom()
  584. node2.writeDataToDom()
  585. expect(node1.node.getAttribute('svgjs:data')).toBe(null)
  586. expect(node2.node.getAttribute('svgjs:data')).toBe('{"foo":"bar"}')
  587. })
  588. })
  589. describe('xml()', () => {
  590. describe('as setter', () => {
  591. it('returns itself', () => {
  592. const g = new G()
  593. expect(g.xml('<rect />', undefined, svg)).toBe(g)
  594. })
  595. it('imports a single element', () => {
  596. const g = new G().xml('<rect />', undefined, svg)
  597. expect(g.children()).toEqual([any(Rect)])
  598. expect(g.children()[0].node.namespaceURI).toBe(svg)
  599. })
  600. it('imports multiple elements', () => {
  601. const g = new G().xml('<rect /><circle />', undefined, svg)
  602. expect(g.children()).toEqual([any(Rect), any(Circle)])
  603. })
  604. it('replaces the current element with the imported elements with outerHtml = true', () => {
  605. const canvas = new Svg()
  606. const g = canvas.group()
  607. g.xml('<rect /><circle />', true, svg)
  608. expect(canvas.children()).toEqual([any(Rect), any(Circle)])
  609. })
  610. it('returns the parent when outerHtml = true', () => {
  611. const canvas = new Svg()
  612. const g = canvas.group()
  613. expect(g.xml('<rect /><circle />', true, svg)).toBe(canvas)
  614. expect(canvas.children()).toEqual([any(Rect), any(Circle)])
  615. })
  616. it('works without a parent', () => {
  617. const canvas = new Svg()
  618. expect(canvas.xml('<rect /><circle />', undefined, svg)).toBe(canvas)
  619. })
  620. })
  621. describe('as getter', () => {
  622. let canvas, group, rect
  623. beforeEach(() => {
  624. canvas = new Svg().removeNamespace()
  625. group = canvas.group()
  626. rect = group.rect(123.456, 234.567)
  627. })
  628. it('returns the svg string of the element by default', () => {
  629. expect(rect.xml(), svg).toBe(
  630. '<rect width="123.456" height="234.567"></rect>'
  631. )
  632. expect(canvas.xml(), svg).toBe(
  633. '<svg><g><rect width="123.456" height="234.567"></rect></g></svg>'
  634. )
  635. })
  636. it('returns the innerHtml when outerHtml = false', () => {
  637. expect(rect.xml(false, svg)).toBe('')
  638. expect(canvas.xml(false, svg)).toBe(
  639. '<g><rect width="123.456" height="234.567"></rect></g>'
  640. )
  641. })
  642. it('runs a function on every exported node', () => {
  643. expect(rect.xml((el) => el.round(1))).toBe(
  644. '<rect width="123.5" height="234.6"></rect>'
  645. )
  646. })
  647. it('runs a function on every exported node and replaces node with returned node if return value is not falsy', () => {
  648. expect(rect.xml(() => new Circle(), svg)).toBe('<circle></circle>')
  649. expect(canvas.xml(() => new G(), svg)).toBe('<g></g>') // outer <svg> was replaced by an empty g
  650. expect(
  651. canvas.xml((el) => {
  652. if (el instanceof Rect) return new Circle()
  653. if (el instanceof Svg) el.removeNamespace()
  654. }, svg)
  655. ).toBe('<svg><g><circle></circle></g></svg>')
  656. })
  657. it('runs a function on every exported node and removes node if return value is false', () => {
  658. expect(group.xml(() => false, svg)).toBe('')
  659. expect(canvas.xml(() => false, svg)).toBe('')
  660. expect(
  661. canvas.xml((el) => {
  662. if (el instanceof Svg) {
  663. el.removeNamespace()
  664. } else {
  665. return false
  666. }
  667. }, svg)
  668. ).toBe('<svg></svg>')
  669. })
  670. it('runs a function on every inner node and exports it when outerHtml = false', () => {
  671. expect(canvas.xml(() => false, false, svg)).toBe('')
  672. expect(canvas.xml(() => undefined, false, svg)).toBe(
  673. '<g><rect width="123.456" height="234.567"></rect></g>'
  674. )
  675. })
  676. })
  677. })
  678. })