handsontableEditor.spec.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. describe('HandsontableEditor', () => {
  2. const 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 getManufacturerData() {
  13. return [
  14. { name: 'BMW', country: 'Germany', owner: 'Bayerische Motoren Werke AG' },
  15. { name: 'Chrysler', country: 'USA', owner: 'Chrysler Group LLC' },
  16. { name: 'Nissan', country: 'Japan', owner: 'Nissan Motor Company Ltd' },
  17. { name: 'Suzuki', country: 'Japan', owner: 'Suzuki Motor Corporation' },
  18. { name: 'Toyota', country: 'Japan', owner: 'Toyota Motor Corporation' },
  19. { name: 'Volvo', country: 'Sweden', owner: 'Zhejiang Geely Holding Group' }
  20. ];
  21. }
  22. it('should create an editor that is a Handsontable instance', () => {
  23. handsontable({
  24. columns: [
  25. {
  26. type: 'handsontable',
  27. handsontable: {
  28. colHeaders: ['Marque', 'Country', 'Parent company'],
  29. data: getManufacturerData()
  30. }
  31. }
  32. ]
  33. });
  34. selectCell(2, 0);
  35. keyDownUp('enter');
  36. expect(spec().$container.find('.handsontableEditor:visible').length).toEqual(1);
  37. });
  38. it('should create an editor directly below the textarea element', () => {
  39. handsontable({
  40. columns: [
  41. {
  42. type: 'handsontable',
  43. handsontable: {
  44. colHeaders: ['Marque', 'Country', 'Parent company'],
  45. data: getManufacturerData()
  46. }
  47. }
  48. ]
  49. });
  50. selectCell(2, 0);
  51. keyDownUp('enter');
  52. expect(spec().$container.find('.handsontableEditor')[0].offsetTop).toEqual(spec().$container.find('.handsontableInput')[0].offsetHeight);
  53. });
  54. it('should prepare the editor only once per instance', () => {
  55. handsontable({
  56. columns: [
  57. {
  58. type: 'handsontable',
  59. handsontable: {
  60. colHeaders: ['Marque', 'Country', 'Parent company'],
  61. data: getManufacturerData()
  62. }
  63. }
  64. ]
  65. });
  66. selectCell(0, 0);
  67. keyDownUp('enter');
  68. keyDownUp('enter');
  69. keyDownUp('enter');
  70. keyDownUp('enter');
  71. keyDownUp('enter');
  72. keyDownUp('enter');
  73. keyDownUp('enter');
  74. keyDownUp('enter');
  75. keyDownUp('enter');
  76. keyDownUp('enter');
  77. keyDownUp('enter');
  78. keyDownUp('enter');
  79. expect(spec().$container.find('.handsontableEditor').length).toEqual(1);
  80. });
  81. it('should reuse the container and display them after select the same or different cell', () => {
  82. handsontable({
  83. columns: [
  84. {
  85. type: 'handsontable',
  86. handsontable: {
  87. colHeaders: ['Marque', 'Country', 'Parent company'],
  88. data: getManufacturerData()
  89. }
  90. }
  91. ]
  92. });
  93. selectCell(0, 0);
  94. keyDownUp('enter');
  95. let container = spec().$container.find('.handsontableEditor')[0];
  96. expect(container.clientHeight).toBeGreaterThan(2);
  97. selectCell(0, 0);
  98. keyDownUp('enter');
  99. container = spec().$container.find('.handsontableEditor')[0];
  100. expect(container.clientHeight).toBeGreaterThan(2);
  101. selectCell(1, 0);
  102. keyDownUp('enter');
  103. container = spec().$container.find('.handsontableEditor')[0];
  104. expect(container.clientHeight).toBeGreaterThan(2);
  105. selectCell(1, 0);
  106. keyDownUp('enter');
  107. container = spec().$container.find('.handsontableEditor')[0];
  108. expect(container.clientHeight).toBeGreaterThan(2);
  109. });
  110. it('should destroy the editor when Esc is pressed', () => {
  111. handsontable({
  112. columns: [
  113. {
  114. type: 'handsontable',
  115. handsontable: {
  116. colHeaders: ['Marque', 'Country', 'Parent company'],
  117. data: getManufacturerData()
  118. }
  119. }
  120. ]
  121. });
  122. selectCell(2, 0);
  123. keyDownUp('enter');
  124. keyDownUp('esc');
  125. expect(spec().$container.find('.handsontableEditor:visible').length).toEqual(0);
  126. });
  127. // see https://github.com/handsontable/handsontable/issues/3380
  128. it('should not throw error while selecting the next cell by hitting enter key', () => {
  129. const spy = jasmine.createSpyObj('error', ['test']);
  130. const prevError = window.onerror;
  131. window.onerror = function() {
  132. spy.test();
  133. };
  134. handsontable({
  135. columns: [{
  136. type: 'handsontable',
  137. handsontable: {
  138. data: [['Marque'], ['Country'], ['Parent company']]
  139. }
  140. }]
  141. });
  142. selectCell(0, 0);
  143. keyDownUp('enter');
  144. keyDownUp('enter');
  145. keyDownUp('enter');
  146. expect(spy.test.calls.count()).toBe(0);
  147. window.onerror = prevError;
  148. });
  149. it('Enter pressed in nested HT should set the value and hide the editor', () => {
  150. handsontable({
  151. columns: [
  152. {
  153. type: 'handsontable',
  154. handsontable: {
  155. colHeaders: ['Marque', 'Country', 'Parent company'],
  156. data: getManufacturerData()
  157. }
  158. }
  159. ]
  160. });
  161. selectCell(2, 0);
  162. keyDownUp('enter');
  163. keyDownUp('arrow_down');
  164. keyDownUp('enter');
  165. expect(spec().$container.find('.handsontableEditor:visible').length).toEqual(0);
  166. expect(getDataAtCell(2, 0)).toEqual('BMW');
  167. });
  168. it('should keep focus on textarea after arrow is pressed', () => {
  169. const hot = handsontable({
  170. columns: [
  171. {
  172. type: 'handsontable',
  173. handsontable: {
  174. colHeaders: ['Marque', 'Country', 'Parent company'],
  175. data: getManufacturerData()
  176. }
  177. }
  178. ]
  179. });
  180. selectCell(2, 0);
  181. keyDownUp('enter');
  182. keyDownUp('arrow_down');
  183. expect(document.activeElement).toEqual(hot.getActiveEditor().TEXTAREA);
  184. });
  185. it('should focus the TD after HT editor is prepared and destroyed', () => {
  186. handsontable({
  187. columns: [
  188. {
  189. type: 'handsontable',
  190. handsontable: {
  191. colHeaders: ['Marque', 'Country', 'Parent company'],
  192. data: getManufacturerData()
  193. }
  194. }
  195. ]
  196. });
  197. selectCell(2, 0);
  198. keyDownUp('arrow_down');
  199. keyDownUp('arrow_down');
  200. expect(getSelected()).toEqual([[4, 0, 4, 0]]);
  201. });
  202. it('should focus the TD after HT editor is prepared, finished (by keyboard) and destroyed', () => {
  203. const selections = [];
  204. handsontable({
  205. columns: [
  206. {
  207. type: 'handsontable',
  208. handsontable: {
  209. colHeaders: ['Marque', 'Country', 'Parent company'],
  210. data: getManufacturerData(),
  211. afterSelection(row) {
  212. selections.push(['inner', row]);
  213. }
  214. }
  215. }
  216. ],
  217. afterSelection(row) {
  218. selections.push(['outer', row]);
  219. }
  220. });
  221. expect(selections.length).toBe(0);
  222. selectCell(1, 0);
  223. expect(selections[0]).toEqual(['outer', 1]);
  224. keyDownUp('arrow_down');
  225. expect(selections[1]).toEqual(['outer', 2]);
  226. keyDownUp('enter');
  227. keyDownUp('arrow_down');
  228. expect(selections[2]).toEqual(['inner', 0]);
  229. keyDownUp('esc');
  230. keyDownUp('arrow_down');
  231. expect(selections[3]).toEqual(['outer', 3]);
  232. expect(selections.length).toBe(4);
  233. });
  234. describe('strict mode', () => {
  235. it('should open editor and select cell (0, 0) in inner HOT', () => {
  236. const hot = handsontable({
  237. columns: [
  238. {
  239. type: 'handsontable',
  240. handsontable: {
  241. colHeaders: ['Marque', 'Country', 'Parent company'],
  242. data: getManufacturerData()
  243. },
  244. strict: true
  245. }
  246. ]
  247. });
  248. selectCell(2, 0);
  249. keyDownUp('enter');
  250. const ht = hot.getActiveEditor();
  251. const innerHot = ht.htEditor;
  252. expect(innerHot.getSelected()).toEqual([[0, 0, 0, 0]]);
  253. });
  254. });
  255. describe('non strict mode', () => {
  256. it('should open editor and DO NOT select any cell in inner HOT', () => {
  257. const hot = handsontable({
  258. columns: [
  259. {
  260. type: 'handsontable',
  261. handsontable: {
  262. colHeaders: ['Marque', 'Country', 'Parent company'],
  263. data: getManufacturerData()
  264. }
  265. }
  266. ]
  267. });
  268. selectCell(2, 0);
  269. keyDownUp('enter');
  270. const ht = hot.getActiveEditor();
  271. const innerHot = ht.htEditor;
  272. expect(innerHot.getSelected()).toBeUndefined();
  273. });
  274. it('should show textarea', () => {
  275. const hot = handsontable({
  276. columns: [
  277. {
  278. type: 'handsontable',
  279. handsontable: {
  280. colHeaders: ['Marque', 'Country', 'Parent company'],
  281. data: getManufacturerData()
  282. }
  283. }
  284. ]
  285. });
  286. selectCell(2, 0);
  287. keyDownUp('enter');
  288. expect(hot.getActiveEditor().TEXTAREA.parentElement.style.zIndex).toEqual('');
  289. expect(hot.getActiveEditor().TEXTAREA.style.visibility).toEqual('');
  290. });
  291. });
  292. describe('IME support', () => {
  293. it('should focus editable element after selecting the cell', async() => {
  294. handsontable({
  295. columns: [
  296. {
  297. type: 'handsontable',
  298. handsontable: {
  299. colHeaders: ['Marque', 'Country', 'Parent company'],
  300. data: getManufacturerData()
  301. }
  302. }
  303. ]
  304. });
  305. selectCell(0, 0, 0, 0, true, false);
  306. await sleep(10);
  307. expect(document.activeElement).toBe(getActiveEditor().TEXTAREA);
  308. });
  309. });
  310. });