@mic-rexjs/usecases-react 1.5.1 → 1.6.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.
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { objectUseCase, entityUseCase, } from '@mic-rexjs/usecases';
3
- import { describe, expect, jest, test } from '@jest/globals';
3
+ import { beforeEach, describe, expect, jest, test } from '@jest/globals';
4
4
  import { renderHook, act, render, fireEvent, screen } from '@testing-library/react';
5
5
  import { useUseCase } from '.';
6
- import { useDeepCompareEffect, useMemoizedFn, useUpdate, useUpdateEffect } from 'ahooks';
6
+ import { useDeepCompareEffect, useMemoizedFn, useMount, useUpdate, useUpdateEffect } from 'ahooks';
7
7
  import { Fragment, useEffect, useRef, useState } from 'react';
8
8
  const EXT_1 = '.png';
9
9
  const EXT_2 = '.jpg';
@@ -48,15 +48,15 @@ const fileUseCase = (options = {}) => {
48
48
  };
49
49
  return { ...entityReducers, init, setPath, readFile, isImage };
50
50
  };
51
+ const subtractionReducer = jest.fn((value1, value2) => {
52
+ return value1 - value2;
53
+ });
51
54
  const mathUseCase = (options = {}) => {
52
55
  const { extraValue = 0 } = options;
53
56
  const add = (value1, value2) => {
54
57
  return value1 + value2 + extraValue;
55
58
  };
56
- const subtraction = (value1, value2) => {
57
- return value1 - value2;
58
- };
59
- return { add, subtraction };
59
+ return { add, subtraction: subtractionReducer };
60
60
  };
61
61
  const fieldPathUseCase = () => {
62
62
  return objectUseCase();
@@ -118,6 +118,9 @@ const useDeepCompareUpdate = (callback, deps) => {
118
118
  callback();
119
119
  }, deps);
120
120
  };
