creator.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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/creator.js';
  11. import CKEditorError from '/ckeditor5/utils/ckeditorerror.js';
  12. let editor;
  13. function initEditor( config ) {
  14. editor = new Editor( null, config );
  15. return editor.init();
  16. }
  17. testUtils.createSinonSandbox();
  18. testUtils.defineEditorCreatorMock( 'test1', {
  19. create: sinon.spy(),
  20. destroy: sinon.spy()
  21. } );
  22. testUtils.defineEditorCreatorMock( 'test-config1', {
  23. create: sinon.spy()
  24. } );
  25. testUtils.defineEditorCreatorMock( 'test-config2', {
  26. create: sinon.spy()
  27. } );
  28. moduleUtils.define( 'test3/test3', [ 'plugin' ], ( Plugin ) => {
  29. return class extends Plugin {};
  30. } );
  31. moduleUtils.define( 'test/creator-async-create', [ 'creator/creator' ], ( Creator ) => {
  32. return class extends Creator {
  33. create() {
  34. return new Promise( ( resolve, reject ) => {
  35. reject( new Error( 'Catch me - create.' ) );
  36. } );
  37. }
  38. destroy() {}
  39. };
  40. } );
  41. moduleUtils.define( 'test/creator-async-destroy', [ 'creator/creator' ], ( Creator ) => {
  42. return class extends Creator {
  43. create() {}
  44. destroy() {
  45. return new Promise( ( resolve, reject ) => {
  46. reject( new Error( 'Catch me - destroy.' ) );
  47. } );
  48. }
  49. };
  50. } );
  51. afterEach( () => {
  52. editor = null; // To make sure we're using the freshly inited editor.
  53. } );
  54. ///////////////////
  55. describe( 'Editor creator', () => {
  56. describe( 'init', () => {
  57. it( 'should instantiate the creator and call create()', () => {
  58. return initEditor( {
  59. creator: 'creator-test1'
  60. } )
  61. .then( () => {
  62. let creator = editor.plugins.get( 'creator-test1' );
  63. expect( creator ).to.be.instanceof( Creator );
  64. // The create method has been called.
  65. sinon.assert.calledOnce( creator.create );
  66. } );
  67. } );
  68. it( 'should throw if creator is not defined', () => {
  69. return initEditor( {} )
  70. .then( () => {
  71. throw new Error( 'This should not be executed.' );
  72. } )
  73. .catch( ( err ) => {
  74. expect( err ).to.be.instanceof( CKEditorError );
  75. expect( err.message ).to.match( /^editor-undefined-creator:/ );
  76. } );
  77. } );
  78. it( 'should use the creator specified in config.creator', () => {
  79. return initEditor( {
  80. creator: 'creator-test-config2',
  81. features: [ 'creator-test-config1', 'creator-test-config2' ],
  82. } )
  83. .then( () => {
  84. let creator1 = editor.plugins.get( 'creator-test-config1' );
  85. let creator2 = editor.plugins.get( 'creator-test-config2' );
  86. sinon.assert.calledOnce( creator2.create );
  87. sinon.assert.notCalled( creator1.create );
  88. } );
  89. } );
  90. it( 'should throw an error if the creator doesn\'t exist', () => {
  91. return initEditor( {
  92. creator: 'bad'
  93. } )
  94. .then( () => {
  95. throw new Error( 'This should not be executed.' );
  96. } )
  97. .catch( ( err ) => {
  98. // It's the Require.JS error.
  99. expect( err ).to.be.an.instanceof( Error );
  100. expect( err.message ).to.match( /^Script error for/ );
  101. } );
  102. } );
  103. it( 'should chain the promise from the creator (enables async creators)', () => {
  104. return initEditor( {
  105. creator: 'test/creator-async-create'
  106. } )
  107. .then( () => {
  108. throw new Error( 'This should not be executed.' );
  109. } )
  110. .catch( ( err ) => {
  111. // Unfortunately fake timers don't work with promises, so throwing in the creator's create()
  112. // seems to be the only way to test that the promise chain isn't broken.
  113. expect( err ).to.have.property( 'message', 'Catch me - create.' );
  114. } );
  115. } );
  116. } );
  117. describe( 'destroy', () => {
  118. it( 'should call "destroy" on the creator', () => {
  119. let creator1;
  120. return initEditor( {
  121. creator: 'creator-test1'
  122. } )
  123. .then( () => {
  124. creator1 = editor.plugins.get( 'creator-test1' );
  125. return editor.destroy();
  126. } )
  127. .then( () => {
  128. sinon.assert.calledOnce( creator1.destroy );
  129. } );
  130. } );
  131. it( 'should chain the promise from the creator (enables async creators)', () => {
  132. return initEditor( {
  133. creator: 'test/creator-async-destroy'
  134. } )
  135. .then( () => {
  136. return editor.destroy();
  137. } )
  138. .then( () => {
  139. throw new Error( 'This should not be executed.' );
  140. } )
  141. .catch( ( err ) => {
  142. // Unfortunately fake timers don't work with promises, so throwing in the creator's destroy()
  143. // seems to be the only way to test that the promise chain isn't broken.
  144. expect( err ).to.have.property( 'message', 'Catch me - destroy.' );
  145. } );
  146. } );
  147. } );
  148. } );