@sankhyalabs/core 5.20.0-dev.9 → 5.20.0-ms.1

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 (180) hide show
  1. package/.docs/classes/Base64Utils.md +39 -0
  2. package/.docs/classes/Change.md +11 -11
  3. package/.docs/classes/ColumnFilterManager.md +145 -0
  4. package/.docs/classes/DataUnit.md +429 -139
  5. package/.docs/classes/DataUnitInMemoryLoader.md +303 -0
  6. package/.docs/classes/DataUnitLoaderUtils.md +151 -0
  7. package/.docs/classes/DateUtils.md +8 -8
  8. package/.docs/classes/FieldComparator.md +2 -2
  9. package/.docs/classes/IDBRepository.md +22 -0
  10. package/.docs/classes/LockManager.md +249 -0
  11. package/.docs/classes/MaskFormatter.md +66 -14
  12. package/.docs/classes/ObjectUtils.md +141 -0
  13. package/.docs/classes/OverflowWatcher.md +310 -46
  14. package/.docs/classes/SelectionInfo.md +25 -11
  15. package/.docs/classes/ServiceCanceledException.md +193 -0
  16. package/.docs/classes/ServiceUtils.md +67 -0
  17. package/.docs/classes/SilentException.md +193 -0
  18. package/.docs/classes/StringUtils.md +24 -0
  19. package/.docs/classes/UserAgentUtils.md +15 -1
  20. package/.docs/enumerations/Action.md +41 -21
  21. package/.docs/enumerations/ChangeOperation.md +4 -4
  22. package/.docs/enumerations/LockManagerOperation.md +33 -0
  23. package/.docs/enumerations/RECORD_DATE_FORMAT.md +27 -0
  24. package/.docs/enumerations/SelectionMode.md +2 -2
  25. package/.docs/enumerations/StorageType.md +37 -0
  26. package/.docs/globals.md +19 -0
  27. package/.docs/interfaces/DUActionInterceptor.md +1 -1
  28. package/.docs/interfaces/DataUnitInMemoryLoaderConfig.md +37 -0
  29. package/.docs/interfaces/IRepository.md +18 -0
  30. package/.docs/interfaces/LoadDataRequest.md +1 -1
  31. package/.docs/interfaces/OverFlowWatcherParams.md +67 -0
  32. package/.docs/interfaces/PageRequest.md +3 -3
  33. package/.docs/interfaces/PaginationInfo.md +25 -0
  34. package/.docs/interfaces/PaginationInfoBuilderParams.md +37 -0
  35. package/.docs/interfaces/QuickFilter.md +3 -3
  36. package/.docs/interfaces/Record.md +4 -4
  37. package/.docs/interfaces/SavedRecord.md +5 -5
  38. package/.docs/interfaces/WaitingChange.md +3 -3
  39. package/.docs/namespaces/MaskFormatter/type-aliases/MaskCharacter.md +1 -1
  40. package/.docs/namespaces/MaskFormatter/variables/MaskCharacter.md +1 -1
  41. package/.docs/type-aliases/DataUnitEventOptions.md +17 -0
  42. package/.docs/variables/OVERFLOWED_CLASS_NAME.md +13 -0
  43. package/.releaserc +1 -0
  44. package/bun.lockb +0 -0
  45. package/dist/dataunit/DataUnit.d.ts +92 -13
  46. package/dist/dataunit/DataUnit.js +219 -71
  47. package/dist/dataunit/DataUnit.js.map +1 -1
  48. package/dist/dataunit/DataUnitHelper.js +6 -5
  49. package/dist/dataunit/DataUnitHelper.js.map +1 -1
  50. package/dist/dataunit/formatting/PrettyFormatter.js +14 -6
  51. package/dist/dataunit/formatting/PrettyFormatter.js.map +1 -1
  52. package/dist/dataunit/loader/DataUnitInMemoryLoaderConfig.d.ts +9 -0
  53. package/dist/dataunit/loader/DataUnitInMemoryLoaderConfig.js +6 -0
  54. package/dist/dataunit/loader/DataUnitInMemoryLoaderConfig.js.map +1 -0
  55. package/dist/dataunit/loader/dataUnitInMemoryLoader.d.ts +25 -0
  56. package/dist/dataunit/loader/dataUnitInMemoryLoader.js +131 -0
  57. package/dist/dataunit/loader/dataUnitInMemoryLoader.js.map +1 -0
  58. package/dist/dataunit/loader/utils/dataUnitLoaderUtils.d.ts +20 -0
  59. package/dist/dataunit/loader/utils/dataUnitLoaderUtils.js +62 -0
  60. package/dist/dataunit/loader/utils/dataUnitLoaderUtils.js.map +1 -0
  61. package/dist/dataunit/loading/LoadDataRequest.d.ts +1 -1
  62. package/dist/dataunit/loading/PaginationInfo.d.ts +8 -0
  63. package/dist/dataunit/metadata/DataType.js +3 -0
  64. package/dist/dataunit/metadata/DataType.js.map +1 -1
  65. package/dist/dataunit/sorting/FieldComparator.d.ts +2 -2
  66. package/dist/dataunit/sorting/FieldComparator.js +4 -9
  67. package/dist/dataunit/sorting/FieldComparator.js.map +1 -1
  68. package/dist/dataunit/state/action/DataUnitAction.d.ts +2 -0
  69. package/dist/dataunit/state/action/DataUnitAction.js +2 -0
  70. package/dist/dataunit/state/action/DataUnitAction.js.map +1 -1
  71. package/dist/dataunit/state/slice/LoadingControlSlice.js +16 -0
  72. package/dist/dataunit/state/slice/LoadingControlSlice.js.map +1 -1
  73. package/dist/dataunit/state/slice/RecordsSlice.js +1 -1
  74. package/dist/dataunit/state/slice/RecordsSlice.js.map +1 -1
  75. package/dist/dataunit/state/slice/SelectionSlice.js +4 -4
  76. package/dist/dataunit/state/slice/SelectionSlice.js.map +1 -1
  77. package/dist/exceptions/ServiceCanceledException.d.ts +14 -0
  78. package/dist/exceptions/ServiceCanceledException.js +13 -0
  79. package/dist/exceptions/ServiceCanceledException.js.map +1 -0
  80. package/dist/exceptions/SilentException.d.ts +14 -0
  81. package/dist/exceptions/SilentException.js +13 -0
  82. package/dist/exceptions/SilentException.js.map +1 -0
  83. package/dist/index.d.ts +13 -3
  84. package/dist/index.js +12 -2
  85. package/dist/index.js.map +1 -1
  86. package/dist/repository/IRepository.d.ts +6 -0
  87. package/dist/repository/indexeddb/IDBRepository.d.ts +1 -0
  88. package/dist/repository/indexeddb/IDBRepository.js +3 -0
  89. package/dist/repository/indexeddb/IDBRepository.js.map +1 -1
  90. package/dist/utils/Base64Utils.d.ts +7 -0
  91. package/dist/utils/Base64Utils.js +13 -0
  92. package/dist/utils/Base64Utils.js.map +1 -0
  93. package/dist/utils/CacheManager/index.d.ts +52 -0
  94. package/dist/utils/CacheManager/index.js +101 -0
  95. package/dist/utils/CacheManager/index.js.map +1 -0
  96. package/dist/utils/CacheManager/interfaces/index.d.ts +5 -0
  97. package/dist/utils/CacheManager/interfaces/index.js +7 -0
  98. package/dist/utils/CacheManager/interfaces/index.js.map +1 -0
  99. package/dist/utils/ColumnFilterManager.d.ts +19 -0
  100. package/dist/utils/ColumnFilterManager.js +73 -0
  101. package/dist/utils/ColumnFilterManager.js.map +1 -0
  102. package/dist/utils/DateUtils.js +3 -0
  103. package/dist/utils/DateUtils.js.map +1 -1
  104. package/dist/utils/ElementUtils.d.ts +2 -0
  105. package/dist/utils/ElementUtils.js +9 -0
  106. package/dist/utils/ElementUtils.js.map +1 -0
  107. package/dist/utils/LockManager.d.ts +58 -0
  108. package/dist/utils/LockManager.js +191 -0
  109. package/dist/utils/LockManager.js.map +1 -0
  110. package/dist/utils/MaskFormatter.d.ts +16 -1
  111. package/dist/utils/MaskFormatter.js +82 -2
  112. package/dist/utils/MaskFormatter.js.map +1 -1
  113. package/dist/utils/ObjectUtils.d.ts +38 -0
  114. package/dist/utils/ObjectUtils.js +51 -0
  115. package/dist/utils/ObjectUtils.js.map +1 -1
  116. package/dist/utils/OnboardingUtils.js +1 -1
  117. package/dist/utils/OnboardingUtils.js.map +1 -1
  118. package/dist/utils/OverflowWatcher/index.d.ts +35 -7
  119. package/dist/utils/OverflowWatcher/index.js +140 -59
  120. package/dist/utils/OverflowWatcher/index.js.map +1 -1
  121. package/dist/utils/ServiceUtils.d.ts +24 -0
  122. package/dist/utils/ServiceUtils.js +40 -0
  123. package/dist/utils/ServiceUtils.js.map +1 -0
  124. package/dist/utils/SortingUtils.d.ts +9 -0
  125. package/dist/utils/SortingUtils.js +24 -0
  126. package/dist/utils/SortingUtils.js.map +1 -0
  127. package/dist/utils/StringUtils.d.ts +6 -0
  128. package/dist/utils/StringUtils.js +11 -0
  129. package/dist/utils/StringUtils.js.map +1 -1
  130. package/dist/utils/UserAgentUtils/index.d.ts +1 -0
  131. package/dist/utils/UserAgentUtils/index.js +5 -0
  132. package/dist/utils/UserAgentUtils/index.js.map +1 -1
  133. package/jest.config.ts +2 -0
  134. package/package.json +2 -1
  135. package/reports/test-report.xml +215 -0
  136. package/setupTests.js +7 -0
  137. package/sonar-project.properties +6 -3
  138. package/src/dataunit/DataUnit.ts +268 -86
  139. package/src/dataunit/DataUnitHelper.ts +6 -5
  140. package/src/dataunit/formatting/PrettyFormatter.ts +15 -6
  141. package/src/dataunit/loader/DataUnitInMemoryLoaderConfig.ts +10 -0
  142. package/src/dataunit/loader/dataUnitInMemoryLoader.ts +176 -0
  143. package/src/dataunit/loader/utils/dataUnitLoaderUtils.ts +86 -0
  144. package/src/dataunit/loading/LoadDataRequest.ts +1 -1
  145. package/src/dataunit/loading/PaginationInfo.ts +10 -0
  146. package/src/dataunit/metadata/DataType.ts +3 -0
  147. package/src/dataunit/sorting/FieldComparator.ts +18 -32
  148. package/src/dataunit/state/action/DataUnitAction.ts +2 -0
  149. package/src/dataunit/state/slice/LoadingControlSlice.ts +42 -0
  150. package/src/dataunit/state/slice/RecordsSlice.ts +1 -1
  151. package/src/dataunit/state/slice/SelectionSlice.ts +4 -4
  152. package/src/dataunit/state/slice/test/RecordsSlice.spec.ts +45 -0
  153. package/src/dataunit/test/DataUnit.spec.ts +44 -0
  154. package/src/exceptions/ServiceCanceledException.ts +25 -0
  155. package/src/exceptions/SilentException.ts +25 -0
  156. package/src/index.ts +30 -3
  157. package/src/repository/IRepository.ts +7 -0
  158. package/src/repository/indexeddb/IDBRepository.ts +4 -0
  159. package/src/utils/Base64Utils.ts +13 -0
  160. package/src/utils/CacheManager/index.ts +103 -0
  161. package/src/utils/CacheManager/interfaces/index.ts +5 -0
  162. package/src/utils/ColumnFilterManager.ts +104 -0
  163. package/src/utils/DateUtils.ts +3 -0
  164. package/src/utils/ElementUtils.ts +10 -0
  165. package/src/utils/LockManager.ts +213 -0
  166. package/src/utils/MaskFormatter.ts +93 -2
  167. package/src/utils/ObjectUtils.ts +56 -0
  168. package/src/utils/OnboardingUtils.ts +1 -1
  169. package/src/utils/OverflowWatcher/index.ts +170 -78
  170. package/src/utils/ServiceUtils.ts +36 -0
  171. package/src/utils/SortingUtils.ts +30 -0
  172. package/src/utils/StringUtils.ts +13 -0
  173. package/src/utils/UserAgentUtils/index.ts +6 -1
  174. package/src/utils/test/objectUtils.spec.ts +109 -0
  175. package/test/dataunit/formatting/PrettyFormatter.spec.ts +177 -0
  176. package/test/dataunit/loader/dataUnitInMemoryLoader.spec.ts +221 -0
  177. package/test/dataunit/loader/utils/dataUnitLoaderUtils.spec.ts +158 -0
  178. package/test/util/ColumnFilterManager.spec.ts +133 -0
  179. package/test/util/ElementUtils.spec.ts +34 -0
  180. package/test/util/OverflowWatcher.spec.ts +152 -118
