@zeedhi/teknisa-components-common 1.107.1 → 1.108.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +7 -7
  3. package/coverage/clover.xml +772 -692
  4. package/coverage/coverage-final.json +47 -47
  5. package/coverage/lcov-report/index.html +15 -15
  6. package/coverage/lcov-report/tests/__helpers__/component-event-helper.ts.html +2 -2
  7. package/coverage/lcov-report/tests/__helpers__/flush-promises-helper.ts.html +2 -2
  8. package/coverage/lcov-report/tests/__helpers__/get-child-helper.ts.html +7 -7
  9. package/coverage/lcov-report/tests/__helpers__/index.html +1 -1
  10. package/coverage/lcov-report/tests/__helpers__/index.ts.html +1 -1
  11. package/coverage/lcov-report/tests/__helpers__/mock-created-helper.ts.html +1 -1
  12. package/coverage/lcov.info +1459 -1275
  13. package/dist/tek-components-common.esm.js +375 -252
  14. package/dist/tek-components-common.umd.js +375 -252
  15. package/jest.config.js +1 -1
  16. package/package.json +2 -2
  17. package/tests/__helpers__/component-event-helper.ts +5 -5
  18. package/tests/__helpers__/flush-promises-helper.ts +3 -3
  19. package/tests/__helpers__/get-child-helper.ts +27 -27
  20. package/tests/__helpers__/index.ts +3 -3
  21. package/tests/__helpers__/mock-created-helper.ts +12 -12
  22. package/tests/__mocks__/@zeedhi/core/i18n.js +74 -74
  23. package/tests/__mocks__/@zeedhi/core.js +4 -4
  24. package/tests/unit/components/crud/crud-add-button.spec.ts +56 -56
  25. package/tests/unit/components/crud/crud-button.spec.ts +94 -94
  26. package/tests/unit/components/crud/crud-cancel-button.spec.ts +91 -91
  27. package/tests/unit/components/crud/crud-delete-button.spec.ts +122 -122
  28. package/tests/unit/components/crud/crud-form.spec.ts +165 -165
  29. package/tests/unit/components/crud/crud-save-button.spec.ts +118 -118
  30. package/tests/unit/components/tek-breadcrumb-header/tek-breadcrumb-header.spec.ts +42 -42
  31. package/tests/unit/components/tek-card-title/CardTitle.spec.ts +34 -34
  32. package/tests/unit/components/tek-datasource/memory-datasource.spec.ts +470 -470
  33. package/tests/unit/components/tek-datasource/rest-datasource.spec.ts +364 -364
  34. package/tests/unit/components/tek-drag-grid/tek-drag-grid.spec.ts +112 -112
  35. package/tests/unit/components/tek-grid/filter-helper.spec.ts +148 -148
  36. package/tests/unit/components/tek-grid/grid-column.spec.ts +270 -270
  37. package/tests/unit/components/tek-grid/grid-columns-button.spec.ts +195 -195
  38. package/tests/unit/components/tek-grid/grid-filter-button.spec.ts +967 -967
  39. package/tests/unit/components/tek-grid/grid.spec.ts +3340 -3116
  40. package/tests/unit/components/tek-grid/layout_options.spec.ts +980 -980
  41. package/tests/unit/components/tek-image/Image.spec.ts +67 -67
  42. package/tests/unit/components/tek-iterable-carousel/iterable-carousel.spec.ts +37 -37
  43. package/tests/unit/components/tek-iterable-component-render/iterable-component-render.spec.ts +200 -200
  44. package/tests/unit/components/tek-loading/Loading.spec.ts +30 -30
  45. package/tests/unit/components/tek-notifications/notifications.spec.ts +201 -201
  46. package/tests/unit/components/tek-product-card/product-card.spec.ts +61 -61
  47. package/tests/unit/components/tek-user-info/TekUserInfoContoller.spec.ts +220 -220
  48. package/tests/unit/components/tek-user-info/tek-user-info-list.spec.ts +86 -86
  49. package/tests/unit/components/tek-user-info/tek-user-info.spec.ts +430 -430
  50. package/tests/unit/components/tree-grid/tree-grid.spec.ts +776 -776
  51. package/tests/unit/utils/grid-base/delete-rows-error.spec.ts +24 -0
  52. package/tests/unit/utils/grid-base/export-options/button-option.spec.ts +44 -44
  53. package/tests/unit/utils/grid-base/export-options/multi-option.spec.ts +135 -135
  54. package/tests/unit/utils/grid-base/grid-controller.spec.ts +267 -174
  55. package/tests/unit/utils/report-filter/report-filter.spec.ts +66 -66
  56. package/tsconfig.eslint.json +8 -8
  57. package/types/components/tek-datasource/memory-datasource.d.ts +2 -4
  58. package/types/components/tek-datasource/rest-datasource.d.ts +6 -3
  59. package/types/components/tek-grid/grid.d.ts +50 -6
  60. package/types/components/tek-grid/interfaces.d.ts +5 -3
  61. package/types/components/tek-tree-grid/tree-grid.d.ts +5 -1
  62. package/types/utils/grid-base/grid-base.d.ts +12 -229
  63. package/types/utils/grid-base/grid-controller.d.ts +1 -3
  64. package/types/components/tek-ag-grid/default-icons.d.ts +0 -53
  65. package/types/components/tek-ag-grid/interfaces.d.ts +0 -9
  66. package/types/components/tek-ag-grid/tek-ag-grid.d.ts +0 -35
  67. package/types/components/tek-datasource/datasource.d.ts +0 -94
  68. package/types/components/tek-grid/default-icons.d.ts +0 -53
  69. package/types/components/tek-grid/filter-dynamic-values.d.ts +0 -9
  70. package/types/components/tek-grid/grid-controller.d.ts +0 -19
  71. package/types/components/tek-grid/grid_column.d.ts +0 -14
  72. package/types/components/tek-grid/grid_controller.d.ts +0 -15
  73. package/types/components/tek-grid/tek-grid.d.ts +0 -35
  74. package/types/components/tek-login/interfaces.d.ts +0 -3
  75. package/types/components/tek-login/login-children.d.ts +0 -3
  76. package/types/components/tek-login/login.d.ts +0 -58
  77. package/types/components/tek-login/login_children.d.ts +0 -3
