8
0

editor.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* bender-tags: editor, browser-only */
  6. 'use strict';
  7. import moduleUtils from '/tests/ckeditor5/_utils/module.js';
  8. import Editor from '/ckeditor5/editor/editor.js';
  9. import Plugin from '/ckeditor5/plugin.js';
  10. import Config from '/ckeditor5/utils/config.js';
  11. import PluginCollection from '/ckeditor5/plugincollection.js';
  12. const pluginClasses = {};
  13. before( () => {
  14. pluginDefinition( 'A/A' );
  15. pluginDefinition( 'B/B' );
  16. pluginDefinition( 'C/C', [ 'B/B' ] );
  17. pluginDefinition( 'D/D', [ 'C/C' ] );
  18. } );
  19. describe( 'Editor', () => {
  20. describe( 'constructor', () => {
  21. it( 'should create a new editor instance', () => {
  22. const editor = new Editor();
  23. expect( editor.config ).to.be.an.instanceof( Config );
  24. expect( editor.commands ).to.be.an.instanceof( Map );
  25. expect( editor.plugins ).to.be.an.instanceof( PluginCollection );
  26. expect( getPlugins( editor ) ).to.be.empty;
  27. } );
  28. } );
  29. describe( 'plugins', () => {
  30. it( 'should be empty on new editor', () => {
  31. const editor = new Editor();
  32. expect( getPlugins( editor ) ).to.be.empty;
  33. } );
  34. } );
  35. describe( 'create', () => {
  36. it( 'should return a promise that resolves properly', () => {
  37. let promise = Editor.create();
  38. expect( promise ).to.be.an.instanceof( Promise );
  39. return promise;
  40. } );
  41. it( 'loads plugins', () => {
  42. // TODO
  43. } );
  44. } );
  45. describe( 'initPlugins', () => {
  46. it( 'should load features', () => {
  47. const editor = new Editor( {
  48. features: [ 'A', 'B' ]
  49. } );
  50. expect( getPlugins( editor ) ).to.be.empty;
  51. return editor.initPlugins().then( () => {
  52. expect( getPlugins( editor ).length ).to.equal( 2 );
  53. expect( editor.plugins.get( 'A' ) ).to.be.an.instanceof( Plugin );
  54. expect( editor.plugins.get( 'B' ) ).to.be.an.instanceof( Plugin );
  55. } );
  56. } );
  57. it( 'should load features passed as a string', () => {
  58. const editor = new Editor( {
  59. features: 'A,B'
  60. } );
  61. expect( getPlugins( editor ) ).to.be.empty;
  62. return editor.initPlugins().then( () => {
  63. expect( getPlugins( editor ).length ).to.equal( 2 );
  64. expect( editor.plugins.get( 'A' ) ).to.be.an.instanceof( Plugin );
  65. expect( editor.plugins.get( 'B' ) ).to.be.an.instanceof( Plugin );
  66. } );
  67. } );
  68. it( 'should initialize plugins in the right order', () => {
  69. const editor = new Editor( {
  70. features: [ 'A', 'D' ]
  71. } );
  72. return editor.initPlugins().then( () => {
  73. sinon.assert.callOrder(
  74. editor.plugins.get( pluginClasses[ 'A/A' ] ).init,
  75. editor.plugins.get( pluginClasses[ 'B/B' ] ).init,
  76. editor.plugins.get( pluginClasses[ 'C/C' ] ).init,
  77. editor.plugins.get( pluginClasses[ 'D/D' ] ).init
  78. );
  79. } );
  80. } );
  81. it( 'should initialize plugins in the right order, waiting for asynchronous ones', () => {
  82. class PluginAsync extends Plugin {}
  83. const asyncSpy = sinon.spy().named( 'async-call-spy' );
  84. // Synchronous plugin that depends on an asynchronous one.
  85. pluginDefinition( 'sync/sync', [ 'async/async' ] );
  86. moduleUtils.define( 'async/async', () => {
  87. PluginAsync.prototype.init = sinon.spy( () => {
  88. return new Promise( ( resolve ) => {
  89. setTimeout( () => {
  90. asyncSpy();
  91. resolve();
  92. }, 0 );
  93. } );
  94. } );
  95. return PluginAsync;
  96. } );
  97. const editor = new Editor( {
  98. features: [ 'A', 'sync' ]
  99. } );
  100. return editor.initPlugins().then( () => {
  101. sinon.assert.callOrder(
  102. editor.plugins.get( pluginClasses[ 'A/A' ] ).init,
  103. editor.plugins.get( PluginAsync ).init,
  104. // This one is called with delay by the async init.
  105. asyncSpy,
  106. editor.plugins.get( pluginClasses[ 'sync/sync' ] ).init
  107. );
  108. } );
  109. } );
  110. } );
  111. } );
  112. // @param {String} name Name of the plugin.
  113. // @param {String[]} deps Dependencies of the plugin (only other plugins).
  114. function pluginDefinition( name, deps ) {
  115. moduleUtils.define( name, deps || [], function() {
  116. class NewPlugin extends Plugin {}
  117. NewPlugin.prototype.init = sinon.spy().named( name );
  118. NewPlugin.requires = Array.from( arguments );
  119. pluginClasses[ name ] = NewPlugin;
  120. return NewPlugin;
  121. } );
  122. }
  123. // Returns an array of loaded plugins.
  124. function getPlugins( editor ) {
  125. const plugins = [];
  126. for ( let entry of editor.plugins ) {
  127. // Keep only plugins kept under their classes.
  128. if ( typeof entry[ 0 ] == 'function' ) {
  129. plugins.push( entry[ 1 ] );
  130. }
  131. }
  132. return plugins;
  133. }