@sankhyalabs/core 6.1.0-dev.2 → 6.1.0-dev.3
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.
- package/.docs/classes/Change.md +11 -11
- package/.docs/classes/ColumnFilterManager.md +6 -6
- package/.docs/classes/DataUnit.md +157 -157
- package/.docs/classes/DataUnitLoaderUtils.md +6 -6
- package/.docs/classes/SelectionInfo.md +16 -16
- package/.docs/enumerations/ChangeOperation.md +4 -4
- package/.docs/enumerations/SelectionMode.md +2 -2
- package/.docs/functions/defaultDataLoader.md +1 -1
- package/.docs/interfaces/DUActionInterceptor.md +1 -1
- package/.docs/interfaces/PageRequest.md +3 -3
- package/.docs/interfaces/PaginationInfoBuilderParams.md +3 -3
- package/.docs/interfaces/QuickFilter.md +3 -3
- package/.docs/interfaces/Record.md +4 -4
- package/.docs/interfaces/SavedRecord.md +5 -5
- package/.docs/interfaces/WaitingChange.md +3 -3
- package/.docs/type-aliases/DataUnitEventOptions.md +1 -1
- package/dist/dataunit/Changes.d.ts +52 -0
- package/dist/dataunit/Changes.js +64 -0
- package/dist/dataunit/Changes.js.map +1 -0
- package/dist/dataunit/DataUnit.d.ts +9 -129
- package/dist/dataunit/DataUnit.js +87 -177
- package/dist/dataunit/DataUnit.js.map +1 -1
- package/dist/dataunit/DataUnitHelper.d.ts +2 -1
- package/dist/dataunit/DataUnitHelper.js.map +1 -1
- package/dist/dataunit/SelectionInfo.d.ts +16 -0
- package/dist/dataunit/SelectionInfo.js +39 -0
- package/dist/dataunit/SelectionInfo.js.map +1 -0
- package/dist/dataunit/interfaces/dataUnit.d.ts +61 -0
- package/dist/dataunit/interfaces/dataUnit.js +13 -0
- package/dist/dataunit/interfaces/dataUnit.js.map +1 -0
- package/dist/dataunit/loader/utils/dataUnitLoaderUtils.d.ts +2 -1
- package/dist/dataunit/loader/utils/dataUnitLoaderUtils.js.map +1 -1
- package/dist/dataunit/loading/LoadDataRequest.d.ts +1 -1
- package/dist/dataunit/loading/LoadDataResponse.d.ts +1 -1
- package/dist/dataunit/sorting/FieldComparator.d.ts +1 -1
- package/dist/dataunit/state/slice/AddedRecordsSlice.d.ts +1 -1
- package/dist/dataunit/state/slice/ChangesSlice.d.ts +2 -1
- package/dist/dataunit/state/slice/ChangesSlice.js +2 -1
- package/dist/dataunit/state/slice/ChangesSlice.js.map +1 -1
- package/dist/dataunit/state/slice/LoadingControlSlice.js.map +1 -1
- package/dist/dataunit/state/slice/RecordsSlice.d.ts +1 -1
- package/dist/dataunit/state/slice/RecordsSlice.js +1 -1
- package/dist/dataunit/state/slice/RecordsSlice.js.map +1 -1
- package/dist/dataunit/state/slice/SelectionSlice.d.ts +2 -1
- package/dist/dataunit/state/slice/SelectionSlice.js +2 -1
- package/dist/dataunit/state/slice/SelectionSlice.js.map +1 -1
- package/dist/dataunit/state/slice/SnapshotSlice.d.ts +1 -1
- package/dist/dataunit/state/slice/WaitingChangesSlice.d.ts +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/ColumnFilterManager.d.ts +2 -1
- package/dist/utils/ColumnFilterManager.js.map +1 -1
- package/dist/utils/SortingUtils.d.ts +1 -1
- package/package.json +2 -1
- package/reports/test-report.xml +648 -447
- package/src/dataunit/Changes.ts +77 -0
- package/src/dataunit/DataUnit.ts +242 -397
- package/src/dataunit/DataUnitHelper.ts +2 -1
- package/src/dataunit/SelectionInfo.ts +55 -0
- package/src/dataunit/interfaces/dataUnit.ts +71 -0
- package/src/dataunit/loader/utils/dataUnitLoaderUtils.ts +2 -1
- package/src/dataunit/loading/LoadDataRequest.ts +1 -1
- package/src/dataunit/loading/LoadDataResponse.ts +1 -1
- package/src/dataunit/sorting/FieldComparator.ts +1 -1
- package/src/dataunit/state/slice/AddedRecordsSlice.ts +1 -1
- package/src/dataunit/state/slice/ChangesSlice.ts +2 -1
- package/src/dataunit/state/slice/LoadingControlSlice.ts +1 -2
- package/src/dataunit/state/slice/RecordsSlice.ts +3 -2
- package/src/dataunit/state/slice/SelectionSlice.ts +2 -1
- package/src/dataunit/state/slice/SnapshotSlice.ts +1 -1
- package/src/dataunit/state/slice/WaitingChangesSlice.ts +1 -1
- package/src/dataunit/state/slice/test/RecordsSlice.spec.ts +1 -1
- package/src/index.ts +4 -1
- package/src/utils/ColumnFilterManager.ts +2 -1
- package/src/utils/SortingUtils.ts +1 -1
- package/test/dataunit/AccessParentsDataUnit.spec.ts +69 -0
- package/test/dataunit/Actions.spec.ts +74 -0
- package/test/dataunit/Change.spec.ts +66 -0
- package/test/dataunit/FieldManager.spec.ts +286 -0
- package/test/dataunit/FilterSortsLockersAndObservers.spec.ts +339 -0
- package/test/dataunit/InfoManager.spec.ts +254 -0
- package/test/dataunit/LoadDataAndMetadata.spec.ts +269 -0
- package/test/dataunit/RecodsSelection.spec.ts +229 -0
- package/test/dataunit/RecordsManager.spec.ts +323 -0
- package/test/dataunit/SavingData.spec.ts +206 -0
- package/test/dataunit/SelectionInfo.spec.ts +143 -0
- package/test/dataunit/loader/dataUnitInMemoryLoader.spec.ts +2 -1
- package/test/dataunit/loader/utils/createDataUnitMock.ts +34 -0
- package/test/dataunit/loader/utils/dataUnitLoaderUtils.spec.ts +1 -1
- package/test/dataunit/resources/metadata.ts +39 -0
- package/test/dataunit/resources/records.ts +29 -0
- package/test/util/ColumnFilterManager.spec.ts +2 -1
- package/tsconfig.json +1 -0
- package/src/dataunit/test/DataUnit.spec.ts +0 -44
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import DataUnit from "../../src/dataunit/DataUnit";
|
|
2
|
+
import { DUActionInterceptor } from "../../src/dataunit/interfaces/dataUnit";
|
|
3
|
+
import { DataType } from "../../src/dataunit/metadata/DataType";
|
|
4
|
+
import { FieldDescriptor } from "../../src/dataunit/metadata/UnitMetadata";
|
|
5
|
+
import { Action } from "../../src/dataunit/state/action/DataUnitAction";
|
|
6
|
+
import { createDataUnitMock } from "./loader/utils/createDataUnitMock";
|
|
7
|
+
|
|
8
|
+
describe('Field manager', () => {
|
|
9
|
+
let dataUnit: DataUnit;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
jest.clearAllMocks();
|
|
13
|
+
window.requestAnimationFrame = (functionCallback: Function) => functionCallback();
|
|
14
|
+
({ dataUnit } = createDataUnitMock());
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe('setFieldValue', () => {
|
|
18
|
+
beforeEach(async () => {
|
|
19
|
+
await dataUnit.loadData();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should not create a new record when suppressCreateNewRecord is true', async () => {
|
|
23
|
+
await dataUnit.setFieldValue('column_name_1', 'new_value_1', undefined, { suppressCreateNewRecord: true });
|
|
24
|
+
const hasNewRecord = dataUnit.hasNewRecord();
|
|
25
|
+
expect(hasNewRecord).toBeFalsy();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should resolve promise with false when value is the same', async () => {
|
|
29
|
+
dataUnit.selectFirst();
|
|
30
|
+
const response = await dataUnit.setFieldValue('column_name_1', 'column_value_1');
|
|
31
|
+
expect(response).toBeFalsy();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should handle with promise values', async () => {
|
|
35
|
+
const dataChanged = jest.fn();
|
|
36
|
+
const interceptors: DUActionInterceptor = {
|
|
37
|
+
interceptAction: (action) => {
|
|
38
|
+
if (action.type === Action.DATA_CHANGED) {
|
|
39
|
+
dataChanged();
|
|
40
|
+
}
|
|
41
|
+
return action;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
dataUnit.addInterceptor(interceptors);
|
|
45
|
+
dataUnit.selectFirst();
|
|
46
|
+
const promiseValue = new Promise((resolve) => resolve('promise_value'));
|
|
47
|
+
const response = await dataUnit.setFieldValue('column_name_1', promiseValue);
|
|
48
|
+
|
|
49
|
+
expect(response).toBeTruthy();
|
|
50
|
+
expect(dataChanged).toHaveBeenCalled();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should return false when value is the same', async () => {
|
|
54
|
+
dataUnit["areEquivalentValues"] = () => false;
|
|
55
|
+
dataUnit.selectFirst();
|
|
56
|
+
const response = await dataUnit.setFieldValue('column_name_1', 'column_value_1');
|
|
57
|
+
expect(response).toBeFalsy();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('disableField', () => {
|
|
62
|
+
beforeEach(async () => {
|
|
63
|
+
await dataUnit.loadMetadata();
|
|
64
|
+
await dataUnit.loadData();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should set readOnly to true', async () => {
|
|
68
|
+
dataUnit.disableField('column_name_1');
|
|
69
|
+
const field = dataUnit.getField('column_name_1');
|
|
70
|
+
expect(field?.readOnly).toBeTruthy();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should set readOnly to true when readonly is undefined', async () => {
|
|
74
|
+
dataUnit.disableField('column_name_2');
|
|
75
|
+
const field = dataUnit.getField('column_name_2');
|
|
76
|
+
expect(field?.readOnly).toBeTruthy();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should not set readOnly when field metadata not exist', async () => {
|
|
80
|
+
dataUnit.disableField('column_none');
|
|
81
|
+
const field = dataUnit.getField('column_none');
|
|
82
|
+
expect(field).toBeUndefined();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('enableField', () => {
|
|
87
|
+
beforeEach(async () => {
|
|
88
|
+
await dataUnit.loadMetadata();
|
|
89
|
+
await dataUnit.loadData();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should set readOnly to false', async () => {
|
|
93
|
+
dataUnit.enableField('column_name_1');
|
|
94
|
+
const field = dataUnit.getField('column_name_1');
|
|
95
|
+
expect(field?.readOnly).toBeFalsy();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should set readOnly to false when readonly is undefined', async () => {
|
|
99
|
+
dataUnit.enableField('column_name_2');
|
|
100
|
+
const field = dataUnit.getField('column_name_2');
|
|
101
|
+
expect(field?.readOnly).toBeFalsy();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should not set readOnly when field metadata not exist', async () => {
|
|
105
|
+
dataUnit.enableField('column_none');
|
|
106
|
+
const field = dataUnit.getField('column_none');
|
|
107
|
+
expect(field).toBeUndefined();
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('hideField', () => {
|
|
112
|
+
beforeEach(async () => {
|
|
113
|
+
await dataUnit.loadMetadata();
|
|
114
|
+
await dataUnit.loadData();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should set visible to false', async () => {
|
|
118
|
+
dataUnit.hideField('column_name_1', { visibleOnConfig: true });
|
|
119
|
+
const field = dataUnit.getField('column_name_1');
|
|
120
|
+
expect(field?.visible).toBeFalsy();
|
|
121
|
+
expect(field?.properties?.visibleOnConfig).toBeTruthy();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should set visible to false when visible is undefined', async () => {
|
|
125
|
+
dataUnit.hideField('column_name_2', { visibleOnConfig: true });
|
|
126
|
+
const field = dataUnit.getField('column_name_2');
|
|
127
|
+
expect(field?.visible).toBeFalsy();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should handle with options undefined', async () => {
|
|
131
|
+
dataUnit.hideField('column_name_3', undefined);
|
|
132
|
+
const field = dataUnit.getField('column_name_3');
|
|
133
|
+
|
|
134
|
+
expect(field?.visible).toBeFalsy();
|
|
135
|
+
expect(field?.properties?.visibleOnConfig).toBeUndefined();
|
|
136
|
+
expect(field?.properties).toBeUndefined();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should not set visible when field metadata not exist', async () => {
|
|
140
|
+
dataUnit.hideField('column_none', { visibleOnConfig: true });
|
|
141
|
+
const field = dataUnit.getField('column_none');
|
|
142
|
+
expect(field).toBeUndefined();
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
describe('showField', () => {
|
|
147
|
+
beforeEach(async () => {
|
|
148
|
+
await dataUnit.loadMetadata();
|
|
149
|
+
await dataUnit.loadData();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should set visible to true', async () => {
|
|
153
|
+
dataUnit.showField('column_name_3');
|
|
154
|
+
const field = dataUnit.getField('column_name_3');
|
|
155
|
+
expect(field?.visible).toBeTruthy();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should set visible to true when visible is undefined', async () => {
|
|
159
|
+
dataUnit.showField('column_name_2');
|
|
160
|
+
const field = dataUnit.getField('column_name_2');
|
|
161
|
+
expect(field?.visible).toBeTruthy();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('should not set visible when field metadata not exist', async () => {
|
|
165
|
+
dataUnit.showField('column_none');
|
|
166
|
+
const field = dataUnit.getField('column_none');
|
|
167
|
+
expect(field).toBeUndefined();
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe('addField', () => {
|
|
172
|
+
beforeEach(async () => {
|
|
173
|
+
await dataUnit.loadMetadata();
|
|
174
|
+
await dataUnit.loadData();
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('should add field standAlone to metadata', async () => {
|
|
178
|
+
const field: FieldDescriptor = {
|
|
179
|
+
name: 'new_field',
|
|
180
|
+
label: 'New field',
|
|
181
|
+
dataType: DataType.TEXT,
|
|
182
|
+
}
|
|
183
|
+
dataUnit.addField(field);
|
|
184
|
+
expect(dataUnit.metadata.fields).toStrictEqual(expect.arrayContaining([{ ...field, standAlone: true }]));
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('valueFromString', () => {
|
|
189
|
+
beforeEach(async () => {
|
|
190
|
+
await dataUnit.loadMetadata();
|
|
191
|
+
await dataUnit.loadData();
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('should return number type', async () => {
|
|
195
|
+
const response = dataUnit.valueFromString('column_name_2', '100');
|
|
196
|
+
expect(response).toEqual(100);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('should return boolean type', async () => {
|
|
200
|
+
const response = dataUnit.valueFromString('column_name_3', 'true');
|
|
201
|
+
expect(response).toEqual(true);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('should return value without any format when not has a metadata to field', async () => {
|
|
205
|
+
const response = dataUnit.valueFromString('column_none', 'true');
|
|
206
|
+
expect(response).toEqual('true');
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
describe('valueToString', () => {
|
|
211
|
+
beforeEach(async () => {
|
|
212
|
+
await dataUnit.loadMetadata();
|
|
213
|
+
await dataUnit.loadData();
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('should return string from the number type', async () => {
|
|
217
|
+
const response = dataUnit.valueToString('column_name_2', 100);
|
|
218
|
+
expect(response).toEqual('100');
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('should return string from the boolean type', async () => {
|
|
222
|
+
const response = dataUnit.valueToString('column_name_3', true);
|
|
223
|
+
expect(response).toEqual('true');
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('should return string value when not has a metadata to field', async () => {
|
|
227
|
+
const response = dataUnit.valueToString('column_none', true);
|
|
228
|
+
expect(response).toEqual('true');
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
describe('getFormattedValue', () => {
|
|
233
|
+
beforeEach(async () => {
|
|
234
|
+
await dataUnit.loadMetadata();
|
|
235
|
+
await dataUnit.loadData();
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('should return string with number format from the number type', async () => {
|
|
239
|
+
const response = dataUnit.getFormattedValue('column_name_2', 100);
|
|
240
|
+
expect(response).toEqual('100,00');
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('should return string from the boolean type', async () => {
|
|
244
|
+
const response = dataUnit.getFormattedValue('column_name_3', true);
|
|
245
|
+
expect(response).toEqual('Sim');
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('should return empty string when value is undefined and not has any record selected', async () => {
|
|
249
|
+
const response = dataUnit.getFormattedValue('column_name_1');
|
|
250
|
+
expect(response).toEqual('');
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('should return value in string when value is undefined and has a record selected', async () => {
|
|
254
|
+
dataUnit.selectFirst();
|
|
255
|
+
const response = dataUnit.getFormattedValue('column_name_1');
|
|
256
|
+
expect(response).toEqual('column_value_1');
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should return value in string formated when receive a string', async () => {
|
|
260
|
+
const response = dataUnit.getFormattedValue('column_name_2', '123');
|
|
261
|
+
expect(response).toEqual('123,00');
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('should return value in string with any formated when dont has a metadata field', async () => {
|
|
265
|
+
const response = dataUnit.getFormattedValue('column_none', '123');
|
|
266
|
+
expect(response).toEqual('123');
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it('should return string value when not has a metadata to field', async () => {
|
|
270
|
+
const response = dataUnit.getFormattedValue('column_none', true);
|
|
271
|
+
expect(response).toEqual('true');
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
describe('addSourceFieldValue', () => {
|
|
276
|
+
beforeEach(async () => {
|
|
277
|
+
await dataUnit.loadMetadata();
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('should return string with number format from the number type', async () => {
|
|
281
|
+
dataUnit.addSourceFieldValue('column_name_1', 'column_name_2');
|
|
282
|
+
const response = dataUnit.getSourceFieldValue('column_name_1');
|
|
283
|
+
expect(response).toEqual('column_name_2');
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
});
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { randomUUID } from "crypto";
|
|
2
|
+
import DataUnit from "../../src/dataunit/DataUnit";
|
|
3
|
+
import { DUActionInterceptor } from "../../src/dataunit/interfaces/dataUnit";
|
|
4
|
+
import { DataType } from "../../src/dataunit/metadata/DataType";
|
|
5
|
+
import { Filter, FilterProvider, Sort, SortingProvider, SortMode } from "../../src/dataunit/metadata/UnitMetadata";
|
|
6
|
+
import { Action } from "../../src/dataunit/state/action/DataUnitAction";
|
|
7
|
+
import { createDataUnitMock } from "./loader/utils/createDataUnitMock";
|
|
8
|
+
|
|
9
|
+
describe('Filters, sorts, lockers and observers', () => {
|
|
10
|
+
let dataUnit: DataUnit;
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
jest.clearAllMocks();
|
|
14
|
+
window.requestAnimationFrame = (functionCallback: Function) => functionCallback();
|
|
15
|
+
({ dataUnit } = createDataUnitMock());
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe('release', () => {
|
|
19
|
+
beforeEach(async () => {
|
|
20
|
+
await dataUnit.loadMetadata();
|
|
21
|
+
await dataUnit.loadData();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should clean dataUnit storage', async () => {
|
|
25
|
+
const releaseCallbacks = jest.spyOn(dataUnit, 'releaseCallbacks');
|
|
26
|
+
dataUnit.release();
|
|
27
|
+
expect(releaseCallbacks).toHaveBeenCalled();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should unsubscribe parent and remove child', async () => {
|
|
31
|
+
const childDataUnit = new DataUnit('test', dataUnit);
|
|
32
|
+
const unsubscribe = jest.spyOn(dataUnit, 'unsubscribe');
|
|
33
|
+
const removeChildDataunit = jest.spyOn(dataUnit, 'removeChildDataunit');
|
|
34
|
+
childDataUnit.release();
|
|
35
|
+
expect(unsubscribe).toHaveBeenCalled();
|
|
36
|
+
expect(removeChildDataunit).toHaveBeenCalled();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('releaseCallbacks', () => {
|
|
41
|
+
beforeEach(async () => {
|
|
42
|
+
await dataUnit.loadMetadata();
|
|
43
|
+
await dataUnit.loadData();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should clean observers, interceptors, sorting and filters provider', async () => {
|
|
47
|
+
const interceptorFn = jest.fn();
|
|
48
|
+
const interceptors: DUActionInterceptor = {
|
|
49
|
+
interceptAction: (action) => {
|
|
50
|
+
interceptorFn();
|
|
51
|
+
return action;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
dataUnit.addInterceptor(interceptors);
|
|
55
|
+
|
|
56
|
+
const sortingFn = jest.fn();
|
|
57
|
+
const sortingProvider: SortingProvider = {
|
|
58
|
+
getSort: () => {
|
|
59
|
+
sortingFn();
|
|
60
|
+
const sort: Sort = {
|
|
61
|
+
field: 'column_name_1',
|
|
62
|
+
dataType: DataType.TEXT,
|
|
63
|
+
mode: SortMode.DESC,
|
|
64
|
+
};
|
|
65
|
+
return [sort];
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
dataUnit.sortingProvider = sortingProvider;
|
|
69
|
+
|
|
70
|
+
const filterFn = jest.fn();
|
|
71
|
+
const FilterProvider: FilterProvider = {
|
|
72
|
+
getFilter: () => {
|
|
73
|
+
filterFn();
|
|
74
|
+
const filter: Filter = {
|
|
75
|
+
name: 'test_filter',
|
|
76
|
+
expression: 'test',
|
|
77
|
+
}
|
|
78
|
+
return [filter];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
dataUnit.addFilterProvider(FilterProvider);
|
|
82
|
+
|
|
83
|
+
const observerFn = jest.fn();
|
|
84
|
+
const observer = async () => {
|
|
85
|
+
observerFn();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
dataUnit.subscribe(observer);
|
|
90
|
+
|
|
91
|
+
dataUnit.releaseCallbacks();
|
|
92
|
+
|
|
93
|
+
await dataUnit.loadData();
|
|
94
|
+
dataUnit.getSort();
|
|
95
|
+
dataUnit.selectFirst();
|
|
96
|
+
|
|
97
|
+
expect(interceptorFn).not.toHaveBeenCalled();
|
|
98
|
+
expect(sortingFn).not.toHaveBeenCalled();
|
|
99
|
+
expect(filterFn).not.toHaveBeenCalled();
|
|
100
|
+
expect(observerFn).not.toHaveBeenCalled();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('should not clean observers when allowReleaseCallbacks is false', async () => {
|
|
104
|
+
dataUnit.allowReleaseCallbacks = false;
|
|
105
|
+
const observerFn = jest.fn();
|
|
106
|
+
const observer = async () => {
|
|
107
|
+
observerFn();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
dataUnit.subscribe(observer);
|
|
111
|
+
|
|
112
|
+
dataUnit.releaseCallbacks();
|
|
113
|
+
await dataUnit.loadData();
|
|
114
|
+
|
|
115
|
+
expect(observerFn).toHaveBeenCalled();
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
describe('addInterceptor', () => {
|
|
120
|
+
beforeEach(async () => {
|
|
121
|
+
await dataUnit.loadMetadata();
|
|
122
|
+
await dataUnit.loadData();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should remove interceptors', async () => {
|
|
126
|
+
const dataLoadedFn = jest.fn();
|
|
127
|
+
const interceptors: DUActionInterceptor = {
|
|
128
|
+
interceptAction: (action) => {
|
|
129
|
+
if (action.type === Action.DATA_LOADED) {
|
|
130
|
+
dataLoadedFn();
|
|
131
|
+
}
|
|
132
|
+
return action;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
dataUnit.addInterceptor(interceptors);
|
|
136
|
+
await dataUnit.loadData();
|
|
137
|
+
expect(dataLoadedFn).toHaveBeenCalled();
|
|
138
|
+
dataUnit.removeInterceptor(interceptors);
|
|
139
|
+
dataLoadedFn.mockClear();
|
|
140
|
+
await dataUnit.loadData();
|
|
141
|
+
expect(dataLoadedFn).not.toHaveBeenCalled();
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
describe('addFilterProvider', () => {
|
|
146
|
+
beforeEach(async () => {
|
|
147
|
+
await dataUnit.loadMetadata();
|
|
148
|
+
await dataUnit.loadData();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('should remove filterProvider', async () => {
|
|
152
|
+
const filterFn = jest.fn();
|
|
153
|
+
const filterProvider: FilterProvider = {
|
|
154
|
+
getFilter: () => {
|
|
155
|
+
filterFn();
|
|
156
|
+
const filter: Filter = {
|
|
157
|
+
name: 'test_filter',
|
|
158
|
+
expression: 'test',
|
|
159
|
+
}
|
|
160
|
+
return [filter];
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
dataUnit.addFilterProvider(filterProvider);
|
|
164
|
+
await dataUnit.loadData();
|
|
165
|
+
expect(filterFn).toHaveBeenCalled();
|
|
166
|
+
dataUnit.removeFilterProvider(filterProvider);
|
|
167
|
+
filterFn.mockClear();
|
|
168
|
+
await dataUnit.loadData();
|
|
169
|
+
expect(filterFn).not.toHaveBeenCalled();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('should add filterProvider with custom key', async () => {
|
|
173
|
+
const filterFn = jest.fn();
|
|
174
|
+
const filter: Filter = {
|
|
175
|
+
name: 'test_filter',
|
|
176
|
+
expression: 'test',
|
|
177
|
+
}
|
|
178
|
+
const filterProvider: FilterProvider = {
|
|
179
|
+
getFilter: () => {
|
|
180
|
+
filterFn();
|
|
181
|
+
return [filter];
|
|
182
|
+
},
|
|
183
|
+
getKey: () => 'customKey',
|
|
184
|
+
}
|
|
185
|
+
dataUnit.addFilterProvider(filterProvider);
|
|
186
|
+
await dataUnit.loadData();
|
|
187
|
+
expect(filterFn).toHaveBeenCalled();
|
|
188
|
+
const response = dataUnit.getFilters();
|
|
189
|
+
expect(response).toStrictEqual([filter]);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
describe('subscribe', () => {
|
|
194
|
+
beforeEach(async () => {
|
|
195
|
+
await dataUnit.loadMetadata();
|
|
196
|
+
await dataUnit.loadData();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('should remove observer', async () => {
|
|
200
|
+
const observerFn = jest.fn();
|
|
201
|
+
const observer = async () => {
|
|
202
|
+
observerFn();
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
dataUnit.subscribe(observer);
|
|
206
|
+
await dataUnit.loadData();
|
|
207
|
+
expect(observerFn).toHaveBeenCalled();
|
|
208
|
+
dataUnit.unsubscribe(observer);
|
|
209
|
+
observerFn.mockClear();
|
|
210
|
+
await dataUnit.loadData();
|
|
211
|
+
expect(observerFn).not.toHaveBeenCalled();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('should set observer with uuid', async () => {
|
|
215
|
+
const uuid = randomUUID();
|
|
216
|
+
const observerFn = jest.fn();
|
|
217
|
+
const observer = async () => {
|
|
218
|
+
observerFn();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
dataUnit.subscribe(observer, uuid);
|
|
222
|
+
await dataUnit.loadData();
|
|
223
|
+
expect(observerFn).toHaveBeenCalled();
|
|
224
|
+
dataUnit.unsubscribe(observer, uuid);
|
|
225
|
+
observerFn.mockClear();
|
|
226
|
+
await dataUnit.loadData();
|
|
227
|
+
expect(observerFn).not.toHaveBeenCalled();
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('should set observer with error', async () => {
|
|
231
|
+
const observerFn = jest.fn();
|
|
232
|
+
const warn = jest.spyOn(global.console, 'warn');
|
|
233
|
+
const observer = () => {
|
|
234
|
+
observerFn();
|
|
235
|
+
throw new Error('test');
|
|
236
|
+
}
|
|
237
|
+
dataUnit.subscribe(observer);
|
|
238
|
+
await dataUnit.loadData();
|
|
239
|
+
expect(warn).toHaveBeenCalledWith('[DataUnit] error while call observer', expect.anything());
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
describe('getAppliedFilters', () => {
|
|
244
|
+
beforeEach(async () => {
|
|
245
|
+
await dataUnit.loadMetadata();
|
|
246
|
+
await dataUnit.loadData();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('should return applied filters', async () => {
|
|
250
|
+
const filter: Filter = {
|
|
251
|
+
name: 'test_filter',
|
|
252
|
+
expression: 'test',
|
|
253
|
+
}
|
|
254
|
+
const FilterProvider: FilterProvider = {
|
|
255
|
+
getFilter: () => {
|
|
256
|
+
return [filter];
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
dataUnit.addFilterProvider(FilterProvider);
|
|
260
|
+
await dataUnit.loadData();
|
|
261
|
+
const response = dataUnit.getAppliedFilters();
|
|
262
|
+
expect(response).toStrictEqual([filter]);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('should return undefined when filter is not applied', () => {
|
|
266
|
+
const newDataUnit = new DataUnit();
|
|
267
|
+
const filter: Filter = {
|
|
268
|
+
name: 'test_filter',
|
|
269
|
+
expression: 'test',
|
|
270
|
+
}
|
|
271
|
+
const FilterProvider: FilterProvider = {
|
|
272
|
+
getFilter: () => {
|
|
273
|
+
return [filter];
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
newDataUnit.addFilterProvider(FilterProvider);
|
|
277
|
+
const response = newDataUnit.getAppliedFilters();
|
|
278
|
+
expect(response).toBeUndefined();
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
describe('addLoadingLocker', () => {
|
|
283
|
+
const dataLoaded = jest.fn();
|
|
284
|
+
|
|
285
|
+
beforeEach(() => {
|
|
286
|
+
dataLoaded.mockClear();
|
|
287
|
+
const interceptors: DUActionInterceptor = {
|
|
288
|
+
interceptAction: (action) => {
|
|
289
|
+
if (action.type === Action.DATA_LOADED) {
|
|
290
|
+
dataLoaded();
|
|
291
|
+
}
|
|
292
|
+
return action;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
dataUnit.addInterceptor(interceptors);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('should loaded data just when unlock', async () => {
|
|
299
|
+
const unlock = dataUnit.addLoadingLocker();
|
|
300
|
+
const promiseLoadData = dataUnit.loadData();
|
|
301
|
+
expect(dataLoaded).not.toHaveBeenCalled();
|
|
302
|
+
unlock();
|
|
303
|
+
await promiseLoadData;
|
|
304
|
+
expect(dataLoaded).toHaveBeenCalled();
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
describe('hasWaitingChanges', () => {
|
|
309
|
+
beforeEach(async () => {
|
|
310
|
+
await dataUnit.loadMetadata();
|
|
311
|
+
await dataUnit.loadData();
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it('should return status waiting changes', () => {
|
|
315
|
+
dataUnit.startChange('column_name_1', {
|
|
316
|
+
blocking: true,
|
|
317
|
+
waitmessage: 'test',
|
|
318
|
+
});
|
|
319
|
+
let hasWaitingChanges = dataUnit.hasWaitingChanges();
|
|
320
|
+
expect(hasWaitingChanges).toBeTruthy();
|
|
321
|
+
dataUnit.cancelWaitingChange('column_name_1');
|
|
322
|
+
hasWaitingChanges = dataUnit.hasWaitingChanges();
|
|
323
|
+
expect(hasWaitingChanges).toBeFalsy();
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
describe('addGlobalLoaderProp', () => {
|
|
328
|
+
it('should set global properties', () => {
|
|
329
|
+
dataUnit.addGlobalLoaderProp('prop_name', 'prop_value');
|
|
330
|
+
const properties = dataUnit.getGlobalLoaderProps();
|
|
331
|
+
expect(properties).toStrictEqual(new Map([['prop_name', 'prop_value']]));
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it('should return empty map when global properties not set', () => {
|
|
335
|
+
const properties = dataUnit.getGlobalLoaderProps();
|
|
336
|
+
expect(properties).toStrictEqual(new Map());
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
});
|