8
0

selectrowcommand.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /**
  2. * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  4. */
  5. import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
  6. import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
  7. import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
  8. import TableEditing from '../../src/tableediting';
  9. import TableSelection from '../../src/tableselection';
  10. import { assertSelectedCells, modelTable } from '../_utils/utils';
  11. import SelectRowCommand from '../../src/commands/selectrowcommand';
  12. describe( 'SelectRowCommand', () => {
  13. let editor, model, modelRoot, command, tableSelection;
  14. beforeEach( () => {
  15. return VirtualTestEditor.create( { plugins: [ Paragraph, TableEditing, TableSelection ] } )
  16. .then( newEditor => {
  17. editor = newEditor;
  18. model = editor.model;
  19. modelRoot = model.document.getRoot();
  20. command = new SelectRowCommand( editor );
  21. tableSelection = editor.plugins.get( TableSelection );
  22. } );
  23. } );
  24. afterEach( () => {
  25. return editor.destroy();
  26. } );
  27. describe( 'isEnabled', () => {
  28. it( 'should be true if the selection is inside table cell', () => {
  29. setData( model, modelTable( [
  30. [ '00[]', '01' ],
  31. [ '10', '11' ]
  32. ] ) );
  33. expect( command.isEnabled ).to.be.true;
  34. } );
  35. it( 'should be true if the selection contains multiple cells', () => {
  36. setData( model, modelTable( [
  37. [ '00', '01' ],
  38. [ '10', '11' ],
  39. [ '20', '21' ]
  40. ] ) );
  41. tableSelection.setCellSelection(
  42. modelRoot.getNodeByPath( [ 0, 0, 0 ] ),
  43. modelRoot.getNodeByPath( [ 0, 0, 1 ] )
  44. );
  45. expect( command.isEnabled ).to.be.true;
  46. } );
  47. it( 'should be false if the selection is outside a table', () => {
  48. setData( model, '<paragraph>11[]</paragraph>' );
  49. expect( command.isEnabled ).to.be.false;
  50. } );
  51. } );
  52. describe( 'execute()', () => {
  53. it( 'should select a row of a table cell with a collapsed selection', () => {
  54. setData( model, modelTable( [
  55. [ '00', '01' ],
  56. [ '[]10', '11' ],
  57. [ '20', '21' ]
  58. ] ) );
  59. command.execute();
  60. assertSelectedCells( model, [
  61. [ 0, 0 ],
  62. [ 1, 1 ],
  63. [ 0, 0 ]
  64. ] );
  65. } );
  66. it( 'should select a row of table cell with a collapsed selection in first table cell', () => {
  67. setData( model, modelTable( [
  68. [ '[]00', '01' ],
  69. [ '10', '11' ],
  70. [ '20', '21' ]
  71. ] ) );
  72. command.execute();
  73. assertSelectedCells( model, [
  74. [ 1, 1 ],
  75. [ 0, 0 ],
  76. [ 0, 0 ]
  77. ] );
  78. } );
  79. it( 'should select a row of table cell with a collapsed selection in last cell in the first column', () => {
  80. setData( model, modelTable( [
  81. [ '00', '01[]' ],
  82. [ '10', '11' ],
  83. [ '20', '21' ]
  84. ] ) );
  85. command.execute();
  86. assertSelectedCells( model, [
  87. [ 1, 1 ],
  88. [ 0, 0 ],
  89. [ 0, 0 ]
  90. ] );
  91. } );
  92. it( 'should select a row of table cell with collapsed selection in the first cell of the last column', () => {
  93. setData( model, modelTable( [
  94. [ '00', '01' ],
  95. [ '[]10', '11' ]
  96. ] ) );
  97. command.execute();
  98. assertSelectedCells( model, [
  99. [ 0, 0 ],
  100. [ 1, 1 ]
  101. ] );
  102. } );
  103. describe( 'with row-spanned cells', () => {
  104. beforeEach( () => {
  105. // +----+----+----+----+----+
  106. // | 00 | 01 | 02 | 03 | 04 |
  107. // + + + +----+----+
  108. // | | | | 13 | 14 |
  109. // + + +----+ +----+
  110. // | | | 22 | | 24 |
  111. // + +----+----+----+----+
  112. // | | 31 | 32 | 33 | 34 |
  113. // +----+----+----+----+----+
  114. setData( model, modelTable( [
  115. [ { rowspan: 4, contents: '00' }, { rowspan: 3, contents: '01' }, { rowspan: 2, contents: '02' }, '03', '04' ],
  116. [ { rowspan: 2, contents: '13' }, '14' ],
  117. [ '22', '23', '24' ],
  118. [ '30', '31', '32', '33', '34' ]
  119. ] ) );
  120. } );
  121. it( 'should select only one row if only one cell is selected', () => {
  122. // Selection in cell 01.
  123. tableSelection.setCellSelection(
  124. modelRoot.getNodeByPath( [ 0, 0, 1 ] ),
  125. modelRoot.getNodeByPath( [ 0, 0, 1 ] )
  126. );
  127. /* eslint-disable no-multi-spaces */
  128. assertSelectedCells( model, [
  129. [ 0, 1, 0, 0, 0 ],
  130. [ 0, 0 ],
  131. [ 0, 0 ],
  132. [ 0, 0, 0, 0 ]
  133. ] );
  134. /* eslint-enable no-multi-spaces */
  135. command.execute();
  136. /* eslint-disable no-multi-spaces */
  137. assertSelectedCells( model, [
  138. [ 1, 1, 1, 1, 1 ],
  139. [ 0, 0 ],
  140. [ 0, 0 ],
  141. [ 0, 0, 0, 0 ]
  142. ] );
  143. /* eslint-enable no-multi-spaces */
  144. } );
  145. it( 'should not select row-spanned rows that start in other row', () => {
  146. // Selection in cell 24.
  147. tableSelection.setCellSelection(
  148. modelRoot.getNodeByPath( [ 0, 2, 1 ] ),
  149. modelRoot.getNodeByPath( [ 0, 2, 1 ] )
  150. );
  151. /* eslint-disable no-multi-spaces */
  152. assertSelectedCells( model, [
  153. [ 0, 0, 0, 0, 0 ],
  154. [ 0, 0 ],
  155. [ 0, 1 ],
  156. [ 0, 0, 0, 0 ]
  157. ] );
  158. /* eslint-enable no-multi-spaces */
  159. command.execute();
  160. /* eslint-disable no-multi-spaces */
  161. assertSelectedCells( model, [
  162. [ 0, 0, 0, 0, 0 ],
  163. [ 0, 0 ],
  164. [ 1, 1 ],
  165. [ 0, 0, 0, 0 ]
  166. ] );
  167. /* eslint-enable no-multi-spaces */
  168. } );
  169. it( 'should not select row-spanned rows that start in other row but include those that start in selected row', () => {
  170. // Selection in cell 14.
  171. tableSelection.setCellSelection(
  172. modelRoot.getNodeByPath( [ 0, 1, 1 ] ),
  173. modelRoot.getNodeByPath( [ 0, 1, 1 ] )
  174. );
  175. /* eslint-disable no-multi-spaces */
  176. assertSelectedCells( model, [
  177. [ 0, 0, 0, 0, 0 ],
  178. [ 0, 1 ],
  179. [ 0, 0 ],
  180. [ 0, 0, 0, 0 ]
  181. ] );
  182. /* eslint-enable no-multi-spaces */
  183. command.execute();
  184. /* eslint-disable no-multi-spaces */
  185. assertSelectedCells( model, [
  186. [ 0, 0, 0, 0, 0 ],
  187. [ 1, 1 ],
  188. [ 0, 0 ],
  189. [ 0, 0, 0, 0 ]
  190. ] );
  191. /* eslint-enable no-multi-spaces */
  192. } );
  193. it( 'should select properly for multiple not spanned cells selected', () => {
  194. // Selection in cells 04 - 14.
  195. tableSelection.setCellSelection(
  196. modelRoot.getNodeByPath( [ 0, 0, 4 ] ),
  197. modelRoot.getNodeByPath( [ 0, 1, 1 ] )
  198. );
  199. /* eslint-disable no-multi-spaces */
  200. assertSelectedCells( model, [
  201. [ 0, 0, 0, 0, 1 ],
  202. [ 0, 1 ],
  203. [ 0, 0 ],
  204. [ 0, 0, 0, 0 ]
  205. ] );
  206. /* eslint-enable no-multi-spaces */
  207. command.execute();
  208. /* eslint-disable no-multi-spaces */
  209. assertSelectedCells( model, [
  210. [ 1, 1, 1, 1, 1 ],
  211. [ 1, 1 ],
  212. [ 0, 0 ],
  213. [ 0, 0, 0, 0 ]
  214. ] );
  215. /* eslint-enable no-multi-spaces */
  216. } );
  217. it( 'should select properly for multiple cells selected including spanned one', () => {
  218. // Selection in cells 13 - 33.
  219. tableSelection.setCellSelection(
  220. modelRoot.getNodeByPath( [ 0, 1, 0 ] ),
  221. modelRoot.getNodeByPath( [ 0, 3, 2 ] )
  222. );
  223. /* eslint-disable no-multi-spaces */
  224. assertSelectedCells( model, [
  225. [ 0, 0, 0, 0, 0 ],
  226. [ 1, 0 ],
  227. [ 0, 0 ],
  228. [ 0, 0, 1, 0 ]
  229. ] );
  230. /* eslint-enable no-multi-spaces */
  231. command.execute();
  232. /* eslint-disable no-multi-spaces */
  233. assertSelectedCells( model, [
  234. [ 0, 0, 0, 0, 0 ],
  235. [ 1, 1 ],
  236. [ 1, 1 ],
  237. [ 1, 1, 1, 1 ]
  238. ] );
  239. /* eslint-enable no-multi-spaces */
  240. } );
  241. } );
  242. describe( 'with multiple rows selected', () => {
  243. it( 'should properly select middle rows', () => {
  244. setData( model, modelTable( [
  245. [ '00', '01' ],
  246. [ '10', '11' ],
  247. [ '20', '21' ],
  248. [ '30', '31' ]
  249. ] ) );
  250. tableSelection.setCellSelection(
  251. modelRoot.getNodeByPath( [ 0, 1, 0 ] ),
  252. modelRoot.getNodeByPath( [ 0, 2, 0 ] )
  253. );
  254. command.execute();
  255. assertSelectedCells( model, [
  256. [ 0, 0 ],
  257. [ 1, 1 ],
  258. [ 1, 1 ],
  259. [ 0, 0 ]
  260. ] );
  261. } );
  262. it( 'should properly select middle rows in reversed order', () => {
  263. setData( model, modelTable( [
  264. [ '00', '01' ],
  265. [ '10', '11' ],
  266. [ '20', '21' ],
  267. [ '30', '31' ]
  268. ] ) );
  269. tableSelection.setCellSelection(
  270. modelRoot.getNodeByPath( [ 0, 2, 0 ] ),
  271. modelRoot.getNodeByPath( [ 0, 1, 0 ] )
  272. );
  273. command.execute();
  274. assertSelectedCells( model, [
  275. [ 0, 0 ],
  276. [ 1, 1 ],
  277. [ 1, 1 ],
  278. [ 0, 0 ]
  279. ] );
  280. } );
  281. it( 'should properly select tailing rows', () => {
  282. setData( model, modelTable( [
  283. [ '00', '01' ],
  284. [ '10', '11' ],
  285. [ '20', '21' ],
  286. [ '30', '31' ]
  287. ] ) );
  288. tableSelection.setCellSelection(
  289. modelRoot.getNodeByPath( [ 0, 2, 0 ] ),
  290. modelRoot.getNodeByPath( [ 0, 3, 0 ] )
  291. );
  292. command.execute();
  293. assertSelectedCells( model, [
  294. [ 0, 0 ],
  295. [ 0, 0 ],
  296. [ 1, 1 ],
  297. [ 1, 1 ]
  298. ] );
  299. } );
  300. it( 'should properly select beginning rows', () => {
  301. setData( model, modelTable( [
  302. [ '00', '01' ],
  303. [ '10', '11' ],
  304. [ '20', '21' ],
  305. [ '30', '31' ]
  306. ] ) );
  307. tableSelection.setCellSelection(
  308. modelRoot.getNodeByPath( [ 0, 0, 0 ] ),
  309. modelRoot.getNodeByPath( [ 0, 1, 0 ] )
  310. );
  311. command.execute();
  312. assertSelectedCells( model, [
  313. [ 1, 1 ],
  314. [ 1, 1 ],
  315. [ 0, 0 ],
  316. [ 0, 0 ]
  317. ] );
  318. } );
  319. it( 'should properly select multiple rows from square selection', () => {
  320. setData( model, modelTable( [
  321. [ '00', '01', '02' ],
  322. [ '10', '11', '12' ],
  323. [ '20', '21', '22' ],
  324. [ '30', '31', '32' ]
  325. ] ) );
  326. tableSelection.setCellSelection(
  327. modelRoot.getNodeByPath( [ 0, 1, 0 ] ),
  328. modelRoot.getNodeByPath( [ 0, 2, 1 ] )
  329. );
  330. command.execute();
  331. assertSelectedCells( model, [
  332. [ 0, 0, 0 ],
  333. [ 1, 1, 1 ],
  334. [ 1, 1, 1 ],
  335. [ 0, 0, 0 ]
  336. ] );
  337. } );
  338. it( 'should support selecting mixed heading and cell rows', () => {
  339. setData( model, modelTable( [
  340. [ '00', '01' ],
  341. [ '10', '11' ],
  342. [ '20', '21' ]
  343. ], { headingColumns: 1 } ) );
  344. tableSelection.setCellSelection(
  345. modelRoot.getNodeByPath( [ 0, 0, 0 ] ),
  346. modelRoot.getNodeByPath( [ 0, 1, 0 ] )
  347. );
  348. command.execute();
  349. assertSelectedCells( model, [
  350. [ 1, 1 ],
  351. [ 1, 1 ],
  352. [ 0, 0 ]
  353. ] );
  354. } );
  355. it( 'should properly select more than 10 rows selected (array sort bug)', () => {
  356. setData( model, modelTable( [
  357. [ '0', 'x' ],
  358. [ '1', 'x' ],
  359. [ '2', 'x' ],
  360. [ '3', 'x' ],
  361. [ '4', 'x' ],
  362. [ '5', 'x' ],
  363. [ '6', 'x' ],
  364. [ '7', 'x' ],
  365. [ '8', 'x' ],
  366. [ '9', 'x' ],
  367. [ '10', 'x' ],
  368. [ '11', 'x' ],
  369. [ '12', 'x' ],
  370. [ '13', 'x' ],
  371. [ '14', 'x' ]
  372. ] ) );
  373. const tableSelection = editor.plugins.get( TableSelection );
  374. const modelRoot = model.document.getRoot();
  375. tableSelection.setCellSelection(
  376. modelRoot.getNodeByPath( [ 0, 1, 0 ] ),
  377. modelRoot.getNodeByPath( [ 0, 12, 0 ] )
  378. );
  379. command.execute();
  380. assertSelectedCells( model, [
  381. [ 0, 0 ], // '0'
  382. [ 1, 1 ], // '1'
  383. [ 1, 1 ], // '2'
  384. [ 1, 1 ], // '3'
  385. [ 1, 1 ], // '4'
  386. [ 1, 1 ], // '5'
  387. [ 1, 1 ], // '6'
  388. [ 1, 1 ], // '7'
  389. [ 1, 1 ], // '8'
  390. [ 1, 1 ], // '9'
  391. [ 1, 1 ], // '10'
  392. [ 1, 1 ], // '11'
  393. [ 1, 1 ], // '12'
  394. [ 0, 0 ], // '13'
  395. [ 0, 0 ] // '14
  396. ] );
  397. } );
  398. } );
  399. describe( 'with entire row selected', () => {
  400. it( 'should select a row if all its cells are selected', () => {
  401. setData( model, modelTable( [
  402. [ '00', '01' ],
  403. [ '10', '11' ],
  404. [ '20', '21' ]
  405. ] ) );
  406. tableSelection.setCellSelection(
  407. modelRoot.getNodeByPath( [ 0, 1, 0 ] ),
  408. modelRoot.getNodeByPath( [ 0, 1, 1 ] )
  409. );
  410. command.execute();
  411. assertSelectedCells( model, [
  412. [ 0, 0 ],
  413. [ 1, 1 ],
  414. [ 0, 0 ]
  415. ] );
  416. } );
  417. it( 'should properly select row if reversed selection is made', () => {
  418. setData( model, modelTable( [
  419. [ '00', '01' ],
  420. [ '10', '11' ]
  421. ] ) );
  422. tableSelection.setCellSelection(
  423. modelRoot.getNodeByPath( [ 0, 0, 1 ] ),
  424. modelRoot.getNodeByPath( [ 0, 0, 0 ] )
  425. );
  426. command.execute();
  427. assertSelectedCells( model, [
  428. [ 1, 1 ],
  429. [ 0, 0 ]
  430. ] );
  431. } );
  432. } );
  433. } );
  434. } );