observeChanges.e2e.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. describe('HandsontableObserveChanges', function () {
  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. function createHOT(data, observeChanges) {
  13. return handsontable({
  14. data: data,
  15. width: 200,
  16. height: 200,
  17. observeChanges: observeChanges
  18. });
  19. }
  20. describe('refreshing table after changes have been detected', function () {
  21. describe('array data', function () {
  22. it('should render newly added row', function (done) {
  23. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  24. var hot = createHOT(data, true);
  25. data.push(['A3', 'B3']);
  26. var htCore = getHtCore();
  27. setTimeout(function () {
  28. expect(htCore.find('tr').length).toEqual(3);
  29. expect(htCore.find('col').length).toEqual(2);
  30. done();
  31. }, 200);
  32. });
  33. it('should render newly added column', function (done) {
  34. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  35. var hot = createHOT(data, true);
  36. var htCore = getHtCore();
  37. data[0].push('C1');
  38. data[1].push('C2');
  39. setTimeout(function () {
  40. expect(htCore.find('tr').length).toEqual(2);
  41. expect(htCore.find('col').length).toEqual(3);
  42. done();
  43. }, 200);
  44. });
  45. it('should render removed row', function (done) {
  46. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  47. var hot = createHOT(data, true);
  48. var htCore = getHtCore();
  49. data.splice(0, 1); // removes one row at index 0
  50. setTimeout(function () {
  51. expect(htCore.find('tr').length).toEqual(1);
  52. expect(htCore.find('col').length).toEqual(2);
  53. done();
  54. }, 200);
  55. });
  56. it('should render removed column', function (done) {
  57. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  58. var hot = createHOT(data, true);
  59. var htCore = getHtCore();
  60. data[0].splice(0, 1); // removes one column at index 0 in first row
  61. data[1].splice(0, 1); // removes one column at index 0 in second row
  62. setTimeout(function () {
  63. expect(htCore.find('tr').length).toEqual(2);
  64. expect(htCore.find('col').length).toEqual(1);
  65. done();
  66. }, 200);
  67. });
  68. it('should render cell change from string to string', function (done) {
  69. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  70. var hot = createHOT(data, true);
  71. var htCore = getHtCore();
  72. data[0][0] = 'new string';
  73. setTimeout(function () {
  74. expect(htCore.find('td:eq(0)').html()).toEqual('new string');
  75. done();
  76. }, 200);
  77. });
  78. it('should render cell change in a new row', function (done) {
  79. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  80. var hot = createHOT(data, true);
  81. var htCore = getHtCore();
  82. data.push(['A3', 'B3']);
  83. setTimeout(function () {
  84. expect(htCore.find('tr:eq(2) td:eq(0)').html()).toEqual('A3');
  85. data[2][0] = 'new string';
  86. }, 200);
  87. setTimeout(function () {
  88. expect(htCore.find('tr:eq(2) td:eq(0)').html()).toEqual('new string');
  89. done();
  90. }, 1200);
  91. });
  92. it('should not render cell change when turned off (`observeChanges: false`)', function (done) {
  93. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  94. createHOT(data, false);
  95. var htCore = getHtCore();
  96. data[0][0] = 'new string';
  97. setTimeout(function () {
  98. expect(htCore.find('td:eq(0)').html()).toEqual('A1');
  99. done();
  100. }, 100);
  101. });
  102. });
  103. describe('object data', function () {
  104. it('should render newly added row', function (done) {
  105. var data = Handsontable.helper.createSpreadsheetObjectData(2, 2);
  106. var hot = createHOT(data, true);
  107. var htCore = getHtCore();
  108. data.push({ prop0: 'A3', prop1: 'B3' });
  109. setTimeout(function () {
  110. expect(htCore.find('tr').length).toEqual(3);
  111. expect(htCore.find('col').length).toEqual(2);
  112. done();
  113. }, 200);
  114. });
  115. it('should render removed row', function (done) {
  116. var data = Handsontable.helper.createSpreadsheetObjectData(2, 2);
  117. var hot = createHOT(data, true);
  118. var htCore = getHtCore();
  119. data.splice(0, 1); // removes one row at index 0
  120. setTimeout(function () {
  121. expect(htCore.find('tr').length).toEqual(1);
  122. expect(htCore.find('col').length).toEqual(2);
  123. done();
  124. }, 200);
  125. });
  126. it('should render cell change from string to string', function (done) {
  127. var data = Handsontable.helper.createSpreadsheetObjectData(2, 2);
  128. var hot = createHOT(data, true);
  129. var htCore = getHtCore();
  130. data[0].prop0 = 'new string';
  131. setTimeout(function () {
  132. expect(htCore.find('td:eq(0)').html()).toEqual('new string');
  133. done();
  134. }, 200);
  135. });
  136. it('should render cell change in a new row', function (done) {
  137. var data = Handsontable.helper.createSpreadsheetObjectData(2, 2);
  138. var hot = createHOT(data, true);
  139. var htCore = getHtCore();
  140. data.push({ prop0: 'A3', prop1: 'B3' });
  141. setTimeout(function () {
  142. expect(htCore.find('tr:eq(2) td:eq(0)').html()).toEqual('A3');
  143. data[2].prop0 = 'new string';
  144. }, 200);
  145. setTimeout(function () {
  146. expect(htCore.find('tr:eq(2) td:eq(0)').html()).toEqual('new string');
  147. done();
  148. }, 1200);
  149. });
  150. it('should not break with undefined data properties', function () {
  151. var data = Handsontable.helper.createSpreadsheetObjectData(2, 2);
  152. data[0].prop0 = undefined;
  153. expect(function () {
  154. var hot = createHOT(data, true);
  155. var htCore = getHtCore();
  156. }).not.toThrow();
  157. });
  158. it('should not render cell change when turned off (`observeChanges: false`)', function (done) {
  159. var data = Handsontable.helper.createSpreadsheetObjectData(2, 2);
  160. createHOT(data, false);
  161. var htCore = getHtCore();
  162. data[0].prop0 = 'new string';
  163. setTimeout(function () {
  164. expect(htCore.find('td:eq(0)').html()).toEqual('A1');
  165. done();
  166. }, 200);
  167. });
  168. });
  169. });
  170. describe('enabling/disabling plugin', function () {
  171. it('should be possible to enable plugin using updateSettings', function (done) {
  172. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  173. var hot = createHOT(data, false);
  174. var htCore = getHtCore();
  175. data[0][0] = 'new string';
  176. setTimeout(function () {
  177. expect(htCore.find('td:eq(0)').html()).toEqual('A1');
  178. updateSettings({
  179. observeChanges: true
  180. });
  181. data[1][0] = 'another new string';
  182. }, 200);
  183. setTimeout(function () {
  184. expect(htCore.find('tr:eq(1) td:eq(0)').html()).toEqual('another new string');
  185. done();
  186. }, 400);
  187. });
  188. it('should be possible to disable plugin using updateSettings', function (done) {
  189. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  190. var hot = createHOT(data, true);
  191. var htCore = getHtCore();
  192. data[0][0] = 'new string';
  193. setTimeout(function () {
  194. expect(htCore.find('tbody tr:eq(0) td:eq(0)').html()).toEqual('new string');
  195. expect(htCore.find('tbody tr:eq(1) td:eq(0)').html()).toEqual('A2');
  196. updateSettings({
  197. observeChanges: false
  198. });
  199. data[1][0] = 'another new string';
  200. }, 200);
  201. setTimeout(function () {
  202. expect(htCore.find('tbody tr:eq(0) td:eq(0)').html()).toEqual('new string');
  203. expect(htCore.find('tbody tr:eq(1) td:eq(0)').html()).toEqual('A2');
  204. hot.render();
  205. expect(htCore.find('tbody tr:eq(0) td:eq(0)').html()).toEqual('new string');
  206. expect(htCore.find('tbody tr:eq(1) td:eq(0)').html()).toEqual('another new string');
  207. done();
  208. }, 300);
  209. });
  210. it('should be possible to pause observing changes without disabling the plugin', function (done) {
  211. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  212. var hot = createHOT(data, true);
  213. var htCore = getHtCore();
  214. data[0][0] = 'new string';
  215. setTimeout(function () {
  216. expect(htCore.find('tbody tr:eq(0) td:eq(0)').html()).toEqual('new string');
  217. expect(htCore.find('tbody tr:eq(1) td:eq(0)').html()).toEqual('A2');
  218. hot.pauseObservingChanges();
  219. data[1][0] = 'another new string';
  220. }, 200);
  221. setTimeout(function () {
  222. expect(htCore.find('tbody tr:eq(0) td:eq(0)').html()).toEqual('new string');
  223. expect(htCore.find('tbody tr:eq(1) td:eq(0)').html()).toEqual('A2');
  224. hot.render();
  225. expect(htCore.find('tbody tr:eq(0) td:eq(0)').html()).toEqual('new string');
  226. expect(htCore.find('tbody tr:eq(1) td:eq(0)').html()).toEqual('another new string');
  227. done();
  228. }, 300);
  229. });
  230. it('should be possible to resume observing changes after it was paused', function (done) {
  231. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  232. var hot = createHOT(data, true);
  233. var htCore = getHtCore();
  234. hot.pauseObservingChanges();
  235. data[0][0] = 'new string';
  236. setTimeout(function () {
  237. expect(htCore.find('tbody tr:eq(0) td:eq(0)').html()).toEqual('A1');
  238. expect(htCore.find('tbody tr:eq(1) td:eq(0)').html()).toEqual('A2');
  239. hot.resumeObservingChanges();
  240. data[1][0] = 'another new string';
  241. }, 100);
  242. setTimeout(function () {
  243. expect(htCore.find('tbody tr:eq(0) td:eq(0)').html()).toEqual('new string');
  244. expect(htCore.find('tbody tr:eq(1) td:eq(0)').html()).toEqual('another new string');
  245. done();
  246. }, 1200);
  247. });
  248. });
  249. describe('observeChanges fires appropriate events when changes are detected', function () {
  250. describe('array data', function () {
  251. it('should fire afterChangesObserved event after changes has been noticed', function (done) {
  252. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  253. var hot = createHOT(data, true);
  254. var afterChangesObservedCallback = jasmine.createSpy('afterChangesObservedCallback');
  255. hot.addHook('afterChangesObserved', afterChangesObservedCallback);
  256. data[0][0] = 'new string';
  257. setTimeout(function () {
  258. expect(afterChangesObservedCallback.calls.count()).toEqual(1);
  259. done();
  260. }, 200);
  261. });
  262. it('should fire afterCreateRow event after detecting that new row has been added', function (done) {
  263. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  264. var hot = createHOT(data, true);
  265. var afterCreateRowCallback = jasmine.createSpy('afterCreateRowCallback');
  266. hot.addHook('afterCreateRow', afterCreateRowCallback);
  267. data.push(['A2', 'B2']);
  268. setTimeout(function () {
  269. expect(afterCreateRowCallback.calls.count()).toEqual(1);
  270. expect(afterCreateRowCallback).toHaveBeenCalledWith(2, 1, 'ObserveChanges.change', undefined, undefined, undefined);
  271. done();
  272. }, 200);
  273. });
  274. it('should fire afterRemoveRow event after detecting that row has been removed', function (done) {
  275. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  276. var hot = createHOT(data, true);
  277. var afterRemoveRowCallback = jasmine.createSpy('afterRemoveRowCallback');
  278. hot.addHook('afterRemoveRow', afterRemoveRowCallback);
  279. data.pop();
  280. setTimeout(function () {
  281. expect(afterRemoveRowCallback.calls.count()).toEqual(1);
  282. expect(afterRemoveRowCallback).toHaveBeenCalledWith(1, 1, 'ObserveChanges.change', undefined, undefined, undefined);
  283. done();
  284. }, 200);
  285. });
  286. it('should fire afterRemoveRow event after detecting that multiple rows have been removed', function (done) {
  287. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  288. var hot = createHOT(data, true);
  289. var afterRemoveRowCallback = jasmine.createSpy('afterRemoveRowCallback');
  290. hot.addHook('afterRemoveRow', afterRemoveRowCallback);
  291. data.splice(0, 2);
  292. setTimeout(function () {
  293. expect(afterRemoveRowCallback.calls.count()).toEqual(2);
  294. // The order of run hooks depends on whether objectObserve uses native Object.observe or a shim
  295. var args = [];
  296. args.push(afterRemoveRowCallback.calls.argsFor(0));
  297. args.push(afterRemoveRowCallback.calls.argsFor(1));
  298. expect(args).toContain([1, 1, 'ObserveChanges.change', undefined, undefined, undefined]);
  299. expect(args).toContain([0, 1, 'ObserveChanges.change', undefined, undefined, undefined]);
  300. done();
  301. }, 200);
  302. });
  303. it('should fire afterCreateCol event after detecting that new col has been added', function (done) {
  304. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  305. var hot = createHOT(data, true);
  306. var afterCreateColCallback = jasmine.createSpy('afterCreateColCallback');
  307. hot.addHook('afterCreateCol', afterCreateColCallback);
  308. data[0].push('C1');
  309. data[1].push('C2');
  310. setTimeout(function () {
  311. expect(afterCreateColCallback.calls.count()).toEqual(1);
  312. expect(afterCreateColCallback.calls.argsFor(0)).toEqual([2, 1, 'ObserveChanges.change', undefined, undefined, undefined]);
  313. done();
  314. }, 200);
  315. });
  316. it('should fire afterRemoveCol event after detecting that col has been removed', function (done) {
  317. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  318. var hot = createHOT(data, true);
  319. var afterRemoveColCallback = jasmine.createSpy('afterRemoveColCallback');
  320. hot.addHook('afterRemoveCol', afterRemoveColCallback);
  321. data[0].pop();
  322. data[1].pop();
  323. setTimeout(function () {
  324. expect(afterRemoveColCallback.calls.count()).toEqual(1);
  325. expect(afterRemoveColCallback.calls.argsFor(0)).toEqual([1, 1, 'ObserveChanges.change', undefined, undefined, undefined]);
  326. done();
  327. }, 200);
  328. });
  329. it('should fire afterRemoveCol event after detecting that multiple cols have been removed', function (done) {
  330. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  331. var hot = createHOT(data, true);
  332. var afterRemoveColCallback = jasmine.createSpy('afterRemoveColCallback');
  333. hot.addHook('afterRemoveCol', afterRemoveColCallback);
  334. data[0].pop();
  335. data[0].pop();
  336. data[1].pop();
  337. data[1].pop();
  338. setTimeout(function () {
  339. expect(afterRemoveColCallback.calls.count()).toEqual(2);
  340. // The order of run hooks depends on whether objectObserve uses native Object.observe or a shim
  341. var args = [];
  342. args.push(afterRemoveColCallback.calls.argsFor(0));
  343. args.push(afterRemoveColCallback.calls.argsFor(1));
  344. expect(args).toContain([1, 1, 'ObserveChanges.change', undefined, undefined, undefined]);
  345. expect(args).toContain([0, 1, 'ObserveChanges.change', undefined, undefined, undefined]);
  346. done();
  347. }, 200);
  348. });
  349. it('should fire afterChange event after detecting that table data has changed', function (done) {
  350. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  351. var hot = createHOT(data, true);
  352. var afterChangeCallback = jasmine.createSpy('afterChangeCallback');
  353. hot.addHook('afterChange', afterChangeCallback);
  354. data[0][0] = 'new string';
  355. setTimeout(function () {
  356. expect(afterChangeCallback.calls.count()).toEqual(1);
  357. expect(afterChangeCallback).toHaveBeenCalledWith([0, 0, null, 'new string'], 'ObserveChanges.change', undefined, undefined, undefined, undefined);
  358. done();
  359. }, 200);
  360. });
  361. });
  362. describe('object data', function () {
  363. it('should fire afterChangesObserved event after changes has been noticed', function (done) {
  364. var data = Handsontable.helper.createSpreadsheetObjectData(2, 2);
  365. var hot = createHOT(data, true);
  366. var afterChangesObservedCallback = jasmine.createSpy('afterChangesObservedCallback');
  367. hot.addHook('afterChangesObserved', afterChangesObservedCallback);
  368. data[0].prop0 = 'new string';
  369. setTimeout(function () {
  370. expect(afterChangesObservedCallback.calls.count()).toEqual(1);
  371. done();
  372. }, 200);
  373. });
  374. it('should fire afterCreateRow event after detecting that new row has been added', function (done) {
  375. var data = Handsontable.helper.createSpreadsheetObjectData(2, 2);
  376. var hot = createHOT(data, true);
  377. var afterCreateRowCallback = jasmine.createSpy('afterCreateRowCallback');
  378. hot.addHook('afterCreateRow', afterCreateRowCallback);
  379. data.push({ prop0: 'A2', prop1: 'B2' });
  380. setTimeout(function () {
  381. expect(afterCreateRowCallback.calls.count()).toEqual(1);
  382. expect(afterCreateRowCallback).toHaveBeenCalledWith(2, 1, 'ObserveChanges.change', undefined, undefined, undefined);
  383. done();
  384. }, 200);
  385. });
  386. it('should fire afterRemoveRow event after detecting that row has been removed', function (done) {
  387. var data = Handsontable.helper.createSpreadsheetObjectData(2, 2);
  388. var hot = createHOT(data, true);
  389. var afterRemoveRowCallback = jasmine.createSpy('afterRemoveRowCallback');
  390. hot.addHook('afterRemoveRow', afterRemoveRowCallback);
  391. data.pop();
  392. setTimeout(function () {
  393. expect(afterRemoveRowCallback.calls.count()).toEqual(1);
  394. expect(afterRemoveRowCallback).toHaveBeenCalledWith(1, 1, 'ObserveChanges.change', undefined, undefined, undefined);
  395. done();
  396. }, 200);
  397. });
  398. it('should fire afterRemoveRow event after detecting that multiple rows have been removed', function (done) {
  399. var data = Handsontable.helper.createSpreadsheetObjectData(2, 2);
  400. var hot = createHOT(data, true);
  401. var afterRemoveRowCallback = jasmine.createSpy('afterRemoveRowCallback');
  402. hot.addHook('afterRemoveRow', afterRemoveRowCallback);
  403. data.splice(0, 2);
  404. setTimeout(function () {
  405. expect(afterRemoveRowCallback.calls.count()).toEqual(2);
  406. // The order of run hooks depends on whether objectObserve uses native Object.observe or a shim
  407. var args = [];
  408. args.push(afterRemoveRowCallback.calls.argsFor(0));
  409. args.push(afterRemoveRowCallback.calls.argsFor(1));
  410. expect(args).toContain([1, 1, 'ObserveChanges.change', undefined, undefined, undefined]);
  411. expect(args).toContain([0, 1, 'ObserveChanges.change', undefined, undefined, undefined]);
  412. done();
  413. }, 200);
  414. });
  415. it('should fire afterChange event after detecting that table data has changed', function (done) {
  416. var data = Handsontable.helper.createSpreadsheetObjectData(2, 2);
  417. var hot = createHOT(data, true);
  418. var afterChangeCallback = jasmine.createSpy('afterChangeCallback');
  419. hot.addHook('afterChange', afterChangeCallback);
  420. data[0].prop0 = 'new string';
  421. setTimeout(function () {
  422. expect(afterChangeCallback.calls.count()).toEqual(1);
  423. expect(afterChangeCallback).toHaveBeenCalledWith([0, 'prop0', null, 'new string'], 'ObserveChanges.change', undefined, undefined, undefined, undefined);
  424. done();
  425. }, 200);
  426. });
  427. });
  428. });
  429. describe('using HOT data manipulation methods, when observeChanges plugin is enabled', function () {
  430. describe('array data', function () {
  431. it('should run render ONCE after detecting that new row has been added', function (done) {
  432. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  433. var hot = createHOT(data, true);
  434. var afterRenderSpy = jasmine.createSpy('afterRenderSpy');
  435. hot.addHook('afterRender', afterRenderSpy);
  436. alter('insert_row');
  437. setTimeout(function () {
  438. expect(countRows()).toEqual(3);
  439. expect(afterRenderSpy.calls.count()).toEqual(1);
  440. done();
  441. }, 200);
  442. });
  443. it('should run render ONCE after detecting that row has been removed', function (done) {
  444. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  445. var hot = createHOT(data, true);
  446. var afterRenderSpy = jasmine.createSpy('afterRenderSpy');
  447. hot.addHook('afterRender', afterRenderSpy);
  448. var afterChangesObservedCallback = jasmine.createSpy('afterChangesObservedCallback');
  449. hot.addHook('afterChangesObserved', afterChangesObservedCallback);
  450. alter('remove_row');
  451. setTimeout(function () {
  452. expect(countRows()).toEqual(1);
  453. expect(afterChangesObservedCallback.calls.count()).toEqual(1);
  454. expect(afterRenderSpy.calls.count()).toEqual(1);
  455. done();
  456. }, 200);
  457. });
  458. it('should run render ONCE after detecting that new column has been added', function (done) {
  459. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  460. var hot = createHOT(data, true);
  461. var afterRenderSpy = jasmine.createSpy('afterRenderSpy');
  462. hot.addHook('afterRender', afterRenderSpy);
  463. alter('insert_col');
  464. setTimeout(function () {
  465. expect(countCols()).toEqual(3);
  466. expect(afterRenderSpy.calls.count()).toEqual(1);
  467. done();
  468. }, 200);
  469. });
  470. it('should run render ONCE after detecting that column has been removed', function (done) {
  471. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  472. var hot = createHOT(data, true);
  473. var afterRenderSpy = jasmine.createSpy('afterRenderSpy');
  474. hot.addHook('afterRender', afterRenderSpy);
  475. var afterChangesObservedCallback = jasmine.createSpy('afterChangesObservedCallback');
  476. hot.addHook('afterChangesObserved', afterChangesObservedCallback);
  477. alter('remove_col');
  478. setTimeout(function () {
  479. expect(countCols()).toEqual(1);
  480. expect(afterChangesObservedCallback.calls.count()).toEqual(1);
  481. expect(afterRenderSpy.calls.count()).toEqual(1);
  482. done();
  483. }, 200);
  484. });
  485. it('should run render ONCE after detecting that table data has changed', function (done) {
  486. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  487. var hot = createHOT(data, true);
  488. var htCore = getHtCore();
  489. var afterRenderSpy = jasmine.createSpy('afterRenderSpy');
  490. hot.addHook('afterRender', afterRenderSpy);
  491. var afterChangesObservedCallback = jasmine.createSpy('afterChangesObservedCallback');
  492. hot.addHook('afterChangesObserved', afterChangesObservedCallback);
  493. setDataAtCell(0, 0, 'new value');
  494. setTimeout(function () {
  495. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('new value');
  496. expect(afterChangesObservedCallback.calls.count()).toEqual(1);
  497. expect(afterRenderSpy.calls.count()).toEqual(1);
  498. done();
  499. }, 200);
  500. });
  501. });
  502. describe('object data', function () {
  503. it('should run render ONCE after detecting that new row has been added', function (done) {
  504. var data = Handsontable.helper.createSpreadsheetObjectData(2, 2);
  505. var hot = createHOT(data, true);
  506. var afterRenderSpy = jasmine.createSpy('afterRenderSpy');
  507. hot.addHook('afterRender', afterRenderSpy);
  508. alter('insert_row');
  509. setTimeout(function () {
  510. expect(countRows()).toEqual(3);
  511. expect(afterRenderSpy.calls.count()).toEqual(1);
  512. done();
  513. }, 200);
  514. });
  515. it('should run render ONCE after detecting that row has been removed', function (done) {
  516. var data = Handsontable.helper.createSpreadsheetObjectData(2, 2);
  517. var hot = createHOT(data, true);
  518. var afterRenderSpy = jasmine.createSpy('afterRenderSpy');
  519. hot.addHook('afterRender', afterRenderSpy);
  520. var afterChangesObservedCallback = jasmine.createSpy('afterChangesObservedCallback');
  521. hot.addHook('afterChangesObserved', afterChangesObservedCallback);
  522. alter('remove_row');
  523. setTimeout(function () {
  524. expect(countRows()).toEqual(1);
  525. expect(afterChangesObservedCallback.calls.count()).toEqual(1);
  526. expect(afterRenderSpy.calls.count()).toEqual(1);
  527. done();
  528. }, 200);
  529. });
  530. it('should run render ONCE after detecting that table data has changed', function (done) {
  531. var data = Handsontable.helper.createSpreadsheetObjectData(2, 2);
  532. var hot = createHOT(data, true);
  533. var afterRenderSpy = jasmine.createSpy('afterRenderSpy');
  534. hot.addHook('afterRender', afterRenderSpy);
  535. var afterChangesObservedCallback = jasmine.createSpy('afterChangesObservedCallback');
  536. hot.addHook('afterChangesObserved', afterChangesObservedCallback);
  537. setDataAtRowProp(0, 'prop0', 'new value');
  538. setTimeout(function () {
  539. expect(spec().$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('new value');
  540. expect(afterChangesObservedCallback.calls.count()).toEqual(1);
  541. expect(afterRenderSpy.calls.count()).toEqual(1);
  542. done();
  543. }, 200);
  544. });
  545. });
  546. });
  547. describe('refreshing table after changes have been detected', function () {
  548. it('should observe changes to new data bound using loadData', function (done) {
  549. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  550. var newData = Handsontable.helper.createSpreadsheetData(2, 2);
  551. var hot = createHOT(data, true);
  552. var htCore = getHtCore();
  553. hot.loadData(newData);
  554. var afterRenderSpy = jasmine.createSpy('afterRenderSpy');
  555. hot.addHook('afterRender', afterRenderSpy);
  556. newData.push(['A3', 'B3']);
  557. setTimeout(function () {
  558. expect(afterRenderSpy.calls.count()).toBe(1);
  559. expect(htCore.find('tr').length).toEqual(3);
  560. expect(htCore.find('col').length).toEqual(2);
  561. done();
  562. }, 200);
  563. });
  564. it('should not observe changes to old data after it was replaced using loadData', function (done) {
  565. var data = Handsontable.helper.createSpreadsheetData(2, 2);
  566. var newData = Handsontable.helper.createSpreadsheetData(2, 2);
  567. var hot = createHOT(data, true);
  568. var htCore = getHtCore();
  569. hot.loadData(newData);
  570. var afterRenderSpy = jasmine.createSpy('afterRenderSpy');
  571. hot.addHook('afterRender', afterRenderSpy);
  572. data.push(['A3', 'B3']);
  573. setTimeout(function () {
  574. expect(afterRenderSpy.calls.count()).toBe(0);
  575. expect(htCore.find('tr').length).toEqual(2);
  576. expect(htCore.find('col').length).toEqual(2);
  577. done();
  578. }, 1000);
  579. });
  580. });
  581. });