creator.js 5.4 KB

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