table.spec.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. describe('WalkontableTable', function () {
  2. var $table,
  3. $container,
  4. $wrapper,
  5. debug = false;
  6. beforeEach(function () {
  7. $wrapper = $('<div></div>').css({ overflow: 'hidden', position: 'relative' });
  8. $wrapper.width(100).height(201);
  9. $container = $('<div></div>');
  10. $table = $('<table></table>'); // create a table that is not attached to document
  11. $wrapper.append($container);
  12. $container.append($table);
  13. $wrapper.appendTo('body');
  14. createDataArray();
  15. });
  16. afterEach(function () {
  17. if (!debug) {
  18. $('.wtHolder').remove();
  19. }
  20. $wrapper.remove();
  21. });
  22. it('should create as many rows as fits in height', function () {
  23. var wt = new Walkontable.Core({
  24. table: $table[0],
  25. data: getData,
  26. totalRows: getTotalRows,
  27. totalColumns: getTotalColumns
  28. });
  29. wt.draw();
  30. expect($table.find('tbody tr').length).toBe(9);
  31. });
  32. it('should create as many rows as in `totalRows` if it is smaller than `height`', function () {
  33. this.data.splice(5, this.data.length - 5);
  34. var wt = new Walkontable.Core({
  35. table: $table[0],
  36. data: getData,
  37. totalRows: getTotalRows,
  38. totalColumns: getTotalColumns
  39. });
  40. wt.draw();
  41. expect($table.find('tbody tr').length).toBe(5);
  42. });
  43. it('first row should have as many columns as in THEAD', function () {
  44. var wt = new Walkontable.Core({
  45. table: $table[0],
  46. data: getData,
  47. totalRows: getTotalRows,
  48. totalColumns: getTotalColumns,
  49. columnHeaders: [function (col, TH) {
  50. TH.innerHTML = col + 1;
  51. }]
  52. });
  53. wt.draw();
  54. expect($table.find('tbody tr:first td').length).toBe($table.find('thead th').length);
  55. });
  56. it('should put a blank cell in the corner if both rowHeaders and colHeaders are set', function () {
  57. var wt = new Walkontable.Core({
  58. table: $table[0],
  59. data: getData,
  60. totalRows: getTotalRows,
  61. totalColumns: getTotalColumns,
  62. columnHeaders: [function (col, TH) {
  63. if (col > -1) {
  64. TH.innerHTML = 'Column';
  65. }
  66. }],
  67. rowHeaders: [function (row, TH) {
  68. if (row > -1) {
  69. TH.innerHTML = 'Row';
  70. }
  71. }]
  72. });
  73. wt.draw();
  74. expect($table.find('thead tr:first th').length).toBe(wt.wtTable.getRenderedColumnsCount() + 1); // 4 columns in THEAD + 1 empty cell in the corner
  75. expect($table.find('thead tr:first th:eq(0)')[0].innerHTML.replace(/&nbsp;/, '')).toBe(''); // corner row is empty (or contains only &nbsp;)
  76. expect($table.find('thead tr:first th:eq(1)')[0].innerHTML).toBe('Column');
  77. expect($table.find('tbody tr:first th:eq(0)')[0].innerHTML).toBe('Row');
  78. });
  79. it('getCell should only return cells from rendered rows', function () {
  80. var wt = new Walkontable.Core({
  81. table: $table[0],
  82. data: getData,
  83. totalRows: getTotalRows,
  84. totalColumns: getTotalColumns
  85. });
  86. wt.draw();
  87. expect(wt.wtTable.getCell(new Walkontable.CellCoords(7, 0)) instanceof HTMLElement).toBe(true);
  88. expect($table.find('tr:eq(8) td:first-child').text()).toEqual(this.data[8][0].toString());
  89. expect(wt.wtTable.getCell(new Walkontable.CellCoords(20, 0))).toBe(-2); // exit code
  90. expect(wt.wtTable.getCell(new Walkontable.CellCoords(25, 0))).toBe(-2); // exit code
  91. });
  92. it('getCoords should return coords of TD', function () {
  93. var wt = new Walkontable.Core({
  94. table: $table[0],
  95. data: getData,
  96. totalRows: getTotalRows,
  97. totalColumns: getTotalColumns
  98. });
  99. wt.draw();
  100. var $td2 = $table.find('tbody tr:eq(1) td:eq(1)');
  101. expect(wt.wtTable.getCoords($td2[0])).toEqual(new Walkontable.CellCoords(1, 1));
  102. });
  103. it('getCoords should return coords of TD (with row header)', function () {
  104. $wrapper.width(300);
  105. function plusOne(i) {
  106. return i + 1;
  107. }
  108. var wt = new Walkontable.Core({
  109. table: $table[0],
  110. data: getData,
  111. totalRows: getTotalRows,
  112. totalColumns: getTotalColumns,
  113. rowHeaders: [function (row, TH) {
  114. TH.innerHTML = plusOne(row);
  115. }]
  116. });
  117. wt.draw();
  118. var $td2 = $table.find('tbody tr:eq(1) td:eq(1)');
  119. expect(wt.wtTable.getCoords($td2[0])).toEqual(new Walkontable.CellCoords(1, 1));
  120. });
  121. it('getStretchedColumnWidth should return valid column width when stretchH is set as \'all\'', function () {
  122. var wt = new Walkontable.Core({
  123. table: $table[0],
  124. data: getData,
  125. totalRows: getTotalRows,
  126. totalColumns: getTotalColumns,
  127. rowHeaders: [function (row, TH) {
  128. TH.innerHTML = row + 1;
  129. }],
  130. stretchH: 'all'
  131. });
  132. wt.draw();
  133. wt.wtViewport.columnsRenderCalculator.refreshStretching(502);
  134. expect(wt.wtTable.getStretchedColumnWidth(0, 50)).toBe(125);
  135. expect(wt.wtTable.getStretchedColumnWidth(1, 50)).toBe(125);
  136. expect(wt.wtTable.getStretchedColumnWidth(2, 50)).toBe(125);
  137. expect(wt.wtTable.getStretchedColumnWidth(3, 50)).toBe(127);
  138. });
  139. it('getStretchedColumnWidth should return valid column width when stretchH is set as \'last\'', function () {
  140. var wt = new Walkontable.Core({
  141. table: $table[0],
  142. data: getData,
  143. totalRows: getTotalRows,
  144. totalColumns: getTotalColumns,
  145. rowHeaders: [function (row, TH) {
  146. TH.innerHTML = row + 1;
  147. }],
  148. stretchH: 'last'
  149. });
  150. wt.draw();
  151. wt.wtViewport.columnsRenderCalculator.refreshStretching(502);
  152. expect(wt.wtTable.getStretchedColumnWidth(0, 50)).toBe(50);
  153. expect(wt.wtTable.getStretchedColumnWidth(1, 50)).toBe(50);
  154. expect(wt.wtTable.getStretchedColumnWidth(2, 50)).toBe(50);
  155. expect(wt.wtTable.getStretchedColumnWidth(3, 50)).toBe(352);
  156. });
  157. it('should use custom cell renderer if provided', function () {
  158. var wt = new Walkontable.Core({
  159. table: $table[0],
  160. data: getData,
  161. totalRows: getTotalRows,
  162. totalColumns: getTotalColumns,
  163. cellRenderer: function cellRenderer(row, column, TD) {
  164. var cellData = getData(row, column);
  165. if (cellData === void 0) {
  166. TD.innerHTML = '';
  167. } else {
  168. TD.innerHTML = cellData;
  169. }
  170. TD.className = '';
  171. TD.style.backgroundColor = 'yellow';
  172. }
  173. });
  174. wt.draw();
  175. expect($table.find('td:first')[0].style.backgroundColor).toBe('yellow');
  176. });
  177. it('should remove rows if they were removed in data source', function () {
  178. this.data.splice(8, this.data.length - 8); // second param is required by IE8
  179. var wt = new Walkontable.Core({
  180. table: $table[0],
  181. data: getData,
  182. totalRows: getTotalRows,
  183. totalColumns: getTotalColumns
  184. });
  185. wt.draw();
  186. expect($table.find('tbody tr').length).toBe(8);
  187. this.data.splice(7, this.data.length - 7); // second param is required by IE8
  188. wt.draw();
  189. expect($table.find('tbody tr').length).toBe(7);
  190. });
  191. it('should render as much columns as the container width allows, if width is null', function () {
  192. var wt = new Walkontable.Core({
  193. table: $table[0],
  194. data: getData,
  195. totalRows: getTotalRows,
  196. totalColumns: getTotalColumns,
  197. columnHeaders: [function (col, TH) {
  198. TH.innerHTML = col + 1;
  199. }]
  200. });
  201. wt.draw();
  202. expect($table.find('thead tr:first').children().length).toBe(2);
  203. expect($table.find('tbody tr:first').children().length).toBe(2);
  204. $wrapper.width(200);
  205. wt.draw();
  206. expect($table.find('thead tr:first').children().length).toBe(4);
  207. expect($table.find('tbody tr:first').children().length).toBe(4);
  208. });
  209. it('should render as much columns as the container width allows, if width is null (with row header)', function () {
  210. var wt = new Walkontable.Core({
  211. table: $table[0],
  212. data: getData,
  213. totalRows: getTotalRows,
  214. totalColumns: getTotalColumns,
  215. rowHeaders: [function (row, TH) {
  216. TH.innerHTML = row + 1;
  217. }],
  218. columnHeaders: [function (col, TH) {
  219. TH.innerHTML = col + 1;
  220. }]
  221. });
  222. wt.draw();
  223. expect($table.find('thead tr:first').children().length).toBe(2);
  224. expect($table.find('tbody tr:first').children().length).toBe(2);
  225. $wrapper.width(200);
  226. wt.draw();
  227. expect($table.find('thead tr:first').children().length).toBe(4);
  228. expect($table.find('tbody tr:first').children().length).toBe(4);
  229. });
  230. it('should use column width function to get column width', function () {
  231. $wrapper.width(600);
  232. var wt = new Walkontable.Core({
  233. table: $table[0],
  234. data: getData,
  235. totalRows: getTotalRows,
  236. totalColumns: getTotalColumns,
  237. rowHeaders: [function (row, TH) {
  238. TH.innerHTML = row + 1;
  239. }],
  240. columnHeaders: [function (col, TH) {
  241. TH.innerHTML = col + 1;
  242. }],
  243. columnWidth: function columnWidth(column) {
  244. return (column + 1) * 50;
  245. }
  246. });
  247. wt.draw();
  248. expect($table.find('tbody tr:first td:eq(0)').outerWidth()).toBe(50);
  249. expect($table.find('tbody tr:first td:eq(1)').outerWidth()).toBe(100);
  250. expect($table.find('tbody tr:first td:eq(2)').outerWidth()).toBe(150);
  251. expect($table.find('tbody tr:first td:eq(3)').outerWidth()).toBe(200);
  252. });
  253. it('should use column width array to get column width', function () {
  254. $wrapper.width(600);
  255. var wt = new Walkontable.Core({
  256. table: $table[0],
  257. data: getData,
  258. totalRows: getTotalRows,
  259. totalColumns: getTotalColumns,
  260. rowHeaders: [function (row, TH) {
  261. TH.innerHTML = row + 1;
  262. }],
  263. columnHeaders: [function (col, TH) {
  264. TH.innerHTML = col + 1;
  265. }],
  266. columnWidth: [50, 100, 150, 201]
  267. });
  268. wt.draw();
  269. expect($table.find('tbody tr:first td:eq(0)').outerWidth()).toBe(50);
  270. expect($table.find('tbody tr:first td:eq(1)').outerWidth()).toBe(100);
  271. expect($table.find('tbody tr:first td:eq(2)').outerWidth()).toBe(150);
  272. expect($table.find('tbody tr:first td:eq(3)').outerWidth()).toBe(201);
  273. });
  274. it('should use column width integer to get column width', function () {
  275. $wrapper.width(600);
  276. var wt = new Walkontable.Core({
  277. table: $table[0],
  278. data: getData,
  279. totalRows: getTotalRows,
  280. totalColumns: getTotalColumns,
  281. rowHeaders: [function (row, TH) {
  282. TH.innerHTML = row + 1;
  283. }],
  284. columnHeaders: [function (col, TH) {
  285. TH.innerHTML = col + 1;
  286. }],
  287. columnWidth: 100
  288. });
  289. wt.draw();
  290. expect($table.find('tbody tr:first td:eq(0)').outerWidth()).toBe(100);
  291. expect($table.find('tbody tr:first td:eq(1)').outerWidth()).toBe(100);
  292. expect($table.find('tbody tr:first td:eq(2)').outerWidth()).toBe(100);
  293. expect($table.find('tbody tr:first td:eq(3)').outerWidth()).toBe(100);
  294. });
  295. it('should use column width also when there are no rows', function () {
  296. this.data.length = 0;
  297. $wrapper.width(600);
  298. var wt = new Walkontable.Core({
  299. table: $table[0],
  300. data: getData,
  301. totalRows: getTotalRows,
  302. totalColumns: 4,
  303. rowHeaders: [function (row, TH) {
  304. TH.innerHTML = row + 1;
  305. }],
  306. columnHeaders: [function (col, TH) {
  307. TH.innerHTML = col + 1;
  308. }],
  309. columnWidth: 100
  310. });
  311. wt.draw();
  312. // start from eq(1) because eq(0) is corner header
  313. expect($table.find('thead tr:first th:eq(1)').outerWidth()).toBe(100);
  314. expect($table.find('thead tr:first th:eq(2)').outerWidth()).toBe(100);
  315. expect($table.find('thead tr:first th:eq(3)').outerWidth()).toBe(100);
  316. expect($table.find('thead tr:first th:eq(4)').outerWidth()).toBe(100);
  317. });
  318. it('should render a cell that is outside of the viewport horizontally', function () {
  319. var wt = new Walkontable.Core({
  320. table: $table[0],
  321. data: getData,
  322. totalRows: getTotalRows,
  323. totalColumns: getTotalColumns
  324. });
  325. wt.draw();
  326. $table.find('tbody td').html('');
  327. wt.draw();
  328. expect($table.find('tbody tr:first td').length).toBe(2);
  329. });
  330. it('should not render a cell when fastDraw == true', function () {
  331. var count = 0,
  332. wt = new Walkontable.Core({
  333. table: $table[0],
  334. data: getData,
  335. totalRows: getTotalRows,
  336. totalColumns: getTotalColumns,
  337. cellRenderer: function cellRenderer(row, column, TD) {
  338. count++;
  339. return wt.wtSettings.defaults.cellRenderer(row, column, TD);
  340. }
  341. });
  342. wt.draw();
  343. var oldCount = count;
  344. wt.draw(true);
  345. expect(count).toBe(oldCount);
  346. });
  347. it('should not ignore fastDraw == true when grid was scrolled by amount of rows that doesn\'t exceed endRow', function () {
  348. var count = 0,
  349. wt = new Walkontable.Core({
  350. table: $table[0],
  351. data: getData,
  352. totalRows: getTotalRows,
  353. totalColumns: getTotalColumns,
  354. cellRenderer: function cellRenderer(row, column, TD) {
  355. count++;
  356. return wt.wtSettings.defaults.cellRenderer(row, column, TD);
  357. },
  358. viewportRowCalculatorOverride: function viewportRowCalculatorOverride(calc) {
  359. calc.endRow += 10;
  360. }
  361. });
  362. wt.draw();
  363. var oldCount = count;
  364. wt.scrollVertical(8);
  365. wt.draw(true);
  366. expect(count).not.toBeGreaterThan(oldCount);
  367. });
  368. it('should ignore fastDraw == true when grid was scrolled by amount of rows that exceeds endRow', function () {
  369. var count = 0,
  370. wt = new Walkontable.Core({
  371. table: $table[0],
  372. data: getData,
  373. totalRows: getTotalRows,
  374. totalColumns: getTotalColumns,
  375. cellRenderer: function cellRenderer(row, column, TD) {
  376. count++;
  377. return wt.wtSettings.defaults.cellRenderer(row, column, TD);
  378. },
  379. viewportRowCalculatorOverride: function viewportRowCalculatorOverride(calc) {
  380. calc.endRow += 10;
  381. }
  382. });
  383. wt.draw();
  384. var oldCount = count;
  385. wt.scrollVertical(10);
  386. wt.draw(true);
  387. expect(count).not.toBeGreaterThan(oldCount);
  388. wt.scrollVertical(11);
  389. wt.draw(true);
  390. expect(count).toBeGreaterThan(oldCount);
  391. });
  392. it('should not ignore fastDraw == true when grid was scrolled by amount of columns that doesn\'t exceed endColumn', function () {
  393. createDataArray(50, 50);
  394. var count = 0,
  395. wt = new Walkontable.Core({
  396. table: $table[0],
  397. data: getData,
  398. totalRows: getTotalRows,
  399. totalColumns: getTotalColumns,
  400. cellRenderer: function cellRenderer(row, column, TD) {
  401. count++;
  402. return wt.wtSettings.defaults.cellRenderer(row, column, TD);
  403. },
  404. viewportColumnCalculatorOverride: function viewportColumnCalculatorOverride(calc) {
  405. calc.endColumn += 10;
  406. }
  407. });
  408. wt.draw();
  409. var oldCount = count;
  410. wt.scrollHorizontal(8);
  411. wt.draw(true);
  412. expect(count).not.toBeGreaterThan(oldCount);
  413. });
  414. it('should ignore fastDraw == true when grid was scrolled by amount of columns that exceeds endColumn', function () {
  415. createDataArray(50, 50);
  416. var count = 0,
  417. wt = new Walkontable.Core({
  418. table: $table[0],
  419. data: getData,
  420. totalRows: getTotalRows,
  421. totalColumns: getTotalColumns,
  422. cellRenderer: function cellRenderer(row, column, TD) {
  423. count++;
  424. return wt.wtSettings.defaults.cellRenderer(row, column, TD);
  425. },
  426. viewportColumnCalculatorOverride: function viewportColumnCalculatorOverride(calc) {
  427. calc.endColumn += 10;
  428. }
  429. });
  430. wt.draw();
  431. var oldCount = count;
  432. wt.scrollHorizontal(10);
  433. wt.draw(true);
  434. expect(count).not.toBeGreaterThan(oldCount);
  435. wt.scrollHorizontal(11);
  436. wt.draw(true);
  437. expect(count).toBeGreaterThan(oldCount);
  438. });
  439. describe('cell header border', function () {
  440. it('should be correct visible in fixedColumns and without row header', function () {
  441. createDataArray(50, 50);
  442. $wrapper.width(500).height(400);
  443. var count = 0,
  444. wt = new Walkontable.Core({
  445. table: $table[0],
  446. data: getData,
  447. totalRows: getTotalRows,
  448. totalColumns: getTotalColumns,
  449. columnWidth: 70,
  450. fixedColumnsLeft: 2,
  451. columnHeaders: [function (col, TH) {}]
  452. });
  453. wt.draw();
  454. expect($('.ht_clone_top_left_corner thead tr th').eq(0).css('border-left-width')).toBe('1px');
  455. expect($('.ht_clone_top_left_corner thead tr th').eq(0).css('border-right-width')).toBe('1px');
  456. expect($('.ht_clone_top_left_corner thead tr th').eq(1).css('border-left-width')).toBe('0px');
  457. expect($('.ht_clone_top_left_corner thead tr th').eq(1).css('border-right-width')).toBe('1px');
  458. });
  459. });
  460. describe('isLastRowFullyVisible', function () {
  461. it('should be false because it is only partially visible', function () {
  462. createDataArray(8, 4);
  463. $wrapper.width(185).height(175);
  464. var wt = new Walkontable.Core({
  465. table: $table[0],
  466. data: getData,
  467. totalRows: getTotalRows,
  468. totalColumns: getTotalColumns
  469. });
  470. wt.draw();
  471. expect(wt.wtTable.isLastRowFullyVisible()).toEqual(false);
  472. });
  473. it('should be true because it is fully visible', function () {
  474. createDataArray(8, 4);
  475. $wrapper.width(185).height(185);
  476. var wt = new Walkontable.Core({
  477. table: $table[0],
  478. data: getData,
  479. totalRows: getTotalRows,
  480. totalColumns: getTotalColumns
  481. });
  482. wt.draw();
  483. wt.scrollVertical(7);
  484. wt.draw();
  485. expect(wt.wtTable.isLastRowFullyVisible()).toEqual(true);
  486. });
  487. });
  488. xdescribe('isLastColumnFullyVisible', function () {
  489. it('should be false because it is only partially visible', function () {
  490. createDataArray(18, 4);
  491. $wrapper.width(209).height(185);
  492. var wt = new Walkontable.Core({
  493. table: $table[0],
  494. data: getData,
  495. totalRows: getTotalRows,
  496. totalColumns: getTotalColumns
  497. });
  498. wt.draw();
  499. expect(wt.wtTable.isLastColumnFullyVisible()).toEqual(false); // few pixels are obstacled by scrollbar
  500. });
  501. it('should be true because it is fully visible', function () {
  502. createDataArray(18, 4);
  503. $wrapper.width(180).height(185);
  504. var wt = new Walkontable.Core({
  505. table: $table[0],
  506. data: getData,
  507. totalRows: getTotalRows,
  508. totalColumns: getTotalColumns
  509. });
  510. wt.draw();
  511. wt.scrollHorizontal(1);
  512. expect(wt.wtTable.isLastColumnFullyVisible()).toEqual(true);
  513. });
  514. });
  515. });