@mic-rexjs/usecases-react 1.3.36 → 1.4.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.
- package/README.md +2 -2
- package/dist/index.min.js +1 -1
- package/es/components/UpdateFragment/index.d.ts +2 -0
- package/es/components/UpdateFragment/index.js +8 -0
- package/es/components/UpdateFragment/types.d.ts +3 -0
- package/es/components/UseCaseFragment/index.d.ts +1 -1
- package/es/components/UseCaseFragment/types.d.ts +3 -3
- package/es/configs/defaultUseCaseContext/index.d.ts +3 -1
- package/es/configs/defaultUseCaseContext/index.js +1 -1
- package/es/configs/defaultUseCaseContext/types.d.ts +11 -0
- package/es/configs/defaultUseCaseContext/types.js +1 -0
- package/es/configs/usecaseContextMap/index.d.ts +1 -3
- package/es/configs/usecaseContextMap/types.d.ts +4 -17
- package/es/hooks/useCompareDeps/index.d.ts +1 -0
- package/es/hooks/useCompareDeps/index.js +24 -0
- package/es/hooks/useConstant/index.d.ts +2 -0
- package/es/hooks/useConstant/index.js +5 -0
- package/es/hooks/useConstant/types.d.ts +3 -0
- package/es/hooks/useConstant/types.js +1 -0
- package/es/hooks/useConstantFn/index.d.ts +1 -0
- package/es/hooks/useConstantFn/index.js +7 -0
- package/es/hooks/useOptionsRefCollection/index.d.ts +3 -0
- package/es/hooks/useOptionsRefCollection/index.js +22 -0
- package/es/hooks/useOptionsRefCollection/types.d.ts +2 -0
- package/es/hooks/useOptionsRefCollection/types.js +1 -0
- package/es/hooks/useProvider/index.d.ts +7 -0
- package/es/hooks/useProvider/index.js +17 -0
- package/es/hooks/useProvider/types.d.ts +3 -0
- package/es/hooks/useProvider/types.js +1 -0
- package/es/hooks/useScope/index.d.ts +2 -0
- package/es/hooks/useScope/index.js +3 -0
- package/es/hooks/useScope/types.d.ts +3 -0
- package/es/hooks/useScope/types.js +1 -0
- package/es/hooks/useUseCase/index.js +68 -89
- package/es/hooks/useUseCase/index.test.js +638 -156
- package/es/hooks/useUseCase/types.d.ts +27 -13
- package/es/hooks/useUseCaseContext/index.d.ts +3 -0
- package/es/hooks/useUseCaseContext/index.js +17 -0
- package/es/index.d.ts +3 -2
- package/es/methods/compareProperty/index.d.ts +2 -0
- package/es/methods/compareProperty/index.js +34 -0
- package/es/methods/compareProperty/types.d.ts +3 -0
- package/es/methods/compareProperty/types.js +1 -0
- package/es/methods/getRootEntity/index.d.ts +2 -0
- package/es/methods/getRootEntity/index.js +9 -0
- package/es/methods/hasField/index.d.ts +1 -0
- package/es/methods/hasField/index.js +6 -0
- package/es/methods/initEntityReducers/index.d.ts +5 -0
- package/es/methods/initEntityReducers/index.js +13 -0
- package/es/methods/initEntityReducers/types.d.ts +3 -0
- package/es/methods/initEntityReducers/types.js +1 -0
- package/es/methods/removeItem/index.d.ts +1 -0
- package/es/methods/removeItem/index.js +7 -0
- package/es/methods/triggerCallbacks/index.d.ts +3 -0
- package/es/methods/triggerCallbacks/index.js +14 -0
- package/es/methods/triggerWatchers/index.d.ts +2 -0
- package/es/methods/triggerWatchers/index.js +14 -0
- package/lib/components/UpdateFragment/index.js +16 -0
- package/lib/configs/defaultUseCaseContext/index.js +1 -1
- package/lib/configs/defaultUseCaseContext/types.js +5 -0
- package/lib/hooks/useCompareDeps/index.js +31 -0
- package/lib/hooks/useConstant/index.js +16 -0
- package/lib/hooks/useConstant/types.js +5 -0
- package/lib/hooks/useConstantFn/index.js +18 -0
- package/lib/hooks/useOptionsRefCollection/index.js +29 -0
- package/lib/hooks/useOptionsRefCollection/types.js +5 -0
- package/lib/hooks/useProvider/index.js +30 -0
- package/lib/hooks/useProvider/types.js +5 -0
- package/lib/hooks/useScope/index.js +10 -0
- package/lib/hooks/useScope/types.js +5 -0
- package/lib/hooks/useUseCase/index.js +73 -115
- package/lib/hooks/useUseCase/index.test.js +841 -240
- package/lib/hooks/useUseCaseContext/index.js +24 -0
- package/lib/methods/compareProperty/index.js +50 -0
- package/lib/methods/compareProperty/types.js +5 -0
- package/lib/methods/getRootEntity/index.js +16 -0
- package/lib/methods/hasField/index.js +15 -0
- package/lib/methods/initEntityReducers/index.js +29 -0
- package/lib/methods/initEntityReducers/types.js +5 -0
- package/lib/methods/removeItem/index.js +14 -0
- package/lib/methods/triggerCallbacks/index.js +22 -0
- package/lib/{hooks/useUseCase/methods → methods}/triggerWatchers/index.js +16 -9
- package/package.json +2 -2
- package/es/core/usecases/optionsGetterCellectionUseCase/index.d.ts +0 -2
- package/es/core/usecases/optionsGetterCellectionUseCase/index.js +0 -13
- package/es/core/usecases/optionsGetterCellectionUseCase/types.d.ts +0 -8
- package/es/hooks/useOptionsTransfer/index.d.ts +0 -3
- package/es/hooks/useOptionsTransfer/index.js +0 -15
- package/es/hooks/useUseCase/methods/triggerCallbacks/index.d.ts +0 -3
- package/es/hooks/useUseCase/methods/triggerCallbacks/index.js +0 -11
- package/es/hooks/useUseCase/methods/triggerWatchers/index.d.ts +0 -2
- package/es/hooks/useUseCase/methods/triggerWatchers/index.js +0 -10
- package/lib/core/usecases/optionsGetterCellectionUseCase/index.js +0 -23
- package/lib/hooks/useOptionsTransfer/index.js +0 -23
- package/lib/hooks/useUseCase/methods/triggerCallbacks/index.js +0 -32
- /package/es/{core/usecases/optionsGetterCellectionUseCase → components/UpdateFragment}/types.js +0 -0
- /package/lib/{core/usecases/optionsGetterCellectionUseCase → components/UpdateFragment}/types.js +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { objectUseCase, } from '@mic-rexjs/usecases';
|
|
2
|
+
import { objectUseCase, entityUseCase, } from '@mic-rexjs/usecases';
|
|
3
3
|
import { describe, expect, jest, test } from '@jest/globals';
|
|
4
4
|
import { renderHook, act, render, fireEvent, screen } from '@testing-library/react';
|
|
5
5
|
import { useUseCase } from '.';
|
|
@@ -34,9 +34,9 @@ const fileUseCase = (options = {}) => {
|
|
|
34
34
|
const size = 2000;
|
|
35
35
|
yield* setPath(entity, path);
|
|
36
36
|
await Promise.resolve(null);
|
|
37
|
-
yield (
|
|
37
|
+
yield (oldEntity) => {
|
|
38
38
|
return {
|
|
39
|
-
...
|
|
39
|
+
...oldEntity,
|
|
40
40
|
size,
|
|
41
41
|
};
|
|
42
42
|
};
|
|
@@ -58,6 +58,9 @@ const mathUseCase = (options = {}) => {
|
|
|
58
58
|
};
|
|
59
59
|
return { add, subtraction };
|
|
60
60
|
};
|
|
61
|
+
const fieldPathUseCase = () => {
|
|
62
|
+
return objectUseCase();
|
|
63
|
+
};
|
|
61
64
|
const Child = ({ textPrefix = '', onUpdate, onPathChange, onUndefinedEntity }) => {
|
|
62
65
|
const [file, { setPath }] = useUseCase(fileUseCase);
|
|
63
66
|
const { path, ext } = file || {};
|
|
@@ -121,31 +124,31 @@ describe('useUseCase', () => {
|
|
|
121
124
|
const { result } = renderHook(() => {
|
|
122
125
|
return useUseCase(defaultFile, fileUseCase);
|
|
123
126
|
});
|
|
124
|
-
const { current:
|
|
125
|
-
expect(
|
|
127
|
+
const { current: cores } = result;
|
|
128
|
+
expect(cores).toHaveLength(3);
|
|
126
129
|
});
|
|
127
130
|
test('`entity` should equal `defaultFile`', () => {
|
|
128
131
|
const { result } = renderHook(() => {
|
|
129
132
|
return useUseCase(defaultFile, fileUseCase);
|
|
130
133
|
});
|
|
131
|
-
const { current:
|
|
132
|
-
const [entity] =
|
|
134
|
+
const { current: cores } = result;
|
|
135
|
+
const [entity] = cores;
|
|
133
136
|
expect(entity).toBe(defaultFile);
|
|
134
137
|
});
|
|
135
138
|
test('`reducers` should be returned as an object', () => {
|
|
136
139
|
const { result } = renderHook(() => {
|
|
137
140
|
return useUseCase(defaultFile, fileUseCase);
|
|
138
141
|
});
|
|
139
|
-
const { current:
|
|
140
|
-
const [, reducers] =
|
|
142
|
+
const { current: cores } = result;
|
|
143
|
+
const [, reducers] = cores;
|
|
141
144
|
expect(typeof reducers).toBe('object');
|
|
142
145
|
});
|
|
143
146
|
test('`Provider` should be returned as a function', () => {
|
|
144
147
|
const { result } = renderHook(() => {
|
|
145
148
|
return useUseCase(defaultFile, fileUseCase);
|
|
146
149
|
});
|
|
147
|
-
const { current:
|
|
148
|
-
const [, , Provider] =
|
|
150
|
+
const { current: cores } = result;
|
|
151
|
+
const [, , Provider] = cores;
|
|
149
152
|
expect(typeof Provider).toBe('function');
|
|
150
153
|
});
|
|
151
154
|
test('after call non-generator reducer, it should not trigger update', () => {
|
|
@@ -189,14 +192,14 @@ describe('useUseCase', () => {
|
|
|
189
192
|
});
|
|
190
193
|
return useUseCase(defaultFile, fileUseCase);
|
|
191
194
|
});
|
|
192
|
-
const { current:
|
|
193
|
-
const [entity, reducers] =
|
|
195
|
+
const { current: cores } = result;
|
|
196
|
+
const [entity, reducers] = cores;
|
|
194
197
|
const { setPath, setEntity } = reducers;
|
|
195
198
|
act(() => {
|
|
196
199
|
setPath(PATH_1);
|
|
197
200
|
setEntity({ size: 5000 });
|
|
198
201
|
});
|
|
199
|
-
expect(result.current).not.toBe(
|
|
202
|
+
expect(result.current).not.toBe(cores);
|
|
200
203
|
expect(result.current[0]).not.toBe(entity);
|
|
201
204
|
expect(result.current[1]).not.toBe(reducers);
|
|
202
205
|
expect(result.current[1].setPath).not.toBe(setPath);
|
|
@@ -216,14 +219,14 @@ describe('useUseCase', () => {
|
|
|
216
219
|
});
|
|
217
220
|
return useUseCase(defaultFile, fileUseCase);
|
|
218
221
|
});
|
|
219
|
-
const { current:
|
|
220
|
-
const [entity, reducers] =
|
|
222
|
+
const { current: cores } = result;
|
|
223
|
+
const [entity, reducers] = cores;
|
|
221
224
|
const { readFile } = reducers;
|
|
222
225
|
const promise = act(() => {
|
|
223
226
|
return readFile(PATH_1);
|
|
224
227
|
});
|
|
225
|
-
expect(result.current).toBe(
|
|
226
|
-
expect(result.current).toEqual(
|
|
228
|
+
expect(result.current).toBe(cores);
|
|
229
|
+
expect(result.current).toEqual(cores);
|
|
227
230
|
expect(onUpdate).toHaveBeenCalledTimes(0);
|
|
228
231
|
await promise;
|
|
229
232
|
expect(result.current[0]).not.toBe(entity);
|
|
@@ -242,8 +245,8 @@ describe('useUseCase', () => {
|
|
|
242
245
|
});
|
|
243
246
|
return useUseCase(defaultFile, fileUseCase);
|
|
244
247
|
});
|
|
245
|
-
const { current:
|
|
246
|
-
const [, reducers] =
|
|
248
|
+
const { current: cores } = result;
|
|
249
|
+
const [, reducers] = cores;
|
|
247
250
|
const { init } = reducers;
|
|
248
251
|
act(() => {
|
|
249
252
|
init({ ...defaultFile, size: 5000 });
|
|
@@ -261,8 +264,8 @@ describe('useUseCase', () => {
|
|
|
261
264
|
});
|
|
262
265
|
return useUseCase(file, fileUseCase, { stateless: true });
|
|
263
266
|
});
|
|
264
|
-
const { current:
|
|
265
|
-
const [, { setPath }] =
|
|
267
|
+
const { current: cores } = result;
|
|
268
|
+
const [, { setPath }] = cores;
|
|
266
269
|
setPath(PATH_1);
|
|
267
270
|
expect(onUpdate).toHaveBeenCalledTimes(0);
|
|
268
271
|
expect(result.current[0].path).toBe('');
|
|
@@ -279,14 +282,14 @@ describe('useUseCase', () => {
|
|
|
279
282
|
});
|
|
280
283
|
return useUseCase(defaultFile, fileUseCase, { stateless: true });
|
|
281
284
|
});
|
|
282
|
-
const { current:
|
|
283
|
-
const [, reducers] =
|
|
285
|
+
const { current: cores } = result;
|
|
286
|
+
const [, reducers] = cores;
|
|
284
287
|
const { setPath } = reducers;
|
|
285
288
|
act(() => {
|
|
286
289
|
setPath(PATH_1);
|
|
287
290
|
});
|
|
288
|
-
expect(result.current).toBe(
|
|
289
|
-
expect(result.current).toEqual(
|
|
291
|
+
expect(result.current).toBe(cores);
|
|
292
|
+
expect(result.current).toEqual(cores);
|
|
290
293
|
expect(onUpdate).toHaveBeenCalledTimes(0);
|
|
291
294
|
});
|
|
292
295
|
test('`options.onChange` should be trigger when entity has changed', () => {
|
|
@@ -294,8 +297,8 @@ describe('useUseCase', () => {
|
|
|
294
297
|
const { result } = renderHook(() => {
|
|
295
298
|
return useUseCase(defaultFile, fileUseCase, { onChange });
|
|
296
299
|
});
|
|
297
|
-
const { current:
|
|
298
|
-
const [, reducers] =
|
|
300
|
+
const { current: cores } = result;
|
|
301
|
+
const [, reducers] = cores;
|
|
299
302
|
const { setPath } = reducers;
|
|
300
303
|
expect(onChange).toHaveBeenCalledTimes(0);
|
|
301
304
|
act(() => {
|
|
@@ -311,8 +314,8 @@ describe('useUseCase', () => {
|
|
|
311
314
|
options: { pathPrefix: '123/' },
|
|
312
315
|
});
|
|
313
316
|
});
|
|
314
|
-
const { current:
|
|
315
|
-
const [{ path }, reducers] =
|
|
317
|
+
const { current: cores } = result;
|
|
318
|
+
const [{ path }, reducers] = cores;
|
|
316
319
|
const { setPath } = reducers;
|
|
317
320
|
expect(path).toBe('');
|
|
318
321
|
act(() => {
|
|
@@ -343,6 +346,33 @@ describe('useUseCase', () => {
|
|
|
343
346
|
expect(onDeepUpdate).toHaveBeenCalledTimes(0);
|
|
344
347
|
});
|
|
345
348
|
test('when `entity` change, it should trigger watchers', () => {
|
|
349
|
+
const onPathChange = jest.fn();
|
|
350
|
+
const onSizeChange = jest.fn();
|
|
351
|
+
const { result } = renderHook(() => {
|
|
352
|
+
return useUseCase(defaultFile, fileUseCase, {
|
|
353
|
+
watch: {
|
|
354
|
+
path: onPathChange,
|
|
355
|
+
size: onSizeChange,
|
|
356
|
+
},
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
const { current: cores } = result;
|
|
360
|
+
const [, { setPath }] = cores;
|
|
361
|
+
expect(onPathChange).toHaveBeenCalledTimes(0);
|
|
362
|
+
act(() => {
|
|
363
|
+
setPath(PATH_1);
|
|
364
|
+
});
|
|
365
|
+
expect(onPathChange).toHaveBeenCalledTimes(1);
|
|
366
|
+
expect(onSizeChange).toHaveBeenCalledTimes(0);
|
|
367
|
+
expect(onPathChange).toHaveBeenLastCalledWith({
|
|
368
|
+
fieldPaths: ['path'],
|
|
369
|
+
newEntity: { ...defaultFile, path: PATH_1, ext: EXT_1 },
|
|
370
|
+
oldEntity: defaultFile,
|
|
371
|
+
newValue: PATH_1,
|
|
372
|
+
oldValue: '',
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
test('watcher should be updated after `entity` change', () => {
|
|
346
376
|
const onPathChange1 = jest.fn();
|
|
347
377
|
const onPathChange2 = jest.fn();
|
|
348
378
|
let onPathChange = onPathChange1;
|
|
@@ -353,8 +383,8 @@ describe('useUseCase', () => {
|
|
|
353
383
|
},
|
|
354
384
|
});
|
|
355
385
|
});
|
|
356
|
-
const { current:
|
|
357
|
-
const [, { setPath, setEntity }] =
|
|
386
|
+
const { current: cores } = result;
|
|
387
|
+
const [, { setPath, setEntity }] = cores;
|
|
358
388
|
onPathChange = onPathChange2;
|
|
359
389
|
expect(onPathChange1).toHaveBeenCalledTimes(0);
|
|
360
390
|
act(() => {
|
|
@@ -362,12 +392,24 @@ describe('useUseCase', () => {
|
|
|
362
392
|
setEntity({ size: 5000 });
|
|
363
393
|
});
|
|
364
394
|
expect(onPathChange1).toHaveBeenCalledTimes(1);
|
|
365
|
-
expect(onPathChange1).toHaveBeenLastCalledWith({
|
|
395
|
+
expect(onPathChange1).toHaveBeenLastCalledWith({
|
|
396
|
+
fieldPaths: ['path'],
|
|
397
|
+
newEntity: { ...defaultFile, path: PATH_1, ext: EXT_1 },
|
|
398
|
+
oldEntity: defaultFile,
|
|
399
|
+
newValue: PATH_1,
|
|
400
|
+
oldValue: '',
|
|
401
|
+
});
|
|
366
402
|
act(() => {
|
|
367
403
|
setPath('');
|
|
368
404
|
});
|
|
369
405
|
expect(onPathChange2).toHaveBeenCalledTimes(1);
|
|
370
|
-
expect(onPathChange2).toHaveBeenLastCalledWith({
|
|
406
|
+
expect(onPathChange2).toHaveBeenLastCalledWith({
|
|
407
|
+
fieldPaths: ['path'],
|
|
408
|
+
newEntity: { ...defaultFile, size: 5000 },
|
|
409
|
+
oldEntity: { ...defaultFile, path: PATH_1, size: 5000, ext: EXT_1 },
|
|
410
|
+
newValue: '',
|
|
411
|
+
oldValue: PATH_1,
|
|
412
|
+
});
|
|
371
413
|
});
|
|
372
414
|
test('when `deps` has changed, it should trigger update', () => {
|
|
373
415
|
const onUpdate = jest.fn();
|
|
@@ -414,72 +456,122 @@ describe('useUseCase', () => {
|
|
|
414
456
|
expect(onDeepUpdate).toHaveBeenCalledTimes(0);
|
|
415
457
|
});
|
|
416
458
|
});
|
|
417
|
-
describe('`useUseCase` should work with 1+
|
|
418
|
-
test('
|
|
459
|
+
describe('`useUseCase` should work with 1+ arguments on non-entity mode', () => {
|
|
460
|
+
test('`entity` should equal `defaultFile`', () => {
|
|
419
461
|
const { result } = renderHook(() => {
|
|
420
|
-
return useUseCase(
|
|
462
|
+
return useUseCase(mathUseCase);
|
|
421
463
|
});
|
|
422
|
-
const { current:
|
|
423
|
-
expect(
|
|
464
|
+
const { current: reducers } = result;
|
|
465
|
+
expect(Array.isArray(reducers)).toBe(false);
|
|
424
466
|
});
|
|
425
|
-
test('
|
|
467
|
+
test('returned reducer should work', () => {
|
|
426
468
|
const { result } = renderHook(() => {
|
|
427
|
-
return useUseCase(
|
|
469
|
+
return useUseCase(mathUseCase);
|
|
428
470
|
});
|
|
429
|
-
const { current:
|
|
430
|
-
const
|
|
431
|
-
expect(
|
|
471
|
+
const { current: reducers } = result;
|
|
472
|
+
const { add } = reducers;
|
|
473
|
+
expect(add(1, 2)).toBe(3);
|
|
432
474
|
});
|
|
433
|
-
test('`
|
|
475
|
+
test('`options.extraValue` should be added after call `add` method', () => {
|
|
434
476
|
const { result } = renderHook(() => {
|
|
435
|
-
return useUseCase(
|
|
477
|
+
return useUseCase(mathUseCase, { extraValue: 5 });
|
|
436
478
|
});
|
|
437
|
-
const { current:
|
|
438
|
-
const
|
|
439
|
-
expect(
|
|
479
|
+
const { current: reducers } = result;
|
|
480
|
+
const { add } = reducers;
|
|
481
|
+
expect(add(1, 2)).toBe(8);
|
|
440
482
|
});
|
|
441
|
-
test('
|
|
483
|
+
test('when `options` has changed, it should not trigger update', () => {
|
|
442
484
|
const onUpdate = jest.fn();
|
|
485
|
+
const onDeepUpdate = jest.fn();
|
|
443
486
|
const { result } = renderHook(() => {
|
|
487
|
+
const [extraValue, setExtraValue] = useState(0);
|
|
488
|
+
const reducers = useUseCase(mathUseCase, { extraValue });
|
|
444
489
|
useUpdateEffect(() => {
|
|
445
490
|
onUpdate();
|
|
446
|
-
});
|
|
447
|
-
|
|
491
|
+
}, [reducers]);
|
|
492
|
+
useDeepCompareUpdate(() => {
|
|
493
|
+
onDeepUpdate();
|
|
494
|
+
}, [reducers]);
|
|
495
|
+
return setExtraValue;
|
|
448
496
|
});
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
const { setPath } = reducers;
|
|
497
|
+
expect(onUpdate).toHaveBeenCalledTimes(0);
|
|
498
|
+
expect(onDeepUpdate).toHaveBeenCalledTimes(0);
|
|
452
499
|
act(() => {
|
|
453
|
-
|
|
500
|
+
result.current(3);
|
|
454
501
|
});
|
|
455
|
-
expect(result.current).toBe(context);
|
|
456
|
-
expect(result.current).toEqual(context);
|
|
457
502
|
expect(onUpdate).toHaveBeenCalledTimes(0);
|
|
503
|
+
expect(onDeepUpdate).toHaveBeenCalledTimes(0);
|
|
458
504
|
});
|
|
459
|
-
test('
|
|
505
|
+
test('when `deps` change, it should update reducers', () => {
|
|
506
|
+
const onUpdate = jest.fn();
|
|
507
|
+
const onDeepUpdate = jest.fn();
|
|
508
|
+
const { result } = renderHook(() => {
|
|
509
|
+
const [extraValue, setExtraValue] = useState(0);
|
|
510
|
+
const reducers = useUseCase(mathUseCase, { extraValue }, [extraValue]);
|
|
511
|
+
useUpdateEffect(() => {
|
|
512
|
+
onUpdate();
|
|
513
|
+
}, [reducers]);
|
|
514
|
+
useDeepCompareUpdate(() => {
|
|
515
|
+
onDeepUpdate();
|
|
516
|
+
}, [reducers]);
|
|
517
|
+
return setExtraValue;
|
|
518
|
+
});
|
|
519
|
+
expect(onUpdate).toHaveBeenCalledTimes(0);
|
|
520
|
+
expect(onDeepUpdate).toHaveBeenCalledTimes(0);
|
|
521
|
+
act(() => {
|
|
522
|
+
result.current(3);
|
|
523
|
+
});
|
|
524
|
+
expect(onUpdate).toHaveBeenCalledTimes(1);
|
|
525
|
+
expect(onDeepUpdate).toHaveBeenCalledTimes(1);
|
|
526
|
+
});
|
|
527
|
+
test('empty `deps` should not update reducers', () => {
|
|
528
|
+
const onUpdate = jest.fn();
|
|
529
|
+
const onDeepUpdate = jest.fn();
|
|
530
|
+
const { result } = renderHook(() => {
|
|
531
|
+
const [extraValue, setExtraValue] = useState(0);
|
|
532
|
+
const reducers = useUseCase(mathUseCase, { extraValue }, []);
|
|
533
|
+
useUpdateEffect(() => {
|
|
534
|
+
onUpdate();
|
|
535
|
+
}, [reducers]);
|
|
536
|
+
useDeepCompareUpdate(() => {
|
|
537
|
+
onDeepUpdate();
|
|
538
|
+
}, [reducers]);
|
|
539
|
+
return setExtraValue;
|
|
540
|
+
});
|
|
541
|
+
expect(onUpdate).toHaveBeenCalledTimes(0);
|
|
542
|
+
expect(onDeepUpdate).toHaveBeenCalledTimes(0);
|
|
543
|
+
act(() => {
|
|
544
|
+
result.current(3);
|
|
545
|
+
});
|
|
546
|
+
expect(onUpdate).toHaveBeenCalledTimes(0);
|
|
547
|
+
expect(onDeepUpdate).toHaveBeenCalledTimes(0);
|
|
548
|
+
});
|
|
549
|
+
test('should not trigger update', () => {
|
|
550
|
+
const onUpdate = jest.fn();
|
|
551
|
+
render(_jsx(MathParent, { onUpdate: onUpdate }));
|
|
552
|
+
fireEvent.click(screen.getByText(PARENT_BUTTON_TEXT));
|
|
553
|
+
expect(onUpdate).toHaveBeenCalledTimes(0);
|
|
554
|
+
});
|
|
555
|
+
});
|
|
556
|
+
describe('`useUseCase` should work with 1+ arguments on context mode', () => {
|
|
557
|
+
test('should work within <Child /> which it is under <Parent />', () => {
|
|
460
558
|
const textPrefix = '>>';
|
|
461
|
-
const
|
|
462
|
-
const
|
|
463
|
-
const
|
|
464
|
-
const onUpdate2 = jest.fn();
|
|
465
|
-
const onPathChange2 = jest.fn();
|
|
466
|
-
const onUndefinedEntity2 = jest.fn();
|
|
559
|
+
const onUpdate = jest.fn();
|
|
560
|
+
const onPathChange = jest.fn();
|
|
561
|
+
const onUndefinedEntity = jest.fn();
|
|
467
562
|
const onSetPath = jest.fn(() => {
|
|
468
563
|
return PATH_1;
|
|
469
564
|
});
|
|
470
|
-
render(
|
|
565
|
+
render(_jsx("div", { children: _jsx(Parent, { onSetPath: onSetPath, children: _jsx(Child, { textPrefix: textPrefix, onUpdate: onUpdate, onPathChange: onPathChange, onUndefinedEntity: onUndefinedEntity }) }) }));
|
|
471
566
|
fireEvent.click(screen.getByText(PARENT_BUTTON_TEXT));
|
|
472
567
|
expect(onSetPath).toHaveBeenCalledTimes(1);
|
|
473
|
-
expect(
|
|
474
|
-
expect(
|
|
568
|
+
expect(onUpdate).toHaveBeenCalledTimes(1);
|
|
569
|
+
expect(onPathChange).toHaveBeenCalledWith(PATH_1);
|
|
475
570
|
fireEvent.click(screen.getByText(textPrefix + CHILD_BUTTON_TEXT));
|
|
476
571
|
expect(onSetPath).toHaveBeenCalledTimes(1);
|
|
477
|
-
expect(
|
|
478
|
-
expect(
|
|
479
|
-
expect(
|
|
480
|
-
expect(onPathChange2).toHaveBeenCalledTimes(0);
|
|
481
|
-
expect(onUndefinedEntity1).toHaveBeenCalledTimes(0);
|
|
482
|
-
expect(onUndefinedEntity2).toHaveBeenCalledTimes(1);
|
|
572
|
+
expect(onUpdate).toHaveBeenCalledTimes(2);
|
|
573
|
+
expect(onPathChange).toHaveBeenCalledWith('');
|
|
574
|
+
expect(onUndefinedEntity).toHaveBeenCalledTimes(0);
|
|
483
575
|
});
|
|
484
576
|
test('`options.onChange` event should be trigger at child elements', () => {
|
|
485
577
|
const onFirstChange = jest.fn();
|
|
@@ -522,6 +614,39 @@ describe('useUseCase', () => {
|
|
|
522
614
|
expect(onFirstChange).toHaveBeenCalledTimes(1);
|
|
523
615
|
expect(onParentPathChange).toHaveBeenCalledTimes(2);
|
|
524
616
|
});
|
|
617
|
+
test('`options.onChange` event should be trigger in orders', () => {
|
|
618
|
+
let changeTimes = 0;
|
|
619
|
+
const updateChangeTimes = () => {
|
|
620
|
+
return ++changeTimes;
|
|
621
|
+
};
|
|
622
|
+
const onChangeA = jest.fn(updateChangeTimes);
|
|
623
|
+
const onChangeB = jest.fn(updateChangeTimes);
|
|
624
|
+
const onChangeC = jest.fn(updateChangeTimes);
|
|
625
|
+
const buttonText = 'my button';
|
|
626
|
+
const A = ({ children }) => {
|
|
627
|
+
useUseCase(fileUseCase, { onChange: onChangeA });
|
|
628
|
+
return _jsx(Fragment, { children: children });
|
|
629
|
+
};
|
|
630
|
+
const B = () => {
|
|
631
|
+
useUseCase(fileUseCase, { onChange: onChangeB });
|
|
632
|
+
return _jsx(Fragment, {});
|
|
633
|
+
};
|
|
634
|
+
const C = () => {
|
|
635
|
+
const [, { setPath }, Provider] = useUseCase(defaultFile, fileUseCase, {
|
|
636
|
+
onChange: onChangeC,
|
|
637
|
+
});
|
|
638
|
+
const onFirstClick = () => {
|
|
639
|
+
setPath(PATH_1);
|
|
640
|
+
};
|
|
641
|
+
return (_jsxs(Provider, { children: [_jsx(A, { children: _jsx(B, {}) }), _jsx("button", { onClick: onFirstClick, children: buttonText })] }));
|
|
642
|
+
};
|
|
643
|
+
render(_jsx(C, {}));
|
|
644
|
+
expect(changeTimes).toBe(0);
|
|
645
|
+
fireEvent.click(screen.getByText(buttonText));
|
|
646
|
+
expect(onChangeA).toHaveReturnedWith(2);
|
|
647
|
+
expect(onChangeB).toHaveReturnedWith(1);
|
|
648
|
+
expect(onChangeC).toHaveReturnedWith(3);
|
|
649
|
+
});
|
|
525
650
|
test('`options.watch` should be trigger at child elements', () => {
|
|
526
651
|
const onFirstExtChange = jest.fn();
|
|
527
652
|
const onSecondExtChange = jest.fn();
|
|
@@ -556,115 +681,472 @@ describe('useUseCase', () => {
|
|
|
556
681
|
expect(onFirstExtChange).toHaveBeenCalledTimes(0);
|
|
557
682
|
fireEvent.click(screen.getByText(firstButtonText));
|
|
558
683
|
expect(onFirstExtChange).toHaveBeenCalledTimes(1);
|
|
559
|
-
expect(onFirstExtChange).toHaveBeenLastCalledWith({
|
|
684
|
+
expect(onFirstExtChange).toHaveBeenLastCalledWith({
|
|
685
|
+
fieldPaths: ['ext'],
|
|
686
|
+
newEntity: { ...defaultFile, ext: EXT_1, path: PATH_1 },
|
|
687
|
+
oldEntity: defaultFile,
|
|
688
|
+
newValue: EXT_1,
|
|
689
|
+
oldValue: '',
|
|
690
|
+
});
|
|
560
691
|
expect(onParentExtChange).toHaveBeenCalledTimes(1);
|
|
561
692
|
expect(onSecondExtChange).toHaveBeenCalledTimes(0);
|
|
562
693
|
fireEvent.click(screen.getByText(secondButtonText));
|
|
563
694
|
expect(onSecondExtChange).toHaveBeenCalledTimes(1);
|
|
564
|
-
expect(onSecondExtChange).toHaveBeenLastCalledWith(
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
path: PATH_1,
|
|
695
|
+
expect(onSecondExtChange).toHaveBeenLastCalledWith({
|
|
696
|
+
fieldPaths: ['ext'],
|
|
697
|
+
newEntity: defaultFile,
|
|
698
|
+
oldEntity: { ...defaultFile, ext: EXT_1, path: PATH_1 },
|
|
699
|
+
newValue: '',
|
|
700
|
+
oldValue: EXT_1,
|
|
568
701
|
});
|
|
569
702
|
expect(onFirstExtChange).toHaveBeenCalledTimes(1);
|
|
570
703
|
expect(onParentExtChange).toHaveBeenCalledTimes(2);
|
|
571
704
|
});
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
return
|
|
577
|
-
}
|
|
578
|
-
const
|
|
579
|
-
|
|
705
|
+
test('`options.watch` should be trigger in orders', () => {
|
|
706
|
+
let changeTimes = 0;
|
|
707
|
+
const updateChangeTimes = (e) => {
|
|
708
|
+
void e;
|
|
709
|
+
return ++changeTimes;
|
|
710
|
+
};
|
|
711
|
+
const onChangeA = jest.fn(updateChangeTimes);
|
|
712
|
+
const onChangeB = jest.fn(updateChangeTimes);
|
|
713
|
+
const onChangeC = jest.fn(updateChangeTimes);
|
|
714
|
+
const buttonText = 'my button';
|
|
715
|
+
const A = ({ children }) => {
|
|
716
|
+
useUseCase(fileUseCase, {
|
|
717
|
+
watch: {
|
|
718
|
+
ext: onChangeA,
|
|
719
|
+
},
|
|
720
|
+
});
|
|
721
|
+
return _jsx(Fragment, { children: children });
|
|
722
|
+
};
|
|
723
|
+
const B = () => {
|
|
724
|
+
useUseCase(fileUseCase, {
|
|
725
|
+
watch: {
|
|
726
|
+
ext: onChangeB,
|
|
727
|
+
},
|
|
728
|
+
});
|
|
729
|
+
return _jsx(Fragment, {});
|
|
730
|
+
};
|
|
731
|
+
const C = () => {
|
|
732
|
+
const [, { setPath }, Provider] = useUseCase(defaultFile, fileUseCase, {
|
|
733
|
+
watch: {
|
|
734
|
+
ext: onChangeC,
|
|
735
|
+
},
|
|
736
|
+
});
|
|
737
|
+
const onFirstClick = () => {
|
|
738
|
+
setPath(PATH_1);
|
|
739
|
+
};
|
|
740
|
+
return (_jsxs(Provider, { children: [_jsx(A, { children: _jsx(B, {}) }), _jsx("button", { onClick: onFirstClick, children: buttonText })] }));
|
|
741
|
+
};
|
|
742
|
+
render(_jsx(C, {}));
|
|
743
|
+
expect(changeTimes).toBe(0);
|
|
744
|
+
fireEvent.click(screen.getByText(buttonText));
|
|
745
|
+
expect(onChangeA).toHaveReturnedWith(2);
|
|
746
|
+
expect(onChangeB).toHaveReturnedWith(1);
|
|
747
|
+
expect(onChangeC).toHaveReturnedWith(3);
|
|
580
748
|
});
|
|
581
|
-
test('
|
|
749
|
+
test('`options.watch` should work with array field path of array', () => {
|
|
750
|
+
const onExtChange = jest.fn();
|
|
751
|
+
const onSizeChange = jest.fn();
|
|
582
752
|
const { result } = renderHook(() => {
|
|
583
|
-
return useUseCase(
|
|
753
|
+
return useUseCase({}, fieldPathUseCase, {
|
|
754
|
+
watch: {
|
|
755
|
+
'list.ext': onExtChange,
|
|
756
|
+
'list.size': onSizeChange,
|
|
757
|
+
},
|
|
758
|
+
});
|
|
584
759
|
});
|
|
585
|
-
const { current:
|
|
586
|
-
const {
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
760
|
+
const { current: cores } = result;
|
|
761
|
+
const [, { setEntity }] = cores;
|
|
762
|
+
act(() => {
|
|
763
|
+
setEntity({ list: [defaultFile] });
|
|
764
|
+
});
|
|
765
|
+
expect(onExtChange).toHaveBeenCalledTimes(1);
|
|
766
|
+
expect(onSizeChange).toHaveBeenCalledTimes(1);
|
|
767
|
+
expect(onExtChange).toHaveBeenCalledWith({
|
|
768
|
+
fieldPaths: ['list', '0', 'ext'],
|
|
769
|
+
newEntity: { list: [defaultFile] },
|
|
770
|
+
oldEntity: {},
|
|
771
|
+
newValue: '',
|
|
772
|
+
oldValue: void 0,
|
|
773
|
+
});
|
|
774
|
+
expect(onSizeChange).toHaveBeenCalledWith({
|
|
775
|
+
fieldPaths: ['list', '0', 'size'],
|
|
776
|
+
newEntity: { list: [defaultFile] },
|
|
777
|
+
oldEntity: {},
|
|
778
|
+
newValue: 0,
|
|
779
|
+
oldValue: void 0,
|
|
780
|
+
});
|
|
781
|
+
act(() => {
|
|
782
|
+
setEntity({ list: [{ ...defaultFile, ext: EXT_1 }] });
|
|
783
|
+
});
|
|
784
|
+
expect(onExtChange).toHaveBeenCalledTimes(2);
|
|
785
|
+
expect(onSizeChange).toHaveBeenCalledTimes(1);
|
|
786
|
+
expect(onExtChange).toHaveBeenCalledWith({
|
|
787
|
+
fieldPaths: ['list', '0', 'ext'],
|
|
788
|
+
newEntity: { list: [{ ...defaultFile, ext: EXT_1 }] },
|
|
789
|
+
oldEntity: { list: [defaultFile] },
|
|
790
|
+
newValue: EXT_1,
|
|
791
|
+
oldValue: '',
|
|
792
|
+
});
|
|
793
|
+
act(() => {
|
|
794
|
+
setEntity({
|
|
795
|
+
list: [
|
|
796
|
+
{ ...defaultFile, ext: EXT_1 },
|
|
797
|
+
{ ...defaultFile, ext: EXT_2 },
|
|
798
|
+
],
|
|
799
|
+
});
|
|
800
|
+
});
|
|
801
|
+
expect(onExtChange).toHaveBeenCalledTimes(3);
|
|
802
|
+
expect(onSizeChange).toHaveBeenCalledTimes(2);
|
|
803
|
+
expect(onExtChange).toHaveBeenCalledWith({
|
|
804
|
+
fieldPaths: ['list', '1', 'ext'],
|
|
805
|
+
newEntity: {
|
|
806
|
+
list: [
|
|
807
|
+
{ ...defaultFile, ext: EXT_1 },
|
|
808
|
+
{ ...defaultFile, ext: EXT_2 },
|
|
809
|
+
],
|
|
810
|
+
},
|
|
811
|
+
oldEntity: { list: [{ ...defaultFile, ext: EXT_1 }] },
|
|
812
|
+
newValue: EXT_2,
|
|
813
|
+
oldValue: void 0,
|
|
814
|
+
});
|
|
815
|
+
expect(onSizeChange).toHaveBeenCalledWith({
|
|
816
|
+
fieldPaths: ['list', '1', 'size'],
|
|
817
|
+
newEntity: {
|
|
818
|
+
list: [
|
|
819
|
+
{ ...defaultFile, ext: EXT_1 },
|
|
820
|
+
{ ...defaultFile, ext: EXT_2 },
|
|
821
|
+
],
|
|
822
|
+
},
|
|
823
|
+
oldEntity: { list: [{ ...defaultFile, ext: EXT_1 }] },
|
|
824
|
+
newValue: 0,
|
|
825
|
+
oldValue: void 0,
|
|
826
|
+
});
|
|
827
|
+
act(() => {
|
|
828
|
+
setEntity({
|
|
829
|
+
nestedList: [],
|
|
830
|
+
});
|
|
831
|
+
});
|
|
832
|
+
expect(onExtChange).toHaveBeenCalledTimes(3);
|
|
833
|
+
expect(onSizeChange).toHaveBeenCalledTimes(2);
|
|
834
|
+
act(() => {
|
|
835
|
+
setEntity(() => {
|
|
836
|
+
return {
|
|
837
|
+
list: [{ ...defaultFile, ext: EXT_2 }, { ...defaultFile, ext: EXT_1 }, defaultFile],
|
|
838
|
+
};
|
|
839
|
+
});
|
|
840
|
+
});
|
|
841
|
+
expect(onExtChange).toHaveBeenCalledTimes(6);
|
|
842
|
+
expect(onSizeChange).toHaveBeenCalledTimes(3);
|
|
843
|
+
expect(onExtChange).toHaveBeenNthCalledWith(4, {
|
|
844
|
+
fieldPaths: ['list', '0', 'ext'],
|
|
845
|
+
newEntity: {
|
|
846
|
+
list: [{ ...defaultFile, ext: EXT_2 }, { ...defaultFile, ext: EXT_1 }, defaultFile],
|
|
847
|
+
},
|
|
848
|
+
oldEntity: {
|
|
849
|
+
list: [
|
|
850
|
+
{ ...defaultFile, ext: EXT_1 },
|
|
851
|
+
{ ...defaultFile, ext: EXT_2 },
|
|
852
|
+
],
|
|
853
|
+
nestedList: [],
|
|
854
|
+
},
|
|
855
|
+
newValue: EXT_2,
|
|
856
|
+
oldValue: EXT_1,
|
|
857
|
+
});
|
|
858
|
+
expect(onExtChange).toHaveBeenNthCalledWith(5, {
|
|
859
|
+
fieldPaths: ['list', '1', 'ext'],
|
|
860
|
+
newEntity: {
|
|
861
|
+
list: [{ ...defaultFile, ext: EXT_2 }, { ...defaultFile, ext: EXT_1 }, defaultFile],
|
|
862
|
+
},
|
|
863
|
+
oldEntity: {
|
|
864
|
+
list: [
|
|
865
|
+
{ ...defaultFile, ext: EXT_1 },
|
|
866
|
+
{ ...defaultFile, ext: EXT_2 },
|
|
867
|
+
],
|
|
868
|
+
nestedList: [],
|
|
869
|
+
},
|
|
870
|
+
newValue: EXT_1,
|
|
871
|
+
oldValue: EXT_2,
|
|
872
|
+
});
|
|
873
|
+
expect(onExtChange).toHaveBeenNthCalledWith(6, {
|
|
874
|
+
fieldPaths: ['list', '2', 'ext'],
|
|
875
|
+
newEntity: {
|
|
876
|
+
list: [{ ...defaultFile, ext: EXT_2 }, { ...defaultFile, ext: EXT_1 }, defaultFile],
|
|
877
|
+
},
|
|
878
|
+
oldEntity: {
|
|
879
|
+
list: [
|
|
880
|
+
{ ...defaultFile, ext: EXT_1 },
|
|
881
|
+
{ ...defaultFile, ext: EXT_2 },
|
|
882
|
+
],
|
|
883
|
+
nestedList: [],
|
|
884
|
+
},
|
|
885
|
+
newValue: '',
|
|
886
|
+
oldValue: void 0,
|
|
887
|
+
});
|
|
888
|
+
expect(onSizeChange).toHaveBeenCalledWith({
|
|
889
|
+
fieldPaths: ['list', '2', 'size'],
|
|
890
|
+
newEntity: {
|
|
891
|
+
list: [{ ...defaultFile, ext: EXT_2 }, { ...defaultFile, ext: EXT_1 }, defaultFile],
|
|
892
|
+
},
|
|
893
|
+
oldEntity: {
|
|
894
|
+
list: [
|
|
895
|
+
{ ...defaultFile, ext: EXT_1 },
|
|
896
|
+
{ ...defaultFile, ext: EXT_2 },
|
|
897
|
+
],
|
|
898
|
+
nestedList: [],
|
|
899
|
+
},
|
|
900
|
+
newValue: 0,
|
|
901
|
+
oldValue: void 0,
|
|
902
|
+
});
|
|
903
|
+
act(() => {
|
|
904
|
+
setEntity(() => {
|
|
905
|
+
return {};
|
|
906
|
+
});
|
|
907
|
+
});
|
|
908
|
+
expect(onExtChange).toHaveBeenCalledTimes(9);
|
|
909
|
+
expect(onSizeChange).toHaveBeenCalledTimes(6);
|
|
910
|
+
expect(onExtChange).toHaveBeenNthCalledWith(7, {
|
|
911
|
+
fieldPaths: ['list', '0', 'ext'],
|
|
912
|
+
newEntity: {},
|
|
913
|
+
oldEntity: {
|
|
914
|
+
list: [{ ...defaultFile, ext: EXT_2 }, { ...defaultFile, ext: EXT_1 }, defaultFile],
|
|
915
|
+
},
|
|
916
|
+
newValue: void 0,
|
|
917
|
+
oldValue: EXT_2,
|
|
918
|
+
});
|
|
919
|
+
expect(onExtChange).toHaveBeenNthCalledWith(8, {
|
|
920
|
+
fieldPaths: ['list', '1', 'ext'],
|
|
921
|
+
newEntity: {},
|
|
922
|
+
oldEntity: {
|
|
923
|
+
list: [{ ...defaultFile, ext: EXT_2 }, { ...defaultFile, ext: EXT_1 }, defaultFile],
|
|
924
|
+
},
|
|
925
|
+
newValue: void 0,
|
|
926
|
+
oldValue: EXT_1,
|
|
927
|
+
});
|
|
928
|
+
expect(onExtChange).toHaveBeenNthCalledWith(9, {
|
|
929
|
+
fieldPaths: ['list', '2', 'ext'],
|
|
930
|
+
newEntity: {},
|
|
931
|
+
oldEntity: {
|
|
932
|
+
list: [{ ...defaultFile, ext: EXT_2 }, { ...defaultFile, ext: EXT_1 }, defaultFile],
|
|
933
|
+
},
|
|
934
|
+
newValue: void 0,
|
|
935
|
+
oldValue: '',
|
|
936
|
+
});
|
|
937
|
+
expect(onSizeChange).toHaveBeenNthCalledWith(4, {
|
|
938
|
+
fieldPaths: ['list', '0', 'size'],
|
|
939
|
+
newEntity: {},
|
|
940
|
+
oldEntity: {
|
|
941
|
+
list: [{ ...defaultFile, ext: EXT_2 }, { ...defaultFile, ext: EXT_1 }, defaultFile],
|
|
942
|
+
},
|
|
943
|
+
newValue: void 0,
|
|
944
|
+
oldValue: 0,
|
|
945
|
+
});
|
|
946
|
+
expect(onSizeChange).toHaveBeenNthCalledWith(5, {
|
|
947
|
+
fieldPaths: ['list', '1', 'size'],
|
|
948
|
+
newEntity: {},
|
|
949
|
+
oldEntity: {
|
|
950
|
+
list: [{ ...defaultFile, ext: EXT_2 }, { ...defaultFile, ext: EXT_1 }, defaultFile],
|
|
951
|
+
},
|
|
952
|
+
newValue: void 0,
|
|
953
|
+
oldValue: 0,
|
|
954
|
+
});
|
|
955
|
+
expect(onSizeChange).toHaveBeenNthCalledWith(6, {
|
|
956
|
+
fieldPaths: ['list', '2', 'size'],
|
|
957
|
+
newEntity: {},
|
|
958
|
+
oldEntity: {
|
|
959
|
+
list: [{ ...defaultFile, ext: EXT_2 }, { ...defaultFile, ext: EXT_1 }, defaultFile],
|
|
960
|
+
},
|
|
961
|
+
newValue: void 0,
|
|
962
|
+
oldValue: 0,
|
|
592
963
|
});
|
|
593
|
-
const { current: reducers } = result;
|
|
594
|
-
const { add } = reducers;
|
|
595
|
-
expect(add(1, 2)).toBe(8);
|
|
596
964
|
});
|
|
597
|
-
test('
|
|
598
|
-
const
|
|
599
|
-
const
|
|
965
|
+
test('`options.watch` should work with field path of array length', () => {
|
|
966
|
+
const onEntityLengthChange = jest.fn();
|
|
967
|
+
const onListLengthChange = jest.fn();
|
|
968
|
+
const lengthUseCase = () => {
|
|
969
|
+
return entityUseCase();
|
|
970
|
+
};
|
|
600
971
|
const { result } = renderHook(() => {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
onDeepUpdate();
|
|
608
|
-
}, [reducers]);
|
|
609
|
-
return setExtraValue;
|
|
972
|
+
return useUseCase([], lengthUseCase, {
|
|
973
|
+
watch: {
|
|
974
|
+
length: onEntityLengthChange,
|
|
975
|
+
'list.length': onListLengthChange,
|
|
976
|
+
},
|
|
977
|
+
});
|
|
610
978
|
});
|
|
611
|
-
|
|
612
|
-
|
|
979
|
+
const { current: cores } = result;
|
|
980
|
+
const [, { setEntity }] = cores;
|
|
981
|
+
expect(onEntityLengthChange).toHaveBeenCalledTimes(0);
|
|
982
|
+
expect(onListLengthChange).toHaveBeenCalledTimes(0);
|
|
613
983
|
act(() => {
|
|
614
|
-
|
|
984
|
+
setEntity([{ list: [defaultFile, defaultFile] }]);
|
|
985
|
+
});
|
|
986
|
+
expect(onEntityLengthChange).toHaveBeenCalledTimes(1);
|
|
987
|
+
expect(onListLengthChange).toHaveBeenCalledTimes(1);
|
|
988
|
+
expect(onEntityLengthChange).toHaveBeenCalledWith({
|
|
989
|
+
fieldPaths: ['length'],
|
|
990
|
+
newEntity: [{ list: [defaultFile, defaultFile] }],
|
|
991
|
+
oldEntity: [],
|
|
992
|
+
newValue: 1,
|
|
993
|
+
oldValue: 0,
|
|
994
|
+
});
|
|
995
|
+
expect(onListLengthChange).toHaveBeenCalledWith({
|
|
996
|
+
fieldPaths: ['0', 'list', 'length'],
|
|
997
|
+
newEntity: [{ list: [defaultFile, defaultFile] }],
|
|
998
|
+
oldEntity: [],
|
|
999
|
+
newValue: 2,
|
|
1000
|
+
oldValue: void 0,
|
|
615
1001
|
});
|
|
616
|
-
expect(onUpdate).toHaveBeenCalledTimes(0);
|
|
617
|
-
expect(onDeepUpdate).toHaveBeenCalledTimes(0);
|
|
618
1002
|
});
|
|
619
|
-
test('
|
|
620
|
-
const
|
|
621
|
-
const onDeepUpdate = jest.fn();
|
|
1003
|
+
test('`options.watch` should work with field path of nested array', () => {
|
|
1004
|
+
const onChange = jest.fn();
|
|
622
1005
|
const { result } = renderHook(() => {
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
}
|
|
628
|
-
useDeepCompareUpdate(() => {
|
|
629
|
-
onDeepUpdate();
|
|
630
|
-
}, [reducers]);
|
|
631
|
-
return setExtraValue;
|
|
1006
|
+
return useUseCase({}, fieldPathUseCase, {
|
|
1007
|
+
watch: {
|
|
1008
|
+
'nestedList.size': onChange,
|
|
1009
|
+
},
|
|
1010
|
+
});
|
|
632
1011
|
});
|
|
633
|
-
|
|
634
|
-
|
|
1012
|
+
const { current: cores } = result;
|
|
1013
|
+
const [, { setEntity }] = cores;
|
|
1014
|
+
expect(onChange).toHaveBeenCalledTimes(0);
|
|
635
1015
|
act(() => {
|
|
636
|
-
|
|
1016
|
+
setEntity({ nestedList: [[[defaultFile]]] });
|
|
1017
|
+
});
|
|
1018
|
+
expect(onChange).toHaveBeenCalledTimes(1);
|
|
1019
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
1020
|
+
fieldPaths: ['nestedList', '0', '0', '0', 'size'],
|
|
1021
|
+
newEntity: { nestedList: [[[defaultFile]]] },
|
|
1022
|
+
oldEntity: {},
|
|
1023
|
+
newValue: 0,
|
|
1024
|
+
oldValue: void 0,
|
|
1025
|
+
});
|
|
1026
|
+
act(() => {
|
|
1027
|
+
setEntity({
|
|
1028
|
+
nestedList: [
|
|
1029
|
+
[
|
|
1030
|
+
[
|
|
1031
|
+
{ ...defaultFile, size: 100 },
|
|
1032
|
+
{ ...defaultFile, size: 200 },
|
|
1033
|
+
],
|
|
1034
|
+
],
|
|
1035
|
+
[[{ ...defaultFile, size: 300 }]],
|
|
1036
|
+
],
|
|
1037
|
+
});
|
|
1038
|
+
});
|
|
1039
|
+
expect(onChange).toHaveBeenCalledTimes(4);
|
|
1040
|
+
expect(onChange).toHaveBeenNthCalledWith(2, {
|
|
1041
|
+
fieldPaths: ['nestedList', '0', '0', '0', 'size'],
|
|
1042
|
+
newEntity: {
|
|
1043
|
+
nestedList: [
|
|
1044
|
+
[
|
|
1045
|
+
[
|
|
1046
|
+
{ ...defaultFile, size: 100 },
|
|
1047
|
+
{ ...defaultFile, size: 200 },
|
|
1048
|
+
],
|
|
1049
|
+
],
|
|
1050
|
+
[[{ ...defaultFile, size: 300 }]],
|
|
1051
|
+
],
|
|
1052
|
+
},
|
|
1053
|
+
oldEntity: { nestedList: [[[defaultFile]]] },
|
|
1054
|
+
newValue: 100,
|
|
1055
|
+
oldValue: 0,
|
|
1056
|
+
});
|
|
1057
|
+
expect(onChange).toHaveBeenNthCalledWith(3, {
|
|
1058
|
+
fieldPaths: ['nestedList', '0', '0', '1', 'size'],
|
|
1059
|
+
newEntity: {
|
|
1060
|
+
nestedList: [
|
|
1061
|
+
[
|
|
1062
|
+
[
|
|
1063
|
+
{ ...defaultFile, size: 100 },
|
|
1064
|
+
{ ...defaultFile, size: 200 },
|
|
1065
|
+
],
|
|
1066
|
+
],
|
|
1067
|
+
[[{ ...defaultFile, size: 300 }]],
|
|
1068
|
+
],
|
|
1069
|
+
},
|
|
1070
|
+
oldEntity: { nestedList: [[[defaultFile]]] },
|
|
1071
|
+
newValue: 200,
|
|
1072
|
+
oldValue: void 0,
|
|
1073
|
+
});
|
|
1074
|
+
expect(onChange).toHaveBeenNthCalledWith(4, {
|
|
1075
|
+
fieldPaths: ['nestedList', '1', '0', '0', 'size'],
|
|
1076
|
+
newEntity: {
|
|
1077
|
+
nestedList: [
|
|
1078
|
+
[
|
|
1079
|
+
[
|
|
1080
|
+
{ ...defaultFile, size: 100 },
|
|
1081
|
+
{ ...defaultFile, size: 200 },
|
|
1082
|
+
],
|
|
1083
|
+
],
|
|
1084
|
+
[[{ ...defaultFile, size: 300 }]],
|
|
1085
|
+
],
|
|
1086
|
+
},
|
|
1087
|
+
oldEntity: { nestedList: [[[defaultFile]]] },
|
|
1088
|
+
newValue: 300,
|
|
1089
|
+
oldValue: void 0,
|
|
637
1090
|
});
|
|
638
|
-
expect(onUpdate).toHaveBeenCalledTimes(1);
|
|
639
|
-
expect(onDeepUpdate).toHaveBeenCalledTimes(1);
|
|
640
1091
|
});
|
|
641
|
-
test('
|
|
642
|
-
const
|
|
643
|
-
const
|
|
1092
|
+
test('`options.watch` should work with field path of object', () => {
|
|
1093
|
+
const onExtChange = jest.fn();
|
|
1094
|
+
const onSizeChange = jest.fn();
|
|
644
1095
|
const { result } = renderHook(() => {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
onDeepUpdate();
|
|
652
|
-
}, [reducers]);
|
|
653
|
-
return setExtraValue;
|
|
1096
|
+
return useUseCase({}, fieldPathUseCase, {
|
|
1097
|
+
watch: {
|
|
1098
|
+
'obj.file.ext': onExtChange,
|
|
1099
|
+
'obj.file.size': onSizeChange,
|
|
1100
|
+
},
|
|
1101
|
+
});
|
|
654
1102
|
});
|
|
655
|
-
|
|
656
|
-
|
|
1103
|
+
const { current: cores } = result;
|
|
1104
|
+
const [, { setEntity }] = cores;
|
|
1105
|
+
expect(onExtChange).toHaveBeenCalledTimes(0);
|
|
657
1106
|
act(() => {
|
|
658
|
-
|
|
1107
|
+
setEntity({
|
|
1108
|
+
obj: {
|
|
1109
|
+
file: {
|
|
1110
|
+
ext: EXT_1,
|
|
1111
|
+
},
|
|
1112
|
+
},
|
|
1113
|
+
});
|
|
1114
|
+
});
|
|
1115
|
+
expect(onExtChange).toHaveBeenCalledTimes(1);
|
|
1116
|
+
expect(onSizeChange).toHaveBeenCalledTimes(0);
|
|
1117
|
+
expect(onExtChange).toHaveBeenCalledWith({
|
|
1118
|
+
fieldPaths: ['obj', 'file', 'ext'],
|
|
1119
|
+
newEntity: {
|
|
1120
|
+
obj: {
|
|
1121
|
+
file: {
|
|
1122
|
+
ext: EXT_1,
|
|
1123
|
+
},
|
|
1124
|
+
},
|
|
1125
|
+
},
|
|
1126
|
+
oldEntity: {},
|
|
1127
|
+
newValue: EXT_1,
|
|
1128
|
+
oldValue: void 0,
|
|
1129
|
+
});
|
|
1130
|
+
act(() => {
|
|
1131
|
+
setEntity(() => {
|
|
1132
|
+
return {};
|
|
1133
|
+
});
|
|
1134
|
+
});
|
|
1135
|
+
expect(onExtChange).toHaveBeenCalledTimes(2);
|
|
1136
|
+
expect(onSizeChange).toHaveBeenCalledTimes(0);
|
|
1137
|
+
expect(onExtChange).toHaveBeenCalledWith({
|
|
1138
|
+
fieldPaths: ['obj', 'file', 'ext'],
|
|
1139
|
+
newEntity: {},
|
|
1140
|
+
oldEntity: {
|
|
1141
|
+
obj: {
|
|
1142
|
+
file: {
|
|
1143
|
+
ext: EXT_1,
|
|
1144
|
+
},
|
|
1145
|
+
},
|
|
1146
|
+
},
|
|
1147
|
+
newValue: void 0,
|
|
1148
|
+
oldValue: EXT_1,
|
|
659
1149
|
});
|
|
660
|
-
expect(onUpdate).toHaveBeenCalledTimes(0);
|
|
661
|
-
expect(onDeepUpdate).toHaveBeenCalledTimes(0);
|
|
662
|
-
});
|
|
663
|
-
test('should not trigger update', () => {
|
|
664
|
-
const onUpdate = jest.fn();
|
|
665
|
-
render(_jsx(MathParent, { onUpdate: onUpdate }));
|
|
666
|
-
fireEvent.click(screen.getByText(PARENT_BUTTON_TEXT));
|
|
667
|
-
expect(onUpdate).toHaveBeenCalledTimes(0);
|
|
668
1150
|
});
|
|
669
1151
|
});
|
|
670
1152
|
});
|