8
0

creator.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. 'use strict';
  6. /* bender-tags: editor, creator */
  7. import moduleUtils from '/tests/ckeditor5/_utils/module.js';
  8. import testUtils from '/tests/ckeditor5/_utils/utils.js';
  9. import Editor from '/ckeditor5/editor.js';
  10. import Creator from '/ckeditor5/creator.js';
  11. import CKEditorError from '/ckeditor5/utils/ckeditorerror.js';
  12. let editor, element;
  13. function initEditor( config ) {
  14. element = document.createElement( 'div' );
  15. document.body.appendChild( element );
  16. editor = new Editor( element, config );
  17. return editor.init();
  18. }
  19. testUtils.createSinonSandbox();
  20. before( () => {
  21. testUtils.defineEditorCreatorMock( 'test1', {
  22. create: sinon.spy(),
  23. destroy: sinon.spy()
  24. } );
  25. testUtils.defineEditorCreatorMock( 'test-config1', {
  26. create: sinon.spy()
  27. } );
  28. testUtils.defineEditorCreatorMock( 'test-config2', {
  29. create: sinon.spy()
  30. } );
  31. moduleUtils.define( 'test3/test3', [ 'plugin' ], ( Plugin ) => {
  32. return class extends Plugin {};
  33. } );
  34. moduleUtils.define( 'test/creator-async-create', [ 'creator' ], ( Creator ) => {
  35. return class extends Creator {
  36. create() {
  37. return new Promise( ( resolve, reject ) => {
  38. reject( new Error( 'Catch me - create.' ) );
  39. } );
  40. }
  41. destroy() {}
  42. };
  43. } );
  44. moduleUtils.define( 'test/creator-async-destroy', [ 'creator' ], ( Creator ) => {
  45. return class extends Creator {
  46. create() {}
  47. destroy() {
  48. return new Promise( ( resolve, reject ) => {
  49. reject( new Error( 'Catch me - destroy.' ) );
  50. } );
  51. }
  52. };
  53. } );
  54. moduleUtils.define( 'test/creator-destroy-order', [ 'creator' ], ( Creator ) => {
  55. return class extends Creator {
  56. create() {}
  57. destroy() {
  58. editor._elementInsideCreatorDestroy = this.editor.element;
  59. editor._destroyOrder.push( 'creator' );
  60. }
  61. };
  62. } );
  63. } );
  64. afterEach( () => {
  65. editor = null; // To make sure we're using the freshly inited editor.
  66. } );
  67. ///////////////////
  68. describe( 'init', () => {
  69. it( 'should instantiate the creator and call create()', () => {
  70. return initEditor( {
  71. creator: 'creator-test1'
  72. } )
  73. .then( () => {
  74. let creator = editor.plugins.get( 'creator-test1' );
  75. expect( creator ).to.be.instanceof( Creator );
  76. // The create method has been called.
  77. sinon.assert.calledOnce( creator.create );
  78. } );
  79. } );
  80. it( 'should throw if creator is not defined', () => {
  81. return initEditor( {} )
  82. .then( () => {
  83. throw new Error( 'This should not be executed.' );
  84. } )
  85. .catch( ( err ) => {
  86. expect( err ).to.be.instanceof( CKEditorError );
  87. expect( err.message ).to.match( /^editor-undefined-creator:/ );
  88. } );
  89. } );
  90. it( 'should use the creator specified in config.creator', () => {
  91. return initEditor( {
  92. creator: 'creator-test-config2',
  93. features: [ 'creator-test-config1', 'creator-test-config2' ],
  94. } )
  95. .then( () => {
  96. let creator1 = editor.plugins.get( 'creator-test-config1' );
  97. let creator2 = editor.plugins.get( 'creator-test-config2' );
  98. sinon.assert.calledOnce( creator2.create );
  99. sinon.assert.notCalled( creator1.create );
  100. } );
  101. } );
  102. it( 'should throw an error if the creator doesn\'t exist', () => {
  103. return initEditor( {
  104. creator: 'bad'
  105. } )
  106. .then( () => {
  107. throw new Error( 'This should not be executed.' );
  108. } )
  109. .catch( ( err ) => {
  110. // It's the Require.JS error.
  111. expect( err ).to.be.an.instanceof( Error );
  112. expect( err.message ).to.match( /^Script error for/ );
  113. } );
  114. } );
  115. it( 'should chain the promise from the creator (enables async creators)', () => {
  116. return initEditor( {
  117. creator: 'test/creator-async-create'
  118. } )
  119. .then( () => {
  120. throw new Error( 'This should not be executed.' );
  121. } )
  122. .catch( ( err ) => {
  123. // Unfortunately fake timers don't work with promises, so throwing in the creator's create()
  124. // seems to be the only way to test that the promise chain isn't broken.
  125. expect( err ).to.have.property( 'message', 'Catch me - create.' );
  126. } );
  127. } );
  128. } );
  129. describe( 'destroy', () => {
  130. it( 'should call "destroy" on the creator', () => {
  131. let creator1;
  132. return initEditor( {
  133. creator: 'creator-test1'
  134. } )
  135. .then( () => {
  136. creator1 = editor.plugins.get( 'creator-test1' );
  137. return editor.destroy();
  138. } )
  139. .then( () => {
  140. sinon.assert.calledOnce( creator1.destroy );
  141. } );
  142. } );
  143. it( 'should chain the promise from the creator (enables async creators)', () => {
  144. return initEditor( {
  145. creator: 'test/creator-async-destroy'
  146. } )
  147. .then( () => {
  148. return editor.destroy();
  149. } )
  150. .then( () => {
  151. throw new Error( 'This should not be executed.' );
  152. } )
  153. .catch( ( err ) => {
  154. // Unfortunately fake timers don't work with promises, so throwing in the creator's destroy()
  155. // seems to be the only way to test that the promise chain isn't broken.
  156. expect( err ).to.have.property( 'message', 'Catch me - destroy.' );
  157. } );
  158. } );
  159. it( 'should do things in the correct order', () => {
  160. return initEditor( {
  161. creator: 'test/creator-destroy-order'
  162. } )
  163. .then( () => {
  164. editor._destroyOrder = [];
  165. editor.on( 'destroy', () => {
  166. editor._destroyOrder.push( 'event' );
  167. } );
  168. return editor.destroy();
  169. } )
  170. .then( () => {
  171. expect( editor._elementInsideCreatorDestroy ).to.not.be.undefined;
  172. expect( editor._destroyOrder ).to.deep.equal( [ 'event', 'creator' ] );
  173. } );
  174. } );
  175. } );