template.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* bender-tags: ui */
  6. /* global HTMLElement */
  7. 'use strict';
  8. const modules = bender.amd.require( 'core/ui/template' );
  9. let Template;
  10. bender.tools.createSinonSandbox();
  11. describe( 'Template', () => {
  12. beforeEach( createClassReferences );
  13. describe( 'constructor', () => {
  14. it( 'accepts the definition', () => {
  15. let def = {
  16. tag: 'p'
  17. };
  18. expect( new Template( def ).def ).to.equal( def );
  19. } );
  20. } );
  21. describe( 'render', () => {
  22. it( 'returns null when no definition', () => {
  23. expect( new Template().render() ).to.be.null;
  24. } );
  25. it( 'creates an element', () => {
  26. let el = new Template( {
  27. tag: 'p',
  28. attrs: {
  29. 'class': [ 'a', 'b' ],
  30. x: 'bar'
  31. },
  32. text: 'foo'
  33. } ).render();
  34. expect( el ).to.be.instanceof( HTMLElement );
  35. expect( el.parentNode ).to.be.null;
  36. expect( el.outerHTML ).to.be.equal( '<p class="a b" x="bar">foo</p>' );
  37. } );
  38. it( 'creates element\'s children', () => {
  39. let el = new Template( {
  40. tag: 'p',
  41. attrs: {
  42. a: 'A'
  43. },
  44. children: [
  45. {
  46. tag: 'b',
  47. text: 'B'
  48. },
  49. {
  50. tag: 'i',
  51. text: 'C',
  52. children: [
  53. {
  54. tag: 'b',
  55. text: 'D'
  56. }
  57. ]
  58. }
  59. ]
  60. } ).render();
  61. expect( el.outerHTML ).to.be.equal( '<p a="A"><b>B</b><i>C<b>D</b></i></p>' );
  62. } );
  63. describe( 'callback', () => {
  64. it( 'works for attributes', () => {
  65. let spy1 = bender.sinon.spy();
  66. let spy2 = bender.sinon.spy();
  67. let el = new Template( {
  68. tag: 'p',
  69. attrs: {
  70. 'class': spy1
  71. },
  72. children: [
  73. {
  74. tag: 'span',
  75. attrs: {
  76. id: spy2
  77. }
  78. }
  79. ]
  80. } ).render();
  81. sinon.assert.calledWithExactly( spy1, el, sinon.match.func );
  82. sinon.assert.calledWithExactly( spy2, el.firstChild, sinon.match.func );
  83. spy1.firstCall.args[ 1 ]( el, 'foo' );
  84. spy2.firstCall.args[ 1 ]( el.firstChild, 'bar' );
  85. expect( el.outerHTML ).to.be.equal( '<p class="foo"><span id="bar"></span></p>' );
  86. } );
  87. it( 'works for "text" property', () => {
  88. let spy1 = bender.sinon.spy();
  89. let spy2 = bender.sinon.spy();
  90. let el = new Template( {
  91. tag: 'p',
  92. text: spy1,
  93. children: [
  94. {
  95. tag: 'span',
  96. text: spy2
  97. }
  98. ]
  99. } ).render();
  100. sinon.assert.calledWithExactly( spy1, el, sinon.match.func );
  101. sinon.assert.calledWithExactly( spy2, el.firstChild, sinon.match.func );
  102. spy2.firstCall.args[ 1 ]( el.firstChild, 'bar' );
  103. expect( el.outerHTML ).to.be.equal( '<p><span>bar</span></p>' );
  104. spy1.firstCall.args[ 1 ]( el, 'foo' );
  105. expect( el.outerHTML ).to.be.equal( '<p>foo</p>' );
  106. } );
  107. it( 'works for "on" property', () => {
  108. let spy1 = bender.sinon.spy();
  109. let spy2 = bender.sinon.spy();
  110. let spy3 = bender.sinon.spy();
  111. let spy4 = bender.sinon.spy();
  112. let el = new Template( {
  113. tag: 'p',
  114. children: [
  115. {
  116. tag: 'span',
  117. on: {
  118. bar: spy2
  119. }
  120. }
  121. ],
  122. on: {
  123. foo: spy1,
  124. baz: [ spy3, spy4 ]
  125. }
  126. } ).render();
  127. sinon.assert.calledWithExactly( spy1, el, 'foo', null );
  128. sinon.assert.calledWithExactly( spy2, el.firstChild, 'bar', null );
  129. sinon.assert.calledWithExactly( spy3, el, 'baz', null );
  130. sinon.assert.calledWithExactly( spy4, el, 'baz', null );
  131. } );
  132. it( 'works for "on" property with selectors', () => {
  133. let spy1 = bender.sinon.spy();
  134. let spy2 = bender.sinon.spy();
  135. let spy3 = bender.sinon.spy();
  136. let spy4 = bender.sinon.spy();
  137. let el = new Template( {
  138. tag: 'p',
  139. children: [
  140. {
  141. tag: 'span',
  142. attrs: {
  143. 'id': 'x'
  144. }
  145. },
  146. {
  147. tag: 'span',
  148. attrs: {
  149. 'class': 'y'
  150. },
  151. on: {
  152. 'bar@p': spy2
  153. }
  154. },
  155. ],
  156. on: {
  157. 'foo@span': spy1,
  158. 'baz@.y': [ spy3, spy4 ]
  159. }
  160. } ).render();
  161. sinon.assert.calledWithExactly( spy1, el, 'foo', 'span' );
  162. sinon.assert.calledWithExactly( spy2, el.lastChild, 'bar', 'p' );
  163. sinon.assert.calledWithExactly( spy3, el, 'baz', '.y' );
  164. sinon.assert.calledWithExactly( spy4, el, 'baz', '.y' );
  165. } );
  166. } );
  167. } );
  168. } );
  169. function createClassReferences() {
  170. Template = modules[ 'core/ui/template' ];
  171. }