inlineeditoruiview.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /**
  2. * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. import InlineEditorUIView from '../src/inlineeditoruiview';
  6. import ToolbarView from '@ckeditor/ckeditor5-ui/src/toolbar/toolbarview';
  7. import BalloonPanelView from '@ckeditor/ckeditor5-ui/src/panel/balloon/balloonpanelview';
  8. import InlineEditableUIView from '@ckeditor/ckeditor5-ui/src/editableui/inline/inlineeditableuiview';
  9. import Locale from '@ckeditor/ckeditor5-utils/src/locale';
  10. import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
  11. import log from '@ckeditor/ckeditor5-utils/src/log';
  12. describe( 'InlineEditorUIView', () => {
  13. let locale, view;
  14. testUtils.createSinonSandbox();
  15. beforeEach( () => {
  16. locale = new Locale( 'en' );
  17. view = new InlineEditorUIView( locale );
  18. } );
  19. describe( 'constructor()', () => {
  20. describe( '#toolbar', () => {
  21. it( 'is created', () => {
  22. expect( view.toolbar ).to.be.instanceof( ToolbarView );
  23. } );
  24. it( 'is given a locale object', () => {
  25. expect( view.toolbar.locale ).to.equal( locale );
  26. } );
  27. it( 'is not rendered', () => {
  28. expect( view.toolbar.isRendered ).to.be.false;
  29. } );
  30. } );
  31. describe( '#panel', () => {
  32. it( 'is created', () => {
  33. expect( view.panel ).to.be.instanceof( BalloonPanelView );
  34. } );
  35. it( 'is given a locale object', () => {
  36. expect( view.panel.locale ).to.equal( locale );
  37. } );
  38. it( 'gets view.panel#withArrow set', () => {
  39. expect( view.panel.withArrow ).to.be.false;
  40. } );
  41. it( 'is not rendered', () => {
  42. expect( view.panel.isRendered ).to.be.false;
  43. } );
  44. } );
  45. describe( '#editable', () => {
  46. it( 'is created', () => {
  47. expect( view.editable ).to.be.instanceof( InlineEditableUIView );
  48. } );
  49. it( 'is given a locale object', () => {
  50. expect( view.editable.locale ).to.equal( locale );
  51. } );
  52. it( 'is not rendered', () => {
  53. expect( view.editable.isRendered ).to.be.false;
  54. } );
  55. } );
  56. } );
  57. describe( 'render()', () => {
  58. beforeEach( () => {
  59. view.render();
  60. } );
  61. afterEach( () => {
  62. view.destroy();
  63. } );
  64. describe( '#toolbar', () => {
  65. it( 'is given the right CSS classes', () => {
  66. expect( view.toolbar.element.classList.contains( 'ck-toolbar_floating' ) ).to.be.true;
  67. } );
  68. it( 'sets the default value of the #viewportTopOffset attribute', () => {
  69. expect( view.viewportTopOffset ).to.equal( 0 );
  70. } );
  71. } );
  72. describe( '#panel', () => {
  73. it( 'is given the right CSS class', () => {
  74. expect( view.panel.element.classList.contains( 'ck-toolbar-container' ) ).to.be.true;
  75. } );
  76. it( 'is put into the #body collection', () => {
  77. expect( view.body.get( 0 ) ).to.equal( view.panel );
  78. } );
  79. } );
  80. describe( '#editable', () => {
  81. it( 'is registered as a child', () => {
  82. const spy = sinon.spy( view.editable, 'destroy' );
  83. view.destroy();
  84. sinon.assert.calledOnce( spy );
  85. } );
  86. } );
  87. } );
  88. describe( 'init()', () => {
  89. it( 'appends #toolbar to panel#content', () => {
  90. const view = new InlineEditorUIView( locale );
  91. expect( view.panel.content ).to.have.length( 0 );
  92. view.render();
  93. expect( view.panel.content.get( 0 ) ).to.equal( view.toolbar );
  94. view.destroy();
  95. } );
  96. } );
  97. describe( 'editableElement', () => {
  98. it( 'returns editable\'s view element', () => {
  99. testUtils.sinon.stub( log, 'warn' ).callsFake( () => {} );
  100. view.render();
  101. expect( view.editableElement.getAttribute( 'contentEditable' ) ).to.equal( 'true' );
  102. view.destroy();
  103. } );
  104. } );
  105. describe( 'panelPositions', () => {
  106. it( 'returns the positions in the right order', () => {
  107. const positions = view.panelPositions;
  108. const editableRect = {
  109. top: 100,
  110. bottom: 200,
  111. left: 100,
  112. right: 100,
  113. width: 100,
  114. height: 100
  115. };
  116. const panelRect = {
  117. width: 50,
  118. height: 50
  119. };
  120. expect( positions ).to.have.length( 2 );
  121. expect( positions[ 0 ]( editableRect, panelRect ).name ).to.equal( 'toolbar_west' );
  122. expect( positions[ 1 ]( editableRect, panelRect ).name ).to.equal( 'toolbar_east' );
  123. } );
  124. describe( 'west', () => {
  125. testTopPositions( 0, 100 );
  126. } );
  127. describe( 'east', () => {
  128. testTopPositions( 1, 150 );
  129. } );
  130. function testTopPositions( positionIndex, expectedLeft ) {
  131. it( 'positions the panel above editable when there\'s enough space', () => {
  132. const position = view.panelPositions[ positionIndex ];
  133. const editableRect = {
  134. top: 101, // !
  135. bottom: 200,
  136. left: 100,
  137. right: 100,
  138. width: 100,
  139. height: 100
  140. };
  141. const panelRect = {
  142. width: 50,
  143. height: 100 // !
  144. };
  145. const { top, left } = position( editableRect, panelRect );
  146. expect( top ).to.equal( 1 );
  147. expect( left ).to.equal( expectedLeft );
  148. } );
  149. it( 'positions the panel over the editable when there\'s not enough space above (1)', () => {
  150. const position = view.panelPositions[ positionIndex ];
  151. const editableRect = {
  152. top: 100, // !
  153. bottom: 300,
  154. left: 100,
  155. right: 100,
  156. width: 100,
  157. height: 200
  158. };
  159. const panelRect = {
  160. width: 50,
  161. height: 100 // !
  162. };
  163. const { top, left } = position( editableRect, panelRect );
  164. expect( top ).to.equal( 0 );
  165. expect( left ).to.equal( expectedLeft );
  166. } );
  167. it( 'positions the panel over the editable when there\'s not enough space above (2)', () => {
  168. const position = view.panelPositions[ positionIndex ];
  169. const editableRect = {
  170. top: 99, // !
  171. bottom: 399,
  172. left: 100,
  173. right: 100,
  174. width: 100,
  175. height: 200
  176. };
  177. const panelRect = {
  178. width: 50,
  179. height: 100 // !
  180. };
  181. const { top, left } = position( editableRect, panelRect );
  182. expect( top ).to.equal( 0 );
  183. expect( left ).to.equal( expectedLeft );
  184. } );
  185. it( 'positions the panel over the editable when there\'s not enough space above (3)', () => {
  186. const position = view.panelPositions[ positionIndex ];
  187. const editableRect = {
  188. top: 51, // !
  189. bottom: 399,
  190. left: 100,
  191. right: 100,
  192. width: 100,
  193. height: 200
  194. };
  195. const panelRect = {
  196. width: 50,
  197. height: 100 // !
  198. };
  199. const { top, left } = position( editableRect, panelRect );
  200. expect( top ).to.equal( 0 );
  201. expect( left ).to.equal( expectedLeft );
  202. } );
  203. it( 'positions the panel below the editable when there\'s not enough space above/over', () => {
  204. const position = view.panelPositions[ positionIndex ];
  205. const editableRect = {
  206. top: 50,
  207. bottom: 150, // !
  208. left: 100,
  209. right: 100,
  210. width: 100,
  211. height: 100
  212. };
  213. const panelRect = {
  214. width: 50,
  215. height: 100 // !
  216. };
  217. const { top, left } = position( editableRect, panelRect );
  218. expect( top ).to.equal( 150 );
  219. expect( left ).to.equal( expectedLeft );
  220. } );
  221. describe( 'view#viewportTopOffset', () => {
  222. it( 'sticks the panel to the offset when there\'s not enough space above', () => {
  223. view.viewportTopOffset = 50;
  224. const position = view.panelPositions[ positionIndex ];
  225. const editableRect = {
  226. top: 0, // !
  227. bottom: 200,
  228. left: 100,
  229. right: 100,
  230. width: 100,
  231. height: 200
  232. };
  233. const panelRect = {
  234. width: 50,
  235. height: 50
  236. };
  237. const { top, left } = position( editableRect, panelRect );
  238. expect( top ).to.equal( 50 );
  239. expect( left ).to.equal( expectedLeft );
  240. } );
  241. it( 'positions the panel below the editable when there\'s not enough space above/over', () => {
  242. view.viewportTopOffset = 50;
  243. const position = view.panelPositions[ positionIndex ];
  244. const editableRect = {
  245. top: 100,
  246. bottom: 150,
  247. left: 100,
  248. right: 100,
  249. width: 100,
  250. height: 50
  251. };
  252. const panelRect = {
  253. width: 50,
  254. height: 80
  255. };
  256. const { top, left } = position( editableRect, panelRect );
  257. expect( top ).to.equal( 150 );
  258. expect( left ).to.equal( expectedLeft );
  259. } );
  260. } );
  261. }
  262. } );
  263. } );