121
+ beforeEach(() => {
122
+ subtractionReducer.mockClear();
123
+ });
121
124
  describe('useUseCase', () => {
122
125
  describe('`useUseCase` should work with 2+ arguments on provider mode', () => {
123
126
  test('check `context.length`', () => {
@@ -256,6 +259,107 @@ describe('useUseCase', () => {
256
259
  expect(result.current[1].init).not.toBe(init);
257
260
  expect(onUpdate).toHaveBeenCalledTimes(1);
258
261
  });
262
+ test('reducer call should be cached if component is at rendering phase', () => {
263
+ const buttonText = 'button';
264
+ const addReducer = jest.fn((entity, substring) => {
265
+ return entity + substring;
266
+ });
267
+ const stringUseCase = () => {
268
+ const entityReducers = entityUseCase();
269
+ return {
270
+ ...entityReducers,
271
+ add: addReducer,
272
+ };
273
+ };
274
+ const CacheTestComponent = () => {
275
+ const [, { add }] = useUseCase('', stringUseCase);
276
+ const update = useUpdate();
277
+ const onClick = () => {
278
+ update();
279
+ };
280
+ add('x');
281
+ return _jsx("button", { onClick: onClick, children: buttonText });
282
+ };
283
+ render(_jsx(CacheTestComponent, {}));
284
+ expect(addReducer).toHaveBeenCalledTimes(1);
285
+ expect(addReducer).toHaveBeenCalledWith('', 'x');
286
+ expect(addReducer).toHaveReturnedWith('x');
287
+ fireEvent.click(screen.getByText(buttonText));
288
+ expect(addReducer).toHaveBeenCalledTimes(1);
289
+ });
290
+ test('reducer call should not be cached if component is not at rendering phase', () => {
291
+ const buttonText = 'button';
292
+ const addReducer = jest.fn((entity, substring) => {
293
+ return entity + substring;
294
+ });
295
+ const stringUseCase = () => {
296
+ const entityReducers = entityUseCase();
297
+ return {
298
+ ...entityReducers,
299
+ add: addReducer,
300
+ };
301
+ };
302
+ const CacheTestComponent = () => {
303
+ const [, { add }] = useUseCase('', stringUseCase);
304
+ const onClick = () => {
305
+ add('x');
306
+ };
307
+ useMount(() => {
308
+ add('x');
309
+ add('x');
310
+ });
311
+ return _jsx("button", { onClick: onClick, children: buttonText });
312
+ };
313
+ render(_jsx(CacheTestComponent, {}));
314
+ expect(addReducer).toHaveBeenCalledTimes(2);
315
+ expect(addReducer).toHaveBeenNthCalledWith(1, '', 'x');
316
+ expect(addReducer).toHaveBeenNthCalledWith(2, '', 'x');
317
+ fireEvent.click(screen.getByText(buttonText));
318
+ expect(addReducer).toHaveBeenCalledTimes(3);
319
+ expect(addReducer).toHaveBeenNthCalledWith(3, '', 'x');
320
+ });
321
+ test('reducer call should not be cached if entity or parameters have changed', () => {
322
+ let count = 0;
323
+ let addedText = 'x';
324
+ const setButtonText = 'button';
325
+ const updateButtonText = 'update';
326
+ const addReducer = jest.fn((entity, substring) => {
327
+ return entity + substring;
328
+ });
329
+ const stringUseCase = () => {
330
+ const entityReducers = entityUseCase();
331
+ return {
332
+ ...entityReducers,
333
+ add: addReducer,
334
+ };
335
+ };
336
+ const CacheTestComponent = () => {
337
+ const [, { add, setEntity }] = useUseCase('', stringUseCase);
338
+ const update = useUpdate();
339
+ add(addedText);
340
+ const onSet = () => {
341
+ setEntity(`${count++}`);
342
+ };
343
+ const onUpdate = () => {
344
+ update();
345
+ };
346
+ return (_jsxs("div", { children: [_jsx("button", { onClick: onSet, children: setButtonText }), _jsx("button", { onClick: onUpdate, children: updateButtonText })] }));
347
+ };
348
+ render(_jsx(CacheTestComponent, {}));
349
+ expect(addReducer).toHaveBeenCalledTimes(1);
350
+ expect(addReducer).toHaveBeenCalledWith('', 'x');
351
+ fireEvent.click(screen.getByText(setButtonText));
352
+ expect(addReducer).toHaveBeenCalledTimes(2);
353
+ expect(addReducer).toHaveBeenCalledWith('0', 'x');
354
+ expect(addReducer).toHaveReturnedWith('0x');
355
+ addedText = 'y';
356
+ fireEvent.click(screen.getByText(updateButtonText));
357
+ expect(addReducer).toHaveBeenCalledTimes(3);
358
+ expect(addReducer).toHaveBeenCalledWith('0', 'y');
359
+ expect(addReducer).toHaveReturnedWith('0y');
360
+ fireEvent.click(screen.getByText(updateButtonText));
361
+ expect(addReducer).toHaveBeenCalledTimes(3);
362
+ });
259
363
  test('`options.stateless` should not generate new reducers when `yeild entity`', () => {
260
364
  const onUpdate = jest.fn();
261
365
  const { result, rerender } = renderHook((file = defaultFile) => {
@@ -455,198 +559,6 @@ describe('useUseCase', () => {
455
559
  expect(onUpdate).toHaveBeenCalledTimes(0);
456
560
  expect(onDeepUpdate).toHaveBeenCalledTimes(0);
457
561
  });
458
- });
459
- describe('`useUseCase` should work with 1+ arguments on non-entity mode', () => {
460
- test('`entity` should equal `defaultFile`', () => {
461
- const { result } = renderHook(() => {
462
- return useUseCase(mathUseCase);
463
- });
464
- const { current: reducers } = result;
465
- expect(Array.isArray(reducers)).toBe(false);
466
- });
467
- test('returned reducer should work', () => {
468
- const { result } = renderHook(() => {
469
- return useUseCase(mathUseCase);
470
- });
471
- const { current: reducers } = result;
472
- const { add } = reducers;
473
- expect(add(1, 2)).toBe(3);
474
- });
475
- test('`options.extraValue` should be added after call `add` method', () => {
476
- const { result } = renderHook(() => {
477
- return useUseCase(mathUseCase, { extraValue: 5 });
478
- });
479
- const { current: reducers } = result;
480
- const { add } = reducers;
481
- expect(add(1, 2)).toBe(8);
482
- });
483
- test('when `options` has changed, it should not trigger update', () => {
484
- const onUpdate = jest.fn();
485
- const onDeepUpdate = jest.fn();
486
- const { result } = renderHook(() => {
487
- const [extraValue, setExtraValue] = useState(0);
488
- const reducers = useUseCase(mathUseCase, { extraValue });
489
- useUpdateEffect(() => {
490
- onUpdate();
491
- }, [reducers]);
492
- useDeepCompareUpdate(() => {
493
- onDeepUpdate();
494
- }, [reducers]);
495
- return setExtraValue;
496
- });
497
- expect(onUpdate).toHaveBeenCalledTimes(0);
498
- expect(onDeepUpdate).toHaveBeenCalledTimes(0);
499
- act(() => {
500
- result.current(3);
501
- });
502
- expect(onUpdate).toHaveBeenCalledTimes(0);
503
- expect(onDeepUpdate).toHaveBeenCalledTimes(0);
504
- });
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 />', () => {
558
- const textPrefix = '>>';
559
- const onUpdate = jest.fn();
560
- const onPathChange = jest.fn();
561
- const onUndefinedEntity = jest.fn();
562
- const onSetPath = jest.fn(() => {
563
- return PATH_1;
564
- });
565
- render(_jsx("div", { children: _jsx(Parent, { onSetPath: onSetPath, children: _jsx(Child, { textPrefix: textPrefix, onUpdate: onUpdate, onPathChange: onPathChange, onUndefinedEntity: onUndefinedEntity }) }) }));
566
- fireEvent.click(screen.getByText(PARENT_BUTTON_TEXT));
567
- expect(onSetPath).toHaveBeenCalledTimes(1);
568
- expect(onUpdate).toHaveBeenCalledTimes(1);
569
- expect(onPathChange).toHaveBeenCalledWith(PATH_1);
570
- fireEvent.click(screen.getByText(textPrefix + CHILD_BUTTON_TEXT));
571
- expect(onSetPath).toHaveBeenCalledTimes(1);
572
- expect(onUpdate).toHaveBeenCalledTimes(2);
573
- expect(onPathChange).toHaveBeenCalledWith('');
574
- expect(onUndefinedEntity).toHaveBeenCalledTimes(0);
575
- });
576
- test('`options.onChange` event should be trigger at child elements', () => {
577
- const onFirstChange = jest.fn();
578
- const onSecondChange = jest.fn();
579
- const onParentPathChange = jest.fn();
580
- const firstButtonText = 'first button';
581
- const secondButtonText = 'second button';
582
- let onChange = onFirstChange;
583
- const A = () => {
584
- useUseCase(fileUseCase, { onChange });
585
- return _jsx(Fragment, {});
586
- };
587
- const B = () => {
588
- const [, { setPath }, Provider] = useUseCase(defaultFile, fileUseCase, {
589
- onChange: onParentPathChange,
590
- });
591
- const onFirstClick = () => {
592
- setPath(PATH_1);
593
- onChange = onSecondChange;
594
- };
595
- const onSecondClick = () => {
596
- setPath('');
597
- };
598
- return (_jsxs(Provider, { children: [_jsx(A, {}), _jsx("button", { onClick: onFirstClick, children: firstButtonText }), _jsx("button", { onClick: onSecondClick, children: secondButtonText })] }));
599
- };
600
- render(_jsx(B, {}));
601
- expect(onFirstChange).toHaveBeenCalledTimes(0);
602
- fireEvent.click(screen.getByText(firstButtonText));
603
- expect(onFirstChange).toHaveBeenCalledTimes(1);
604
- expect(onFirstChange).toHaveBeenLastCalledWith({ ...defaultFile, ext: EXT_1, path: PATH_1 }, defaultFile);
605
- expect(onParentPathChange).toHaveBeenCalledTimes(1);
606
- expect(onSecondChange).toHaveBeenCalledTimes(0);
607
- fireEvent.click(screen.getByText(secondButtonText));
608
- expect(onSecondChange).toHaveBeenCalledTimes(1);
609
- expect(onSecondChange).toHaveBeenLastCalledWith(defaultFile, {
610
- ...defaultFile,
611
- ext: EXT_1,
612
- path: PATH_1,
613
- });
614
- expect(onFirstChange).toHaveBeenCalledTimes(1);
615
- expect(onParentPathChange).toHaveBeenCalledTimes(2);
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
- });
650
562
  test('`options.watch` should be trigger at child elements', () => {
651
563
  const onFirstExtChange = jest.fn();
652
564
  const onSecondExtChange = jest.fn();
@@ -1149,4 +1061,373 @@ describe('useUseCase', () => {
1149
1061
  });
1150
1062
  });
1151
1063
  });
1064
+ describe('`useUseCase` should work with 1+ arguments on non-entity mode', () => {
1065
+ test('`entity` should equal `defaultFile`', () => {
1066
+ const { result } = renderHook(() => {
1067
+ return useUseCase(mathUseCase);
1068
+ });
1069
+ const { current: reducers } = result;
1070
+ expect(Array.isArray(reducers)).toBe(false);
1071
+ });
1072
+ test('returned reducer should work', () => {
1073
+ const { result } = renderHook(() => {
1074
+ return useUseCase(mathUseCase);
1075
+ });
1076
+ const { current: reducers } = result;
1077
+ const { add } = reducers;
1078
+ expect(add(1, 2)).toBe(3);
1079
+ });
1080
+ test('reducer call should not be cached if component is at rendering phase', () => {
1081
+ const buttonText = 'button';
1082
+ const CacheTestComponent = () => {
1083
+ const { subtraction } = useUseCase(mathUseCase);
1084
+ const update = useUpdate();
1085
+ const onClick = () => {
1086
+ update();
1087
+ };
1088
+ subtraction(5, 3);
1089
+ return _jsx("button", { onClick: onClick, children: buttonText });
1090
+ };
1091
+ render(_jsx(CacheTestComponent, {}));
1092
+ expect(subtractionReducer).toHaveBeenCalledTimes(1);
1093
+ expect(subtractionReducer).toHaveBeenCalledWith(5, 3);
1094
+ expect(subtractionReducer).toHaveReturnedWith(2);
1095
+ fireEvent.click(screen.getByText(buttonText));
1096
+ expect(subtractionReducer).toHaveBeenCalledTimes(2);
1097
+ fireEvent.click(screen.getByText(buttonText));
1098
+ expect(subtractionReducer).toHaveBeenCalledTimes(3);
1099
+ });
1100
+ test('reducer call should not be cached if component is not at rendering phase', () => {
1101
+ const buttonText = 'button';
1102
+ const CacheTestComponent = () => {
1103
+ const { subtraction } = useUseCase(mathUseCase);
1104
+ const onClick = () => {
1105
+ subtraction(5, 3);
1106
+ };
1107
+ useMount(() => {
1108
+ subtraction(5, 3);
1109
+ subtraction(5, 3);
1110
+ });
1111
+ return _jsx("button", { onClick: onClick, children: buttonText });
1112
+ };
1113
+ render(_jsx(CacheTestComponent, {}));
1114
+ expect(subtractionReducer).toHaveBeenCalledTimes(2);
1115
+ expect(subtractionReducer).toHaveBeenNthCalledWith(1, 5, 3);
1116
+ expect(subtractionReducer).toHaveNthReturnedWith(1, 2);
1117
+ expect(subtractionReducer).toHaveBeenNthCalledWith(2, 5, 3);
1118
+ expect(subtractionReducer).toHaveNthReturnedWith(2, 2);
1119
+ fireEvent.click(screen.getByText(buttonText));
1120
+ expect(subtractionReducer).toHaveBeenCalledTimes(3);
1121
+ expect(subtractionReducer).toHaveBeenNthCalledWith(3, 5, 3);
1122
+ expect(subtractionReducer).toHaveNthReturnedWith(3, 2);
1123
+ });
1124
+ test('reducer call should not be cached if parameters have changed', () => {
1125
+ let count = 0;
1126
+ const buttonText = 'button';
1127
+ const StringUseCaseTestComponent = () => {
1128
+ const { subtraction } = useUseCase(mathUseCase);
1129
+ const update = useUpdate();
1130
+ subtraction(5, count++);
1131
+ const onUpdate = () => {
1132
+ update();
1133
+ };
1134
+ return (_jsx("div", { children: _jsx("button", { onClick: onUpdate, children: buttonText }) }));
1135
+ };
1136
+ render(_jsx(StringUseCaseTestComponent, {}));
1137
+ expect(subtractionReducer).toHaveBeenCalledTimes(1);
1138
+ expect(subtractionReducer).toHaveBeenCalledWith(5, 0);
1139
+ fireEvent.click(screen.getByText(buttonText));
1140
+ expect(subtractionReducer).toHaveBeenCalledTimes(2);
1141
+ expect(subtractionReducer).toHaveBeenCalledWith(5, 1);
1142
+ expect(subtractionReducer).toHaveReturnedWith(4);
1143
+ });
1144
+ test('`options.extraValue` should be added after call `add` method', () => {
1145
+ const { result } = renderHook(() => {
1146
+ return useUseCase(mathUseCase, { extraValue: 5 });
1147
+ });
1148
+ const { current: reducers } = result;
1149
+ const { add } = reducers;
1150
+ expect(add(1, 2)).toBe(8);
1151
+ });
1152
+ test('when `options` has changed, it should not trigger update', () => {
1153
+ const onUpdate = jest.fn();
1154
+ const onDeepUpdate = jest.fn();
1155
+ const { result } = renderHook(() => {
1156
+ const [extraValue, setExtraValue] = useState(0);
1157
+ const reducers = useUseCase(mathUseCase, { extraValue });
1158
+ useUpdateEffect(() => {
1159
+ onUpdate();
1160
+ }, [reducers]);
1161
+ useDeepCompareUpdate(() => {
1162
+ onDeepUpdate();
1163
+ }, [reducers]);
1164
+ return setExtraValue;
1165
+ });
1166
+ expect(onUpdate).toHaveBeenCalledTimes(0);
1167
+ expect(onDeepUpdate).toHaveBeenCalledTimes(0);
1168
+ act(() => {
1169
+ result.current(3);
1170
+ });
1171
+ expect(onUpdate).toHaveBeenCalledTimes(0);
1172
+ expect(onDeepUpdate).toHaveBeenCalledTimes(0);
1173
+ });
1174
+ test('when `deps` change, it should update reducers', () => {
1175
+ const onUpdate = jest.fn();
1176
+ const onDeepUpdate = jest.fn();
1177
+ const { result } = renderHook(() => {
1178
+ const [extraValue, setExtraValue] = useState(0);
1179
+ const reducers = useUseCase(mathUseCase, { extraValue }, [extraValue]);
1180
+ useUpdateEffect(() => {
1181
+ onUpdate();
1182
+ }, [reducers]);
1183
+ useDeepCompareUpdate(() => {
1184
+ onDeepUpdate();
1185
+ }, [reducers]);
1186
+ return setExtraValue;
1187
+ });
1188
+ expect(onUpdate).toHaveBeenCalledTimes(0);
1189
+ expect(onDeepUpdate).toHaveBeenCalledTimes(0);
1190
+ act(() => {
1191
+ result.current(3);
1192
+ });
1193
+ expect(onUpdate).toHaveBeenCalledTimes(1);
1194
+ expect(onDeepUpdate).toHaveBeenCalledTimes(1);
1195
+ });
1196
+ test('empty `deps` should not update reducers', () => {
1197
+ const onUpdate = jest.fn();
1198
+ const onDeepUpdate = jest.fn();
1199
+ const { result } = renderHook(() => {
1200
+ const [extraValue, setExtraValue] = useState(0);
1201
+ const reducers = useUseCase(mathUseCase, { extraValue }, []);
1202
+ useUpdateEffect(() => {
1203
+ onUpdate();
1204
+ }, [reducers]);
1205
+ useDeepCompareUpdate(() => {
1206
+ onDeepUpdate();
1207
+ }, [reducers]);
1208
+ return setExtraValue;
1209
+ });
1210
+ expect(onUpdate).toHaveBeenCalledTimes(0);
1211
+ expect(onDeepUpdate).toHaveBeenCalledTimes(0);
1212
+ act(() => {
1213
+ result.current(3);
1214
+ });
1215
+ expect(onUpdate).toHaveBeenCalledTimes(0);
1216
+ expect(onDeepUpdate).toHaveBeenCalledTimes(0);
1217
+ });
1218
+ test('should not trigger update', () => {
1219
+ const onUpdate = jest.fn();
1220
+ render(_jsx(MathParent, { onUpdate: onUpdate }));
1221
+ fireEvent.click(screen.getByText(PARENT_BUTTON_TEXT));
1222
+ expect(onUpdate).toHaveBeenCalledTimes(0);
1223
+ });
1224
+ });
1225
+ describe('`useUseCase` should work with 1+ arguments on context mode', () => {
1226
+ test('should work within <Child /> which it is under <Parent />', () => {
1227
+ const textPrefix = '>>';
1228
+ const onUpdate = jest.fn();
1229
+ const onPathChange = jest.fn();
1230
+ const onUndefinedEntity = jest.fn();
1231
+ const onSetPath = jest.fn(() => {
1232
+ return PATH_1;
1233
+ });
1234
+ render(_jsx("div", { children: _jsx(Parent, { onSetPath: onSetPath, children: _jsx(Child, { textPrefix: textPrefix, onUpdate: onUpdate, onPathChange: onPathChange, onUndefinedEntity: onUndefinedEntity }) }) }));
1235
+ fireEvent.click(screen.getByText(PARENT_BUTTON_TEXT));
1236
+ expect(onSetPath).toHaveBeenCalledTimes(1);
1237
+ expect(onUpdate).toHaveBeenCalledTimes(1);
1238
+ expect(onPathChange).toHaveBeenCalledWith(PATH_1);
1239
+ fireEvent.click(screen.getByText(textPrefix + CHILD_BUTTON_TEXT));
1240
+ expect(onSetPath).toHaveBeenCalledTimes(1);
1241
+ expect(onUpdate).toHaveBeenCalledTimes(2);
1242
+ expect(onPathChange).toHaveBeenCalledWith('');
1243
+ expect(onUndefinedEntity).toHaveBeenCalledTimes(0);
1244
+ });
1245
+ test('reducer call should be cached if component is at rendering phase in child components', () => {
1246
+ const buttonText = 'button';
1247
+ const addReducer = jest.fn((entity, substring) => {
1248
+ return entity + substring;
1249
+ });
1250
+ const stringUseCase = () => {
1251
+ const entityReducers = entityUseCase();
1252
+ return {
1253
+ ...entityReducers,
1254
+ add: addReducer,
1255
+ };
1256
+ };
1257
+ const A = () => {
1258
+ const [, { add }] = useUseCase(stringUseCase);
1259
+ const update = useUpdate();
1260
+ const onClick = () => {
1261
+ update();
1262
+ };
1263
+ add('x');
1264
+ return _jsx("button", { onClick: onClick, children: buttonText });
1265
+ };
1266
+ const B = () => {
1267
+ const [, , Provider] = useUseCase('', stringUseCase);
1268
+ return (_jsx(Provider, { children: _jsx(A, {}) }));
1269
+ };
1270
+ render(_jsx(B, {}));
1271
+ expect(addReducer).toHaveBeenCalledTimes(1);
1272
+ expect(addReducer).toHaveBeenCalledWith('', 'x');
1273
+ expect(addReducer).toHaveReturnedWith('x');
1274
+ fireEvent.click(screen.getByText(buttonText));
1275
+ expect(addReducer).toHaveBeenCalledTimes(1);
1276
+ });
1277
+ test('reducer call should not be cached if component is not at rendering phase in child components', () => {
1278
+ const buttonText = 'button';
1279
+ const addReducer = jest.fn((entity, substring) => {
1280
+ return entity + substring;
1281
+ });
1282
+ const stringUseCase = () => {
1283
+ const entityReducers = entityUseCase();
1284
+ return {
1285
+ ...entityReducers,
1286
+ add: addReducer,
1287
+ };
1288
+ };
1289
+ const A = () => {
1290
+ const [, { add }] = useUseCase(stringUseCase);
1291
+ const onClick = () => {
1292
+ add('x');
1293
+ };
1294
+ useMount(() => {
1295
+ add('x');
1296
+ add('x');
1297
+ });
1298
+ return _jsx("button", { onClick: onClick, children: buttonText });
1299
+ };
1300
+ const B = () => {
1301
+ const [, , Provider] = useUseCase('', stringUseCase);
1302
+ return (_jsx(Provider, { children: _jsx(A, {}) }));
1303
+ };
1304
+ render(_jsx(B, {}));
1305
+ expect(addReducer).toHaveBeenCalledTimes(2);
1306
+ expect(addReducer).toHaveBeenNthCalledWith(1, '', 'x');
1307
+ expect(addReducer).toHaveBeenNthCalledWith(2, '', 'x');
1308
+ fireEvent.click(screen.getByText(buttonText));
1309
+ expect(addReducer).toHaveBeenCalledTimes(3);
1310
+ expect(addReducer).toHaveBeenNthCalledWith(3, '', 'x');
1311
+ });
1312
+ test('reducer call should not be cached if entity or parameters have changed in child components', () => {
1313
+ let count = 0;
1314
+ let addedText = 'x';
1315
+ const setButtonText = 'button';
1316
+ const updateButtonText = 'update';
1317
+ const addReducer = jest.fn((entity, substring) => {
1318
+ return entity + substring;
1319
+ });
1320
+ const stringUseCase = () => {
1321
+ const entityReducers = entityUseCase();
1322
+ return {
1323
+ ...entityReducers,
1324
+ add: addReducer,
1325
+ };
1326
+ };
1327
+ const A = () => {
1328
+ const [, { add, setEntity }] = useUseCase(stringUseCase);
1329
+ const update = useUpdate();
1330
+ add(addedText);
1331
+ const onSet = () => {
1332
+ setEntity(`${count++}`);
1333
+ };
1334
+ const onUpdate = () => {
1335
+ update();
1336
+ };
1337
+ return (_jsxs("div", { children: [_jsx("button", { onClick: onSet, children: setButtonText }), _jsx("button", { onClick: onUpdate, children: updateButtonText })] }));
1338
+ };
1339
+ const B = () => {
1340
+ const [, , Provider] = useUseCase('', stringUseCase);
1341
+ return (_jsx(Provider, { children: _jsx(A, {}) }));
1342
+ };
1343
+ render(_jsx(B, {}));
1344
+ expect(addReducer).toHaveBeenCalledTimes(1);
1345
+ expect(addReducer).toHaveBeenCalledWith('', 'x');
1346
+ fireEvent.click(screen.getByText(setButtonText));
1347
+ expect(addReducer).toHaveBeenCalledTimes(2);
1348
+ expect(addReducer).toHaveBeenCalledWith('0', 'x');
1349
+ expect(addReducer).toHaveReturnedWith('0x');
1350
+ addedText = 'y';
1351
+ fireEvent.click(screen.getByText(updateButtonText));
1352
+ expect(addReducer).toHaveBeenCalledTimes(3);
1353
+ expect(addReducer).toHaveBeenCalledWith('0', 'y');
1354
+ expect(addReducer).toHaveReturnedWith('0y');
1355
+ fireEvent.click(screen.getByText(updateButtonText));
1356
+ expect(addReducer).toHaveBeenCalledTimes(3);
1357
+ });
1358
+ test('`options.onChange` event should be trigger at child elements', () => {
1359
+ const onFirstChange = jest.fn();
1360
+ const onSecondChange = jest.fn();
1361
+ const onParentPathChange = jest.fn();
1362
+ const firstButtonText = 'first button';
1363
+ const secondButtonText = 'second button';
1364
+ let onChange = onFirstChange;
1365
+ const A = () => {
1366
+ useUseCase(fileUseCase, { onChange });
1367
+ return _jsx(Fragment, {});
1368
+ };
1369
+ const B = () => {
1370
+ const [, { setPath }, Provider] = useUseCase(defaultFile, fileUseCase, {
1371
+ onChange: onParentPathChange,
1372
+ });
1373
+ const onFirstClick = () => {
1374
+ setPath(PATH_1);
1375
+ onChange = onSecondChange;
1376
+ };
1377
+ const onSecondClick = () => {
1378
+ setPath('');
1379
+ };
1380
+ return (_jsxs(Provider, { children: [_jsx(A, {}), _jsx("button", { onClick: onFirstClick, children: firstButtonText }), _jsx("button", { onClick: onSecondClick, children: secondButtonText })] }));
1381
+ };
1382
+ render(_jsx(B, {}));
1383
+ expect(onFirstChange).toHaveBeenCalledTimes(0);
1384
+ fireEvent.click(screen.getByText(firstButtonText));
1385
+ expect(onFirstChange).toHaveBeenCalledTimes(1);
1386
+ expect(onFirstChange).toHaveBeenLastCalledWith({ ...defaultFile, ext: EXT_1, path: PATH_1 }, defaultFile);
1387
+ expect(onParentPathChange).toHaveBeenCalledTimes(1);
1388
+ expect(onSecondChange).toHaveBeenCalledTimes(0);
1389
+ fireEvent.click(screen.getByText(secondButtonText));
1390
+ expect(onSecondChange).toHaveBeenCalledTimes(1);
1391
+ expect(onSecondChange).toHaveBeenLastCalledWith(defaultFile, {
1392
+ ...defaultFile,
1393
+ ext: EXT_1,
1394
+ path: PATH_1,
1395
+ });
1396
+ expect(onFirstChange).toHaveBeenCalledTimes(1);
1397
+ expect(onParentPathChange).toHaveBeenCalledTimes(2);
1398
+ });
1399
+ test('`options.onChange` event should be trigger in orders', () => {
1400
+ let changeTimes = 0;
1401
+ const updateChangeTimes = () => {
1402
+ return ++changeTimes;
1403
+ };
1404
+ const onChangeA = jest.fn(updateChangeTimes);
1405
+ const onChangeB = jest.fn(updateChangeTimes);
1406
+ const onChangeC = jest.fn(updateChangeTimes);
1407
+ const buttonText = 'my button';
1408
+ const A = ({ children }) => {
1409
+ useUseCase(fileUseCase, { onChange: onChangeA });
1410
+ return _jsx(Fragment, { children: children });
1411
+ };
1412
+ const B = () => {
1413
+ useUseCase(fileUseCase, { onChange: onChangeB });
1414
+ return _jsx(Fragment, {});
1415
+ };
1416
+ const C = () => {
1417
+ const [, { setPath }, Provider] = useUseCase(defaultFile, fileUseCase, {
1418
+ onChange: onChangeC,
1419
+ });
1420
+ const onFirstClick = () => {
1421
+ setPath(PATH_1);
1422
+ };
1423
+ return (_jsxs(Provider, { children: [_jsx(A, { children: _jsx(B, {}) }), _jsx("button", { onClick: onFirstClick, children: buttonText })] }));
1424
+ };
1425
+ render(_jsx(C, {}));
1426
+ expect(changeTimes).toBe(0);
1427
+ fireEvent.click(screen.getByText(buttonText));
1428
+ expect(onChangeA).toHaveReturnedWith(2);
1429
+ expect(onChangeB).toHaveReturnedWith(1);
1430
+ expect(onChangeC).toHaveReturnedWith(3);
1431
+ });
1432
+ });
1152
1433
  });