6201dba2a6243916a18265be87b842fdf071ec27c90f77065e115d322c6fd4097ea64853385d6ed1c13f0b41a2fa9e056469c1345b909dcdda217d46d839fe 18 KB

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