b433391ebbe5f31851ae7173b0e039e42e85656a2ad0701e9921cc3fd2333262540cf441e8983978cc0ca837f4042239218383ac0a0dfb805362d04c86b569 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987
  1. describe('Core_alter', () => {
  2. var id = 'testContainer';
  3. beforeEach(function() {
  4. this.$container = $(`<div id="${id}"></div>`).appendTo('body');
  5. });
  6. afterEach(function() {
  7. if (this.$container) {
  8. destroy();
  9. this.$container.remove();
  10. }
  11. });
  12. var arrayOfNestedObjects = function() {
  13. return [
  14. {id: 1,
  15. name: {
  16. first: 'Ted',
  17. last: 'Right'
  18. },
  19. address: 'Street Name',
  20. zip: '80410',
  21. city: 'City Name'},
  22. {id: 2,
  23. name: {
  24. first: 'Frank',
  25. last: 'Honest'
  26. },
  27. address: 'Street Name',
  28. zip: '80410',
  29. city: 'City Name'},
  30. {id: 3,
  31. name: {
  32. first: 'Joan',
  33. last: 'Well'
  34. },
  35. address: 'Street Name',
  36. zip: '80410',
  37. city: 'City Name'}
  38. ];
  39. };
  40. var arrayOfArrays = function() {
  41. return [
  42. ['', 'Kia', 'Nissan', 'Toyota', 'Honda'],
  43. ['2008', 10, 11, 12, 13],
  44. ['2009', 20, 11, 14, 13],
  45. ['2010', 30, 15, 12, 13]
  46. ];
  47. };
  48. describe('remove row', () => {
  49. it('should remove row', () => {
  50. handsontable({
  51. minRows: 5,
  52. data: arrayOfNestedObjects(),
  53. columns: [
  54. {data: 'id'},
  55. {data: 'name.first'}
  56. ]
  57. });
  58. alter('remove_row', 1);
  59. expect(getDataAtCell(1, 1)).toEqual('Joan'); // Joan should be moved up
  60. expect(getData().length).toEqual(5); // new row should be added by keepEmptyRows
  61. });
  62. it('should fire beforeRemoveRow event before removing row', () => {
  63. var onBeforeRemoveRow = jasmine.createSpy('onBeforeRemoveRow');
  64. var hot = handsontable({
  65. data: arrayOfNestedObjects(),
  66. columns: [
  67. {data: 'id'},
  68. {data: 'name.first'}
  69. ],
  70. beforeRemoveRow: onBeforeRemoveRow,
  71. });
  72. alter('remove_row', 2, 1, 'customSource');
  73. expect(onBeforeRemoveRow).toHaveBeenCalledWith(countRows(), 1, [2], 'customSource', undefined, undefined);
  74. });
  75. it('should not remove row if removing has been canceled by beforeRemoveRow event handler', () => {
  76. var onBeforeRemoveRow = jasmine.createSpy('onBeforeRemoveRow');
  77. onBeforeRemoveRow.and.callFake(() => false);
  78. var hot = handsontable({
  79. data: arrayOfNestedObjects(),
  80. columns: [
  81. {data: 'id'},
  82. {data: 'name.first'}
  83. ],
  84. beforeRemoveRow: onBeforeRemoveRow
  85. });
  86. expect(countRows()).toEqual(3);
  87. alter('remove_row');
  88. expect(countRows()).toEqual(3);
  89. });
  90. it('should not remove rows below minRows', () => {
  91. handsontable({
  92. startRows: 5,
  93. minRows: 4
  94. });
  95. alter('remove_row', 1);
  96. alter('remove_row', 1);
  97. alter('remove_row', 1);
  98. expect(countRows()).toEqual(4);
  99. });
  100. it('should not remove cols below minCols', () => {
  101. handsontable({
  102. startCols: 5,
  103. minCols: 4
  104. });
  105. alter('remove_col', 1);
  106. alter('remove_col', 1);
  107. alter('remove_col', 1);
  108. expect(countCols()).toEqual(4);
  109. });
  110. it('should remove one row if amount parameter is empty', function() {
  111. handsontable({
  112. data: [
  113. ['a1', 'a2', 'a3'],
  114. ['b1', 'b2', 'b3'],
  115. ['c1', 'c2', 'c3'],
  116. ['d1', 'd2', 'd3'],
  117. ['e1', 'e2', 'e3']
  118. ]
  119. });
  120. alter('remove_row', 1);
  121. expect(countRows()).toEqual(4);
  122. expect(this.$container.find('tr:eq(0) td:eq(0)').html()).toEqual('a1');
  123. expect(this.$container.find('tr:eq(1) td:eq(1)').html()).toEqual('c2');
  124. });
  125. it('should remove as many rows as given in the amount parameter', function() {
  126. handsontable({
  127. data: [
  128. ['a1', 'a2', 'a3'],
  129. ['b1', 'b2', 'b3'],
  130. ['c1', 'c2', 'c3'],
  131. ['d1', 'd2', 'd3'],
  132. ['e1', 'e2', 'e3']
  133. ]
  134. });
  135. alter('remove_row', 1, 3);
  136. expect(countRows()).toEqual(2);
  137. expect(this.$container.find('tr:eq(0) td:eq(0)').html()).toEqual('a1');
  138. expect(this.$container.find('tr:eq(1) td:eq(1)').html()).toEqual('e2');
  139. });
  140. it('should not remove more rows that exist', () => {
  141. handsontable({
  142. data: [
  143. ['a1', 'a2', 'a3'],
  144. ['b1', 'b2', 'b3'],
  145. ['c1', 'c2', 'c3'],
  146. ['d1', 'd2', 'd3'],
  147. ['e1', 'e2', 'e3']
  148. ]
  149. });
  150. alter('remove_row', 1, 10);
  151. expect(countRows()).toEqual(1);
  152. expect(getHtCore().find('tr:last td:last').html()).toEqual('a3');
  153. });
  154. it('should remove one row from end if no parameters are given', () => {
  155. handsontable({
  156. data: [
  157. ['a1', 'a2', 'a3'],
  158. ['b1', 'b2', 'b3'],
  159. ['c1', 'c2', 'c3'],
  160. ['d1', 'd2', 'd3'],
  161. ['e1', 'e2', 'e3']
  162. ]
  163. });
  164. alter('remove_row');
  165. expect(countRows()).toEqual(4);
  166. expect(getHtCore().find('tr:last td:eq(0)').html()).toEqual('d1');
  167. });
  168. it('should remove amount of rows from end if index parameter is not given', () => {
  169. handsontable({
  170. data: [
  171. ['a1', 'a2', 'a3'],
  172. ['b1', 'b2', 'b3'],
  173. ['c1', 'c2', 'c3'],
  174. ['d1', 'd2', 'd3'],
  175. ['e1', 'e2', 'e3']
  176. ]
  177. });
  178. alter('remove_row', null, 3);
  179. expect(countRows()).toEqual(2);
  180. expect(getHtCore().find('tr:last td:eq(0)').html()).toEqual('b1');
  181. });
  182. it('should remove rows from table with fixedRows', () => {
  183. handsontable({
  184. data: [
  185. ['a1', 'a2', 'a3'],
  186. ['b1', 'b2', 'b3']
  187. ],
  188. fixedRowsTop: 1,
  189. minSpareRows: 0
  190. });
  191. alter('remove_row', 1);
  192. expect(countRows()).toEqual(1);
  193. });
  194. it('should remove all rows from table with fixedRows', () => {
  195. handsontable({
  196. data: [
  197. ['a1', 'a2', 'a3'],
  198. ['b1', 'b2', 'b3']
  199. ],
  200. fixedRowsTop: 1,
  201. minSpareRows: 0
  202. });
  203. alter('remove_row', 1);
  204. alter('remove_row', 1);
  205. expect(countRows()).toEqual(0);
  206. });
  207. it('should remove row\'s cellProperties', () => {
  208. handsontable({
  209. startCols: 1,
  210. startRows: 3
  211. });
  212. getCellMeta(0, 0).someValue = [0, 0];
  213. getCellMeta(1, 0).someValue = [1, 0];
  214. getCellMeta(2, 0).someValue = [2, 0];
  215. alter('remove_row', 0);
  216. expect(getCellMeta(0, 0).someValue).toEqual([1, 0]);
  217. expect(getCellMeta(1, 0).someValue).toEqual([2, 0]);
  218. });
  219. it('should fire callback on remove row', () => {
  220. var outputBefore;
  221. var outputAfter;
  222. handsontable({
  223. minRows: 5,
  224. data: arrayOfNestedObjects(),
  225. columns: [
  226. {data: 'id'},
  227. {data: 'name.first'}
  228. ],
  229. beforeRemoveRow(index, amount, removedRows, source) {
  230. outputBefore = [index, amount, removedRows, source];
  231. },
  232. afterRemoveRow(index, amount, removedRows, source) {
  233. outputAfter = [index, amount, removedRows, source];
  234. }
  235. });
  236. alter('remove_row', 1, 2, 'customSource');
  237. expect(outputBefore).toEqual([1, 2, [1, 2], 'customSource']);
  238. expect(outputAfter).toEqual([1, 2, [1, 2], 'customSource']);
  239. });
  240. it('should decrement the number of fixed rows, if a fix row is removed', () => {
  241. var hot = handsontable({
  242. startCols: 1,
  243. startRows: 3,
  244. fixedRowsTop: 4
  245. });
  246. alter('remove_row', 1, 1);
  247. expect(hot.getSettings().fixedRowsTop).toEqual(3);
  248. alter('remove_row', 1, 2);
  249. expect(hot.getSettings().fixedRowsTop).toEqual(1);
  250. });
  251. it('should shift the cell meta according to the new row layout', () => {
  252. var hot = handsontable({
  253. startCols: 3,
  254. startRows: 4
  255. });
  256. setCellMeta(2, 1, 'className', 'test');
  257. alter('remove_row', 1, 1);
  258. expect(getCellMeta(1, 1).className).toEqual('test');
  259. });
  260. it('should shift the cell meta according to the new rows (>1) layout', () => {
  261. var hot = handsontable({
  262. startCols: 3,
  263. startRows: 4
  264. });
  265. setCellMeta(2, 1, 'className', 'test');
  266. alter('remove_row', 0, 2);
  267. expect(getCellMeta(0, 1).className).toEqual('test');
  268. });
  269. });
  270. describe('remove column', () => {
  271. it('should remove one column if amount parameter is empty', function() {
  272. handsontable({
  273. data: [
  274. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
  275. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
  276. ]
  277. });
  278. alter('remove_col', 1);
  279. expect(countCols()).toEqual(7);
  280. expect(this.$container.find('tr:eq(0) td:eq(0)').html()).toEqual('a');
  281. expect(this.$container.find('tr:eq(1) td:eq(1)').html()).toEqual('c');
  282. });
  283. it('should remove as many columns as given in the amount parameter', function() {
  284. handsontable({
  285. data: [
  286. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
  287. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
  288. ]
  289. });
  290. alter('remove_col', 1, 3);
  291. expect(countCols()).toEqual(5);
  292. expect(this.$container.find('tr:eq(0) td:eq(0)').html()).toEqual('a');
  293. expect(this.$container.find('tr:eq(1) td:eq(1)').html()).toEqual('e');
  294. });
  295. it('should not remove more columns that exist', function() {
  296. handsontable({
  297. data: [
  298. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
  299. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
  300. ]
  301. });
  302. alter('remove_col', 6, 3);
  303. expect(countCols()).toEqual(6);
  304. expect(this.$container.find('tr:eq(1) td:last').html()).toEqual('f');
  305. });
  306. it('should remove one column from end if no parameters are given', function() {
  307. handsontable({
  308. data: [
  309. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
  310. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
  311. ]
  312. });
  313. alter('remove_col');
  314. expect(countCols()).toEqual(7);
  315. expect(this.$container.find('tr:eq(1) td:last').html()).toEqual('g');
  316. });
  317. it('should remove amount of columns from end if index parameter is not given', function() {
  318. handsontable({
  319. data: [
  320. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
  321. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
  322. ]
  323. });
  324. alter('remove_col', null, 3);
  325. expect(countCols()).toEqual(5);
  326. expect(this.$container.find('tr:eq(1) td:last').html()).toEqual('e');
  327. });
  328. it('should fire beforeRemoveCol event before removing col', () => {
  329. var onBeforeRemoveCol = jasmine.createSpy('onBeforeRemoveCol');
  330. var hot = handsontable({
  331. beforeRemoveCol: onBeforeRemoveCol
  332. });
  333. alter('remove_col');
  334. expect(onBeforeRemoveCol).toHaveBeenCalledWith(countCols(), 1, [4], undefined, undefined, undefined);
  335. });
  336. it('should not remove column if removing has been canceled by beforeRemoveCol event handler', () => {
  337. var onBeforeRemoveCol = jasmine.createSpy('onBeforeRemoveCol');
  338. onBeforeRemoveCol.and.callFake(() => false);
  339. var hot = handsontable({
  340. beforeRemoveCol: onBeforeRemoveCol
  341. });
  342. expect(countCols()).toEqual(5);
  343. alter('remove_col');
  344. expect(countCols()).toEqual(5);
  345. });
  346. it('should fire callback on remove col', () => {
  347. var outputBefore;
  348. var outputAfter;
  349. handsontable({
  350. minRows: 5,
  351. data: arrayOfArrays(),
  352. beforeRemoveCol(index, amount, removedCols, source) {
  353. outputBefore = [index, amount, removedCols, source];
  354. },
  355. afterRemoveCol(index, amount, removedCols, source) {
  356. outputAfter = [index, amount, removedCols, source];
  357. }
  358. });
  359. alter('remove_col', 1, 2, 'customSource');
  360. expect(outputBefore).toEqual([1, 2, [1, 2], 'customSource']);
  361. expect(outputAfter).toEqual([1, 2, [1, 2], 'customSource']);
  362. });
  363. it('should remove column\'s properties', () => {
  364. handsontable({
  365. startCols: 3,
  366. startRows: 1
  367. });
  368. getCellMeta(0, 0).someValue = [0, 0];
  369. getCellMeta(0, 1).someValue = [0, 1];
  370. getCellMeta(0, 2).someValue = [0, 2];
  371. alter('remove_col', 0);
  372. expect(getCellMeta(0, 0).someValue).toEqual([0, 1]);
  373. expect(getCellMeta(0, 1).someValue).toEqual([0, 2]);
  374. });
  375. it('should remove column when not all rows are visible in the viewport', function() {
  376. this.$container.css({
  377. height: '100',
  378. overflow: 'auto'
  379. });
  380. handsontable({
  381. startCols: 3,
  382. startRows: 20
  383. });
  384. expect(getHtCore().find('tbody tr').length).toBeLessThan(20);
  385. expect(countCols()).toEqual(3);
  386. alter('remove_col', 0);
  387. expect(countCols()).toEqual(2);
  388. });
  389. it('should not remove column header together with the column, if headers were NOT specified explicitly', () => {
  390. handsontable({
  391. startCols: 3,
  392. startRows: 2,
  393. colHeaders: true
  394. });
  395. expect(getColHeader()).toEqual(['A', 'B', 'C']);
  396. expect(countCols()).toEqual(3);
  397. alter('remove_col', 1);
  398. expect(countCols()).toEqual(2);
  399. expect(getColHeader()).toEqual(['A', 'B']);
  400. });
  401. it('should remove column header together with the column, if headers were specified explicitly', () => {
  402. handsontable({
  403. startCols: 3,
  404. startRows: 2,
  405. colHeaders: ['Header0', 'Header1', 'Header2']
  406. });
  407. expect(getColHeader()).toEqual(['Header0', 'Header1', 'Header2']);
  408. expect(countCols()).toEqual(3);
  409. alter('remove_col', 1);
  410. expect(countCols()).toEqual(2);
  411. expect(getColHeader()).toEqual(['Header0', 'Header2']);
  412. });
  413. it('should decrement the number of fixed columns, if a fix column is removed', () => {
  414. var hot = handsontable({
  415. startCols: 1,
  416. startRows: 3,
  417. fixedColumnsLeft: 4
  418. });
  419. alter('remove_col', 1, 1);
  420. expect(hot.getSettings().fixedColumnsLeft).toEqual(3);
  421. alter('remove_col', 1, 2);
  422. expect(hot.getSettings().fixedColumnsLeft).toEqual(1);
  423. });
  424. it('should shift the cell meta according to the new column layout', () => {
  425. var hot = handsontable({
  426. startCols: 4,
  427. startRows: 3
  428. });
  429. setCellMeta(1, 2, 'className', 'test');
  430. alter('remove_col', 1, 1);
  431. expect(getCellMeta(1, 1).className).toEqual('test');
  432. });
  433. it('should shift the cell meta according to the new columns (>1) layout', () => {
  434. var hot = handsontable({
  435. startCols: 4,
  436. startRows: 3
  437. });
  438. setCellMeta(1, 2, 'className', 'test');
  439. alter('remove_col', 0, 2);
  440. expect(getCellMeta(1, 0).className).toEqual('test');
  441. });
  442. });
  443. describe('insert row', () => {
  444. it('should insert row at given index', function() {
  445. handsontable({
  446. data: [
  447. ['a1', 'a2', 'a3'],
  448. ['b1', 'b2', 'b3'],
  449. ['c1', 'c2', 'c3'],
  450. ['d1', 'd2', 'd3'],
  451. ['e1', 'e2', 'e3']
  452. ]
  453. });
  454. alter('insert_row', 1);
  455. expect(countRows()).toEqual(6);
  456. expect(this.$container.find('tr:eq(2) td:eq(0)').html()).toEqual('b1');
  457. });
  458. it('should insert row at the end if index is not given', () => {
  459. handsontable({
  460. data: [
  461. ['a1', 'a2', 'a3'],
  462. ['b1', 'b2', 'b3'],
  463. ['c1', 'c2', 'c3'],
  464. ['d1', 'd2', 'd3'],
  465. ['e1', 'e2', 'e3']
  466. ]
  467. });
  468. alter('insert_row');
  469. expect(countRows()).toEqual(6);
  470. expect(getHtCore().find('tr:eq(4) td:eq(0)').html()).toEqual('e1');
  471. expect(getHtCore().find('tr:last td:eq(0)').html()).toEqual('');
  472. });
  473. it('should not change cellMeta after executing `insert row` without parameters (#3581, #3989, #2114)', () => {
  474. var greenRenderer = function(instance, td, row, col, prop, value, cellProperties) {
  475. Handsontable.renderers.TextRenderer.apply(this, arguments);
  476. td.style.backgroundColor = 'green';
  477. };
  478. handsontable({
  479. data: [
  480. [0, 'a', true],
  481. [1, 'b', false],
  482. [2, 'c', true],
  483. [3, 'd', true]
  484. ],
  485. cell: [
  486. {row: 0, col: 0, renderer: greenRenderer, type: 'text', readOnly: true}
  487. ],
  488. columns: [
  489. {type: 'numeric'},
  490. {type: 'text'},
  491. {type: 'checkbox'}
  492. ]
  493. });
  494. alter('insert_row');
  495. expect(getCellMeta(1, 0).renderer).not.toBe(greenRenderer);
  496. expect(getCellMeta(1, 0).readOnly).toBe(false);
  497. expect(getCellMeta(4, 0).renderer).not.toBe(greenRenderer);
  498. expect(getCellMeta(4, 0).readOnly).toBe(false);
  499. });
  500. it('should add new row which respect defined type of cells after executing `insert_row`', () => {
  501. handsontable({
  502. data: [
  503. [0, 'a', true],
  504. [1, 'b', false],
  505. [2, 'c', true],
  506. [3, 'd', true]
  507. ],
  508. cell: [
  509. {row: 0, col: 0, type: 'text'}
  510. ],
  511. columns: [
  512. {type: 'numeric'},
  513. {type: 'text'},
  514. {type: 'checkbox'}
  515. ]
  516. });
  517. alter('insert_row');
  518. // added row
  519. expect(getCellMeta(4, 0).type).toEqual('numeric');
  520. expect(getDataAtCell(4, 0)).toEqual(null);
  521. expect(getCellMeta(4, 2).type).toEqual('checkbox');
  522. expect(getDataAtCell(4, 2)).toEqual(null);
  523. });
  524. it('should insert the amount of rows at given index', function() {
  525. handsontable({
  526. data: [
  527. ['a1', 'a2', 'a3'],
  528. ['b1', 'b2', 'b3'],
  529. ['c1', 'c2', 'c3'],
  530. ['d1', 'd2', 'd3'],
  531. ['e1', 'e2', 'e3']
  532. ]
  533. });
  534. alter('insert_row', 1, 3);
  535. expect(countRows()).toEqual(8);
  536. expect(this.$container.find('tr:eq(1) td:eq(0)').html()).toEqual('');
  537. expect(this.$container.find('tr:eq(4) td:eq(0)').html()).toEqual('b1');
  538. });
  539. it('should insert the amount of rows at the end if index is not given', () => {
  540. handsontable({
  541. data: [
  542. ['a1', 'a2', 'a3'],
  543. ['b1', 'b2', 'b3'],
  544. ['c1', 'c2', 'c3'],
  545. ['d1', 'd2', 'd3'],
  546. ['e1', 'e2', 'e3']
  547. ]
  548. });
  549. alter('insert_row', null, 3);
  550. expect(countRows()).toEqual(8);
  551. expect(getHtCore().find('tr:eq(4) td:eq(0)').html()).toEqual('e1');
  552. expect(getHtCore().find('tr:eq(5) td:eq(0)').html()).toEqual('');
  553. expect(getHtCore().find('tr:eq(6) td:eq(0)').html()).toEqual('');
  554. expect(getHtCore().find('tr:eq(7) td:eq(0)').html()).toEqual('');
  555. });
  556. it('should insert not more rows than maxRows', () => {
  557. handsontable({
  558. startRows: 5,
  559. maxRows: 7
  560. });
  561. alter('insert_row', 1);
  562. alter('insert_row', 1);
  563. alter('insert_row', 1);
  564. expect(countRows()).toEqual(7);
  565. });
  566. it('when amount parameter is used, should not insert more rows than allowed by maxRows', function() {
  567. handsontable({
  568. data: [
  569. ['a1', 'a2', 'a3'],
  570. ['b1', 'b2', 'b3'],
  571. ['c1', 'c2', 'c3'],
  572. ['d1', 'd2', 'd3'],
  573. ['e1', 'e2', 'e3']
  574. ],
  575. maxRows: 10
  576. });
  577. alter('insert_row', 1, 10);
  578. expect(countRows()).toEqual(10);
  579. expect(this.$container.find('tr:eq(6) td:eq(0)').html()).toEqual('b1');
  580. });
  581. it('should not add more source rows than defined in maxRows when trimming rows using the modifyRow hook', () => {
  582. var hot = handsontable({
  583. data: Handsontable.helper.createSpreadsheetData(10, 4),
  584. modifyRow(row) {
  585. return [8, 9].indexOf(row) > -1 ? null : row;
  586. },
  587. maxRows: 10
  588. });
  589. expect(hot.countRows()).toEqual(8);
  590. hot.populateFromArray(7, 0, [['a'], ['b'], ['c']]);
  591. expect(hot.countSourceRows()).toEqual(10);
  592. expect(hot.getDataAtCell(7, 0)).toEqual('a');
  593. });
  594. it('should fire callback on create row', () => {
  595. var outputBefore;
  596. var outputAfter;
  597. handsontable({
  598. minRows: 5,
  599. data: arrayOfNestedObjects(),
  600. columns: [
  601. {data: 'id'},
  602. {data: 'name.first'}
  603. ],
  604. beforeCreateRow(index, amount, source) {
  605. outputBefore = [index, amount, source];
  606. },
  607. afterCreateRow(index, amount, source) {
  608. outputAfter = [index, amount, source];
  609. },
  610. });
  611. alter('insert_row', 3, 1, 'customSource');
  612. expect(outputBefore).toEqual([3, 1, 'customSource']);
  613. expect(outputAfter).toEqual([3, 1, 'customSource']);
  614. });
  615. it('should keep the single-cell selection in the same position as before inserting the row', () => {
  616. handsontable({
  617. minRows: 5,
  618. data: [
  619. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
  620. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
  621. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
  622. ]
  623. });
  624. selectCell(2, 2);
  625. alter('insert_row', 2);
  626. var selected = getSelected();
  627. expect(selected[0]).toEqual(3);
  628. expect(selected[2]).toEqual(3);
  629. });
  630. it('should shift the cell meta according to the new row layout', () => {
  631. var hot = handsontable({
  632. startCols: 4,
  633. startRows: 3
  634. });
  635. setCellMeta(2, 1, 'className', 'test');
  636. alter('insert_row', 1, 1);
  637. expect(getCellMeta(3, 1).className).toEqual('test');
  638. });
  639. it('should shift the cell meta according to the new rows (>1) layout', () => {
  640. var hot = handsontable({
  641. startCols: 4,
  642. startRows: 3
  643. });
  644. setCellMeta(2, 1, 'className', 'test');
  645. alter('insert_row', 0, 3);
  646. expect(getCellMeta(5, 1).className).toEqual('test');
  647. });
  648. });
  649. describe('insert column', () => {
  650. it('should insert column at given index', function() {
  651. handsontable({
  652. data: [
  653. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
  654. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
  655. ]
  656. });
  657. alter('insert_col', 1);
  658. expect(countCols()).toEqual(9);
  659. expect(this.$container.find('tr:eq(1) td:eq(2)').html()).toEqual('b');
  660. });
  661. it('should insert column at the end if index is not given', function() {
  662. handsontable({
  663. data: [
  664. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
  665. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
  666. ]
  667. });
  668. alter('insert_col');
  669. expect(countCols()).toEqual(9);
  670. expect(this.$container.find('tr:eq(1) td:eq(7)').html()).toEqual('h');
  671. });
  672. it('should insert the amount of columns at given index', function() {
  673. handsontable({
  674. data: [
  675. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
  676. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
  677. ]
  678. });
  679. alter('insert_col', 1, 3);
  680. expect(countCols()).toEqual(11);
  681. expect(this.$container.find('tr:eq(1) td:eq(4)').html()).toEqual('b');
  682. });
  683. it('should insert the amount of columns at the end if index is not given', function() {
  684. handsontable({
  685. data: [
  686. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
  687. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
  688. ]
  689. });
  690. alter('insert_col', null, 3);
  691. expect(countCols()).toEqual(11);
  692. expect(this.$container.find('tr:eq(1) td:eq(7)').html()).toEqual('h');
  693. expect(this.$container.find('tr:eq(1) td:eq(8)').html()).toEqual('');
  694. expect(this.$container.find('tr:eq(1) td:eq(9)').html()).toEqual('');
  695. expect(this.$container.find('tr:eq(1) td:eq(10)').html()).toEqual('');
  696. });
  697. it('should insert not more cols than maxCols', () => {
  698. handsontable({
  699. startCols: 5,
  700. maxCols: 7
  701. });
  702. alter('insert_col', 1);
  703. alter('insert_col', 1);
  704. alter('insert_col', 1);
  705. expect(countCols()).toEqual(7);
  706. });
  707. it('should not insert more columns than allowed by maxCols, when amount parameter is used', function() {
  708. handsontable({
  709. data: [
  710. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
  711. ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
  712. ],
  713. maxCols: 10
  714. });
  715. alter('insert_col', 1, 10);
  716. expect(countCols()).toEqual(10);
  717. expect(this.$container.find('tr:eq(1) td:eq(1)').html()).toEqual('');
  718. expect(this.$container.find('tr:eq(1) td:eq(2)').html()).toEqual('');
  719. expect(this.$container.find('tr:eq(1) td:eq(3)').html()).toEqual('b');
  720. });
  721. it('should fire callback on create col', () => {
  722. var outputBefore;
  723. var outputAfter;
  724. handsontable({
  725. minRows: 5,
  726. data: arrayOfArrays(),
  727. beforeCreateCol(index, amount, source) {
  728. outputBefore = [index, amount, source];
  729. },
  730. afterCreateCol(index, amount, source) {
  731. outputAfter = [index, amount, source];
  732. },
  733. });
  734. alter('insert_col', 2, 1, 'customSource');
  735. expect(outputBefore).toEqual([2, 1, 'customSource']);
  736. expect(outputAfter).toEqual([2, 1, 'customSource']);
  737. });
  738. it('should not create column header together with the column, if headers were NOT specified explicitly', () => {
  739. handsontable({
  740. startCols: 3,
  741. startRows: 2,
  742. colHeaders: true
  743. });
  744. expect(getColHeader()).toEqual(['A', 'B', 'C']);
  745. expect(countCols()).toEqual(3);
  746. alter('insert_col', 1);
  747. expect(countCols()).toEqual(4);
  748. expect(getColHeader()).toEqual(['A', 'B', 'C', 'D']);
  749. });
  750. it('should create column header together with the column, if headers were specified explicitly', () => {
  751. handsontable({
  752. startCols: 3,
  753. startRows: 2,
  754. colHeaders: ['Header0', 'Header1', 'Header2']
  755. });
  756. expect(getColHeader()).toEqual(['Header0', 'Header1', 'Header2']);
  757. expect(countCols()).toEqual(3);
  758. alter('insert_col', 1);
  759. expect(countCols()).toEqual(4);
  760. expect(getColHeader()).toEqual(['Header0', 'B', 'Header1', 'Header2']);
  761. });
  762. it('should stretch the table after adding another column (if stretching is set to \'all\')', function() {
  763. this.$container.css({
  764. width: 500,
  765. });
  766. var hot = handsontable({
  767. startCols: 5,
  768. startRows: 10,
  769. stretchH: 'all'
  770. });
  771. expect(Handsontable.dom.outerWidth(hot.view.TBODY)).toEqual(500);
  772. alter('insert_col', null, 1);
  773. expect(Handsontable.dom.outerWidth(hot.view.TBODY)).toEqual(500);
  774. alter('insert_col', null, 1);
  775. expect(Handsontable.dom.outerWidth(hot.view.TBODY)).toEqual(500);
  776. });
  777. it('should shift the cell meta according to the new column layout', () => {
  778. var hot = handsontable({
  779. startCols: 4,
  780. startRows: 3
  781. });
  782. setCellMeta(1, 2, 'className', 'test');
  783. alter('insert_col', 1, 1);
  784. expect(getCellMeta(1, 3).className).toEqual('test');
  785. });
  786. it('should shift the cell meta according to the new columns (>1) layout', () => {
  787. var hot = handsontable({
  788. startCols: 4,
  789. startRows: 3
  790. });
  791. setCellMeta(1, 2, 'className', 'test');
  792. alter('insert_col', 0, 3);
  793. expect(getCellMeta(1, 5).className).toEqual('test');
  794. });
  795. });
  796. });