@@ -0,0 +1,133 @@
1
+ import { ColumnFilterManager, IColumnFilter } from '../../src/utils/ColumnFilterManager.js';
2
+ import { FieldDescriptor, Filter, FilterParam } from '../../src/dataunit/metadata/UnitMetadata.js';
3
+ import DataUnit, { Record } from '../../src/dataunit/DataUnit';
4
+
5
+
6
+ describe('ColumnFilterManager', () => {
7
+ beforeEach(() => {
8
+ jest.clearAllMocks();
9
+ });
10
+
11
+
12
+ describe('getColumnFilters', () => {
13
+ it('should return an empty map if filters are undefined or empty', () => {
14
+ expect(ColumnFilterManager.getColumnFilters(undefined as any, 'field')).toEqual(new Map());
15
+ expect(ColumnFilterManager.getColumnFilters([], 'field')).toEqual(new Map());
16
+ });
17
+
18
+ it('should return a map of filters matching the pattern and not the provided fieldName', () => {
19
+ const filters: Filter[] = [
20
+ { name: 'FILTRO_COLUNA_field1', expression: '' },
21
+ { name: 'FILTRO_COLUNA_field2', expression: '' },
22
+ ];
23
+
24
+ const result = ColumnFilterManager.getColumnFilters(filters, 'field1');
25
+
26
+ expect(result.size).toBe(1);
27
+ expect(result.has('FILTRO_COLUNA_field2')).toBe(true);
28
+ expect(result.get('FILTRO_COLUNA_field2')?.columnName).toBe('field2');
29
+ });
30
+ });
31
+
32
+
33
+ describe('getFilterFunction', () => {
34
+ const mockDataUnit = {
35
+ getField: jest.fn(),
36
+ valueFromString: jest.fn()
37
+ } as unknown as DataUnit;
38
+
39
+ mockDataUnit.getField = jest.fn().mockReturnValue({} as FieldDescriptor);
40
+ mockDataUnit.valueFromString = jest.fn().mockReturnValue('test');
41
+
42
+ beforeEach(() => {
43
+ jest.clearAllMocks();
44
+ })
45
+
46
+ it('should return undefined if no filters are provided', () => {
47
+ expect(ColumnFilterManager.getFilterFunction(mockDataUnit, undefined)).toBeUndefined();
48
+ expect(ColumnFilterManager.getFilterFunction(mockDataUnit, [])).toBeUndefined();
49
+ });
50
+
51
+ it('should return a function that evaluates records based on filters', () => {
52
+ const filters: IColumnFilter[] = [
53
+ {
54
+ columnName: 'field1',
55
+ name: 'FILTRO_COLUNA_field1',
56
+ expression: '',
57
+ params: [{value: "mockedPAram"} as FilterParam]
58
+ },
59
+ ];
60
+
61
+
62
+ const filterFunction = ColumnFilterManager.getFilterFunction(mockDataUnit, filters);
63
+ expect(filterFunction).toBeDefined();
64
+
65
+ const record: Record = { field1: 'test' } as unknown as Record;
66
+ expect(filterFunction!(record)).toBe(true);
67
+ });
68
+
69
+ it('should return a function that evaluates records and return false', () => {
70
+ const filters: IColumnFilter[] = [
71
+ {
72
+ columnName: 'field1',
73
+ name: 'FILTRO_COLUNA_field1',
74
+ expression: '',
75
+ },
76
+ ];
77
+
78
+ const filterFunction = ColumnFilterManager.getFilterFunction(mockDataUnit, filters);
79
+ expect(filterFunction).toBeDefined();
80
+
81
+ const record: Record = { field1: 'test' } as unknown as Record;
82
+ expect(filterFunction!(record)).toBe(false);
83
+ });
84
+ });
85
+
86
+
87
+ describe("compileDistinct", () => {
88
+ const mockDataUnit = {
89
+ getField: jest.fn(),
90
+ valueFromString: jest.fn()
91
+ } as unknown as DataUnit;
92
+
93
+ mockDataUnit.getFormattedValue = jest.fn().mockImplementation((_, value) => value);
94
+ mockDataUnit.getFormattedValue = jest.fn().mockImplementation((_, value) => value);
95
+
96
+ const filters: Filter[] = [{ name: "FILTRO_COLUNA_fieldName", expression: '' }];
97
+ mockDataUnit.getLastLoadRequest = jest.fn().mockReturnValue({ filters });
98
+
99
+
100
+ beforeEach(() => {
101
+ jest.clearAllMocks();
102
+ })
103
+
104
+ it("should return an array of distinct field values formatted correctly", () => {
105
+ mockDataUnit.records = [
106
+ { fieldName: "value1" },
107
+ { fieldName: "value2" },
108
+ { fieldName: "value1" },
109
+ ] as unknown as Record[];
110
+
111
+ const distinct = ColumnFilterManager.compileDistinct("fieldName", mockDataUnit);
112
+
113
+ expect(distinct).toEqual([
114
+ { label: "value1", value: "value1", check: true },
115
+ { label: "value2", value: "value2", check: true },
116
+ ]);
117
+ });
118
+
119
+ it("should filter records if a load request is present", () => {
120
+ mockDataUnit.records = [
121
+ { fieldName: "value1" },
122
+ { fieldName: "value2" },
123
+ ] as unknown as Record[];
124
+
125
+ const distinct = ColumnFilterManager.compileDistinct("fieldName", mockDataUnit);
126
+
127
+ expect(distinct).toEqual([
128
+ { label: "value1", value: "value1", check: true },
129
+ { label: "value2", value: "value2", check: true },
130
+ ]);
131
+ });
132
+ });
133
+ });
@@ -0,0 +1,34 @@
1
+ import { calcMarginSize } from '../../src/utils/ElementUtils';
2
+ import { OverflowDirection } from '../../src';
3
+
4
+ describe('calcMarginSize', () => {
5
+ it('should calculate correctly the size of horizontal margin', () => {
6
+ const element = document.createElement('div');
7
+ element.style.marginLeft = '10px';
8
+ element.style.marginRight = '15px';
9
+ document.body.appendChild(element);
10
+
11
+ const size = calcMarginSize(element, OverflowDirection.HORIZONTAL);
12
+ expect(size).toBe(25);
13
+ });
14
+
15
+ it('should calculate correctly the size of vertical margin', () => {
16
+ const element = document.createElement('div');
17
+ element.style.marginTop = '5px';
18
+ element.style.marginBottom = '20px';
19
+ document.body.appendChild(element);
20
+
21
+ const size = calcMarginSize(element, OverflowDirection.VERTICAL);
22
+ expect(size).toBe(25);
23
+ });
24
+
25
+ it('should threat values defined as zero', () => {
26
+ const element = document.createElement('div');
27
+ document.body.appendChild(element);
28
+
29
+ const horizontalSize = calcMarginSize(element, OverflowDirection.HORIZONTAL);
30
+ const verticalSize = calcMarginSize(element, OverflowDirection.VERTICAL);
31
+ expect(horizontalSize).toBe(0);
32
+ expect(verticalSize).toBe(0);
33
+ });
34
+ });
@@ -1,118 +1,152 @@
1
- import OverFlowWatcher, { OnOverflowCallBack, OverflowDirection } from '../../src/utils/OverflowWatcher';
2
-
3
- describe('OverflowWatcher', function () {
4
-
5
- let element: HTMLElement;
6
- let callbackHorizontalDirection: OnOverflowCallBack;
7
- let watcherHorizontalDirection: OverFlowWatcher;
8
- let callbackVerticalDirection: OnOverflowCallBack;
9
- let watcherVerticallDirection: OverFlowWatcher;
10
- let child1:HTMLDivElement;
11
- let child2:HTMLDivElement;
12
-
13
- beforeEach(() => {
14
-
15
- global.ResizeObserver = jest.fn().mockImplementation(() => ({
16
- observe: jest.fn(),
17
- unobserve: jest.fn(),
18
- disconnect: jest.fn(),
19
- }))
20
-
21
- element = document.createElement('div');
22
-
23
- //Horizontal
24
- callbackHorizontalDirection = jest.fn();
25
- watcherHorizontalDirection = new OverFlowWatcher(element, callbackHorizontalDirection);
26
-
27
-
28
- //Vertical
29
- callbackVerticalDirection = jest.fn();
30
- watcherVerticallDirection = new OverFlowWatcher(element, callbackVerticalDirection, OverflowDirection.VERTICAL);
31
-
32
- child1 = document.createElement('div');
33
- child2 = document.createElement('div');
34
-
35
- child1.style.width = '50px';
36
- child2.style.width = '100px';
37
- child1.style.height = '50px';
38
- child2.style.height = '100px';
39
-
40
- //TODO: No futuro utilizar JSDOM para não precisar fazer mock dessas coisas
41
- child1['getBoundingClientRect'] = () => {
42
- return {
43
- width: 50,
44
- height: 50,
45
- } as DOMRect;
46
- }
47
-
48
- child2['getBoundingClientRect'] = () => {
49
- return {
50
- width: 100,
51
- height: 100,
52
- } as DOMRect;
53
- }
54
-
55
- element.appendChild(child1);
56
- element.appendChild(child2);
57
- });
58
-
59
- afterEach(() => {
60
- watcherHorizontalDirection.destroy();
61
- watcherVerticallDirection.destroy();
62
- });
63
-
64
- test('constructor initializes properties correctly', () => {
65
- expect(watcherHorizontalDirection['_onResize']).toBe(callbackHorizontalDirection);
66
- expect(watcherHorizontalDirection['_scrollDirection']).toBe(OverflowDirection.HORIZONTAL);
67
- expect(watcherHorizontalDirection['_deltaSize']).toBe(10);
68
- });
69
-
70
- test('handleResize horizontal calls callback with hidden items', () => {
71
- const entries: any[] = [{
72
- contentRect: {
73
- width: 120
74
- },
75
- target: element
76
- }];
77
-
78
- watcherHorizontalDirection['handleResize'](entries);
79
-
80
- expect(callbackHorizontalDirection).toHaveBeenCalledWith([child2]);
81
-
82
- entries[0].contentRect.width = 100;
83
- watcherHorizontalDirection['handleResize'](entries);
84
-
85
- expect(callbackHorizontalDirection).toHaveBeenCalledWith([child2]);
86
- });
87
-
88
- test('handleResize vertical calls callback with hidden items', () => {
89
- const entries: any[] = [{
90
- contentRect: {
91
- height: 120
92
- },
93
- target: element
94
- }];
95
-
96
- watcherVerticallDirection['handleResize'](entries);
97
-
98
- expect(callbackVerticalDirection).toHaveBeenCalledWith([child2]);
99
- });
100
-
101
- test('isChangedSize returns true if no previous size', () => {
102
- const newContentRect: DOMRectReadOnly = { width: 100 } as DOMRectReadOnly;
103
- watcherHorizontalDirection['_lastContentRect'] = undefined;
104
-
105
- const result = watcherHorizontalDirection['isChangedSize'](newContentRect);
106
-
107
- expect(result).toBe(true);
108
- });
109
-
110
- test('prevent resize without entries', () => {
111
- const entries: any[] = [];
112
-
113
- watcherHorizontalDirection['handleResize'](entries);
114
-
115
- expect(callbackHorizontalDirection).toHaveBeenCalledTimes(0);
116
- });
117
-
118
- });
1
+ import OverflowWatcher, { OverFlowWatcherParams, OverflowDirection, OVERFLOWED_CLASS_NAME } from '../../src/utils/OverflowWatcher';
2
+
3
+ describe('OverflowWatcher', () => {
4
+ let mockElement: HTMLElement;
5
+ let mockCallback: jest.Mock;
6
+ let watcherInstance: OverflowWatcher;
7
+
8
+ beforeEach(() => {
9
+ mockElement = document.createElement('div');
10
+ Object.defineProperty(mockElement, 'clientWidth', { value: 90, configurable: true });
11
+ document.body.appendChild(mockElement);
12
+ mockCallback = jest.fn();
13
+
14
+ const params: OverFlowWatcherParams = {
15
+ element: mockElement,
16
+ callback: mockCallback,
17
+ overFlowDirection: OverflowDirection.HORIZONTAL,
18
+ debounce: 1,
19
+ deltaSize: 1,
20
+ notOverFlow: ['testId'],
21
+ };
22
+
23
+ watcherInstance = new OverflowWatcher(params);
24
+ mockElement.getBoundingClientRect = jest.fn().mockReturnValue(getMockedRectClientValue(200));
25
+ setPrivateField(watcherInstance, '_lastContainerSize', 100);
26
+ setPrivateField(watcherInstance, '_lastContainerInstance', mockElement);
27
+ });
28
+
29
+ afterEach(() => {
30
+ watcherInstance.destroy();
31
+ });
32
+
33
+ it('should initialize with provided parameters', () => {
34
+ expect(watcherInstance).toBeDefined();
35
+ });
36
+
37
+ it('should disconect ResizeObserver when destroy is called', () => {
38
+ const disconnectSpy = jest.spyOn(ResizeObserver.prototype, 'disconnect');
39
+ watcherInstance.destroy();
40
+ expect(disconnectSpy).toHaveBeenCalled();
41
+ });
42
+
43
+ it('Should call callback on forceUpdate', () => {
44
+ appendMockedChildren(mockElement);
45
+ watcherInstance.forceUpdate();
46
+ expect(mockCallback).toHaveBeenCalled();
47
+ });
48
+
49
+ it('Should call callback on forceUpdate with childSpan', () => {
50
+ appendMockedChildren(mockElement);
51
+ watcherInstance.forceUpdate();
52
+
53
+ const childSpan = mockElement.children[1];
54
+ expect(mockCallback).toHaveBeenCalledWith(expect.arrayContaining([childSpan]));
55
+ });
56
+
57
+ it('Should call callback on forceUpdate with childSpan when notOverFlow is empty', () => {
58
+ appendMockedChildren(mockElement);
59
+
60
+ const params: OverFlowWatcherParams = {
61
+ element: mockElement,
62
+ callback: mockCallback,
63
+ overFlowDirection: OverflowDirection.HORIZONTAL,
64
+ debounce: 1,
65
+ deltaSize: 1,
66
+ };
67
+
68
+ const withNoOverFlow = new OverflowWatcher(params);
69
+ setPrivateField(withNoOverFlow, '_lastContainerSize', 100);
70
+ setPrivateField(withNoOverFlow, '_lastContainerInstance', mockElement);
71
+
72
+ withNoOverFlow.forceUpdate();
73
+
74
+ const childSpan = mockElement.children[1];
75
+ expect(mockCallback).toHaveBeenCalledWith(expect.arrayContaining([childSpan]));
76
+ });
77
+
78
+ it('Should call callback on forceUpdate with childSpan considering overflowed elements', () => {
79
+ appendMockedChildren(mockElement);
80
+ const childButton = mockElement.children[0];
81
+ const childSpan = mockElement.children[1];
82
+ childSpan.classList.add(OVERFLOWED_CLASS_NAME);
83
+
84
+ const hiddemItemsMock: Map<Element, {size: number, margin: number}> = new Map();
85
+ hiddemItemsMock.set(childSpan, {size: 50, margin: 0});
86
+ hiddemItemsMock.set(childButton, {size: 0, margin: 50});
87
+ setPrivateField(watcherInstance, '_hiddenItemsProps', hiddemItemsMock);
88
+
89
+ watcherInstance.forceUpdate();
90
+
91
+ expect(mockCallback).toHaveBeenCalledWith(expect.arrayContaining([childSpan]));
92
+ });
93
+
94
+ it('Should call callback on forceUpdate with empty list', () => {
95
+ appendMockedChildren(mockElement);
96
+ setPrivateField(watcherInstance, '_lastContainerSize', 200);
97
+ watcherInstance.forceUpdate();
98
+ const childButton = mockElement.children[0];
99
+ const childSpan = mockElement.children[1];
100
+
101
+ expect(mockCallback).not.toHaveBeenCalledWith(expect.arrayContaining([childButton, childSpan]));
102
+ });
103
+
104
+ it('should ignore elements that can not overflow', () => {
105
+ appendMockedChildren(mockElement);
106
+
107
+ const notOverflowElement = document.createElement('div');
108
+ notOverflowElement.setAttribute('data-element-id', 'testId') ;
109
+ notOverflowElement.getBoundingClientRect = jest.fn().mockReturnValue(getMockedRectClientValue(50));
110
+
111
+ const notOverflowElement2 = document.createElement('div');
112
+ notOverflowElement2.setAttribute('data-element-id', 'testId2') ;
113
+ notOverflowElement2.getBoundingClientRect = jest.fn().mockReturnValue(getMockedRectClientValue(50));
114
+
115
+ mockElement.appendChild(notOverflowElement);
116
+ mockElement.appendChild(notOverflowElement2);
117
+
118
+ watcherInstance.addNotOverFlowElement('testId');
119
+ watcherInstance.addNotOverFlowElement('testId2');
120
+
121
+ watcherInstance.forceUpdate();
122
+
123
+ expect(mockCallback).not.toHaveBeenCalledWith(expect.arrayContaining([notOverflowElement]));
124
+ });
125
+
126
+ it('Should not call callback on forceUpdate', () => {
127
+ watcherInstance.forceUpdate();
128
+ expect(mockCallback).not.toHaveBeenCalled();
129
+ });
130
+
131
+ });
132
+
133
+ function appendMockedChildren(mockElement: HTMLElement) {
134
+ const chilldButton = document.createElement('button');
135
+ const childSpan = document.createElement('span');
136
+
137
+ chilldButton.getBoundingClientRect = jest.fn().mockReturnValue(getMockedRectClientValue(50));
138
+ childSpan.getBoundingClientRect = jest.fn().mockReturnValue(getMockedRectClientValue(50));
139
+
140
+ mockElement.appendChild(chilldButton);
141
+ mockElement.appendChild(childSpan);
142
+ }
143
+
144
+ function getMockedRectClientValue(size: number) {
145
+ return {
146
+ x: 0, y: 0, width: size, height: 10, top: 0, right: 0, bottom: 0, left: 0, toJSON: () => {}
147
+ };
148
+ }
149
+
150
+ function setPrivateField<T>(instance: T, fieldName: string, value: any): void {
151
+ (instance as any)[fieldName] = value;
152
+ }