plugincollection.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* globals document */
  6. 'use strict';
  7. var modules = bender.amd.require( 'plugincollection', 'plugin', 'editor', 'log' );
  8. var editor;
  9. var PluginA, PluginB;
  10. var sandbox = sinon.sandbox.create();
  11. afterEach( sandbox.restore.bind( sandbox ) );
  12. before( function() {
  13. var Editor = modules.editor;
  14. var Plugin = modules.plugin;
  15. PluginA = class extends Plugin {};
  16. PluginB = class extends Plugin {};
  17. editor = new Editor( document.body.appendChild( document.createElement( 'div' ) ) );
  18. } );
  19. // Create fake plugins that will be used on tests.
  20. CKEDITOR.define( 'plugin!A', function() {
  21. return PluginA;
  22. } );
  23. CKEDITOR.define( 'plugin!B', function() {
  24. return PluginB;
  25. } );
  26. CKEDITOR.define( 'plugin!C', [ 'plugin', 'plugin!B' ], function( Plugin ) {
  27. return class extends Plugin {};
  28. } );
  29. CKEDITOR.define( 'plugin!D', [ 'plugin', 'plugin!A', 'plugin!C' ], function( Plugin ) {
  30. return class extends Plugin {};
  31. } );
  32. CKEDITOR.define( 'plugin!E', [ 'plugin', 'plugin!F' ], function( Plugin ) {
  33. return class extends Plugin {};
  34. } );
  35. CKEDITOR.define( 'plugin!F', [ 'plugin', 'plugin!E' ], function( Plugin ) {
  36. return class extends Plugin {};
  37. } );
  38. /////////////
  39. describe( 'load', function() {
  40. it( 'should add collection items for loaded plugins', function() {
  41. var PluginCollection = modules.plugincollection;
  42. var plugins = new PluginCollection( editor );
  43. return plugins.load( 'A,B' )
  44. .then( function() {
  45. expect( plugins.length ).to.equal( 2 );
  46. expect( plugins.get( 0 ) ).to.be.an.instanceof( PluginA );
  47. expect( plugins.get( 1 ) ).to.be.an.instanceof( PluginB );
  48. } );
  49. } );
  50. it( 'should load dependency plugins', function() {
  51. var PluginCollection = modules.plugincollection;
  52. var plugins = new PluginCollection( editor );
  53. return plugins.load( 'A,C' )
  54. .then( function() {
  55. expect( plugins.length ).to.equal( 3 );
  56. // The order must have dependencies first.
  57. expect( plugins.get( 0 ).name ).to.equal( 'A' );
  58. expect( plugins.get( 1 ).name ).to.equal( 'B' );
  59. expect( plugins.get( 2 ).name ).to.equal( 'C' );
  60. } );
  61. } );
  62. it( 'should be ok when dependencies are loaded first', function() {
  63. var PluginCollection = modules.plugincollection;
  64. var plugins = new PluginCollection( editor );
  65. return plugins.load( 'A,B,C' )
  66. .then( function() {
  67. expect( plugins.length ).to.equal( 3 );
  68. // The order must have dependencies first.
  69. expect( plugins.get( 0 ).name ).to.equal( 'A' );
  70. expect( plugins.get( 1 ).name ).to.equal( 'B' );
  71. expect( plugins.get( 2 ).name ).to.equal( 'C' );
  72. } );
  73. } );
  74. it( 'should load deep dependency plugins', function() {
  75. var PluginCollection = modules.plugincollection;
  76. var plugins = new PluginCollection( editor );
  77. return plugins.load( 'D' )
  78. .then( function() {
  79. expect( plugins.length ).to.equal( 4 );
  80. // The order must have dependencies first.
  81. expect( plugins.get( 0 ).name ).to.equal( 'A' );
  82. expect( plugins.get( 1 ).name ).to.equal( 'B' );
  83. expect( plugins.get( 2 ).name ).to.equal( 'C' );
  84. expect( plugins.get( 3 ).name ).to.equal( 'D' );
  85. } );
  86. } );
  87. it( 'should handle cross dependency plugins', function() {
  88. var PluginCollection = modules.plugincollection;
  89. var plugins = new PluginCollection( editor );
  90. return plugins.load( 'A,E' )
  91. .then( function() {
  92. expect( plugins.length ).to.equal( 3 );
  93. // The order must have dependencies first.
  94. expect( plugins.get( 0 ).name ).to.equal( 'A' );
  95. expect( plugins.get( 1 ).name ).to.equal( 'F' );
  96. expect( plugins.get( 2 ).name ).to.equal( 'E' );
  97. } );
  98. } );
  99. it( 'should set the `editor` property on loaded plugins', function() {
  100. var PluginCollection = modules.plugincollection;
  101. var plugins = new PluginCollection( editor );
  102. return plugins.load( 'A,B' )
  103. .then( function() {
  104. expect( plugins.get( 0 ).editor ).to.equal( editor );
  105. expect( plugins.get( 1 ).editor ).to.equal( editor );
  106. } );
  107. } );
  108. it( 'should set the `path` property on loaded plugins', function() {
  109. var PluginCollection = modules.plugincollection;
  110. var plugins = new PluginCollection( editor );
  111. return plugins.load( 'A,B' )
  112. .then( function() {
  113. expect( plugins.get( 'A' ).path ).to.equal( CKEDITOR.getPluginPath( 'A' ) );
  114. expect( plugins.get( 'B' ).path ).to.equal( CKEDITOR.getPluginPath( 'B' ) );
  115. } );
  116. } );
  117. it( 'should set the `deps` property on loaded plugins', function() {
  118. var PluginCollection = modules.plugincollection;
  119. var plugins = new PluginCollection( editor );
  120. return plugins.load( 'A,D' )
  121. .then( function() {
  122. expect( plugins.get( 'A' ).deps ).to.deep.equal( [] );
  123. expect( plugins.get( 'B' ).deps ).to.deep.equal( [] );
  124. expect( plugins.get( 'C' ).deps ).to.deep.equal( [ 'B' ] );
  125. expect( plugins.get( 'D' ).deps ).to.deep.equal( [ 'A', 'C' ] );
  126. } );
  127. } );
  128. it( 'should throw an error for invalid plugins', function() {
  129. var PluginCollection = modules.plugincollection;
  130. var log = modules.log;
  131. var logSpy = sandbox.stub( log, 'error' );
  132. var plugins = new PluginCollection( editor );
  133. return plugins.load( 'A,BAD,B' )
  134. // Throw here, so if by any chance plugins.load() was resolved correctly catch() will be stil executed.
  135. .then( function() {
  136. throw new Error( 'Test error: this promise should not be resolved successfully' );
  137. } )
  138. .catch( function( err ) {
  139. expect( err ).to.be.an.instanceof( Error );
  140. // Make sure it's the Require.JS error, not the one thrown above.
  141. expect( err ).to.have.property( 'requireType', 'scripterror' );
  142. sinon.assert.calledOnce( logSpy );
  143. expect( logSpy.args[ 0 ][ 0 ] ).to.match( /^plugincollection-load:/ );
  144. } );
  145. } );
  146. } );
  147. describe( 'add', function() {
  148. it( 'should add plugins to the collection', function() {
  149. var PluginCollection = modules.plugincollection;
  150. var plugins = new PluginCollection( editor );
  151. var pluginA = new PluginA();
  152. var pluginB = new PluginB();
  153. // `add()` requires the `name` property to the defined.
  154. pluginA.name = 'A';
  155. pluginB.name = 'B';
  156. plugins.add( pluginA );
  157. plugins.add( pluginB );
  158. expect( plugins.length ).to.equal( 2 );
  159. expect( plugins.get( 0 ) ).to.be.an.instanceof( PluginA );
  160. expect( plugins.get( 1 ) ).to.be.an.instanceof( PluginB );
  161. } );
  162. it( 'should do nothing if the plugin is already loaded', function() {
  163. var PluginCollection = modules.plugincollection;
  164. var plugins = new PluginCollection( editor );
  165. return plugins.load( 'A,B' )
  166. .then( function() {
  167. // Check length before `add()`.
  168. expect( plugins.length ).to.equal( 2 );
  169. var pluginA = new PluginA();
  170. pluginA.name = 'A';
  171. plugins.add( pluginA );
  172. // Length should not change after `add()`.
  173. expect( plugins.length ).to.equal( 2 );
  174. } );
  175. } );
  176. } );
  177. describe( 'get', function() {
  178. it( 'should get a plugin by name', function() {
  179. var PluginCollection = modules.plugincollection;
  180. var plugins = new PluginCollection( editor );
  181. return plugins.load( 'A,B' )
  182. .then( function() {
  183. expect( plugins.get( 'A' ) ).to.be.an.instanceof( PluginA );
  184. expect( plugins.get( 'B' ) ).to.be.an.instanceof( PluginB );
  185. } );
  186. } );
  187. it( 'should return undefined for non existing plugin', function() {
  188. var PluginCollection = modules.plugincollection;
  189. var plugins = new PluginCollection( editor );
  190. return plugins.load( 'A,B' )
  191. .then( function() {
  192. expect( plugins.get( 'C' ) ).to.be.an( 'undefined' );
  193. } );
  194. } );
  195. } );