creator.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* bender-tags: creator */
  6. 'use strict';
  7. import testUtils from '/tests/_utils/utils.js';
  8. import Creator from '/ckeditor5/core/creator.js';
  9. import Editor from '/ckeditor5/core/editor.js';
  10. import Plugin from '/ckeditor5/core/plugin.js';
  11. testUtils.createSinonSandbox();
  12. describe( 'Creator', () => {
  13. let creator, editor;
  14. beforeEach( () => {
  15. const editorElement = document.createElement( 'div' );
  16. document.body.appendChild( editorElement );
  17. editor = new Editor( editorElement );
  18. creator = new Creator( editor );
  19. } );
  20. describe( 'create', () => {
  21. it( 'should init the UI', () => {
  22. const promise = new Promise( () => {} );
  23. editor.ui = {
  24. init: sinon.stub().returns( promise )
  25. };
  26. const ret = creator.create();
  27. expect( ret ).to.equal( promise );
  28. expect( editor.ui.init.called ).to.be.true;
  29. } );
  30. it( 'should not fail when there is no UI', () => {
  31. expect( editor.ui ).to.not.exist;
  32. return creator.create()
  33. .then(); // Just checking whether a promise was returned.
  34. } );
  35. } );
  36. describe( 'destroy', () => {
  37. it( 'calls super.destroy', () => {
  38. const pluginSpy = testUtils.sinon.spy( Plugin.prototype, 'destroy' );
  39. editor.ui = {
  40. destroy() {}
  41. };
  42. creator.destroy();
  43. expect( pluginSpy.called ).to.be.true;
  44. } );
  45. it( 'should destroy the UI (sync)', () => {
  46. const uiSpy = sinon.spy();
  47. editor.ui = {
  48. destroy: uiSpy
  49. };
  50. return creator.destroy()
  51. .then( () => {
  52. expect( uiSpy.called ).to.be.true;
  53. expect( editor.ui ).to.be.null;
  54. } );
  55. } );
  56. it( 'should destroy the UI (async)', () => {
  57. const uiSpy = sinon.stub().returns( Promise.resolve() );
  58. editor.ui = {
  59. destroy: uiSpy
  60. };
  61. return creator.destroy()
  62. .then( () => {
  63. expect( uiSpy.called ).to.be.true;
  64. expect( editor.ui ).to.be.null;
  65. } );
  66. } );
  67. it( 'should wait until UI is destroyed (async)', () => {
  68. let resolved = false;
  69. let resolve;
  70. const uiSpy = sinon.stub().returns(
  71. new Promise( ( r ) => {
  72. resolve = r;
  73. } )
  74. );
  75. editor.ui = {
  76. destroy: uiSpy
  77. };
  78. // Is there an easier method to verify whether the promise chain isn't broken? ;/
  79. setTimeout( () => {
  80. resolved = true;
  81. resolve( 'foo' );
  82. } );
  83. return creator.destroy()
  84. .then( () => {
  85. expect( resolved ).to.be.true;
  86. } );
  87. } );
  88. it( 'should restore the replaced element', () => {
  89. const spy = testUtils.sinon.stub( creator, '_restoreElement' );
  90. const element = document.createElement( 'div' );
  91. editor.ui = {
  92. destroy() {}
  93. };
  94. creator._replaceElement( element );
  95. creator.destroy();
  96. expect( spy.calledOnce ).to.be.true;
  97. } );
  98. } );
  99. describe( 'updateEditorElement', () => {
  100. it( 'should pass data to the element', () => {
  101. editor.editable = {
  102. getData() {
  103. return 'foo';
  104. }
  105. };
  106. creator.updateEditorElement();
  107. expect( editor.element.innerHTML ).to.equal( 'foo' );
  108. } );
  109. } );
  110. describe( 'loadDataFromEditorElement', () => {
  111. it( 'should pass data to the element', () => {
  112. editor.editable = {
  113. setData: sinon.spy()
  114. };
  115. editor.element.innerHTML = 'foo';
  116. creator.loadDataFromEditorElement();
  117. expect( editor.editable.setData.args[ 0 ][ 0 ] ).to.equal( 'foo' );
  118. } );
  119. } );
  120. describe( 'getDataFromElement', () => {
  121. [ 'textarea', 'template', 'div' ].forEach( ( elementName ) => {
  122. it( 'should return the content of a ' + elementName, function() {
  123. const data = Creator.getDataFromElement( document.getElementById( 'getData-' + elementName ) );
  124. expect( data ).to.equal( '<b>foo</b>' );
  125. } );
  126. } );
  127. } );
  128. describe( 'setDataInElement', () => {
  129. [ 'textarea', 'template', 'div' ].forEach( ( elementName ) => {
  130. it( 'should set the content of a ' + elementName, () => {
  131. const el = document.createElement( elementName );
  132. const expectedData = '<b>foo</b>';
  133. Creator.setDataInElement( el, expectedData );
  134. const actualData = Creator.getDataFromElement( el );
  135. expect( actualData ).to.equal( actualData );
  136. } );
  137. } );
  138. } );
  139. describe( '_replaceElement', () => {
  140. it( 'should use editor ui element when arg not provided', () => {
  141. editor.ui = {
  142. view: {
  143. element: document.createElement( 'div' )
  144. }
  145. };
  146. creator._replaceElement();
  147. expect( editor.element.nextSibling ).to.equal( editor.ui.view.element );
  148. } );
  149. } );
  150. describe( '_restoreElement', () => {
  151. it( 'should remove the replacement element', () => {
  152. const element = document.createElement( 'div' );
  153. creator._replaceElement( element );
  154. expect( editor.element.nextSibling ).to.equal( element );
  155. creator._restoreElement();
  156. expect( element.parentNode ).to.be.null;
  157. } );
  158. } );
  159. } );