tablenavigation.js 80 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271
  1. import { getCode } from '@ckeditor/ckeditor5-utils/src/keyboard';
  2. import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
  3. import { modelTable } from './_utils/utils';
  4. import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
  5. import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
  6. import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
  7. import ImageEditing from '@ckeditor/ckeditor5-image/src/image/imageediting';
  8. import MediaEmbedEditing from '@ckeditor/ckeditor5-media-embed/src/mediaembedediting';
  9. import TableNavigation from '../src/tablenavigation';
  10. import Table from '../src/table';
  11. import TableEditing from '../src/tableediting';
  12. import TableSelection from '../src/tableselection';
  13. import ImageCaptionEditing from '@ckeditor/ckeditor5-image/src/imagecaption/imagecaptionediting';
  14. import HorizontalLineEditing from '@ckeditor/ckeditor5-horizontal-line/src/horizontallineediting';
  15. import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
  16. import Image from '@ckeditor/ckeditor5-image/src/image';
  17. import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';
  18. import HorizontalLine from '@ckeditor/ckeditor5-horizontal-line/src/horizontalline';
  19. import global from '@ckeditor/ckeditor5-utils/src/dom/global';
  20. describe( 'TableNavigation', () => {
  21. let editor, model, modelRoot, tableSelection;
  22. const imageUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAUCAQAAADRyVAeAAAAKklEQVR42u3PAQ0AAAwCI' +
  23. 'O0f+u/hoAHNZUJFRERERERERERERERERLYiD9N4FAFj2iK6AAAAAElFTkSuQmCC';
  24. beforeEach( () => {
  25. return VirtualTestEditor
  26. .create( {
  27. plugins: [ TableEditing, TableNavigation, TableSelection, Paragraph, ImageEditing, ImageCaptionEditing, MediaEmbedEditing,
  28. HorizontalLineEditing ]
  29. } )
  30. .then( newEditor => {
  31. editor = newEditor;
  32. model = editor.model;
  33. modelRoot = model.document.getRoot();
  34. tableSelection = editor.plugins.get( TableSelection );
  35. } );
  36. } );
  37. afterEach( () => {
  38. editor.destroy();
  39. } );
  40. it( 'should have pluginName', () => {
  41. expect( TableNavigation.pluginName ).to.equal( 'TableNavigation' );
  42. } );
  43. describe( 'Tab key handling', () => {
  44. let domEvtDataStub;
  45. beforeEach( () => {
  46. domEvtDataStub = {
  47. keyCode: getCode( 'Tab' ),
  48. preventDefault: sinon.spy(),
  49. stopPropagation: sinon.spy()
  50. };
  51. } );
  52. it( 'should do nothing if not tab pressed', () => {
  53. setModelData( model, modelTable( [
  54. [ '11', '12[]' ]
  55. ] ) );
  56. domEvtDataStub.keyCode = getCode( 'a' );
  57. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  58. sinon.assert.notCalled( domEvtDataStub.preventDefault );
  59. sinon.assert.notCalled( domEvtDataStub.stopPropagation );
  60. assertEqualMarkup( getModelData( model ), modelTable( [
  61. [ '11', '12[]' ]
  62. ] ) );
  63. } );
  64. it( 'should do nothing if Ctrl+Tab is pressed', () => {
  65. setModelData( model, modelTable( [
  66. [ '11', '12[]' ]
  67. ] ) );
  68. domEvtDataStub.ctrlKey = true;
  69. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  70. sinon.assert.notCalled( domEvtDataStub.preventDefault );
  71. sinon.assert.notCalled( domEvtDataStub.stopPropagation );
  72. assertEqualMarkup( getModelData( model ), modelTable( [
  73. [ '11', '12[]' ]
  74. ] ) );
  75. } );
  76. describe( 'on TAB', () => {
  77. it( 'should do nothing if selection is not in a table', () => {
  78. setModelData( model, '<paragraph>[]</paragraph>' + modelTable( [ [ '11', '12' ] ] ) );
  79. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  80. sinon.assert.notCalled( domEvtDataStub.preventDefault );
  81. sinon.assert.notCalled( domEvtDataStub.stopPropagation );
  82. assertEqualMarkup( getModelData( model ), '<paragraph>[]</paragraph>' + modelTable( [
  83. [ '11', '12' ]
  84. ] ) );
  85. } );
  86. it( 'should move to next cell', () => {
  87. setModelData( model, modelTable( [
  88. [ '11[]', '12' ]
  89. ] ) );
  90. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  91. sinon.assert.calledOnce( domEvtDataStub.preventDefault );
  92. sinon.assert.calledOnce( domEvtDataStub.stopPropagation );
  93. assertEqualMarkup( getModelData( model ), modelTable( [
  94. [ '11', '[12]' ]
  95. ] ) );
  96. } );
  97. it( 'should create another row and move to first cell in new row', () => {
  98. setModelData( model, modelTable( [
  99. [ '11', '[12]' ]
  100. ] ) );
  101. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  102. assertEqualMarkup( getModelData( model ), modelTable( [
  103. [ '11', '12' ],
  104. [ '[]', '' ]
  105. ] ) );
  106. } );
  107. it( 'should not create another row and not move the caret if insertTableRowBelow command is disabled', () => {
  108. setModelData( model, modelTable( [
  109. [ '11', '12[]' ]
  110. ] ) );
  111. const insertTableRowBelowCommand = editor.commands.get( 'insertTableRowBelow' );
  112. insertTableRowBelowCommand.forceDisabled( 'test' );
  113. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  114. assertEqualMarkup( getModelData( model ), modelTable( [
  115. [ '11', '12[]' ]
  116. ] ) );
  117. } );
  118. it( 'should move to the first cell of next row if on end of a row', () => {
  119. setModelData( model, modelTable( [
  120. [ '11', '12[]' ],
  121. [ '21', '22' ]
  122. ] ) );
  123. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  124. assertEqualMarkup( getModelData( model ), modelTable( [
  125. [ '11', '12' ],
  126. [ '[21]', '22' ]
  127. ] ) );
  128. } );
  129. it( 'should move to the next table cell if part of block content is selected', () => {
  130. setModelData( model, modelTable( [
  131. [ '11', '<paragraph>12</paragraph><paragraph>[foo]</paragraph><paragraph>bar</paragraph>', '13' ]
  132. ] ) );
  133. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  134. assertEqualMarkup( getModelData( model ), modelTable( [
  135. [
  136. '11',
  137. '<paragraph>12</paragraph><paragraph>foo</paragraph><paragraph>bar</paragraph>',
  138. '[13]'
  139. ]
  140. ] ) );
  141. } );
  142. it( 'should move to next cell with an image', () => {
  143. setModelData( model, modelTable( [
  144. [ '11[]', '<paragraph>foo</paragraph><image><caption></caption></image>' ]
  145. ] ) );
  146. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  147. sinon.assert.calledOnce( domEvtDataStub.preventDefault );
  148. sinon.assert.calledOnce( domEvtDataStub.stopPropagation );
  149. assertEqualMarkup( getModelData( model ), modelTable( [
  150. [ '11', '<paragraph>[foo</paragraph><image><caption></caption></image>]' ]
  151. ] ) );
  152. } );
  153. it( 'should move to next cell with an blockQuote', () => {
  154. model.schema.register( 'blockQuote', {
  155. allowWhere: '$block',
  156. allowContentOf: '$root'
  157. } );
  158. editor.conversion.elementToElement( { model: 'blockQuote', view: 'blockquote' } );
  159. setModelData( model, modelTable( [
  160. [ '11[]', '<blockQuote><paragraph>foo</paragraph></blockQuote>' ]
  161. ] ) );
  162. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  163. sinon.assert.calledOnce( domEvtDataStub.preventDefault );
  164. sinon.assert.calledOnce( domEvtDataStub.stopPropagation );
  165. assertEqualMarkup( getModelData( model ), modelTable( [
  166. [ '11', '<blockQuote><paragraph>[foo]</paragraph></blockQuote>' ]
  167. ] ) );
  168. } );
  169. it( 'should listen with lower priority then its children', () => {
  170. // Cancel TAB event.
  171. editor.keystrokes.set( 'Tab', ( data, cancel ) => cancel() );
  172. setModelData( model, modelTable( [
  173. [ '11[]', '12' ]
  174. ] ) );
  175. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  176. sinon.assert.calledOnce( domEvtDataStub.preventDefault );
  177. sinon.assert.calledOnce( domEvtDataStub.stopPropagation );
  178. assertEqualMarkup( getModelData( model ), modelTable( [
  179. [ '11[]', '12' ]
  180. ] ) );
  181. } );
  182. describe( 'on table widget selected', () => {
  183. beforeEach( () => {
  184. editor.model.schema.register( 'block', {
  185. allowWhere: '$block',
  186. allowContentOf: '$block',
  187. isObject: true
  188. } );
  189. editor.conversion.elementToElement( { model: 'block', view: 'block' } );
  190. } );
  191. it( 'should move caret to the first table cell on TAB', () => {
  192. const spy = sinon.spy();
  193. editor.keystrokes.set( 'Tab', spy, { priority: 'lowest' } );
  194. setModelData( model, '[' + modelTable( [
  195. [ '11', '12' ]
  196. ] ) + ']' );
  197. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  198. sinon.assert.calledOnce( domEvtDataStub.preventDefault );
  199. sinon.assert.calledOnce( domEvtDataStub.stopPropagation );
  200. assertEqualMarkup( getModelData( model ), modelTable( [
  201. [ '[11]', '12' ]
  202. ] ) );
  203. // Should cancel event - so no other tab handler is called.
  204. sinon.assert.notCalled( spy );
  205. } );
  206. it( 'shouldn\'t do anything on other blocks', () => {
  207. const spy = sinon.spy();
  208. editor.editing.view.document.on( 'keydown', spy );
  209. setModelData( model, '[<block>foo</block>]' );
  210. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  211. sinon.assert.notCalled( domEvtDataStub.preventDefault );
  212. sinon.assert.notCalled( domEvtDataStub.stopPropagation );
  213. assertEqualMarkup( getModelData( model ), '[<block>foo</block>]' );
  214. // Should not cancel event.
  215. sinon.assert.calledOnce( spy );
  216. } );
  217. } );
  218. } );
  219. describe( 'on SHIFT+TAB', () => {
  220. beforeEach( () => {
  221. domEvtDataStub.shiftKey = true;
  222. } );
  223. it( 'should do nothing if selection is not in a table', () => {
  224. setModelData( model, '<paragraph>[]</paragraph>' + modelTable( [
  225. [ '11', '12' ]
  226. ] ) );
  227. domEvtDataStub.keyCode = getCode( 'Tab' );
  228. domEvtDataStub.shiftKey = true;
  229. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  230. sinon.assert.notCalled( domEvtDataStub.preventDefault );
  231. sinon.assert.notCalled( domEvtDataStub.stopPropagation );
  232. assertEqualMarkup( getModelData( model ), '<paragraph>[]</paragraph>' + modelTable( [
  233. [ '11', '12' ]
  234. ] ) );
  235. } );
  236. it( 'should move to previous cell', () => {
  237. setModelData( model, modelTable( [
  238. [ '11', '12[]' ]
  239. ] ) );
  240. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  241. sinon.assert.calledOnce( domEvtDataStub.preventDefault );
  242. sinon.assert.calledOnce( domEvtDataStub.stopPropagation );
  243. assertEqualMarkup( getModelData( model ), modelTable( [
  244. [ '[11]', '12' ]
  245. ] ) );
  246. } );
  247. it( 'should not move if caret is in first table cell', () => {
  248. setModelData( model, '<paragraph>foo</paragraph>' + modelTable( [
  249. [ '[]11', '12' ]
  250. ] ) );
  251. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  252. assertEqualMarkup( getModelData( model ),
  253. '<paragraph>foo</paragraph>' + modelTable( [ [ '[]11', '12' ] ] )
  254. );
  255. } );
  256. it( 'should move to the last cell of previous row if on beginning of a row', () => {
  257. setModelData( model, modelTable( [
  258. [ '11', '12' ],
  259. [ '[]21', '22' ]
  260. ] ) );
  261. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  262. assertEqualMarkup( getModelData( model ), modelTable( [
  263. [ '11', '[12]' ],
  264. [ '21', '22' ]
  265. ] ) );
  266. } );
  267. it( 'should move to the previous table cell if part of block content is selected', () => {
  268. setModelData( model, modelTable( [
  269. [ '11', '<paragraph>12</paragraph><paragraph>[foo]</paragraph><paragraph>bar</paragraph>', '13' ]
  270. ] ) );
  271. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  272. assertEqualMarkup( getModelData( model ), modelTable( [
  273. [
  274. '[11]',
  275. '<paragraph>12</paragraph><paragraph>foo</paragraph><paragraph>bar</paragraph>',
  276. '13'
  277. ]
  278. ] ) );
  279. } );
  280. it( 'should move to previous cell with an image', () => {
  281. setModelData( model, modelTable( [
  282. [ '<paragraph>foo</paragraph><image><caption></caption></image>', 'bar[]' ]
  283. ] ) );
  284. editor.editing.view.document.fire( 'keydown', domEvtDataStub );
  285. sinon.assert.calledOnce( domEvtDataStub.preventDefault );
  286. sinon.assert.calledOnce( domEvtDataStub.stopPropagation );
  287. assertEqualMarkup( getModelData( model ), modelTable( [
  288. [ '<paragraph>[foo</paragraph><image><caption></caption></image>]', 'bar' ]
  289. ] ) );
  290. } );
  291. } );
  292. } );
  293. describe( 'Arrow keys handling', () => {
  294. let leftArrowDomEvtDataStub, rightArrowDomEvtDataStub, upArrowDomEvtDataStub, downArrowDomEvtDataStub;
  295. beforeEach( () => {
  296. leftArrowDomEvtDataStub = {
  297. keyCode: getCode( 'ArrowLeft' ),
  298. preventDefault: sinon.spy(),
  299. stopPropagation: sinon.spy(),
  300. domTarget: global.document.body
  301. };
  302. rightArrowDomEvtDataStub = {
  303. keyCode: getCode( 'ArrowRight' ),
  304. preventDefault: sinon.spy(),
  305. stopPropagation: sinon.spy(),
  306. domTarget: global.document.body
  307. };
  308. upArrowDomEvtDataStub = {
  309. keyCode: getCode( 'ArrowUp' ),
  310. preventDefault: sinon.spy(),
  311. stopPropagation: sinon.spy(),
  312. domTarget: global.document.body
  313. };
  314. downArrowDomEvtDataStub = {
  315. keyCode: getCode( 'ArrowDown' ),
  316. preventDefault: sinon.spy(),
  317. stopPropagation: sinon.spy(),
  318. domTarget: global.document.body
  319. };
  320. } );
  321. it( 'should do nothing if not arrow key pressed', () => {
  322. setModelData( model, modelTable( [
  323. [ '00', '01[]' ]
  324. ] ) );
  325. leftArrowDomEvtDataStub.keyCode = getCode( 'a' );
  326. editor.editing.view.document.fire( 'keydown', leftArrowDomEvtDataStub );
  327. sinon.assert.notCalled( leftArrowDomEvtDataStub.preventDefault );
  328. sinon.assert.notCalled( leftArrowDomEvtDataStub.stopPropagation );
  329. assertEqualMarkup( getModelData( model ), modelTable( [
  330. [ '00', '01[]' ]
  331. ] ) );
  332. } );
  333. it( 'should do nothing if selection is not in a table', () => {
  334. const modelData = '<paragraph>[]foobar</paragraph>' + modelTable( [ [ '00', '01' ] ] );
  335. setModelData( model, modelData );
  336. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  337. sinon.assert.notCalled( upArrowDomEvtDataStub.preventDefault );
  338. sinon.assert.notCalled( upArrowDomEvtDataStub.stopPropagation );
  339. assertEqualMarkup( getModelData( model ), modelData );
  340. } );
  341. describe( '#_navigateFromCellInDirection (finding proper cell to move selection to)', () => {
  342. let tableNavigation;
  343. beforeEach( () => {
  344. tableNavigation = editor.plugins.get( TableNavigation );
  345. } );
  346. describe( 'with no col/row-spanned cells', () => {
  347. beforeEach( () => {
  348. setModelData( model, '<paragraph>foo</paragraph>' + modelTable( [
  349. [ '00', '01', '02' ],
  350. [ '10', '11', '12' ],
  351. [ '20', '21', '22' ]
  352. ] ) + '<paragraph>bar</paragraph>' );
  353. } );
  354. describe( 'from the first table cell', () => {
  355. let tableCell;
  356. beforeEach( () => {
  357. tableCell = modelRoot.getNodeByPath( [ 1, 0, 0 ] );
  358. } );
  359. it( 'should navigate to the start position of the cell on the right when direction is "right"', () => {
  360. tableNavigation._navigateFromCellInDirection( tableCell, 'right' );
  361. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>' + modelTable( [
  362. [ '00', '[]01', '02' ],
  363. [ '10', '11', '12' ],
  364. [ '20', '21', '22' ]
  365. ] ) + '<paragraph>bar</paragraph>' );
  366. } );
  367. it( 'should navigate to the start position the cell below when direction is "down"', () => {
  368. tableNavigation._navigateFromCellInDirection( tableCell, 'down' );
  369. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>' + modelTable( [
  370. [ '00', '01', '02' ],
  371. [ '[]10', '11', '12' ],
  372. [ '20', '21', '22' ]
  373. ] ) + '<paragraph>bar</paragraph>' );
  374. } );
  375. it( 'should select a whole table when direction is "up"', () => {
  376. tableNavigation._navigateFromCellInDirection( tableCell, 'up' );
  377. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>[' + modelTable( [
  378. [ '00', '01', '02' ],
  379. [ '10', '11', '12' ],
  380. [ '20', '21', '22' ]
  381. ] ) + ']<paragraph>bar</paragraph>' );
  382. } );
  383. it( 'should select a whole table when direction is "left"', () => {
  384. tableNavigation._navigateFromCellInDirection( tableCell, 'left' );
  385. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>[' + modelTable( [
  386. [ '00', '01', '02' ],
  387. [ '10', '11', '12' ],
  388. [ '20', '21', '22' ]
  389. ] ) + ']<paragraph>bar</paragraph>' );
  390. } );
  391. } );
  392. describe( 'from the last table cell', () => {
  393. let tableCell;
  394. beforeEach( () => {
  395. tableCell = modelRoot.getNodeByPath( [ 1, 2, 2 ] );
  396. } );
  397. it( 'should navigate to the end position of the cell on the left when direction is "left"', () => {
  398. tableNavigation._navigateFromCellInDirection( tableCell, 'left' );
  399. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>' + modelTable( [
  400. [ '00', '01', '02' ],
  401. [ '10', '11', '12' ],
  402. [ '20', '21[]', '22' ]
  403. ] ) + '<paragraph>bar</paragraph>' );
  404. } );
  405. it( 'should navigate to the end position of the cell above when direction is "up"', () => {
  406. tableNavigation._navigateFromCellInDirection( tableCell, 'up' );
  407. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>' + modelTable( [
  408. [ '00', '01', '02' ],
  409. [ '10', '11', '12[]' ],
  410. [ '20', '21', '22' ]
  411. ] ) + '<paragraph>bar</paragraph>' );
  412. } );
  413. it( 'should select a whole table when direction is "down"', () => {
  414. tableNavigation._navigateFromCellInDirection( tableCell, 'down' );
  415. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>[' + modelTable( [
  416. [ '00', '01', '02' ],
  417. [ '10', '11', '12' ],
  418. [ '20', '21', '22' ]
  419. ] ) + ']<paragraph>bar</paragraph>' );
  420. } );
  421. it( 'should select a whole table when direction is "right"', () => {
  422. tableNavigation._navigateFromCellInDirection( tableCell, 'right' );
  423. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>[' + modelTable( [
  424. [ '00', '01', '02' ],
  425. [ '10', '11', '12' ],
  426. [ '20', '21', '22' ]
  427. ] ) + ']<paragraph>bar</paragraph>' );
  428. } );
  429. } );
  430. describe( 'from a cell in the first column (but not first row)', () => {
  431. let tableCell;
  432. beforeEach( () => {
  433. tableCell = modelRoot.getNodeByPath( [ 1, 1, 0 ] );
  434. } );
  435. it( 'should navigate to start position of the cell on the right when direction is "right"', () => {
  436. tableNavigation._navigateFromCellInDirection( tableCell, 'right' );
  437. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>' + modelTable( [
  438. [ '00', '01', '02' ],
  439. [ '10', '[]11', '12' ],
  440. [ '20', '21', '22' ]
  441. ] ) + '<paragraph>bar</paragraph>' );
  442. } );
  443. it( 'should navigate to the end position of the cell above when direction is "up"', () => {
  444. tableNavigation._navigateFromCellInDirection( tableCell, 'up' );
  445. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>' + modelTable( [
  446. [ '00[]', '01', '02' ],
  447. [ '10', '11', '12' ],
  448. [ '20', '21', '22' ]
  449. ] ) + '<paragraph>bar</paragraph>' );
  450. } );
  451. it( 'should navigate to the start position of the cell below when direction is "down"', () => {
  452. tableNavigation._navigateFromCellInDirection( tableCell, 'down' );
  453. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>' + modelTable( [
  454. [ '00', '01', '02' ],
  455. [ '10', '11', '12' ],
  456. [ '[]20', '21', '22' ]
  457. ] ) + '<paragraph>bar</paragraph>' );
  458. } );
  459. it( 'should navigate to the end position of the last cell in the previous row when direction is "left"', () => {
  460. tableNavigation._navigateFromCellInDirection( tableCell, 'left' );
  461. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>' + modelTable( [
  462. [ '00', '01', '02[]' ],
  463. [ '10', '11', '12' ],
  464. [ '20', '21', '22' ]
  465. ] ) + '<paragraph>bar</paragraph>' );
  466. } );
  467. } );
  468. describe( 'from a cell in the last column (but not last row)', () => {
  469. let tableCell;
  470. beforeEach( () => {
  471. tableCell = modelRoot.getNodeByPath( [ 1, 1, 2 ] );
  472. } );
  473. it( 'should navigate to the end position of the cell on the left when direction is "left"', () => {
  474. tableNavigation._navigateFromCellInDirection( tableCell, 'left' );
  475. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>' + modelTable( [
  476. [ '00', '01', '02' ],
  477. [ '10', '11[]', '12' ],
  478. [ '20', '21', '22' ]
  479. ] ) + '<paragraph>bar</paragraph>' );
  480. } );
  481. it( 'should navigate to the end position the cell above when direction is "up"', () => {
  482. tableNavigation._navigateFromCellInDirection( tableCell, 'up' );
  483. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>' + modelTable( [
  484. [ '00', '01', '02[]' ],
  485. [ '10', '11', '12' ],
  486. [ '20', '21', '22' ]
  487. ] ) + '<paragraph>bar</paragraph>' );
  488. } );
  489. it( 'should navigate to the start position of the cell below when direction is "down"', () => {
  490. tableNavigation._navigateFromCellInDirection( tableCell, 'down' );
  491. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>' + modelTable( [
  492. [ '00', '01', '02' ],
  493. [ '10', '11', '12' ],
  494. [ '20', '21', '[]22' ]
  495. ] ) + '<paragraph>bar</paragraph>' );
  496. } );
  497. it( 'should navigate to the start position of the first cell in the next row when direction is "right"', () => {
  498. tableNavigation._navigateFromCellInDirection( tableCell, 'right' );
  499. assertEqualMarkup( getModelData( model ), '<paragraph>foo</paragraph>' + modelTable( [
  500. [ '00', '01', '02' ],
  501. [ '10', '11', '12' ],
  502. [ '[]20', '21', '22' ]
  503. ] ) + '<paragraph>bar</paragraph>' );
  504. } );
  505. } );
  506. } );
  507. describe( 'with col/row-spanned cells', () => {
  508. beforeEach( () => {
  509. // +----+----+----+----+----+
  510. // | 00 | 01 | 02 | 03 | 04 |
  511. // +----+----+----+----+----+
  512. // | 10 | 11 | 13 | 14 |
  513. // +----+ + +----+
  514. // | 20 | | | 24 |
  515. // +----+----+----+----+----+
  516. // | 30 | 31 | 33 | 34 |
  517. // +----+----+----+----+----+
  518. // | 40 | 41 | 42 | 43 | 44 |
  519. // +----+----+----+----+----+
  520. setModelData( model, modelTable( [
  521. [ '00', '01', '02', '03', '04' ],
  522. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  523. [ '20', '24' ],
  524. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  525. [ '40', '41', '42', '43', '44' ]
  526. ] ) );
  527. } );
  528. describe( 'when navigating to the right', () => {
  529. it( 'should navigate to the row-col-spanned cell when approaching from the upper spanned row', () => {
  530. const tableCell = modelRoot.getNodeByPath( [ 0, 1, 0 ] );
  531. tableNavigation._navigateFromCellInDirection( tableCell, 'right' );
  532. assertEqualMarkup( getModelData( model ), modelTable( [
  533. [ '00', '01', '02', '03', '04' ],
  534. [ '10', { contents: '[]11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  535. [ '20', '24' ],
  536. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  537. [ '40', '41', '42', '43', '44' ]
  538. ] ) );
  539. } );
  540. it( 'should navigate to the row-col-spanned cell when approaching from the lower spanned row', () => {
  541. const tableCell = modelRoot.getNodeByPath( [ 0, 2, 0 ] );
  542. tableNavigation._navigateFromCellInDirection( tableCell, 'right' );
  543. assertEqualMarkup( getModelData( model ), modelTable( [
  544. [ '00', '01', '02', '03', '04' ],
  545. [ '10', { contents: '[]11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  546. [ '20', '24' ],
  547. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  548. [ '40', '41', '42', '43', '44' ]
  549. ] ) );
  550. } );
  551. it( 'should navigate to the row-spanned cell when approaching from the other row-spanned cell', () => {
  552. const tableCell = modelRoot.getNodeByPath( [ 0, 1, 1 ] );
  553. tableNavigation._navigateFromCellInDirection( tableCell, 'right' );
  554. assertEqualMarkup( getModelData( model ), modelTable( [
  555. [ '00', '01', '02', '03', '04' ],
  556. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '[]13', rowspan: 2 }, '14' ],
  557. [ '20', '24' ],
  558. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  559. [ '40', '41', '42', '43', '44' ]
  560. ] ) );
  561. } );
  562. it( 'should navigate to the cell in the upper spanned row when approaching from the row-spanned cell', () => {
  563. const tableCell = modelRoot.getNodeByPath( [ 0, 1, 2 ] ); // Cell 13.
  564. tableNavigation._navigateFromCellInDirection( tableCell, 'right' );
  565. assertEqualMarkup( getModelData( model ), modelTable( [
  566. [ '00', '01', '02', '03', '04' ],
  567. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '[]14' ],
  568. [ '20', '24' ],
  569. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  570. [ '40', '41', '42', '43', '44' ]
  571. ] ) );
  572. } );
  573. it( 'should navigate to the col-spanned cell', () => {
  574. const tableCell = modelRoot.getNodeByPath( [ 0, 3, 0 ] );
  575. tableNavigation._navigateFromCellInDirection( tableCell, 'right' );
  576. assertEqualMarkup( getModelData( model ), modelTable( [
  577. [ '00', '01', '02', '03', '04' ],
  578. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  579. [ '20', '24' ],
  580. [ '30', { contents: '[]31', colspan: 2 }, '33', '34' ],
  581. [ '40', '41', '42', '43', '44' ]
  582. ] ) );
  583. } );
  584. it( 'should navigate from the col-spanned cell', () => {
  585. const tableCell = modelRoot.getNodeByPath( [ 0, 3, 1 ] );
  586. tableNavigation._navigateFromCellInDirection( tableCell, 'right' );
  587. assertEqualMarkup( getModelData( model ), modelTable( [
  588. [ '00', '01', '02', '03', '04' ],
  589. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  590. [ '20', '24' ],
  591. [ '30', { contents: '31', colspan: 2 }, '[]33', '34' ],
  592. [ '40', '41', '42', '43', '44' ]
  593. ] ) );
  594. } );
  595. } );
  596. describe( 'when navigating to the left', () => {
  597. it( 'should navigate to the row-spanned cell when approaching from the upper spanned row', () => {
  598. const tableCell = modelRoot.getNodeByPath( [ 0, 1, 3 ] ); // Cell 14.
  599. tableNavigation._navigateFromCellInDirection( tableCell, 'left' );
  600. assertEqualMarkup( getModelData( model ), modelTable( [
  601. [ '00', '01', '02', '03', '04' ],
  602. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13[]', rowspan: 2 }, '14' ],
  603. [ '20', '24' ],
  604. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  605. [ '40', '41', '42', '43', '44' ]
  606. ] ) );
  607. } );
  608. it( 'should navigate to the row-spanned cell when approaching from the lower spanned row', () => {
  609. const tableCell = modelRoot.getNodeByPath( [ 0, 2, 1 ] ); // Cell 24.
  610. tableNavigation._navigateFromCellInDirection( tableCell, 'left' );
  611. assertEqualMarkup( getModelData( model ), modelTable( [
  612. [ '00', '01', '02', '03', '04' ],
  613. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13[]', rowspan: 2 }, '14' ],
  614. [ '20', '24' ],
  615. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  616. [ '40', '41', '42', '43', '44' ]
  617. ] ) );
  618. } );
  619. it( 'should navigate to the row-spanned cell when approaching from the other row-spanned cell', () => {
  620. const tableCell = modelRoot.getNodeByPath( [ 0, 1, 2 ] ); // Cell 13.
  621. tableNavigation._navigateFromCellInDirection( tableCell, 'left' );
  622. assertEqualMarkup( getModelData( model ), modelTable( [
  623. [ '00', '01', '02', '03', '04' ],
  624. [ '10', { contents: '11[]', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  625. [ '20', '24' ],
  626. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  627. [ '40', '41', '42', '43', '44' ]
  628. ] ) );
  629. } );
  630. it( 'should navigate to the cell in the upper spanned row when approaching from the row-spanned cell', () => {
  631. const tableCell = modelRoot.getNodeByPath( [ 0, 1, 1 ] ); // Cell 11.
  632. tableNavigation._navigateFromCellInDirection( tableCell, 'left' );
  633. assertEqualMarkup( getModelData( model ), modelTable( [
  634. [ '00', '01', '02', '03', '04' ],
  635. [ '10[]', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  636. [ '20', '24' ],
  637. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  638. [ '40', '41', '42', '43', '44' ]
  639. ] ) );
  640. } );
  641. it( 'should navigate to the col-spanned cell', () => {
  642. const tableCell = modelRoot.getNodeByPath( [ 0, 3, 2 ] ); // Cell 33.
  643. tableNavigation._navigateFromCellInDirection( tableCell, 'left' );
  644. assertEqualMarkup( getModelData( model ), modelTable( [
  645. [ '00', '01', '02', '03', '04' ],
  646. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  647. [ '20', '24' ],
  648. [ '30', { contents: '31[]', colspan: 2 }, '33', '34' ],
  649. [ '40', '41', '42', '43', '44' ]
  650. ] ) );
  651. } );
  652. it( 'should navigate from the col-spanned cell', () => {
  653. const tableCell = modelRoot.getNodeByPath( [ 0, 3, 1 ] );
  654. tableNavigation._navigateFromCellInDirection( tableCell, 'left' );
  655. assertEqualMarkup( getModelData( model ), modelTable( [
  656. [ '00', '01', '02', '03', '04' ],
  657. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  658. [ '20', '24' ],
  659. [ '30[]', { contents: '31', colspan: 2 }, '33', '34' ],
  660. [ '40', '41', '42', '43', '44' ]
  661. ] ) );
  662. } );
  663. } );
  664. describe( 'when navigating down', () => {
  665. it( 'should navigate to the row-col-spanned cell when approaching from the first spanned column', () => {
  666. const tableCell = modelRoot.getNodeByPath( [ 0, 0, 1 ] );
  667. tableNavigation._navigateFromCellInDirection( tableCell, 'down' );
  668. assertEqualMarkup( getModelData( model ), modelTable( [
  669. [ '00', '01', '02', '03', '04' ],
  670. [ '10', { contents: '[]11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  671. [ '20', '24' ],
  672. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  673. [ '40', '41', '42', '43', '44' ]
  674. ] ) );
  675. } );
  676. it( 'should navigate to the row-col-spanned cell when approaching from the last spanned column', () => {
  677. const tableCell = modelRoot.getNodeByPath( [ 0, 0, 2 ] );
  678. tableNavigation._navigateFromCellInDirection( tableCell, 'down' );
  679. assertEqualMarkup( getModelData( model ), modelTable( [
  680. [ '00', '01', '02', '03', '04' ],
  681. [ '10', { contents: '[]11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  682. [ '20', '24' ],
  683. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  684. [ '40', '41', '42', '43', '44' ]
  685. ] ) );
  686. } );
  687. it( 'should navigate to the row-spanned cell when approaching from the other col-spanned cell', () => {
  688. const tableCell = modelRoot.getNodeByPath( [ 0, 1, 1 ] );
  689. tableNavigation._navigateFromCellInDirection( tableCell, 'down' );
  690. assertEqualMarkup( getModelData( model ), modelTable( [
  691. [ '00', '01', '02', '03', '04' ],
  692. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  693. [ '20', '24' ],
  694. [ '30', { contents: '[]31', colspan: 2 }, '33', '34' ],
  695. [ '40', '41', '42', '43', '44' ]
  696. ] ) );
  697. } );
  698. it( 'should navigate to the cell in the first spanned column when approaching from the col-spanned cell', () => {
  699. const tableCell = modelRoot.getNodeByPath( [ 0, 1, 1 ] ); // Cell 11.
  700. tableNavigation._navigateFromCellInDirection( tableCell, 'down' );
  701. assertEqualMarkup( getModelData( model ), modelTable( [
  702. [ '00', '01', '02', '03', '04' ],
  703. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  704. [ '20', '24' ],
  705. [ '30', { contents: '[]31', colspan: 2 }, '33', '34' ],
  706. [ '40', '41', '42', '43', '44' ]
  707. ] ) );
  708. } );
  709. it( 'should navigate to the row-spanned cell', () => {
  710. const tableCell = modelRoot.getNodeByPath( [ 0, 0, 3 ] );
  711. tableNavigation._navigateFromCellInDirection( tableCell, 'down' );
  712. assertEqualMarkup( getModelData( model ), modelTable( [
  713. [ '00', '01', '02', '03', '04' ],
  714. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '[]13', rowspan: 2 }, '14' ],
  715. [ '20', '24' ],
  716. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  717. [ '40', '41', '42', '43', '44' ]
  718. ] ) );
  719. } );
  720. it( 'should navigate from the row-spanned cell', () => {
  721. const tableCell = modelRoot.getNodeByPath( [ 0, 1, 2 ] ); // Cell 13.
  722. tableNavigation._navigateFromCellInDirection( tableCell, 'down' );
  723. assertEqualMarkup( getModelData( model ), modelTable( [
  724. [ '00', '01', '02', '03', '04' ],
  725. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  726. [ '20', '24' ],
  727. [ '30', { contents: '31', colspan: 2 }, '[]33', '34' ],
  728. [ '40', '41', '42', '43', '44' ]
  729. ] ) );
  730. } );
  731. } );
  732. describe( 'when navigating up', () => {
  733. it( 'should navigate to the col-spanned cell when approaching from the first spanned column', () => {
  734. const tableCell = modelRoot.getNodeByPath( [ 0, 4, 1 ] );
  735. tableNavigation._navigateFromCellInDirection( tableCell, 'up' );
  736. assertEqualMarkup( getModelData( model ), modelTable( [
  737. [ '00', '01', '02', '03', '04' ],
  738. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  739. [ '20', '24' ],
  740. [ '30', { contents: '31[]', colspan: 2 }, '33', '34' ],
  741. [ '40', '41', '42', '43', '44' ]
  742. ] ) );
  743. } );
  744. it( 'should navigate to the col-spanned cell when approaching from the last spanned column', () => {
  745. const tableCell = modelRoot.getNodeByPath( [ 0, 4, 2 ] );
  746. tableNavigation._navigateFromCellInDirection( tableCell, 'up' );
  747. assertEqualMarkup( getModelData( model ), modelTable( [
  748. [ '00', '01', '02', '03', '04' ],
  749. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  750. [ '20', '24' ],
  751. [ '30', { contents: '31[]', colspan: 2 }, '33', '34' ],
  752. [ '40', '41', '42', '43', '44' ]
  753. ] ) );
  754. } );
  755. it( 'should navigate to the row-col-spanned cell when approaching from the other col-spanned cell', () => {
  756. const tableCell = modelRoot.getNodeByPath( [ 0, 3, 1 ] );
  757. tableNavigation._navigateFromCellInDirection( tableCell, 'up' );
  758. assertEqualMarkup( getModelData( model ), modelTable( [
  759. [ '00', '01', '02', '03', '04' ],
  760. [ '10', { contents: '11[]', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  761. [ '20', '24' ],
  762. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  763. [ '40', '41', '42', '43', '44' ]
  764. ] ) );
  765. } );
  766. it( 'should navigate to the cell in the first spanned column when approaching from the col-spanned cell', () => {
  767. const tableCell = modelRoot.getNodeByPath( [ 0, 1, 1 ] );
  768. tableNavigation._navigateFromCellInDirection( tableCell, 'up' );
  769. assertEqualMarkup( getModelData( model ), modelTable( [
  770. [ '00', '01[]', '02', '03', '04' ],
  771. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  772. [ '20', '24' ],
  773. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  774. [ '40', '41', '42', '43', '44' ]
  775. ] ) );
  776. } );
  777. it( 'should navigate to the row-spanned cell', () => {
  778. const tableCell = modelRoot.getNodeByPath( [ 0, 3, 2 ] ); // Cell 33.
  779. tableNavigation._navigateFromCellInDirection( tableCell, 'up' );
  780. assertEqualMarkup( getModelData( model ), modelTable( [
  781. [ '00', '01', '02', '03', '04' ],
  782. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13[]', rowspan: 2 }, '14' ],
  783. [ '20', '24' ],
  784. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  785. [ '40', '41', '42', '43', '44' ]
  786. ] ) );
  787. } );
  788. it( 'should navigate from the row-spanned cell', () => {
  789. const tableCell = modelRoot.getNodeByPath( [ 0, 1, 2 ] ); // Cell 13.
  790. tableNavigation._navigateFromCellInDirection( tableCell, 'up' );
  791. assertEqualMarkup( getModelData( model ), modelTable( [
  792. [ '00', '01', '02', '03[]', '04' ],
  793. [ '10', { contents: '11', colspan: 2, rowspan: 2 }, { contents: '13', rowspan: 2 }, '14' ],
  794. [ '20', '24' ],
  795. [ '30', { contents: '31', colspan: 2 }, '33', '34' ],
  796. [ '40', '41', '42', '43', '44' ]
  797. ] ) );
  798. } );
  799. } );
  800. } );
  801. } );
  802. describe( 'with the table cells selected from outside', () => {
  803. describe( 'on single table cell selected', () => {
  804. beforeEach( () => {
  805. setModelData( model, modelTable( [
  806. [ '00', '01', '02' ],
  807. [ '10', '11', '12' ],
  808. [ '20', '21', '22' ]
  809. ] ) );
  810. tableSelection._setCellSelection(
  811. modelRoot.getNodeByPath( [ 0, 1, 1 ] ),
  812. modelRoot.getNodeByPath( [ 0, 1, 1 ] )
  813. );
  814. } );
  815. it( 'should move to the cell on the left', () => {
  816. editor.editing.view.document.fire( 'keydown', leftArrowDomEvtDataStub );
  817. sinon.assert.calledOnce( leftArrowDomEvtDataStub.preventDefault );
  818. sinon.assert.calledOnce( leftArrowDomEvtDataStub.stopPropagation );
  819. assertEqualMarkup( getModelData( model ), modelTable( [
  820. [ '00', '01', '02' ],
  821. [ '10[]', '11', '12' ],
  822. [ '20', '21', '22' ]
  823. ] ) );
  824. } );
  825. it( 'should move to the cell on the right', () => {
  826. editor.editing.view.document.fire( 'keydown', rightArrowDomEvtDataStub );
  827. sinon.assert.calledOnce( rightArrowDomEvtDataStub.preventDefault );
  828. sinon.assert.calledOnce( rightArrowDomEvtDataStub.stopPropagation );
  829. assertEqualMarkup( getModelData( model ), modelTable( [
  830. [ '00', '01', '02' ],
  831. [ '10', '11', '[]12' ],
  832. [ '20', '21', '22' ]
  833. ] ) );
  834. } );
  835. it( 'should move to the cell above selection', () => {
  836. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  837. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  838. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  839. assertEqualMarkup( getModelData( model ), modelTable( [
  840. [ '00', '01[]', '02' ],
  841. [ '10', '11', '12' ],
  842. [ '20', '21', '22' ]
  843. ] ) );
  844. } );
  845. it( 'should move to the cell below selection', () => {
  846. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  847. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  848. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  849. assertEqualMarkup( getModelData( model ), modelTable( [
  850. [ '00', '01', '02' ],
  851. [ '10', '11', '12' ],
  852. [ '20', '[]21', '22' ]
  853. ] ) );
  854. } );
  855. } );
  856. describe( 'on multiple table cell selected vertically', () => {
  857. beforeEach( () => {
  858. setModelData( model, modelTable( [
  859. [ '00', '01', '02', '03' ],
  860. [ '10', '11', '12', '13' ],
  861. [ '20', '21', '22', '23' ],
  862. [ '30', '31', '32', '33' ]
  863. ] ) );
  864. tableSelection._setCellSelection(
  865. modelRoot.getNodeByPath( [ 0, 1, 1 ] ),
  866. modelRoot.getNodeByPath( [ 0, 2, 1 ] )
  867. );
  868. } );
  869. it( 'should move to the cell on the left top of selection', () => {
  870. editor.editing.view.document.fire( 'keydown', leftArrowDomEvtDataStub );
  871. sinon.assert.calledOnce( leftArrowDomEvtDataStub.preventDefault );
  872. sinon.assert.calledOnce( leftArrowDomEvtDataStub.stopPropagation );
  873. assertEqualMarkup( getModelData( model ), modelTable( [
  874. [ '00', '01', '02', '03' ],
  875. [ '10[]', '11', '12', '13' ],
  876. [ '20', '21', '22', '23' ],
  877. [ '30', '31', '32', '33' ]
  878. ] ) );
  879. } );
  880. it( 'should move to the cell on the right bottom of selection', () => {
  881. editor.editing.view.document.fire( 'keydown', rightArrowDomEvtDataStub );
  882. sinon.assert.calledOnce( rightArrowDomEvtDataStub.preventDefault );
  883. sinon.assert.calledOnce( rightArrowDomEvtDataStub.stopPropagation );
  884. assertEqualMarkup( getModelData( model ), modelTable( [
  885. [ '00', '01', '02', '03' ],
  886. [ '10', '11', '12', '13' ],
  887. [ '20', '21', '[]22', '23' ],
  888. [ '30', '31', '32', '33' ]
  889. ] ) );
  890. } );
  891. it( 'should move to the cell above selection', () => {
  892. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  893. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  894. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  895. assertEqualMarkup( getModelData( model ), modelTable( [
  896. [ '00', '01[]', '02', '03' ],
  897. [ '10', '11', '12', '13' ],
  898. [ '20', '21', '22', '23' ],
  899. [ '30', '31', '32', '33' ]
  900. ] ) );
  901. } );
  902. it( 'should move to the cell below selection', () => {
  903. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  904. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  905. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  906. assertEqualMarkup( getModelData( model ), modelTable( [
  907. [ '00', '01', '02', '03' ],
  908. [ '10', '11', '12', '13' ],
  909. [ '20', '21', '22', '23' ],
  910. [ '30', '[]31', '32', '33' ]
  911. ] ) );
  912. } );
  913. } );
  914. describe( 'on multiple table cell selected horizontally', () => {
  915. beforeEach( () => {
  916. setModelData( model, modelTable( [
  917. [ '00', '01', '02', '03' ],
  918. [ '10', '11', '12', '13' ],
  919. [ '20', '21', '22', '23' ],
  920. [ '30', '31', '32', '33' ]
  921. ] ) );
  922. // Note that this also tests that selection direction doesn't matter.
  923. tableSelection._setCellSelection(
  924. modelRoot.getNodeByPath( [ 0, 1, 2 ] ),
  925. modelRoot.getNodeByPath( [ 0, 1, 1 ] )
  926. );
  927. } );
  928. it( 'should move to the cell on the left top of selection', () => {
  929. editor.editing.view.document.fire( 'keydown', leftArrowDomEvtDataStub );
  930. sinon.assert.calledOnce( leftArrowDomEvtDataStub.preventDefault );
  931. sinon.assert.calledOnce( leftArrowDomEvtDataStub.stopPropagation );
  932. assertEqualMarkup( getModelData( model ), modelTable( [
  933. [ '00', '01', '02', '03' ],
  934. [ '10[]', '11', '12', '13' ],
  935. [ '20', '21', '22', '23' ],
  936. [ '30', '31', '32', '33' ]
  937. ] ) );
  938. } );
  939. it( 'should move to the cell on the right bottom of selection', () => {
  940. editor.editing.view.document.fire( 'keydown', rightArrowDomEvtDataStub );
  941. sinon.assert.calledOnce( rightArrowDomEvtDataStub.preventDefault );
  942. sinon.assert.calledOnce( rightArrowDomEvtDataStub.stopPropagation );
  943. assertEqualMarkup( getModelData( model ), modelTable( [
  944. [ '00', '01', '02', '03' ],
  945. [ '10', '11', '12', '[]13' ],
  946. [ '20', '21', '22', '23' ],
  947. [ '30', '31', '32', '33' ]
  948. ] ) );
  949. } );
  950. it( 'should move to the cell above selection', () => {
  951. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  952. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  953. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  954. assertEqualMarkup( getModelData( model ), modelTable( [
  955. [ '00', '01[]', '02', '03' ],
  956. [ '10', '11', '12', '13' ],
  957. [ '20', '21', '22', '23' ],
  958. [ '30', '31', '32', '33' ]
  959. ] ) );
  960. } );
  961. it( 'should move to the cell below selection', () => {
  962. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  963. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  964. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  965. assertEqualMarkup( getModelData( model ), modelTable( [
  966. [ '00', '01', '02', '03' ],
  967. [ '10', '11', '12', '13' ],
  968. [ '20', '21', '[]22', '23' ],
  969. [ '30', '31', '32', '33' ]
  970. ] ) );
  971. } );
  972. } );
  973. describe( 'on multiple table cell selected diagonally', () => {
  974. beforeEach( () => {
  975. setModelData( model, modelTable( [
  976. [ '00', '01', '02', '03' ],
  977. [ '10', '11', '12', '13' ],
  978. [ '20', '21', '22', '23' ],
  979. [ '30', '31', '32', '33' ]
  980. ] ) );
  981. tableSelection._setCellSelection(
  982. modelRoot.getNodeByPath( [ 0, 1, 1 ] ),
  983. modelRoot.getNodeByPath( [ 0, 2, 2 ] )
  984. );
  985. } );
  986. it( 'should move to the cell on the left top of selection', () => {
  987. editor.editing.view.document.fire( 'keydown', leftArrowDomEvtDataStub );
  988. sinon.assert.calledOnce( leftArrowDomEvtDataStub.preventDefault );
  989. sinon.assert.calledOnce( leftArrowDomEvtDataStub.stopPropagation );
  990. assertEqualMarkup( getModelData( model ), modelTable( [
  991. [ '00', '01', '02', '03' ],
  992. [ '10[]', '11', '12', '13' ],
  993. [ '20', '21', '22', '23' ],
  994. [ '30', '31', '32', '33' ]
  995. ] ) );
  996. } );
  997. it( 'should move to the cell on the right bottom of selection', () => {
  998. editor.editing.view.document.fire( 'keydown', rightArrowDomEvtDataStub );
  999. sinon.assert.calledOnce( rightArrowDomEvtDataStub.preventDefault );
  1000. sinon.assert.calledOnce( rightArrowDomEvtDataStub.stopPropagation );
  1001. assertEqualMarkup( getModelData( model ), modelTable( [
  1002. [ '00', '01', '02', '03' ],
  1003. [ '10', '11', '12', '13' ],
  1004. [ '20', '21', '22', '[]23' ],
  1005. [ '30', '31', '32', '33' ]
  1006. ] ) );
  1007. } );
  1008. it( 'should move to the cell above selection', () => {
  1009. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1010. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  1011. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  1012. assertEqualMarkup( getModelData( model ), modelTable( [
  1013. [ '00', '01[]', '02', '03' ],
  1014. [ '10', '11', '12', '13' ],
  1015. [ '20', '21', '22', '23' ],
  1016. [ '30', '31', '32', '33' ]
  1017. ] ) );
  1018. } );
  1019. it( 'should move to the cell below selection', () => {
  1020. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1021. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1022. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1023. assertEqualMarkup( getModelData( model ), modelTable( [
  1024. [ '00', '01', '02', '03' ],
  1025. [ '10', '11', '12', '13' ],
  1026. [ '20', '21', '22', '23' ],
  1027. [ '30', '31', '[]32', '33' ]
  1028. ] ) );
  1029. } );
  1030. } );
  1031. } );
  1032. describe( 'with selection inside a table cell', () => {
  1033. describe( 'with selection at the edge of a cell', () => {
  1034. describe( 'simple cell text content', () => {
  1035. it( 'should navigate to the cell on the left', () => {
  1036. setModelData( model, modelTable( [
  1037. [ '00', '01', '02' ],
  1038. [ '10', '[]11', '12' ],
  1039. [ '20', '21', '22' ]
  1040. ] ) );
  1041. editor.editing.view.document.fire( 'keydown', leftArrowDomEvtDataStub );
  1042. sinon.assert.calledOnce( leftArrowDomEvtDataStub.preventDefault );
  1043. sinon.assert.calledOnce( leftArrowDomEvtDataStub.stopPropagation );
  1044. assertEqualMarkup( getModelData( model ), modelTable( [
  1045. [ '00', '01', '02' ],
  1046. [ '10[]', '11', '12' ],
  1047. [ '20', '21', '22' ]
  1048. ] ) );
  1049. } );
  1050. it( 'should navigate to the cell on the right', () => {
  1051. setModelData( model, modelTable( [
  1052. [ '00', '01', '02' ],
  1053. [ '10', '11[]', '12' ],
  1054. [ '20', '21', '22' ]
  1055. ] ) );
  1056. editor.editing.view.document.fire( 'keydown', rightArrowDomEvtDataStub );
  1057. sinon.assert.calledOnce( rightArrowDomEvtDataStub.preventDefault );
  1058. sinon.assert.calledOnce( rightArrowDomEvtDataStub.stopPropagation );
  1059. assertEqualMarkup( getModelData( model ), modelTable( [
  1060. [ '00', '01', '02' ],
  1061. [ '10', '11', '[]12' ],
  1062. [ '20', '21', '22' ]
  1063. ] ) );
  1064. } );
  1065. it( 'should navigate to the cell above', () => {
  1066. setModelData( model, modelTable( [
  1067. [ '00', '01', '02' ],
  1068. [ '10', '[]11', '12' ],
  1069. [ '20', '21', '22' ]
  1070. ] ) );
  1071. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1072. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  1073. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  1074. assertEqualMarkup( getModelData( model ), modelTable( [
  1075. [ '00', '01[]', '02' ],
  1076. [ '10', '11', '12' ],
  1077. [ '20', '21', '22' ]
  1078. ] ) );
  1079. } );
  1080. it( 'should navigate to the cell below', () => {
  1081. setModelData( model, modelTable( [
  1082. [ '00', '01', '02' ],
  1083. [ '10', '11[]', '12' ],
  1084. [ '20', '21', '22' ]
  1085. ] ) );
  1086. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1087. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1088. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1089. assertEqualMarkup( getModelData( model ), modelTable( [
  1090. [ '00', '01', '02' ],
  1091. [ '10', '11', '12' ],
  1092. [ '20', '[]21', '22' ]
  1093. ] ) );
  1094. } );
  1095. } );
  1096. describe( 'multiple paragraphs in the cell content', () => {
  1097. it( 'should navigate to the cell on the left', () => {
  1098. setModelData( model, modelTable( [
  1099. [ '00', '01', '02' ],
  1100. [ '10', '<paragraph>[]11</paragraph><paragraph>x</paragraph>', '12' ],
  1101. [ '20', '21', '22' ]
  1102. ] ) );
  1103. editor.editing.view.document.fire( 'keydown', leftArrowDomEvtDataStub );
  1104. sinon.assert.calledOnce( leftArrowDomEvtDataStub.preventDefault );
  1105. sinon.assert.calledOnce( leftArrowDomEvtDataStub.stopPropagation );
  1106. assertEqualMarkup( getModelData( model ), modelTable( [
  1107. [ '00', '01', '02' ],
  1108. [ '10[]', '<paragraph>11</paragraph><paragraph>x</paragraph>', '12' ],
  1109. [ '20', '21', '22' ]
  1110. ] ) );
  1111. } );
  1112. it( 'should navigate to the cell on the right', () => {
  1113. setModelData( model, modelTable( [
  1114. [ '00', '01', '02' ],
  1115. [ '10', '<paragraph>11</paragraph><paragraph>x[]</paragraph>', '12' ],
  1116. [ '20', '21', '22' ]
  1117. ] ) );
  1118. editor.editing.view.document.fire( 'keydown', rightArrowDomEvtDataStub );
  1119. sinon.assert.calledOnce( rightArrowDomEvtDataStub.preventDefault );
  1120. sinon.assert.calledOnce( rightArrowDomEvtDataStub.stopPropagation );
  1121. assertEqualMarkup( getModelData( model ), modelTable( [
  1122. [ '00', '01', '02' ],
  1123. [ '10', '<paragraph>11</paragraph><paragraph>x</paragraph>', '[]12' ],
  1124. [ '20', '21', '22' ]
  1125. ] ) );
  1126. } );
  1127. it( 'should navigate to the cell above', () => {
  1128. setModelData( model, modelTable( [
  1129. [ '00', '01', '02' ],
  1130. [ '10', '<paragraph>[]11</paragraph><paragraph>x</paragraph>', '12' ],
  1131. [ '20', '21', '22' ]
  1132. ] ) );
  1133. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1134. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  1135. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  1136. assertEqualMarkup( getModelData( model ), modelTable( [
  1137. [ '00', '01[]', '02' ],
  1138. [ '10', '<paragraph>11</paragraph><paragraph>x</paragraph>', '12' ],
  1139. [ '20', '21', '22' ]
  1140. ] ) );
  1141. } );
  1142. it( 'should navigate to the cell below', () => {
  1143. setModelData( model, modelTable( [
  1144. [ '00', '01', '02' ],
  1145. [ '10', '<paragraph>11</paragraph><paragraph>x[]</paragraph>', '12' ],
  1146. [ '20', '21', '22' ]
  1147. ] ) );
  1148. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1149. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1150. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1151. assertEqualMarkup( getModelData( model ), modelTable( [
  1152. [ '00', '01', '02' ],
  1153. [ '10', '<paragraph>11</paragraph><paragraph>x</paragraph>', '12' ],
  1154. [ '20', '[]21', '22' ]
  1155. ] ) );
  1156. } );
  1157. } );
  1158. describe( 'image widget with caption as only cell content', () => {
  1159. it( 'should navigate to the cell on the left', () => {
  1160. setModelData( model, modelTable( [
  1161. [ '00', '01', '02' ],
  1162. [ '10', `<image src="${ imageUrl }"><caption>[]11</caption></image>`, '12' ],
  1163. [ '20', '21', '22' ]
  1164. ] ) );
  1165. editor.editing.view.document.fire( 'keydown', leftArrowDomEvtDataStub );
  1166. sinon.assert.calledOnce( leftArrowDomEvtDataStub.preventDefault );
  1167. sinon.assert.calledOnce( leftArrowDomEvtDataStub.stopPropagation );
  1168. assertEqualMarkup( getModelData( model ), modelTable( [
  1169. [ '00', '01', '02' ],
  1170. [ '10[]', `<image src="${ imageUrl }"><caption>11</caption></image>`, '12' ],
  1171. [ '20', '21', '22' ]
  1172. ] ) );
  1173. } );
  1174. it( 'should navigate to the cell on the right', () => {
  1175. setModelData( model, modelTable( [
  1176. [ '00', '01', '02' ],
  1177. [ '10', `<image src="${ imageUrl }"><caption>11[]</caption></image>`, '12' ],
  1178. [ '20', '21', '22' ]
  1179. ] ) );
  1180. editor.editing.view.document.fire( 'keydown', rightArrowDomEvtDataStub );
  1181. sinon.assert.calledOnce( rightArrowDomEvtDataStub.preventDefault );
  1182. sinon.assert.calledOnce( rightArrowDomEvtDataStub.stopPropagation );
  1183. assertEqualMarkup( getModelData( model ), modelTable( [
  1184. [ '00', '01', '02' ],
  1185. [ '10', `<image src="${ imageUrl }"><caption>11</caption></image>`, '[]12' ],
  1186. [ '20', '21', '22' ]
  1187. ] ) );
  1188. } );
  1189. it( 'should navigate to the cell above', () => {
  1190. setModelData( model, modelTable( [
  1191. [ '00', '01', '02' ],
  1192. [ '10', `<image src="${ imageUrl }"><caption>[]11</caption></image>`, '12' ],
  1193. [ '20', '21', '22' ]
  1194. ] ) );
  1195. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1196. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  1197. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  1198. assertEqualMarkup( getModelData( model ), modelTable( [
  1199. [ '00', '01[]', '02' ],
  1200. [ '10', `<image src="${ imageUrl }"><caption>11</caption></image>`, '12' ],
  1201. [ '20', '21', '22' ]
  1202. ] ) );
  1203. } );
  1204. it( 'should navigate to the cell below', () => {
  1205. setModelData( model, modelTable( [
  1206. [ '00', '01', '02' ],
  1207. [ '10', `<image src="${ imageUrl }"><caption>11[]</caption></image>`, '12' ],
  1208. [ '20', '21', '22' ]
  1209. ] ) );
  1210. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1211. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1212. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1213. assertEqualMarkup( getModelData( model ), modelTable( [
  1214. [ '00', '01', '02' ],
  1215. [ '10', `<image src="${ imageUrl }"><caption>11</caption></image>`, '12' ],
  1216. [ '20', '[]21', '22' ]
  1217. ] ) );
  1218. } );
  1219. } );
  1220. describe( 'horizontal line as only cell content (widget without $text positions)', () => {
  1221. beforeEach( () => {
  1222. setModelData( model, modelTable( [
  1223. [ '00', '01', '02' ],
  1224. [ '10', '[<horizontalLine></horizontalLine>]', '12' ],
  1225. [ '20', '21', '22' ]
  1226. ] ) );
  1227. } );
  1228. it( 'should navigate to the cell on the left', () => {
  1229. editor.editing.view.document.fire( 'keydown', leftArrowDomEvtDataStub );
  1230. sinon.assert.calledOnce( leftArrowDomEvtDataStub.preventDefault );
  1231. sinon.assert.calledOnce( leftArrowDomEvtDataStub.stopPropagation );
  1232. assertEqualMarkup( getModelData( model ), modelTable( [
  1233. [ '00', '01', '02' ],
  1234. [ '10[]', '<horizontalLine></horizontalLine>', '12' ],
  1235. [ '20', '21', '22' ]
  1236. ] ) );
  1237. } );
  1238. it( 'should navigate to the cell on the right', () => {
  1239. editor.editing.view.document.fire( 'keydown', rightArrowDomEvtDataStub );
  1240. sinon.assert.calledOnce( rightArrowDomEvtDataStub.preventDefault );
  1241. sinon.assert.calledOnce( rightArrowDomEvtDataStub.stopPropagation );
  1242. assertEqualMarkup( getModelData( model ), modelTable( [
  1243. [ '00', '01', '02' ],
  1244. [ '10', '<horizontalLine></horizontalLine>', '[]12' ],
  1245. [ '20', '21', '22' ]
  1246. ] ) );
  1247. } );
  1248. it( 'should navigate to the cell above', () => {
  1249. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1250. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  1251. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  1252. assertEqualMarkup( getModelData( model ), modelTable( [
  1253. [ '00', '01[]', '02' ],
  1254. [ '10', '<horizontalLine></horizontalLine>', '12' ],
  1255. [ '20', '21', '22' ]
  1256. ] ) );
  1257. } );
  1258. it( 'should navigate to the cell below', () => {
  1259. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1260. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1261. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1262. assertEqualMarkup( getModelData( model ), modelTable( [
  1263. [ '00', '01', '02' ],
  1264. [ '10', '<horizontalLine></horizontalLine>', '12' ],
  1265. [ '20', '[]21', '22' ]
  1266. ] ) );
  1267. } );
  1268. } );
  1269. describe( 'two horizontal lines as only cell content (widget without $text positions)', () => {
  1270. it( 'should navigate to the cell on the left', () => {
  1271. setModelData( model, modelTable( [
  1272. [ '00', '01', '02' ],
  1273. [ '10', '[<horizontalLine></horizontalLine>]<horizontalLine></horizontalLine>', '12' ],
  1274. [ '20', '21', '22' ]
  1275. ] ) );
  1276. editor.editing.view.document.fire( 'keydown', leftArrowDomEvtDataStub );
  1277. sinon.assert.calledOnce( leftArrowDomEvtDataStub.preventDefault );
  1278. sinon.assert.calledOnce( leftArrowDomEvtDataStub.stopPropagation );
  1279. assertEqualMarkup( getModelData( model ), modelTable( [
  1280. [ '00', '01', '02' ],
  1281. [ '10[]', '<horizontalLine></horizontalLine><horizontalLine></horizontalLine>', '12' ],
  1282. [ '20', '21', '22' ]
  1283. ] ) );
  1284. } );
  1285. it( 'should navigate to the cell on the right', () => {
  1286. setModelData( model, modelTable( [
  1287. [ '00', '01', '02' ],
  1288. [ '10', '<horizontalLine></horizontalLine>[<horizontalLine></horizontalLine>]', '12' ],
  1289. [ '20', '21', '22' ]
  1290. ] ) );
  1291. editor.editing.view.document.fire( 'keydown', rightArrowDomEvtDataStub );
  1292. sinon.assert.calledOnce( rightArrowDomEvtDataStub.preventDefault );
  1293. sinon.assert.calledOnce( rightArrowDomEvtDataStub.stopPropagation );
  1294. assertEqualMarkup( getModelData( model ), modelTable( [
  1295. [ '00', '01', '02' ],
  1296. [ '10', '<horizontalLine></horizontalLine><horizontalLine></horizontalLine>', '[]12' ],
  1297. [ '20', '21', '22' ]
  1298. ] ) );
  1299. } );
  1300. it( 'should navigate to the cell above', () => {
  1301. setModelData( model, modelTable( [
  1302. [ '00', '01', '02' ],
  1303. [ '10', '[<horizontalLine></horizontalLine>]<horizontalLine></horizontalLine>', '12' ],
  1304. [ '20', '21', '22' ]
  1305. ] ) );
  1306. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1307. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  1308. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  1309. assertEqualMarkup( getModelData( model ), modelTable( [
  1310. [ '00', '01[]', '02' ],
  1311. [ '10', '<horizontalLine></horizontalLine><horizontalLine></horizontalLine>', '12' ],
  1312. [ '20', '21', '22' ]
  1313. ] ) );
  1314. } );
  1315. it( 'should navigate to the cell below', () => {
  1316. setModelData( model, modelTable( [
  1317. [ '00', '01', '02' ],
  1318. [ '10', '<horizontalLine></horizontalLine>[<horizontalLine></horizontalLine>]', '12' ],
  1319. [ '20', '21', '22' ]
  1320. ] ) );
  1321. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1322. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1323. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1324. assertEqualMarkup( getModelData( model ), modelTable( [
  1325. [ '00', '01', '02' ],
  1326. [ '10', '<horizontalLine></horizontalLine><horizontalLine></horizontalLine>', '12' ],
  1327. [ '20', '[]21', '22' ]
  1328. ] ) );
  1329. } );
  1330. } );
  1331. } );
  1332. describe( 'with selection not at the edge of a cell', () => {
  1333. let editorElement, editor, model, styleElement;
  1334. beforeEach( async () => {
  1335. editorElement = global.document.createElement( 'div' );
  1336. global.document.body.appendChild( editorElement );
  1337. editor = await ClassicTestEditor.create( editorElement, {
  1338. plugins: [ Table, Paragraph, Image, ImageCaption, HorizontalLine ]
  1339. } );
  1340. model = editor.model;
  1341. styleElement = global.document.createElement( 'style' );
  1342. styleElement.type = 'text/css';
  1343. styleElement.appendChild( global.document.createTextNode(
  1344. `
  1345. * {
  1346. font-size: 12px !important;
  1347. font-family: serif !important;
  1348. margin: 0 !important;
  1349. padding: 0 !important;
  1350. border: 0 !important
  1351. }
  1352. td { width: 30px !important; }
  1353. tr:nth-child(2) td:nth-child(2) { width: 300px !important; }
  1354. `
  1355. ) );
  1356. global.document.querySelector( 'head' ).appendChild( styleElement );
  1357. } );
  1358. afterEach( async () => {
  1359. editorElement.remove();
  1360. styleElement.remove();
  1361. await editor.destroy();
  1362. } );
  1363. describe( 'simple cell text content', () => {
  1364. it( 'should not navigate to the cell on the left', () => {
  1365. setModelData( model, modelTable( [
  1366. [ '00', '01', '02' ],
  1367. [ '10', '1[]1', '12' ],
  1368. [ '20', '21', '22' ]
  1369. ] ) );
  1370. editor.editing.view.document.fire( 'keydown', leftArrowDomEvtDataStub );
  1371. sinon.assert.notCalled( leftArrowDomEvtDataStub.preventDefault );
  1372. sinon.assert.notCalled( leftArrowDomEvtDataStub.stopPropagation );
  1373. } );
  1374. it( 'should not navigate to the cell on the right', () => {
  1375. setModelData( model, modelTable( [
  1376. [ '00', '01', '02' ],
  1377. [ '10', '1[]1', '12' ],
  1378. [ '20', '21', '22' ]
  1379. ] ) );
  1380. editor.editing.view.document.fire( 'keydown', rightArrowDomEvtDataStub );
  1381. sinon.assert.notCalled( rightArrowDomEvtDataStub.preventDefault );
  1382. sinon.assert.notCalled( rightArrowDomEvtDataStub.stopPropagation );
  1383. } );
  1384. it( 'should not navigate to the cell above', () => {
  1385. setModelData( model, modelTable( [
  1386. [ '00', '01', '02' ],
  1387. [ '10', '1[]1', '12' ],
  1388. [ '20', '21', '22' ]
  1389. ] ) );
  1390. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1391. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  1392. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  1393. assertEqualMarkup( getModelData( model ), modelTable( [
  1394. [ '00', '01', '02' ],
  1395. [ '10', '[]11', '12' ],
  1396. [ '20', '21', '22' ]
  1397. ] ) );
  1398. } );
  1399. it( 'should not navigate to the cell below', () => {
  1400. setModelData( model, modelTable( [
  1401. [ '00', '01', '02' ],
  1402. [ '10', '1[]1', '12' ],
  1403. [ '20', '21', '22' ]
  1404. ] ) );
  1405. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1406. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1407. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1408. assertEqualMarkup( getModelData( model ), modelTable( [
  1409. [ '00', '01', '02' ],
  1410. [ '10', '11[]', '12' ],
  1411. [ '20', '21', '22' ]
  1412. ] ) );
  1413. } );
  1414. } );
  1415. describe( 'selection inside paragraph', () => {
  1416. const text = new Array( 20 ).fill( 0 ).map( () => 'word' ).join( ' ' );
  1417. it( 'should not navigate if caret is in the middle line of a text', () => {
  1418. setModelData( model, modelTable( [
  1419. [ '00', '01', '02' ],
  1420. [ '10', text + '[] ' + text, '12' ],
  1421. [ '20', '21', '22' ]
  1422. ] ) );
  1423. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1424. sinon.assert.notCalled( upArrowDomEvtDataStub.preventDefault );
  1425. sinon.assert.notCalled( upArrowDomEvtDataStub.stopPropagation );
  1426. } );
  1427. it( 'should move caret to beginning of cell content if caret is in the first line of a text', () => {
  1428. setModelData( model, modelTable( [
  1429. [ '00', '01', '02' ],
  1430. [ '10', 'word[] word' + text, '12' ],
  1431. [ '20', '21', '22' ]
  1432. ] ) );
  1433. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1434. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  1435. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  1436. assertEqualMarkup( getModelData( model ), modelTable( [
  1437. [ '00', '01', '02' ],
  1438. [ '10', '[]word word' + text, '12' ],
  1439. [ '20', '21', '22' ]
  1440. ] ) );
  1441. } );
  1442. it( 'should move caret to end of cell content if caret is in the last line of a text', () => {
  1443. setModelData( model, modelTable( [
  1444. [ '00', '01', '02' ],
  1445. [ '10', text + 'word[] word', '12' ],
  1446. [ '20', '21', '22' ]
  1447. ] ) );
  1448. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1449. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1450. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1451. assertEqualMarkup( getModelData( model ), modelTable( [
  1452. [ '00', '01', '02' ],
  1453. [ '10', text + 'word word[]', '12' ],
  1454. [ '20', '21', '22' ]
  1455. ] ) );
  1456. } );
  1457. } );
  1458. describe( 'with selection in the wrap area', () => {
  1459. const text = new Array( 10 ).fill( 0 ).map( () => 'word' ).join( ' ' );
  1460. it( 'should move caret to end if caret is after the last space in the line next to the last one', () => {
  1461. // This is also first position in the last line.
  1462. setModelData( model, modelTable( [
  1463. [ '00', '01', '02' ],
  1464. [ '10', text + ' []word word word', '12' ],
  1465. [ '20', '21', '22' ]
  1466. ] ) );
  1467. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1468. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1469. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1470. assertEqualMarkup( getModelData( model ), modelTable( [
  1471. [ '00', '01', '02' ],
  1472. [ '10', text + ' word word word[]', '12' ],
  1473. [ '20', '21', '22' ]
  1474. ] ) );
  1475. } );
  1476. it( 'should move caret to end if caret is at the last space in the line next to last one', () => {
  1477. setModelData( model, modelTable( [
  1478. [ '00', '01', '02' ],
  1479. [ '10', text + '[] word word word', '12' ],
  1480. [ '20', '21', '22' ]
  1481. ] ) );
  1482. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1483. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1484. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1485. assertEqualMarkup( getModelData( model ), modelTable( [
  1486. [ '00', '01', '02' ],
  1487. [ '10', text + ' word word word[]', '12' ],
  1488. [ '20', '21', '22' ]
  1489. ] ) );
  1490. } );
  1491. it( 'should not move caret if it\'s just before the last space in the line next to last one', () => {
  1492. setModelData( model, modelTable( [
  1493. [ '00', '01', '02' ],
  1494. [ '10', text.substring( 0, text.length - 1 ) + '[]d word word word', '12' ],
  1495. [ '20', '21', '22' ]
  1496. ] ) );
  1497. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1498. sinon.assert.notCalled( downArrowDomEvtDataStub.preventDefault );
  1499. sinon.assert.notCalled( downArrowDomEvtDataStub.stopPropagation );
  1500. } );
  1501. } );
  1502. describe( 'with multiple paragraphs of text', () => {
  1503. const text = new Array( 100 ).fill( 0 ).map( () => 'word' ).join( ' ' );
  1504. it( 'should not navigate if caret is in the middle line of a text', () => {
  1505. setModelData( model, modelTable( [
  1506. [ '00', '01', '02' ],
  1507. [ '10', `<paragraph>${ text }[]${ text }</paragraph><paragraph>foobar</paragraph>`, '12' ],
  1508. [ '20', '21', '22' ]
  1509. ] ) );
  1510. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1511. sinon.assert.notCalled( upArrowDomEvtDataStub.preventDefault );
  1512. sinon.assert.notCalled( upArrowDomEvtDataStub.stopPropagation );
  1513. } );
  1514. it( 'should move caret to beginning of cell content if caret is in the first line of a text', () => {
  1515. setModelData( model, modelTable( [
  1516. [ '00', '01', '02' ],
  1517. [ '10', `<paragraph>word[]${ text }</paragraph><paragraph>foobar</paragraph>`, '12' ],
  1518. [ '20', '21', '22' ]
  1519. ] ) );
  1520. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1521. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  1522. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  1523. assertEqualMarkup( getModelData( model ), modelTable( [
  1524. [ '00', '01', '02' ],
  1525. [ '10', `<paragraph>[]word${ text }</paragraph><paragraph>foobar</paragraph>`, '12' ],
  1526. [ '20', '21', '22' ]
  1527. ] ) );
  1528. } );
  1529. it( 'should not move caret to end of cell content if caret is not last line of text', () => {
  1530. setModelData( model, modelTable( [
  1531. [ '00', '01', '02' ],
  1532. [ '10', `<paragraph>${ text }word []word</paragraph><paragraph>foobar</paragraph>`, '12' ],
  1533. [ '20', '21', '22' ]
  1534. ] ) );
  1535. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1536. sinon.assert.notCalled( downArrowDomEvtDataStub.preventDefault );
  1537. sinon.assert.notCalled( downArrowDomEvtDataStub.stopPropagation );
  1538. } );
  1539. it( 'should move caret to end of cell content if caret is in the last line of a text', () => {
  1540. setModelData( model, modelTable( [
  1541. [ '00', '01', '02' ],
  1542. [ '10', `<paragraph>foobar</paragraph><paragraph>${ text }word []word</paragraph>`, '12' ],
  1543. [ '20', '21', '22' ]
  1544. ] ) );
  1545. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1546. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1547. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1548. assertEqualMarkup( getModelData( model ), modelTable( [
  1549. [ '00', '01', '02' ],
  1550. [ '10', `<paragraph>foobar</paragraph><paragraph>${ text }word word[]</paragraph>`, '12' ],
  1551. [ '20', '21', '22' ]
  1552. ] ) );
  1553. } );
  1554. } );
  1555. describe( 'with horizontal line widget', () => {
  1556. const text = new Array( 100 ).fill( 0 ).map( () => 'word' ).join( ' ' );
  1557. it( 'should not navigate if caret is in the middle line of a text', () => {
  1558. setModelData( model, modelTable( [
  1559. [ '00', '01', '02' ],
  1560. [ '10', `<horizontalLine></horizontalLine><paragraph>${ text }[]${ text }</paragraph>`, '12' ],
  1561. [ '20', '21', '22' ]
  1562. ] ) );
  1563. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1564. sinon.assert.notCalled( upArrowDomEvtDataStub.preventDefault );
  1565. sinon.assert.notCalled( upArrowDomEvtDataStub.stopPropagation );
  1566. } );
  1567. it( 'should move caret to beginning of cell content if caret is in the first line of a text', () => {
  1568. setModelData( model, modelTable( [
  1569. [ '00', '01', '02' ],
  1570. [ '10', `<horizontalLine></horizontalLine><paragraph>word[] ${ text }</paragraph>`, '12' ],
  1571. [ '20', '21', '22' ]
  1572. ] ) );
  1573. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1574. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  1575. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  1576. assertEqualMarkup( getModelData( model ), modelTable( [
  1577. [ '00', '01', '02' ],
  1578. [ '10', `[<horizontalLine></horizontalLine>]<paragraph>word ${ text }</paragraph>`, '12' ],
  1579. [ '20', '21', '22' ]
  1580. ] ) );
  1581. } );
  1582. it( 'should move caret to end of cell content if caret is in the last line of a text', () => {
  1583. setModelData( model, modelTable( [
  1584. [ '00', '01', '02' ],
  1585. [ '10', `<paragraph>${ text } word []word</paragraph><horizontalLine></horizontalLine>`, '12' ],
  1586. [ '20', '21', '22' ]
  1587. ] ) );
  1588. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1589. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1590. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1591. assertEqualMarkup( getModelData( model ), modelTable( [
  1592. [ '00', '01', '02' ],
  1593. [ '10', `<paragraph>${ text } word word</paragraph>[<horizontalLine></horizontalLine>]`, '12' ],
  1594. [ '20', '21', '22' ]
  1595. ] ) );
  1596. } );
  1597. it( 'should not move caret to end of cell content if widget is selected in middle of cell content', () => {
  1598. const paragraph = `<paragraph>${ text }</paragraph>`;
  1599. const hr = '<horizontalLine></horizontalLine>';
  1600. setModelData( model, modelTable( [
  1601. [ '00', '01', '02' ],
  1602. [ '10', `${ paragraph }[${ hr }]${ paragraph }${ hr }`, '12' ],
  1603. [ '20', '21', '22' ]
  1604. ] ) );
  1605. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1606. assertEqualMarkup( getModelData( model ), modelTable( [
  1607. [ '00', '01', '02' ],
  1608. [ '10', `${ paragraph }${ hr }<paragraph>[]${ text }</paragraph>${ hr }`, '12' ],
  1609. [ '20', '21', '22' ]
  1610. ] ) );
  1611. } );
  1612. it( 'should not move caret to end of cell content if widget is next to selection', () => {
  1613. const paragraph = `<paragraph>${ text }</paragraph>`;
  1614. const hr = '<horizontalLine></horizontalLine>';
  1615. setModelData( model, modelTable( [
  1616. [ '00', '01', '02' ],
  1617. [ '10', `${ paragraph }[]${ hr }`, '12' ],
  1618. [ '20', '21', '22' ]
  1619. ] ) );
  1620. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1621. assertEqualMarkup( getModelData( model ), modelTable( [
  1622. [ '00', '01', '02' ],
  1623. [ '10', `${ paragraph }[${ hr }]`, '12' ],
  1624. [ '20', '21', '22' ]
  1625. ] ) );
  1626. } );
  1627. } );
  1628. describe( 'contains image widget with caption and selection inside the caption', () => {
  1629. it( 'should not navigate to the cell on the left', () => {
  1630. setModelData( model, modelTable( [
  1631. [ '00', '01', '02' ],
  1632. [ '10', `<paragraph>foo</paragraph><image src="${ imageUrl }"><caption>[]11</caption></image>`, '12' ],
  1633. [ '20', '21', '22' ]
  1634. ] ) );
  1635. editor.editing.view.document.fire( 'keydown', leftArrowDomEvtDataStub );
  1636. sinon.assert.notCalled( leftArrowDomEvtDataStub.preventDefault );
  1637. sinon.assert.notCalled( leftArrowDomEvtDataStub.stopPropagation );
  1638. } );
  1639. it( 'should not navigate to the cell on the right', () => {
  1640. setModelData( model, modelTable( [
  1641. [ '00', '01', '02' ],
  1642. [ '10', `<image src="${ imageUrl }"><caption>11[]</caption></image><paragraph>foo</paragraph>`, '12' ],
  1643. [ '20', '21', '22' ]
  1644. ] ) );
  1645. editor.editing.view.document.fire( 'keydown', rightArrowDomEvtDataStub );
  1646. sinon.assert.notCalled( rightArrowDomEvtDataStub.preventDefault );
  1647. sinon.assert.notCalled( rightArrowDomEvtDataStub.stopPropagation );
  1648. } );
  1649. it( 'should not navigate to the cell above', () => {
  1650. setModelData( model, modelTable( [
  1651. [ '00', '01', '02' ],
  1652. [ '10', `<paragraph>foo</paragraph><image src="${ imageUrl }"><caption>1[]1</caption></image>`, '12' ],
  1653. [ '20', '21', '22' ]
  1654. ] ) );
  1655. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1656. sinon.assert.notCalled( upArrowDomEvtDataStub.preventDefault );
  1657. sinon.assert.notCalled( upArrowDomEvtDataStub.stopPropagation );
  1658. } );
  1659. it( 'should not navigate to the cell above but should select image widget', () => {
  1660. setModelData( model, modelTable( [
  1661. [ '00', '01', '02' ],
  1662. [ '10', `<image src="${ imageUrl }"><caption>1[]1</caption></image><paragraph>foo</paragraph>`, '12' ],
  1663. [ '20', '21', '22' ]
  1664. ] ) );
  1665. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1666. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  1667. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  1668. assertEqualMarkup( getModelData( model ), modelTable( [
  1669. [ '00', '01', '02' ],
  1670. [ '10', `[<image src="${ imageUrl }"><caption>11</caption></image>]<paragraph>foo</paragraph>`, '12' ],
  1671. [ '20', '21', '22' ]
  1672. ] ) );
  1673. } );
  1674. it( 'should not navigate to the cell below when followed by paragraph', () => {
  1675. setModelData( model, modelTable( [
  1676. [ '00', '01', '02' ],
  1677. [ '10', `<image src="${ imageUrl }"><caption>1[]1</caption></image><paragraph>foo</paragraph>`, '12' ],
  1678. [ '20', '21', '22' ]
  1679. ] ) );
  1680. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1681. sinon.assert.notCalled( downArrowDomEvtDataStub.preventDefault );
  1682. sinon.assert.notCalled( downArrowDomEvtDataStub.stopPropagation );
  1683. } );
  1684. it( 'should not navigate to the cell below but should select image widget', () => {
  1685. setModelData( model, modelTable( [
  1686. [ '00', '01', '02' ],
  1687. [ '10', `<paragraph>foo</paragraph><image src="${ imageUrl }"><caption>1[]1</caption></image>`, '12' ],
  1688. [ '20', '21', '22' ]
  1689. ] ) );
  1690. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1691. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1692. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1693. assertEqualMarkup( getModelData( model ), modelTable( [
  1694. [ '00', '01', '02' ],
  1695. [ '10', `<paragraph>foo</paragraph>[<image src="${ imageUrl }"><caption>11</caption></image>]`, '12' ],
  1696. [ '20', '21', '22' ]
  1697. ] ) );
  1698. } );
  1699. it( 'should not navigate to the cell above but should select image widget without caption', () => {
  1700. setModelData( model, modelTable( [
  1701. [ '00', '01', '02' ],
  1702. [ '10', `<image src="${ imageUrl }"><caption></caption></image><paragraph>f[]oo</paragraph>`, '12' ],
  1703. [ '20', '21', '22' ]
  1704. ] ) );
  1705. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1706. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  1707. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  1708. assertEqualMarkup( getModelData( model ), modelTable( [
  1709. [ '00', '01', '02' ],
  1710. [ '10', `[<image src="${ imageUrl }"><caption></caption></image>]<paragraph>foo</paragraph>`, '12' ],
  1711. [ '20', '21', '22' ]
  1712. ] ) );
  1713. } );
  1714. it( 'should not navigate to the cell below but should select image widget without caption', () => {
  1715. setModelData( model, modelTable( [
  1716. [ '00', '01', '02' ],
  1717. [ '10', `<paragraph>f[]oo</paragraph><image src="${ imageUrl }"><caption></caption></image>`, '12' ],
  1718. [ '20', '21', '22' ]
  1719. ] ) );
  1720. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1721. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1722. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1723. assertEqualMarkup( getModelData( model ), modelTable( [
  1724. [ '00', '01', '02' ],
  1725. [ '10', `<paragraph>foo</paragraph>[<image src="${ imageUrl }"><caption></caption></image>]`, '12' ],
  1726. [ '20', '21', '22' ]
  1727. ] ) );
  1728. } );
  1729. } );
  1730. } );
  1731. } );
  1732. describe( 'for right-to-left content language', () => {
  1733. beforeEach( () => {
  1734. return VirtualTestEditor
  1735. .create( {
  1736. plugins: [ TableEditing, TableNavigation, TableSelection, Paragraph, ImageEditing, MediaEmbedEditing ],
  1737. language: 'ar'
  1738. } )
  1739. .then( newEditor => {
  1740. editor = newEditor;
  1741. model = editor.model;
  1742. modelRoot = model.document.getRoot();
  1743. tableSelection = editor.plugins.get( TableSelection );
  1744. } );
  1745. } );
  1746. describe( 'with the table cell selected from outside', () => {
  1747. beforeEach( () => {
  1748. setModelData( model, modelTable( [
  1749. [ '00', '01', '02' ],
  1750. [ '10', '11', '12' ],
  1751. [ '20', '21', '22' ]
  1752. ] ) );
  1753. tableSelection._setCellSelection(
  1754. modelRoot.getNodeByPath( [ 0, 1, 1 ] ),
  1755. modelRoot.getNodeByPath( [ 0, 1, 1 ] )
  1756. );
  1757. } );
  1758. it( 'should move to the cell on the right (it\'s visually flipped by browser)', () => {
  1759. editor.editing.view.document.fire( 'keydown', leftArrowDomEvtDataStub );
  1760. sinon.assert.calledOnce( leftArrowDomEvtDataStub.preventDefault );
  1761. sinon.assert.calledOnce( leftArrowDomEvtDataStub.stopPropagation );
  1762. assertEqualMarkup( getModelData( model ), modelTable( [
  1763. [ '00', '01', '02' ],
  1764. [ '10', '11', '[]12' ],
  1765. [ '20', '21', '22' ]
  1766. ] ) );
  1767. } );
  1768. it( 'should move to the cell on the left (it\'s visually flipped by browser)', () => {
  1769. editor.editing.view.document.fire( 'keydown', rightArrowDomEvtDataStub );
  1770. sinon.assert.calledOnce( rightArrowDomEvtDataStub.preventDefault );
  1771. sinon.assert.calledOnce( rightArrowDomEvtDataStub.stopPropagation );
  1772. assertEqualMarkup( getModelData( model ), modelTable( [
  1773. [ '00', '01', '02' ],
  1774. [ '10[]', '11', '12' ],
  1775. [ '20', '21', '22' ]
  1776. ] ) );
  1777. } );
  1778. it( 'should move to the cell above selection', () => {
  1779. editor.editing.view.document.fire( 'keydown', upArrowDomEvtDataStub );
  1780. sinon.assert.calledOnce( upArrowDomEvtDataStub.preventDefault );
  1781. sinon.assert.calledOnce( upArrowDomEvtDataStub.stopPropagation );
  1782. assertEqualMarkup( getModelData( model ), modelTable( [
  1783. [ '00', '01[]', '02' ],
  1784. [ '10', '11', '12' ],
  1785. [ '20', '21', '22' ]
  1786. ] ) );
  1787. } );
  1788. it( 'should move to the cell below selection', () => {
  1789. editor.editing.view.document.fire( 'keydown', downArrowDomEvtDataStub );
  1790. sinon.assert.calledOnce( downArrowDomEvtDataStub.preventDefault );
  1791. sinon.assert.calledOnce( downArrowDomEvtDataStub.stopPropagation );
  1792. assertEqualMarkup( getModelData( model ), modelTable( [
  1793. [ '00', '01', '02' ],
  1794. [ '10', '11', '12' ],
  1795. [ '20', '[]21', '22' ]
  1796. ] ) );
  1797. } );
  1798. } );
  1799. } );
  1800. } );
  1801. } );