4f1ccacf8a49fd3e34e225b4cbc01d827ce0173b2939d44298bb25ed3668d9832d7b4779e844ca30ce959c5743d74d57a2091c98df047141ed7a4829bdc5b2 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. describe('Search plugin', () => {
  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. describe('enabling/disabling plugin', () => {
  13. it('should expose `search` object when plugin is enabled', () => {
  14. var hot = handsontable({
  15. search: true
  16. });
  17. expect(hot.search).toBeDefined();
  18. });
  19. it('should NOT expose `search` object when plugin is disabled', () => {
  20. var hot = handsontable({
  21. search: false
  22. });
  23. expect(hot.search).not.toBeDefined();
  24. });
  25. it('plugin should be disabled by default', () => {
  26. var hot = handsontable();
  27. expect(hot.search).not.toBeDefined();
  28. });
  29. it('should disable plugin using updateSettings', () => {
  30. var hot = handsontable({
  31. search: true
  32. });
  33. expect(hot.search).toBeDefined();
  34. updateSettings({
  35. search: false
  36. });
  37. expect(hot.search).not.toBeDefined();
  38. });
  39. it('should enable plugin using updateSettings', () => {
  40. var hot = handsontable({
  41. search: false
  42. });
  43. expect(hot.search).not.toBeDefined();
  44. updateSettings({
  45. search: true
  46. });
  47. expect(hot.search).toBeDefined();
  48. });
  49. });
  50. describe('query method', () => {
  51. afterEach(() => {
  52. Handsontable.plugins.Search.global.setDefaultQueryMethod(Handsontable.plugins.Search.DEFAULT_QUERY_METHOD);
  53. });
  54. it('should use the default query method if no queryMethod is passed to query function', () => {
  55. spyOn(Handsontable.plugins.Search, 'DEFAULT_QUERY_METHOD');
  56. var defaultQueryMethod = Handsontable.plugins.Search.DEFAULT_QUERY_METHOD;
  57. Handsontable.plugins.Search.global.setDefaultQueryMethod(defaultQueryMethod);
  58. var hot = handsontable({
  59. data: Handsontable.helper.createSpreadsheetData(5, 5),
  60. search: true
  61. });
  62. var searchResult = hot.search.query('A');
  63. expect(defaultQueryMethod.calls.count()).toEqual(25);
  64. });
  65. it('should use the custom default query method if no queryMethod is passed to query function', () => {
  66. var customDefaultQueryMethod = jasmine.createSpy('customDefaultQueryMethod');
  67. var hot = handsontable({
  68. data: Handsontable.helper.createSpreadsheetData(5, 5),
  69. search: true
  70. });
  71. Handsontable.plugins.Search.global.setDefaultQueryMethod(customDefaultQueryMethod);
  72. var searchResult = hot.search.query('A');
  73. expect(customDefaultQueryMethod.calls.count()).toEqual(25);
  74. });
  75. it('should use the query method from the constructor if no queryMethod is passed to query function', () => {
  76. var customQueryMethod = jasmine.createSpy('customDefaultQueryMethod');
  77. var hot = handsontable({
  78. data: Handsontable.helper.createSpreadsheetData(5, 5),
  79. search: {
  80. queryMethod: customQueryMethod
  81. }
  82. });
  83. var searchResult = hot.search.query('A');
  84. expect(customQueryMethod.calls.count()).toEqual(25);
  85. });
  86. it('should use method passed to query function', () => {
  87. var customQueryMethod = jasmine.createSpy('customQueryMethod');
  88. var hot = handsontable({
  89. data: Handsontable.helper.createSpreadsheetData(5, 5),
  90. search: true
  91. });
  92. var searchResult = hot.search.query('A', null, customQueryMethod);
  93. expect(customQueryMethod.calls.count()).toEqual(25);
  94. });
  95. });
  96. describe('default query method', () => {
  97. it('should use query method to find phrase', () => {
  98. var hot = handsontable({
  99. data: Handsontable.helper.createSpreadsheetData(5, 5),
  100. search: true
  101. });
  102. var searchResult = hot.search.query('A');
  103. expect(searchResult.length).toEqual(5);
  104. for (var i = 0; i < searchResult.length; i++) {
  105. expect(searchResult[i].row).toEqual(i);
  106. expect(searchResult[i].col).toEqual(0);
  107. expect(searchResult[i].data).toEqual(hot.getDataAtCell(i, 0));
  108. }
  109. });
  110. it('default query method should be case insensitive', () => {
  111. var hot = handsontable({
  112. data: Handsontable.helper.createSpreadsheetData(5, 5),
  113. search: true
  114. });
  115. var searchResult = hot.search.query('a');
  116. expect(searchResult.length).toEqual(5);
  117. searchResult = hot.search.query('A');
  118. expect(searchResult.length).toEqual(5);
  119. });
  120. it('default query method should work with numeric values', () => {
  121. var hot = handsontable({
  122. data: [
  123. [1, 2],
  124. [22, 4]
  125. ],
  126. search: true
  127. });
  128. var searchResult = hot.search.query('2');
  129. expect(searchResult.length).toEqual(2);
  130. });
  131. it('default query method should interpret query as string, not regex', () => {
  132. var hot = handsontable({
  133. data: Handsontable.helper.createSpreadsheetData(5, 5),
  134. search: true
  135. });
  136. var searchResult = hot.search.query('A*');
  137. expect(searchResult.length).toEqual(0);
  138. });
  139. it('default query method should always return false if query string is empty', () => {
  140. var hot = handsontable({
  141. data: Handsontable.helper.createSpreadsheetData(5, 5),
  142. search: true
  143. });
  144. var searchResult = hot.search.query('A');
  145. expect(searchResult.length).toEqual(5);
  146. searchResult = hot.search.query('');
  147. expect(searchResult.length).toEqual(0);
  148. });
  149. it('default query method should always return false if no query string has been specified', () => {
  150. var hot = handsontable({
  151. data: Handsontable.helper.createSpreadsheetData(5, 5),
  152. search: true
  153. });
  154. var searchResult = hot.search.query('A');
  155. expect(searchResult.length).toEqual(5);
  156. searchResult = hot.search.query();
  157. expect(searchResult.length).toEqual(0);
  158. });
  159. it('default query method should always return false if no query string is not a string', () => {
  160. var hot = handsontable({
  161. data: Handsontable.helper.createSpreadsheetData(5, 5),
  162. search: true
  163. });
  164. var searchResult = hot.search.query('A');
  165. expect(searchResult.length).toEqual(5);
  166. searchResult = hot.search.query([1, 2, 3]);
  167. expect(searchResult.length).toEqual(0);
  168. });
  169. });
  170. describe('search callback', () => {
  171. afterEach(() => {
  172. Handsontable.plugins.Search.global.setDefaultCallback(Handsontable.plugins.Search.DEFAULT_CALLBACK);
  173. });
  174. it('should invoke default callback for each cell', () => {
  175. spyOn(Handsontable.plugins.Search, 'DEFAULT_CALLBACK');
  176. var defaultCallback = Handsontable.plugins.Search.DEFAULT_CALLBACK;
  177. Handsontable.plugins.Search.global.setDefaultCallback(defaultCallback);
  178. var hot = handsontable({
  179. data: Handsontable.helper.createSpreadsheetData(5, 5),
  180. search: true
  181. });
  182. var searchResult = hot.search.query('A');
  183. expect(defaultCallback.calls.count()).toEqual(25);
  184. });
  185. it('should change the default callback', () => {
  186. spyOn(Handsontable.plugins.Search, 'DEFAULT_CALLBACK');
  187. var hot = handsontable({
  188. data: Handsontable.helper.createSpreadsheetData(5, 5),
  189. search: true
  190. });
  191. var defaultCallback = jasmine.createSpy('defaultCallback');
  192. Handsontable.plugins.Search.global.setDefaultCallback(defaultCallback);
  193. var searchResult = hot.search.query('A');
  194. expect(Handsontable.plugins.Search.DEFAULT_CALLBACK).not.toHaveBeenCalled();
  195. expect(defaultCallback.calls.count()).toEqual(25);
  196. });
  197. it('should invoke callback passed in constructor', () => {
  198. var searchCallback = jasmine.createSpy('searchCallback');
  199. var hot = handsontable({
  200. data: Handsontable.helper.createSpreadsheetData(5, 5),
  201. search: {
  202. callback: searchCallback
  203. }
  204. });
  205. var searchResult = hot.search.query('A');
  206. expect(searchCallback.calls.count()).toEqual(25);
  207. });
  208. it('should invoke custom callback for each cell which has been tested', () => {
  209. var hot = handsontable({
  210. data: Handsontable.helper.createSpreadsheetData(5, 5),
  211. search: true
  212. });
  213. var searchCallback = jasmine.createSpy('searchCallback');
  214. var searchResult = hot.search.query('A', searchCallback);
  215. expect(searchCallback.calls.count()).toEqual(25);
  216. for (var rowIndex = 0, rowCount = countRows(); rowIndex < rowCount; rowIndex++) {
  217. for (var colIndex = 0, colCount = countCols(); colIndex < colCount; colIndex++) {
  218. var callArgs = searchCallback.calls.argsFor((rowIndex * 5) + colIndex);
  219. expect(callArgs[0]).toEqual(hot);
  220. expect(callArgs[1]).toEqual(rowIndex);
  221. expect(callArgs[2]).toEqual(colIndex);
  222. expect(callArgs[3]).toEqual(hot.getDataAtCell(rowIndex, colIndex));
  223. if (colIndex == 0) {
  224. expect(callArgs[4]).toBe(true);
  225. } else {
  226. expect(callArgs[4]).toBe(false);
  227. }
  228. }
  229. }
  230. });
  231. });
  232. describe('default search callback', () => {
  233. it('should add isSearchResult = true, to cell properties of all matched cells', () => {
  234. var hot = handsontable({
  235. data: Handsontable.helper.createSpreadsheetData(5, 5),
  236. search: true
  237. });
  238. var searchResult = hot.search.query('2');
  239. for (var rowIndex = 0, rowCount = countRows(); rowIndex < rowCount; rowIndex++) {
  240. for (var colIndex = 0, colCount = countCols(); colIndex < colCount; colIndex++) {
  241. var cellProperties = getCellMeta(rowIndex, colIndex);
  242. if (rowIndex == 1) {
  243. expect(cellProperties.isSearchResult).toBeTruthy();
  244. } else {
  245. expect(cellProperties.isSearchResult).toBeFalsy();
  246. }
  247. }
  248. }
  249. });
  250. });
  251. describe('search result decorator', () => {
  252. it('should add default search result class to cells which mach the query', () => {
  253. var hot = handsontable({
  254. data: Handsontable.helper.createSpreadsheetData(5, 5),
  255. search: true
  256. });
  257. var searchResult = hot.search.query('2');
  258. render();
  259. for (var rowIndex = 0, rowCount = countRows(); rowIndex < rowCount; rowIndex++) {
  260. for (var colIndex = 0, colCount = countCols(); colIndex < colCount; colIndex++) {
  261. var cell = getCell(rowIndex, colIndex);
  262. if (rowIndex == 1) {
  263. expect($(cell).hasClass(Handsontable.plugins.Search.DEFAULT_SEARCH_RESULT_CLASS)).toBe(true);
  264. } else {
  265. expect($(cell).hasClass(Handsontable.plugins.Search.DEFAULT_SEARCH_RESULT_CLASS)).toBe(false);
  266. }
  267. }
  268. }
  269. });
  270. it('should add custom search result class to cells which mach the query', () => {
  271. var hot = handsontable({
  272. data: Handsontable.helper.createSpreadsheetData(5, 5),
  273. search: {
  274. searchResultClass: 'customSearchResultClass'
  275. }
  276. });
  277. var searchResult = hot.search.query('2');
  278. render();
  279. for (var rowIndex = 0, rowCount = countRows(); rowIndex < rowCount; rowIndex++) {
  280. for (var colIndex = 0, colCount = countCols(); colIndex < colCount; colIndex++) {
  281. var cell = getCell(rowIndex, colIndex);
  282. if (rowIndex == 1) {
  283. expect($(cell).hasClass('customSearchResultClass')).toBe(true);
  284. } else {
  285. expect($(cell).hasClass('customSearchResultClass')).toBe(false);
  286. }
  287. }
  288. }
  289. });
  290. });
  291. describe('HOT properties compatibility', () => {
  292. it('should work properly when the last row is empty', () => { // connected with https://github.com/handsontable/handsontable/issues/1606
  293. var hot = handsontable({
  294. data: Handsontable.helper.createSpreadsheetData(5, 5),
  295. colHeaders: true,
  296. search: true,
  297. minSpareRows: 1
  298. }),
  299. errorThrown = false;
  300. try {
  301. hot.search.query('A');
  302. } catch (err) {
  303. errorThrown = true;
  304. }
  305. expect(errorThrown).toBe(false);
  306. });
  307. });
  308. });