@@ -1,776 +1,776 @@
1
- import {
2
- Button, Dropdown, Form, IButton, IForm, IModal, Modal, ModalService, Report, Search, Text, TextInput,
3
- } from '@zeedhi/common';
4
- import {
5
- Http, IDictionary, KeyMap, Metadata,
6
- } from '@zeedhi/core';
7
- import {
8
- ITekGridFilterButton,
9
- ITekTreeGrid, TekGridColumn, TekGridFilterButton, TekRestDatasource, TekTreeGrid,
10
- } from '../../../../src';
11
- import { getChild, setClick } from '../../../__helpers__';
12
-
13
- const flushPromises = () => new Promise(setImmediate);
14
-
15
- const clickOnFilterButton = (grid: TekTreeGrid, event?: any) => {
16
- const buttonProps = getChild<ITekGridFilterButton>(grid.toolbarSlot, `${grid.name}_filterButton`);
17
- const button = new TekGridFilterButton(buttonProps);
18
- setClick(button, event);
19
-
20
- return button;
21
- };
22
-
23
- describe('TekTreeGrid', () => {
24
- beforeEach(() => {
25
- // clear all metadata instances before testing
26
- const { instances } = Metadata as any;
27
- Object.keys(instances).forEach((key) => {
28
- Metadata.clearInstance(key, instances[key].componentId);
29
- });
30
- });
31
-
32
- describe('constructor()', () => {
33
- it('should create new grid with default values', () => {
34
- const instance = new TekTreeGrid({ name: 'TreeGrid', component: 'TekTreeGrid' });
35
- expect(instance.title).toBe('');
36
- expect(instance.addButton).toBeFalsy();
37
- expect(instance.deleteButton).toBe('none');
38
- expect(instance.filterButton).toBeFalsy();
39
- expect(instance.columnFilterButton).toBeFalsy();
40
- expect(instance.dragColumns).toBeTruthy();
41
- expect(instance.resizeColumns).toBeTruthy();
42
- expect(instance.showLayoutOptions).toBeTruthy();
43
- expect(instance.showReload).toBeTruthy();
44
- expect(instance.columnsButton).toBeFalsy();
45
- expect(instance.columnsButtonIgnore).toEqual([]);
46
- });
47
-
48
- it('should create new Grid replacing default values', () => {
49
- const instance = new TekTreeGrid({
50
- name: 'grid',
51
- component: 'TekTreeGrid',
52
- title: 'title',
53
- addButton: true,
54
- deleteButton: 'selection',
55
- filterButton: true,
56
- columnFilterButton: true,
57
- dragColumns: false,
58
- resizeColumns: false,
59
- showLayoutOptions: false,
60
- showReload: false,
61
- columns: [
62
- { name: 'id' },
63
- ],
64
- columnsButton: true,
65
- columnsButtonIgnore: ['id'],
66
- });
67
- expect(instance.title).toBe('title');
68
- expect(instance.addButton).toBeTruthy();
69
- expect(instance.deleteButton).toBe('selection');
70
- expect(instance.filterButton).toBeTruthy();
71
- expect(instance.columnFilterButton).toBeTruthy();
72
- expect(instance.dragColumns).toBeFalsy();
73
- expect(instance.resizeColumns).toBeFalsy();
74
- expect(instance.showLayoutOptions).toBeFalsy();
75
- expect(instance.showReload).toBeFalsy();
76
- expect(instance.columns[0]).toBeInstanceOf(TekGridColumn);
77
- expect(instance.columnsButton).toBeTruthy();
78
- expect(instance.columnsButtonIgnore).toEqual(['id']);
79
- });
80
-
81
- it('should create toolbar and footer', () => {
82
- const instance = new TekTreeGrid({
83
- name: 'grid',
84
- component: 'TekGrid',
85
- title: 'title',
86
- addButton: true,
87
- deleteButton: 'selection',
88
- filterButton: true,
89
- columnFilterButton: true,
90
- dragColumns: false,
91
- resizeColumns: false,
92
- showLayoutOptions: false,
93
- });
94
- instance.onCreated();
95
- expect(instance.toolbarSlot.length).toBe(3);
96
- });
97
-
98
- it('should overwrite toolbar', () => {
99
- const instance = new TekTreeGrid({
100
- name: 'grid',
101
- component: 'TekGrid',
102
- title: 'title',
103
- addButton: true,
104
- deleteButton: 'selection',
105
- filterButton: true,
106
- columnFilterButton: true,
107
- dragColumns: false,
108
- resizeColumns: false,
109
- showLayoutOptions: false,
110
- toolbarSlot: [],
111
- });
112
- instance.onCreated();
113
- expect(instance.toolbarSlot.length).toBe(0);
114
- });
115
- });
116
-
117
- describe('navigation', () => {
118
- const dispatchEvent = (key: string, modifiers: any) => {
119
- const event = new KeyboardEvent('keydown', modifiers);
120
- delete (event as any).key;
121
- Object.defineProperty(event, 'key', { value: key });
122
- delete (event as any).code;
123
- Object.defineProperty(event, 'code', { value: key });
124
- document.dispatchEvent(event);
125
- };
126
-
127
- it('should open filter modal input with keymap', async () => {
128
- const instance = new TekTreeGrid({
129
- name: 'grid_navigation_2',
130
- component: 'TekGrid',
131
- filterButton: true,
132
- });
133
- const elem = document.createElement('DIV');
134
-
135
- (KeyMap as any).isElementActive = () => true;
136
-
137
- instance.onMounted(elem);
138
- await flushPromises();
139
-
140
- const method = jest.fn();
141
-
142
- const spyMetadata = jest.spyOn(Metadata, 'getInstance').mockImplementation(() => new TekGridFilterButton({
143
- name: 'grid_navigation_2_filterButton',
144
- component: 'TekGridFilterButton',
145
- grid: instance,
146
- events: {
147
- click: method,
148
- },
149
- }));
150
-
151
- dispatchEvent('l', { ctrlKey: true }); // ctrl+l keydown
152
- await flushPromises();
153
-
154
- instance.onBeforeDestroy();
155
- await flushPromises();
156
-
157
- expect(method).toHaveBeenCalled();
158
- (KeyMap as any).isElementActive = () => false;
159
- spyMetadata.mockReset();
160
- });
161
-
162
- it('should open action dropdown with keymap', async () => {
163
- const instance = new TekTreeGrid({
164
- name: 'grid_navigation_2',
165
- component: 'TekTreeGrid',
166
- });
167
- const elem = document.createElement('DIV');
168
-
169
- (KeyMap as any).isElementActive = () => true;
170
-
171
- instance.onMounted(elem);
172
- await flushPromises();
173
-
174
- const instanceDropDown = new Dropdown({
175
- name: 'grid_navigation_2_actions_dropdown',
176
- component: 'ZdDropdown',
177
- activator: {
178
- name: 'grid_navigation_2_actionsButton',
179
- component: 'ZdButton',
180
- },
181
- children: [],
182
- });
183
- const instanceDropDownSpy = jest.spyOn(instanceDropDown, 'setFocus').mockImplementation(() => true);
184
- const spyMetadata = jest.spyOn(Metadata, 'getInstance').mockImplementation(() => instanceDropDown);
185
-
186
- dispatchEvent('enter', { ctrlKey: true, enterKey: true }); // ctrl + enter keydown
187
- await flushPromises();
188
-
189
- expect(spyMetadata).toHaveBeenCalled();
190
- expect(instanceDropDownSpy).toHaveBeenCalled();
191
-
192
- instance.onBeforeDestroy();
193
- await flushPromises();
194
-
195
- (KeyMap as any).isElementActive = () => false;
196
- spyMetadata.mockReset();
197
- instanceDropDownSpy.mockReset();
198
- });
199
-
200
- it('should focus in searchInput with keymap', async () => {
201
- const instance = new TekTreeGrid({
202
- name: 'grid_navigation_3',
203
- component: 'TekTreeGrid',
204
- });
205
- const elem = document.createElement('DIV');
206
-
207
- (KeyMap as any).isElementActive = () => true;
208
- instance.onMounted(elem);
209
- await flushPromises();
210
-
211
- const searchInput = new Search({
212
- name: 'grid_navigation_3_gridSearch',
213
- component: 'ZdSearch',
214
- parent: instance,
215
- });
216
-
217
- const spySetFocus = jest.spyOn(searchInput, 'setFocus').mockImplementation(() => true);
218
- const spyMetadata = jest.spyOn(Metadata, 'getInstance').mockImplementation(() => searchInput);
219
-
220
- dispatchEvent('f', { ctrlKey: true }); // ctrl+f keydown
221
- await flushPromises();
222
-
223
- expect(spySetFocus).toHaveBeenCalled();
224
-
225
- instance.onBeforeDestroy();
226
- await flushPromises();
227
-
228
- (KeyMap as any).isElementActive = () => false;
229
- spySetFocus.mockReset();
230
- spyMetadata.mockReset();
231
- });
232
- });
233
- describe('filterClick()', () => {
234
- it('should apply filter from form to tekdatasource', () => {
235
- const httpSpy = jest.spyOn(Http, 'get').mockImplementation(() => Promise.resolve({
236
- data: {
237
- data: [
238
- { id: 1, name: 'employee 1', department: 1 },
239
- { id: 2, name: 'employee 2', department: 1 },
240
- { id: 3, name: 'employee 3', department: 1 },
241
- { id: 4, name: 'employee 4', department: 2 },
242
- { id: 5, name: 'employee 5', department: 2 },
243
- ],
244
- pagination: {
245
- page: 1,
246
- total: 5,
247
- limit: 15,
248
- },
249
- },
250
- }));
251
-
252
- const instance = new TekTreeGrid({
253
- name: 'grid_filterClick11',
254
- component: 'TekTreeGrid',
255
- datasource: {
256
- type: 'tek-rest',
257
- },
258
- columns: [
259
- {
260
- name: 'id',
261
- filterProps: [{ name: 'id_edit', operation: 'IN', relation: 'AND' }],
262
- },
263
- {
264
- name: 'name',
265
- componentProps: { name: 'name_edit', component: 'ZdSelect' },
266
- filterProps: [{
267
- name: 'name_edit', label: 'name', operation: 'NOT_EQUALS', relation: 'OR',
268
- }],
269
- },
270
- ],
271
- });
272
-
273
- let form: IForm = { name: 'form', component: 'ZdForm' };
274
- let applyButton: IButton = { name: 'apply', component: 'ZdButton' };
275
- const spyModalService = jest.spyOn(ModalService, 'create').mockImplementation((modal: IModal) => {
276
- form = getChild(modal.children || [], `${instance.name}-filter-form`);
277
-
278
- const modalFooter = getChild(modal.children || [], `${instance.name}-filter-footer`);
279
- applyButton = getChild(modalFooter.rightSlot, `${instance.name}-filter-okButton`);
280
-
281
- return new Modal(modal);
282
- });
283
-
284
- instance.onCreated();
285
-
286
- const buttonProps = getChild<ITekGridFilterButton>(instance.toolbarSlot, `${instance.name}_filterButton`);
287
- const button = new TekGridFilterButton(buttonProps);
288
- setClick(button);
289
-
290
- const formObject = new Form(form);
291
- const spyMetadata = jest.spyOn(Metadata, 'getInstance').mockImplementation(() => formObject);
292
- const spyDatasourceGet = jest.spyOn(instance.datasource, 'get');
293
- formObject.value = {
294
- 'grid_filterClick11-filter-AND-IN-id-0': ['1', '2', '3'],
295
- 'grid_filterClick11-filter-OR-NOT_EQUALS-name-0': 'teste',
296
- 'grid_filterClick11-filter-AND-CONTAINS-phone-0': '',
297
- 'grid_filterClick11-filter-AND-GREATER_THAN_EQUALS-salary-0': '1000',
298
- 'grid_filterClick11-filter-AND-LESS_THAN_EQUALS-salary-0': '2000',
299
- };
300
- const applyButtonObject = new Button(applyButton);
301
- formObject.validate = () => false;
302
- setClick(applyButtonObject);
303
- expect((instance.datasource as TekRestDatasource).dynamicFilter).toEqual({});
304
-
305
- formObject.validate = () => true;
306
- setClick(applyButtonObject);
307
- expect((instance.datasource as TekRestDatasource).dynamicFilter).toEqual({
308
- id: [
309
- {
310
- operation: 'IN',
311
- relation: 'AND',
312
- value: ['1', '2', '3'],
313
- },
314
- ],
315
- name: [
316
- {
317
- operation: 'NOT_EQUALS',
318
- relation: 'OR',
319
- value: 'teste',
320
- },
321
- ],
322
- salary: [
323
- {
324
- operation: 'GREATER_THAN_EQUALS',
325
- relation: 'AND',
326
- value: '1000',
327
- },
328
- {
329
- operation: 'LESS_THAN_EQUALS',
330
- relation: 'AND',
331
- value: '2000',
332
- },
333
- ],
334
- });
335
- expect(instance.columnHasFilterData({ name: 'name' } as TekGridColumn)).toBeTruthy();
336
- expect(spyDatasourceGet).toBeCalled();
337
- spyMetadata.mockReset();
338
- spyDatasourceGet.mockReset();
339
- spyModalService.mockReset();
340
- httpSpy.mockReset();
341
- });
342
-
343
- it('should apply filter from form to datasource', () => {
344
- let beforeApplyFilterCalled = false;
345
- let changeLayoutCalled = false;
346
- const instance = new TekTreeGrid({
347
- name: 'grid_filterClick12',
348
- component: 'TekTreeGrid',
349
- columns: [
350
- {
351
- name: 'id',
352
- },
353
- {
354
- name: 'name',
355
- },
356
- ],
357
- events: {
358
- beforeApplyFilter: () => { beforeApplyFilterCalled = true; },
359
- changeLayout: () => { changeLayoutCalled = true; },
360
- },
361
- });
362
-
363
- let form: IForm = { name: 'form', component: 'ZdForm' };
364
- let applyButton: IButton = { name: 'apply', component: 'ZdButton' };
365
- const spyModalService = jest.spyOn(ModalService, 'create').mockImplementation((modal: IModal) => {
366
- form = getChild(modal.children || [], `${instance.name}-filter-form`);
367
-
368
- const modalFooter = getChild(modal.children || [], `${instance.name}-filter-footer`);
369
- applyButton = getChild(modalFooter.rightSlot, `${instance.name}-filter-okButton`);
370
-
371
- return new Modal(modal);
372
- });
373
-
374
- instance.onCreated();
375
-
376
- clickOnFilterButton(instance);
377
-
378
- const formObject = new Form(form);
379
- const spyMetadata = jest.spyOn(Metadata, 'getInstance').mockImplementation(() => formObject);
380
- const spyDatasourceGet = jest.spyOn(instance.datasource, 'get');
381
- formObject.value = {
382
- 'grid_filterClick12-filter-AND-CONTAINS-id-0': '1;2;3',
383
- 'grid_filterClick12-filter-AND-CONTAINS-name-0': 'teste',
384
- };
385
- const applyButtonObject = new Button(applyButton);
386
- setClick(applyButtonObject, { defaultPrevented: true });
387
- expect((instance.datasource as TekRestDatasource).filter).toEqual({
388
- id: '1;2;3',
389
- name: 'teste',
390
- });
391
- expect(beforeApplyFilterCalled).toBeTruthy();
392
- expect(changeLayoutCalled).toBeTruthy();
393
- expect(instance.columnHasFilterData({ name: 'name' } as TekGridColumn)).toBeTruthy();
394
- expect(spyDatasourceGet).not.toBeCalled();
395
- spyMetadata.mockReset();
396
- spyDatasourceGet.mockReset();
397
- spyModalService.mockReset();
398
- });
399
- });
400
-
401
- describe('setSearch()', () => {
402
- let baseProps: ITekTreeGrid;
403
- let httpSpy: jest.SpyInstance;
404
-
405
- beforeEach(() => {
406
- httpSpy = jest.spyOn(Http, 'get').mockImplementation(() => Promise.resolve({
407
- data: {
408
- data: [
409
- { id: 1, name: 'task 1' },
410
- { id: 11, name: 'task 1.1', parent: 1 },
411
- { id: 12, name: 'task 1.2', parent: 1 },
412
- { id: 2, name: 'task 2' },
413
- { id: 3, name: 'task 3' },
414
- ],
415
- pagination: {
416
- page: 1,
417
- total: 5,
418
- limit: 15,
419
- },
420
- },
421
- }));
422
-
423
- baseProps = {
424
- name: 'grid_search',
425
- component: 'TekTreeGrid',
426
- columns: [
427
- {
428
- name: 'id',
429
- },
430
- {
431
- name: 'name',
432
- },
433
- ],
434
- datasource: {
435
- type: 'tek-rest',
436
- lazyLoad: false,
437
- route: '/grid',
438
- },
439
- };
440
-
441
- httpSpy.mockClear();
442
- });
443
-
444
- afterAll(() => {
445
- httpSpy.mockClear();
446
- });
447
-
448
- it('should set datasource search_join based on columns that have datasource', async () => {
449
- const instance = new TekTreeGrid(baseProps);
450
-
451
- await instance.setSearch('1');
452
- expect(instance.datasource).toBeInstanceOf(TekRestDatasource);
453
- expect((instance.datasource as TekRestDatasource).searchJoin).toEqual({});
454
- expect(httpSpy).toHaveBeenCalledTimes(1);
455
- });
456
- });
457
-
458
- describe('getReport()', () => {
459
- let httpReportSpy: jest.SpyInstance;
460
- let reportSpy: jest.SpyInstance;
461
-
462
- beforeEach(() => {
463
- reportSpy = jest.spyOn(Report.prototype, 'getReport').mockReturnValue(Promise.resolve(''));
464
- httpReportSpy = jest.spyOn(Http, 'post').mockImplementation((url) => {
465
- if (url === 'https://zhreport.teknisa.com/generateReport') {
466
- return Promise.resolve({
467
- data: { messages: [{ message: 'pdf-report.html' }] },
468
- });
469
- }
470
-
471
- return Promise.reject();
472
- });
473
- });
474
-
475
- afterEach(() => {
476
- reportSpy.mockClear();
477
- httpReportSpy.mockClear();
478
- });
479
-
480
- it('should call window open on getReport method', async () => {
481
- (window as any).open = jest.fn();
482
-
483
- const instance = new TekTreeGrid({
484
- name: 'grid',
485
- component: 'TekTreeGrid',
486
- events: {
487
- beforeOpenReport: jest.fn(),
488
- },
489
- datasource: {
490
- type: 'tek-rest',
491
- uniqueKey: 'id',
492
- route: '/zeedhi',
493
- lazyLoad: false,
494
- data: [
495
- { id: '1', department_id: '1' },
496
- ],
497
- },
498
- columns: [
499
- {
500
- name: 'id',
501
- label: 'ID',
502
- },
503
- {
504
- name: 'department_id',
505
- label: 'Department ID',
506
- },
507
- ],
508
- });
509
-
510
- const spy = jest.spyOn(window, 'open');
511
- await instance.getReport('pdf');
512
-
513
- expect(spy).toHaveBeenCalledTimes(1);
514
-
515
- (window as any).open.mockClear();
516
- spy.mockClear();
517
- });
518
-
519
- it('should call window open on getReport method when using tekmemorydatasource', async () => {
520
- (window as any).open = jest.fn();
521
-
522
- const instance = new TekTreeGrid({
523
- name: 'grid',
524
- component: 'TekTreeGrid',
525
- events: {
526
- beforeOpenReport: jest.fn(),
527
- },
528
- columns: [
529
- {
530
- name: 'id',
531
- label: 'ID',
532
- },
533
- {
534
- name: 'department_id',
535
- label: 'Department ID',
536
- },
537
- ],
538
- });
539
-
540
- const spy = jest.spyOn(window, 'open');
541
- await instance.getReport('pdf');
542
-
543
- expect(spy).toHaveBeenCalledTimes(1);
544
-
545
- (window as any).open.mockClear();
546
- spy.mockClear();
547
- });
548
- });
549
-
550
- describe('rowClick', () => {
551
- it('rowClick method should call events.rowClick', () => {
552
- const rowClick = jest.fn();
553
-
554
- const data = [
555
- { id: '1', name: 'First' },
556
- { id: '2', name: 'Second' },
557
- { id: '3', name: 'Third' },
558
- ];
559
- const grid = new TekTreeGrid({
560
- name: 'grid',
561
- component: 'TekGrid',
562
- columns: [
563
- { name: 'id' },
564
- { name: 'name' },
565
- ],
566
- datasource: {
567
- data,
568
- },
569
- events: {
570
- rowClick,
571
- },
572
- });
573
-
574
- const event = new Event('click');
575
- const element = document.createElement('div');
576
- grid.rowClick(data[0], event, element);
577
-
578
- expect(rowClick).toHaveBeenCalledWith({
579
- event,
580
- element,
581
- row: data[0],
582
- component: grid,
583
- });
584
- expect(grid.datasource.currentRow).toEqual(data[0]);
585
- });
586
-
587
- it('should not call events.rowClick if cellClick prevents it', async () => {
588
- const rowClick = jest.fn();
589
-
590
- const data = [
591
- { id: '1', name: 'First' },
592
- { id: '2', name: 'Second' },
593
- { id: '3', name: 'Third' },
594
- ];
595
- const grid = new TekTreeGrid({
596
- name: 'grid',
597
- component: 'TekGrid',
598
- columns: [
599
- { name: 'id' },
600
- { name: 'name' },
601
- ],
602
- datasource: {
603
- data,
604
- },
605
- events: {
606
- rowClick,
607
- cellClick: () => true,
608
- },
609
- });
610
- await flushPromises();
611
-
612
- const event = new Event('click');
613
- const element = document.createElement('div');
614
- grid.cellClick(data[0], grid.getColumn('id') as any, event, element);
615
- grid.rowClick(data[0], event, element);
616
-
617
- expect(rowClick).not.toHaveBeenCalled();
618
- expect(grid.datasource.currentRow).toEqual({});
619
- });
620
- });
621
-
622
- describe('layoutOptions', () => {
623
- it('should return layout options instance', async () => {
624
- const grid = new TekTreeGrid({
625
- name: 'grid',
626
- component: 'TekGrid',
627
- showLayoutOptions: false,
628
- });
629
-
630
- expect(grid.layoutOptions).toBeUndefined();
631
-
632
- grid.showLayoutOptions = true;
633
- const layoutOptionsComp = { name: 'grid_layout_options' };
634
- const spyMetadata = jest.spyOn(Metadata, 'getInstance').mockImplementation(() => layoutOptionsComp);
635
- expect(grid.layoutOptions).toEqual(layoutOptionsComp);
636
- spyMetadata.mockClear();
637
- });
638
- });
639
-
640
- describe('getAtomInstance', () => {
641
- const createAtom = (name: string) => new Text({
642
- name: `${name}_gridTitle`,
643
- component: 'ZdText',
644
- text: 'Employees',
645
- });
646
-
647
- it('when called, should return the instance of an atom component', () => {
648
- const instance = new TekTreeGrid({ name: 'Grid', component: 'TekGrid' });
649
- const atom = createAtom(instance.name);
650
- const spyMetadata = jest.spyOn(Metadata, 'getInstance').mockImplementation(() => atom);
651
-
652
- const gridAtom = instance.getAtomInstance<Text>('TITLE');
653
-
654
- expect(gridAtom).toEqual(atom);
655
- spyMetadata.mockClear();
656
- });
657
- });
658
-
659
- describe('getFilterInputs', () => {
660
- const mockMetadata = (instance: TekTreeGrid) => {
661
- const inputs: IDictionary = {};
662
- instance.columns.forEach((col) => {
663
- if (!col.filterable || !col.filterProps) return;
664
-
665
- col.filterProps.forEach((filter: any, index: number) => {
666
- const relation = filter.relation || 'AND';
667
- const operation = filter.operation || 'CONTAINS';
668
-
669
- const name = `${instance.name}-filter-${relation}-${operation}-${col.name}-${index}`;
670
- inputs[name] = new TextInput({
671
- name,
672
- ...filter.filterProps,
673
- });
674
- });
675
- });
676
- return jest.spyOn(Metadata, 'getInstance').mockImplementation((name: string) => inputs[name]);
677
- };
678
-
679
- it('when called with null parameter, should return all the filter inputs', () => {
680
- const spyModalService = jest.spyOn(ModalService, 'create').mockImplementation((modal: IModal) => (new Modal(modal)));
681
- const instance = new TekTreeGrid({
682
- name: 'grid',
683
- component: 'TekGrid',
684
- datasource: {
685
- type: 'tek-rest',
686
- uniqueKey: 'id',
687
- route: '/zeedhi',
688
- lazyLoad: false,
689
- },
690
- columns: [
691
- { name: 'id' },
692
- { name: 'name', filterable: true, filterProps: [{ name: 'name_edit', label: 'name' }] },
693
- {
694
- name: 'salary',
695
- filterable: true,
696
- filterProps: [
697
- {
698
- name: 'salary_edit',
699
- component: 'ZdCurrency',
700
- operation: 'GREATER_THAN_EQUALS',
701
- label: 'Salary (min)',
702
- },
703
- {
704
- name: 'salary_edit',
705
- component: 'ZdCurrency',
706
- operation: 'LESS_THAN_EQUALS',
707
- label: 'Salary (max)',
708
- },
709
- ],
710
- },
711
- ],
712
- });
713
-
714
- const spy = mockMetadata(instance);
715
- instance.onCreated();
716
-
717
- const filterButton = clickOnFilterButton(instance);
718
- filterButton.onCreated();
719
-
720
- const inputs = instance.getFilterInputs();
721
- expect(inputs[0].name).toBe('grid-filter-AND-CONTAINS-name-0');
722
- expect(inputs[1].name).toBe('grid-filter-AND-GREATER_THAN_EQUALS-salary-0');
723
- expect(inputs[2].name).toBe('grid-filter-AND-LESS_THAN_EQUALS-salary-1');
724
- spy.mockClear();
725
- spyModalService.mockReset();
726
- });
727
-
728
- it('when called, should return the instances of filters with multiple inputs', () => {
729
- const spyModalService = jest.spyOn(ModalService, 'create').mockImplementation((modal: IModal) => (new Modal(modal)));
730
- const instance = new TekTreeGrid({
731
- name: 'grid',
732
- component: 'TekGrid',
733
- datasource: {
734
- type: 'tek-rest',
735
- uniqueKey: 'id',
736
- route: '/zeedhi',
737
- lazyLoad: false,
738
- },
739
- columns: [
740
- { name: 'id' },
741
- { name: 'name', filterable: true, filterProps: [{ name: 'name_edit', label: 'name' }] },
742
- {
743
- name: 'salary',
744
- filterable: true,
745
- filterProps: [
746
- {
747
- name: 'salary_edit',
748
- component: 'ZdCurrency',
749
- operation: 'GREATER_THAN_EQUALS',
750
- label: 'Salary (min)',
751
- },
752
- {
753
- name: 'salary_edit',
754
- component: 'ZdCurrency',
755
- operation: 'LESS_THAN_EQUALS',
756
- label: 'Salary (max)',
757
- },
758
- ],
759
- },
760
- ],
761
- });
762
-
763
- const spy = mockMetadata(instance);
764
- instance.onCreated();
765
-
766
- const filterButton = clickOnFilterButton(instance);
767
- filterButton.onCreated();
768
-
769
- const inputs = instance.getFilterInputs('salary');
770
- expect(inputs[0].name).toBe('grid-filter-AND-GREATER_THAN_EQUALS-salary-0');
771
- expect(inputs[1].name).toBe('grid-filter-AND-LESS_THAN_EQUALS-salary-1');
772
- spy.mockClear();
773
- spyModalService.mockReset();
774
- });
775
- });
776
- });
1
+ import {
2
+ Button, Dropdown, Form, IButton, IForm, IModal, Modal, ModalService, Report, Search, Text, TextInput,
3
+ } from '@zeedhi/common';
4
+ import {
5
+ Http, IDictionary, KeyMap, Metadata,
6
+ } from '@zeedhi/core';
7
+ import {
8
+ ITekGridFilterButton,
9
+ ITekTreeGrid, TekGridColumn, TekGridFilterButton, TekRestDatasource, TekTreeGrid,
10
+ } from '../../../../src';
11
+ import { getChild, setClick } from '../../../__helpers__';
12
+
13
+ const flushPromises = () => new Promise(setImmediate);
14
+
15
+ const clickOnFilterButton = (grid: TekTreeGrid, event?: any) => {
16
+ const buttonProps = getChild<ITekGridFilterButton>(grid.toolbarSlot, `${grid.name}_filterButton`);
17
+ const button = new TekGridFilterButton(buttonProps);
18
+ setClick(button, event);
19
+
20
+ return button;
21
+ };
22
+
23
+ describe('TekTreeGrid', () => {
24
+ beforeEach(() => {
25
+ // clear all metadata instances before testing
26
+ const { instances } = Metadata as any;
27
+ Object.keys(instances).forEach((key) => {
28
+ Metadata.clearInstance(key, instances[key].componentId);
29
+ });
30
+ });
31
+
32
+ describe('constructor()', () => {
33
+ it('should create new grid with default values', () => {
34
+ const instance = new TekTreeGrid({ name: 'TreeGrid', component: 'TekTreeGrid' });
35
+ expect(instance.title).toBe('');
36
+ expect(instance.addButton).toBeFalsy();
37
+ expect(instance.deleteButton).toBe('none');
38
+ expect(instance.filterButton).toBeFalsy();
39
+ expect(instance.columnFilterButton).toBeFalsy();
40
+ expect(instance.dragColumns).toBeTruthy();
41
+ expect(instance.resizeColumns).toBeTruthy();
42
+ expect(instance.showLayoutOptions).toBeTruthy();
43
+ expect(instance.showReload).toBeTruthy();
44
+ expect(instance.columnsButton).toBeFalsy();
45
+ expect(instance.columnsButtonIgnore).toEqual([]);
46
+ });
47
+
48
+ it('should create new Grid replacing default values', () => {
49
+ const instance = new TekTreeGrid({
50
+ name: 'grid',
51
+ component: 'TekTreeGrid',
52
+ title: 'title',
53
+ addButton: true,
54
+ deleteButton: 'selection',
55
+ filterButton: true,
56
+ columnFilterButton: true,
57
+ dragColumns: false,
58
+ resizeColumns: false,
59
+ showLayoutOptions: false,
60
+ showReload: false,
61
+ columns: [
62
+ { name: 'id' },
63
+ ],
64
+ columnsButton: true,
65
+ columnsButtonIgnore: ['id'],
66
+ });
67
+ expect(instance.title).toBe('title');
68
+ expect(instance.addButton).toBeTruthy();
69
+ expect(instance.deleteButton).toBe('selection');
70
+ expect(instance.filterButton).toBeTruthy();
71
+ expect(instance.columnFilterButton).toBeTruthy();
72
+ expect(instance.dragColumns).toBeFalsy();
73
+ expect(instance.resizeColumns).toBeFalsy();
74
+ expect(instance.showLayoutOptions).toBeFalsy();
75
+ expect(instance.showReload).toBeFalsy();
76
+ expect(instance.columns[0]).toBeInstanceOf(TekGridColumn);
77
+ expect(instance.columnsButton).toBeTruthy();
78
+ expect(instance.columnsButtonIgnore).toEqual(['id']);
79
+ });
80
+
81
+ it('should create toolbar and footer', () => {
82
+ const instance = new TekTreeGrid({
83
+ name: 'grid',
84
+ component: 'TekGrid',
85
+ title: 'title',
86
+ addButton: true,
87
+ deleteButton: 'selection',
88
+ filterButton: true,
89
+ columnFilterButton: true,
90
+ dragColumns: false,
91
+ resizeColumns: false,
92
+ showLayoutOptions: false,
93
+ });
94
+ instance.onCreated();
95
+ expect(instance.toolbarSlot.length).toBe(3);
96
+ });
97
+
98
+ it('should overwrite toolbar', () => {
99
+ const instance = new TekTreeGrid({
100
+ name: 'grid',
101
+ component: 'TekGrid',
102
+ title: 'title',
103
+ addButton: true,
104
+ deleteButton: 'selection',
105
+ filterButton: true,
106
+ columnFilterButton: true,
107
+ dragColumns: false,
108
+ resizeColumns: false,
109
+ showLayoutOptions: false,
110
+ toolbarSlot: [],
111
+ });
112
+ instance.onCreated();
113
+ expect(instance.toolbarSlot.length).toBe(0);
114
+ });
115
+ });
116
+
117
+ describe('navigation', () => {
118
+ const dispatchEvent = (key: string, modifiers: any) => {
119
+ const event = new KeyboardEvent('keydown', modifiers);
120
+ delete (event as any).key;
121
+ Object.defineProperty(event, 'key', { value: key });
122
+ delete (event as any).code;
123
+ Object.defineProperty(event, 'code', { value: key });
124
+ document.dispatchEvent(event);
125
+ };
126
+
127
+ it('should open filter modal input with keymap', async () => {
128
+ const instance = new TekTreeGrid({
129
+ name: 'grid_navigation_2',
130
+ component: 'TekGrid',
131
+ filterButton: true,
132
+ });
133
+ const elem = document.createElement('DIV');
134
+
135
+ (KeyMap as any).isElementActive = () => true;
136
+
137
+ instance.onMounted(elem);
138
+ await flushPromises();
139
+
140
+ const method = jest.fn();
141
+
142
+ const spyMetadata = jest.spyOn(Metadata, 'getInstance').mockImplementation(() => new TekGridFilterButton({
143
+ name: 'grid_navigation_2_filterButton',
144
+ component: 'TekGridFilterButton',
145
+ grid: instance,
146
+ events: {
147
+ click: method,
148
+ },
149
+ }));
150
+
151
+ dispatchEvent('l', { ctrlKey: true }); // ctrl+l keydown
152
+ await flushPromises();
153
+
154
+ instance.onBeforeDestroy();
155
+ await flushPromises();
156
+
157
+ expect(method).toHaveBeenCalled();
158
+ (KeyMap as any).isElementActive = () => false;
159
+ spyMetadata.mockReset();
160
+ });
161
+
162
+ it('should open action dropdown with keymap', async () => {
163
+ const instance = new TekTreeGrid({
164
+ name: 'grid_navigation_2',
165
+ component: 'TekTreeGrid',
166
+ });
167
+ const elem = document.createElement('DIV');
168
+
169
+ (KeyMap as any).isElementActive = () => true;
170
+
171
+ instance.onMounted(elem);
172
+ await flushPromises();
173
+
174
+ const instanceDropDown = new Dropdown({
175
+ name: 'grid_navigation_2_actions_dropdown',
176
+ component: 'ZdDropdown',
177
+ activator: {
178
+ name: 'grid_navigation_2_actionsButton',
179
+ component: 'ZdButton',
180
+ },
181
+ children: [],
182
+ });
183
+ const instanceDropDownSpy = jest.spyOn(instanceDropDown, 'setFocus').mockImplementation(() => true);
184
+ const spyMetadata = jest.spyOn(Metadata, 'getInstance').mockImplementation(() => instanceDropDown);
185
+
186
+ dispatchEvent('enter', { ctrlKey: true, enterKey: true }); // ctrl + enter keydown
187
+ await flushPromises();
188
+
189
+ expect(spyMetadata).toHaveBeenCalled();
190
+ expect(instanceDropDownSpy).toHaveBeenCalled();
191
+
192
+ instance.onBeforeDestroy();
193
+ await flushPromises();
194
+
195
+ (KeyMap as any).isElementActive = () => false;
196
+ spyMetadata.mockReset();
197
+ instanceDropDownSpy.mockReset();
198
+ });
199
+
200
+ it('should focus in searchInput with keymap', async () => {
201
+ const instance = new TekTreeGrid({
202
+ name: 'grid_navigation_3',
203
+ component: 'TekTreeGrid',
204
+ });
205
+ const elem = document.createElement('DIV');
206
+
207
+ (KeyMap as any).isElementActive = () => true;
208
+ instance.onMounted(elem);
209
+ await flushPromises();
210
+
211
+ const searchInput = new Search({
212
+ name: 'grid_navigation_3_gridSearch',
213
+ component: 'ZdSearch',
214
+ parent: instance,
215
+ });
216
+
217
+ const spySetFocus = jest.spyOn(searchInput, 'setFocus').mockImplementation(() => true);
218
+ const spyMetadata = jest.spyOn(Metadata, 'getInstance').mockImplementation(() => searchInput);
219
+
220
+ dispatchEvent('f', { ctrlKey: true }); // ctrl+f keydown
221
+ await flushPromises();
222
+
223
+ expect(spySetFocus).toHaveBeenCalled();
224
+
225
+ instance.onBeforeDestroy();
226
+ await flushPromises();
227
+
228
+ (KeyMap as any).isElementActive = () => false;
229
+ spySetFocus.mockReset();
230
+ spyMetadata.mockReset();
231
+ });
232
+ });
233
+ describe('filterClick()', () => {
234
+ it('should apply filter from form to tekdatasource', () => {
235
+ const httpSpy = jest.spyOn(Http, 'get').mockImplementation(() => Promise.resolve({
236
+ data: {
237
+ data: [
238
+ { id: 1, name: 'employee 1', department: 1 },
239
+ { id: 2, name: 'employee 2', department: 1 },
240
+ { id: 3, name: 'employee 3', department: 1 },
241
+ { id: 4, name: 'employee 4', department: 2 },
242
+ { id: 5, name: 'employee 5', department: 2 },
243
+ ],
244
+ pagination: {
245
+ page: 1,
246
+ total: 5,
247
+ limit: 15,
248
+ },
249
+ },
250
+ }));
251
+
252
+ const instance = new TekTreeGrid({
253
+ name: 'grid_filterClick11',
254
+ component: 'TekTreeGrid',
255
+ datasource: {
256
+ type: 'tek-rest',
257
+ },
258
+ columns: [
259
+ {
260
+ name: 'id',
261
+ filterProps: [{ name: 'id_edit', operation: 'IN', relation: 'AND' }],
262
+ },
263
+ {
264
+ name: 'name',
265
+ componentProps: { name: 'name_edit', component: 'ZdSelect' },
266
+ filterProps: [{
267
+ name: 'name_edit', label: 'name', operation: 'NOT_EQUALS', relation: 'OR',
268
+ }],
269
+ },
270
+ ],
271
+ });
272
+
273
+ let form: IForm = { name: 'form', component: 'ZdForm' };
274
+ let applyButton: IButton = { name: 'apply', component: 'ZdButton' };
275
+ const spyModalService = jest.spyOn(ModalService, 'create').mockImplementation((modal: IModal) => {
276
+ form = getChild(modal.children || [], `${instance.name}-filter-form`);
277
+
278
+ const modalFooter = getChild(modal.children || [], `${instance.name}-filter-footer`);
279
+ applyButton = getChild(modalFooter.rightSlot, `${instance.name}-filter-okButton`);
280
+
281
+ return new Modal(modal);
282
+ });
283
+
284
+ instance.onCreated();
285
+
286
+ const buttonProps = getChild<ITekGridFilterButton>(instance.toolbarSlot, `${instance.name}_filterButton`);
287
+ const button = new TekGridFilterButton(buttonProps);
288
+ setClick(button);
289
+
290
+ const formObject = new Form(form);
291
+ const spyMetadata = jest.spyOn(Metadata, 'getInstance').mockImplementation(() => formObject);
292
+ const spyDatasourceGet = jest.spyOn(instance.datasource, 'get');
293
+ formObject.value = {
294
+ 'grid_filterClick11-filter-AND-IN-id-0': ['1', '2', '3'],
295
+ 'grid_filterClick11-filter-OR-NOT_EQUALS-name-0': 'teste',
296
+ 'grid_filterClick11-filter-AND-CONTAINS-phone-0': '',
297
+ 'grid_filterClick11-filter-AND-GREATER_THAN_EQUALS-salary-0': '1000',
298
+ 'grid_filterClick11-filter-AND-LESS_THAN_EQUALS-salary-0': '2000',
299
+ };
300
+ const applyButtonObject = new Button(applyButton);
301
+ formObject.validate = () => false;
302
+ setClick(applyButtonObject);
303
+ expect((instance.datasource as TekRestDatasource).dynamicFilter).toEqual({});
304
+
305
+ formObject.validate = () => true;
306
+ setClick(applyButtonObject);
307
+ expect((instance.datasource as TekRestDatasource).dynamicFilter).toEqual({
308
+ id: [
309
+ {
310
+ operation: 'IN',
311
+ relation: 'AND',
312
+ value: ['1', '2', '3'],
313
+ },
314
+ ],
315
+ name: [
316
+ {
317
+ operation: 'NOT_EQUALS',
318
+ relation: 'OR',
319
+ value: 'teste',
320
+ },
321
+ ],
322
+ salary: [
323
+ {
324
+ operation: 'GREATER_THAN_EQUALS',
325
+ relation: 'AND',
326
+ value: '1000',
327
+ },
328
+ {
329
+ operation: 'LESS_THAN_EQUALS',
330
+ relation: 'AND',
331
+ value: '2000',
332
+ },
333
+ ],
334
+ });
335
+ expect(instance.columnHasFilterData({ name: 'name' } as TekGridColumn)).toBeTruthy();
336
+ expect(spyDatasourceGet).toBeCalled();
337
+ spyMetadata.mockReset();
338
+ spyDatasourceGet.mockReset();
339
+ spyModalService.mockReset();
340
+ httpSpy.mockReset();
341
+ });
342
+
343
+ it('should apply filter from form to datasource', () => {
344
+ let beforeApplyFilterCalled = false;
345
+ let changeLayoutCalled = false;
346
+ const instance = new TekTreeGrid({
347
+ name: 'grid_filterClick12',
348
+ component: 'TekTreeGrid',
349
+ columns: [
350
+ {
351
+ name: 'id',
352
+ },
353
+ {
354
+ name: 'name',
355
+ },
356
+ ],
357
+ events: {
358
+ beforeApplyFilter: () => { beforeApplyFilterCalled = true; },
359
+ changeLayout: () => { changeLayoutCalled = true; },
360
+ },
361
+ });
362
+
363
+ let form: IForm = { name: 'form', component: 'ZdForm' };
364
+ let applyButton: IButton = { name: 'apply', component: 'ZdButton' };
365
+ const spyModalService = jest.spyOn(ModalService, 'create').mockImplementation((modal: IModal) => {
366
+ form = getChild(modal.children || [], `${instance.name}-filter-form`);
367
+
368
+ const modalFooter = getChild(modal.children || [], `${instance.name}-filter-footer`);
369
+ applyButton = getChild(modalFooter.rightSlot, `${instance.name}-filter-okButton`);
370
+
371
+ return new Modal(modal);
372
+ });
373
+
374
+ instance.onCreated();
375
+
376
+ clickOnFilterButton(instance);
377
+
378
+ const formObject = new Form(form);
379
+ const spyMetadata = jest.spyOn(Metadata, 'getInstance').mockImplementation(() => formObject);
380
+ const spyDatasourceGet = jest.spyOn(instance.datasource, 'get');
381
+ formObject.value = {
382
+ 'grid_filterClick12-filter-AND-CONTAINS-id-0': '1;2;3',
383
+ 'grid_filterClick12-filter-AND-CONTAINS-name-0': 'teste',
384
+ };
385
+ const applyButtonObject = new Button(applyButton);
386
+ setClick(applyButtonObject, { defaultPrevented: true });
387
+ expect((instance.datasource as TekRestDatasource).filter).toEqual({
388
+ id: '1;2;3',
389
+ name: 'teste',
390
+ });
391
+ expect(beforeApplyFilterCalled).toBeTruthy();
392
+ expect(changeLayoutCalled).toBeTruthy();
393
+ expect(instance.columnHasFilterData({ name: 'name' } as TekGridColumn)).toBeTruthy();
394
+ expect(spyDatasourceGet).not.toBeCalled();
395
+ spyMetadata.mockReset();
396
+ spyDatasourceGet.mockReset();
397
+ spyModalService.mockReset();
398
+ });
399
+ });
400
+
401
+ describe('setSearch()', () => {
402
+ let baseProps: ITekTreeGrid;
403
+ let httpSpy: jest.SpyInstance;
404
+
405
+ beforeEach(() => {
406
+ httpSpy = jest.spyOn(Http, 'get').mockImplementation(() => Promise.resolve({
407
+ data: {
408
+ data: [
409
+ { id: 1, name: 'task 1' },
410
+ { id: 11, name: 'task 1.1', parent: 1 },
411
+ { id: 12, name: 'task 1.2', parent: 1 },
412
+ { id: 2, name: 'task 2' },
413
+ { id: 3, name: 'task 3' },
414
+ ],
415
+ pagination: {
416
+ page: 1,
417
+ total: 5,
418
+ limit: 15,
419
+ },
420
+ },
421
+ }));
422
+
423
+ baseProps = {
424
+ name: 'grid_search',
425
+ component: 'TekTreeGrid',
426
+ columns: [
427
+ {
428
+ name: 'id',
429
+ },
430
+ {
431
+ name: 'name',
432
+ },
433
+ ],
434
+ datasource: {
435
+ type: 'tek-rest',
436
+ lazyLoad: false,
437
+ route: '/grid',
438
+ },
439
+ };
440
+
441
+ httpSpy.mockClear();
442
+ });
443
+
444
+ afterAll(() => {
445
+ httpSpy.mockClear();
446
+ });
447
+
448
+ it('should set datasource search_join based on columns that have datasource', async () => {
449
+ const instance = new TekTreeGrid(baseProps);
450
+
451
+ await instance.setSearch('1');
452
+ expect(instance.datasource).toBeInstanceOf(TekRestDatasource);
453
+ expect((instance.datasource as TekRestDatasource).searchJoin).toEqual({});
454
+ expect(httpSpy).toHaveBeenCalledTimes(1);
455
+ });
456
+ });
457
+
458
+ describe('getReport()', () => {
459
+ let httpReportSpy: jest.SpyInstance;
460
+ let reportSpy: jest.SpyInstance;
461
+
462
+ beforeEach(() => {
463
+ reportSpy = jest.spyOn(Report.prototype, 'getReport').mockReturnValue(Promise.resolve(''));
464
+ httpReportSpy = jest.spyOn(Http, 'post').mockImplementation((url) => {
465
+ if (url === 'https://zhreport.teknisa.com/generateReport') {
466
+ return Promise.resolve({
467
+ data: { messages: [{ message: 'pdf-report.html' }] },
468
+ });
469
+ }
470
+
471
+ return Promise.reject();
472
+ });
473
+ });
474
+
475
+ afterEach(() => {
476
+ reportSpy.mockClear();
477
+ httpReportSpy.mockClear();
478
+ });
479
+
480
+ it('should call window open on getReport method', async () => {
481
+ (window as any).open = jest.fn();
482
+
483
+ const instance = new TekTreeGrid({
484
+ name: 'grid',
485
+ component: 'TekTreeGrid',
486
+ events: {
487
+ beforeOpenReport: jest.fn(),
488
+ },
489
+ datasource: {
490
+ type: 'tek-rest',
491
+ uniqueKey: 'id',
492
+ route: '/zeedhi',
493
+ lazyLoad: false,
494
+ data: [
495
+ { id: '1', department_id: '1' },
496
+ ],
497
+ },
498
+ columns: [
499
+ {
500
+ name: 'id',
501
+ label: 'ID',
502
+ },
503
+ {
504
+ name: 'department_id',
505
+ label: 'Department ID',
506
+ },
507
+ ],
508
+ });
509
+
510
+ const spy = jest.spyOn(window, 'open');
511
+ await instance.getReport('pdf');
512
+
513
+ expect(spy).toHaveBeenCalledTimes(1);
514
+
515
+ (window as any).open.mockClear();
516
+ spy.mockClear();
517
+ });
518
+
519
+ it('should call window open on getReport method when using tekmemorydatasource', async () => {
520
+ (window as any).open = jest.fn();
521
+
522
+ const instance = new TekTreeGrid({
523
+ name: 'grid',
524
+ component: 'TekTreeGrid',
525
+ events: {
526
+ beforeOpenReport: jest.fn(),
527
+ },
528
+ columns: [
529
+ {
530
+ name: 'id',
531
+ label: 'ID',
532
+ },
533
+ {
534
+ name: 'department_id',
535
+ label: 'Department ID',
536
+ },
537
+ ],
538
+ });
539
+
540
+ const spy = jest.spyOn(window, 'open');
541
+ await instance.getReport('pdf');
542
+
543
+ expect(spy).toHaveBeenCalledTimes(1);
544
+
545
+ (window as any).open.mockClear();
546
+ spy.mockClear();
547
+ });
548
+ });
549
+
550
+ describe('rowClick', () => {
551
+ it('rowClick method should call events.rowClick', () => {
552
+ const rowClick = jest.fn();
553
+
554
+ const data = [
555
+ { id: '1', name: 'First' },
556
+ { id: '2', name: 'Second' },
557
+ { id: '3', name: 'Third' },
558
+ ];
559
+ const grid = new TekTreeGrid({
560
+ name: 'grid',
561
+ component: 'TekGrid',
562
+ columns: [
563
+ { name: 'id' },
564
+ { name: 'name' },
565
+ ],
566
+ datasource: {
567
+ data,
568
+ },
569
+ events: {
570
+ rowClick,
571
+ },
572
+ });
573
+
574
+ const event = new Event('click');
575
+ const element = document.createElement('div');
576
+ grid.rowClick(data[0], event, element);
577
+
578
+ expect(rowClick).toHaveBeenCalledWith({
579
+ event,
580
+ element,
581
+ row: data[0],
582
+ component: grid,
583
+ });
584
+ expect(grid.datasource.currentRow).toEqual(data[0]);
585
+ });
586
+
587
+ it('should not call events.rowClick if cellClick prevents it', async () => {
588
+ const rowClick = jest.fn();
589
+
590
+ const data = [
591
+ { id: '1', name: 'First' },
592
+ { id: '2', name: 'Second' },
593
+ { id: '3', name: 'Third' },
594
+ ];
595
+ const grid = new TekTreeGrid({
596
+ name: 'grid',
597
+ component: 'TekGrid',
598
+ columns: [
599
+ { name: 'id' },
600
+ { name: 'name' },
601
+ ],
602
+ datasource: {
603
+ data,
604
+ },
605
+ events: {
606
+ rowClick,
607
+ cellClick: () => true,
608
+ },
609
+ });
610
+ await flushPromises();
611
+
612
+ const event = new Event('click');
613
+ const element = document.createElement('div');
614
+ grid.cellClick(data[0], grid.getColumn('id') as any, event, element);
615
+ grid.rowClick(data[0], event, element);
616
+
617
+ expect(rowClick).not.toHaveBeenCalled();
618
+ expect(grid.datasource.currentRow).toEqual({});
619
+ });
620
+ });
621
+
622
+ describe('layoutOptions', () => {
623
+ it('should return layout options instance', async () => {
624
+ const grid = new TekTreeGrid({
625
+ name: 'grid',
626
+ component: 'TekGrid',
627
+ showLayoutOptions: false,
628
+ });
629
+
630
+ expect(grid.layoutOptions).toBeUndefined();
631
+
632
+ grid.showLayoutOptions = true;
633
+ const layoutOptionsComp = { name: 'grid_layout_options' };
634
+ const spyMetadata = jest.spyOn(Metadata, 'getInstance').mockImplementation(() => layoutOptionsComp);
635
+ expect(grid.layoutOptions).toEqual(layoutOptionsComp);
636
+ spyMetadata.mockClear();
637
+ });
638
+ });
639
+
640
+ describe('getAtomInstance', () => {
641
+ const createAtom = (name: string) => new Text({
642
+ name: `${name}_gridTitle`,
643
+ component: 'ZdText',
644
+ text: 'Employees',
645
+ });
646
+
647
+ it('when called, should return the instance of an atom component', () => {
648
+ const instance = new TekTreeGrid({ name: 'Grid', component: 'TekGrid' });
649
+ const atom = createAtom(instance.name);
650
+ const spyMetadata = jest.spyOn(Metadata, 'getInstance').mockImplementation(() => atom);
651
+
652
+ const gridAtom = instance.getAtomInstance<Text>('TITLE');
653
+
654
+ expect(gridAtom).toEqual(atom);
655
+ spyMetadata.mockClear();
656
+ });
657
+ });
658
+
659
+ describe('getFilterInputs', () => {
660
+ const mockMetadata = (instance: TekTreeGrid) => {
661
+ const inputs: IDictionary = {};
662
+ instance.columns.forEach((col) => {
663
+ if (!col.filterable || !col.filterProps) return;
664
+
665
+ col.filterProps.forEach((filter: any, index: number) => {
666
+ const relation = filter.relation || 'AND';
667
+ const operation = filter.operation || 'CONTAINS';
668
+
669
+ const name = `${instance.name}-filter-${relation}-${operation}-${col.name}-${index}`;
670
+ inputs[name] = new TextInput({
671
+ name,
672
+ ...filter.filterProps,
673
+ });
674
+ });
675
+ });
676
+ return jest.spyOn(Metadata, 'getInstance').mockImplementation((name: string) => inputs[name]);
677
+ };
678
+
679
+ it('when called with null parameter, should return all the filter inputs', () => {
680
+ const spyModalService = jest.spyOn(ModalService, 'create').mockImplementation((modal: IModal) => (new Modal(modal)));
681
+ const instance = new TekTreeGrid({
682
+ name: 'grid',
683
+ component: 'TekGrid',
684
+ datasource: {
685
+ type: 'tek-rest',
686
+ uniqueKey: 'id',
687
+ route: '/zeedhi',
688
+ lazyLoad: false,
689
+ },
690
+ columns: [
691
+ { name: 'id' },
692
+ { name: 'name', filterable: true, filterProps: [{ name: 'name_edit', label: 'name' }] },
693
+ {
694
+ name: 'salary',
695
+ filterable: true,
696
+ filterProps: [
697
+ {
698
+ name: 'salary_edit',
699
+ component: 'ZdCurrency',
700
+ operation: 'GREATER_THAN_EQUALS',
701
+ label: 'Salary (min)',
702
+ },
703
+ {
704
+ name: 'salary_edit',
705
+ component: 'ZdCurrency',
706
+ operation: 'LESS_THAN_EQUALS',
707
+ label: 'Salary (max)',
708
+ },
709
+ ],
710
+ },
711
+ ],
712
+ });
713
+
714
+ const spy = mockMetadata(instance);
715
+ instance.onCreated();
716
+
717
+ const filterButton = clickOnFilterButton(instance);
718
+ filterButton.onCreated();
719
+
720
+ const inputs = instance.getFilterInputs();
721
+ expect(inputs[0].name).toBe('grid-filter-AND-CONTAINS-name-0');
722
+ expect(inputs[1].name).toBe('grid-filter-AND-GREATER_THAN_EQUALS-salary-0');
723
+ expect(inputs[2].name).toBe('grid-filter-AND-LESS_THAN_EQUALS-salary-1');
724
+ spy.mockClear();
725
+ spyModalService.mockReset();
726
+ });
727
+
728
+ it('when called, should return the instances of filters with multiple inputs', () => {
729
+ const spyModalService = jest.spyOn(ModalService, 'create').mockImplementation((modal: IModal) => (new Modal(modal)));
730
+ const instance = new TekTreeGrid({
731
+ name: 'grid',
732
+ component: 'TekGrid',
733
+ datasource: {
734
+ type: 'tek-rest',
735
+ uniqueKey: 'id',
736
+ route: '/zeedhi',
737
+ lazyLoad: false,
738
+ },
739
+ columns: [
740
+ { name: 'id' },
741
+ { name: 'name', filterable: true, filterProps: [{ name: 'name_edit', label: 'name' }] },
742
+ {
743
+ name: 'salary',
744
+ filterable: true,
745
+ filterProps: [
746
+ {
747
+ name: 'salary_edit',
748
+ component: 'ZdCurrency',
749
+ operation: 'GREATER_THAN_EQUALS',
750
+ label: 'Salary (min)',
751
+ },
752
+ {
753
+ name: 'salary_edit',
754
+ component: 'ZdCurrency',
755
+ operation: 'LESS_THAN_EQUALS',
756
+ label: 'Salary (max)',
757
+ },
758
+ ],
759
+ },
760
+ ],
761
+ });
762
+
763
+ const spy = mockMetadata(instance);
764
+ instance.onCreated();
765
+
766
+ const filterButton = clickOnFilterButton(instance);
767
+ filterButton.onCreated();
768
+
769
+ const inputs = instance.getFilterInputs('salary');
770
+ expect(inputs[0].name).toBe('grid-filter-AND-GREATER_THAN_EQUALS-salary-0');
771
+ expect(inputs[1].name).toBe('grid-filter-AND-LESS_THAN_EQUALS-salary-1');
772
+ spy.mockClear();
773
+ spyModalService.mockReset();
774
+ });
775
+ });
776
+ });