@applicaster/zapp-react-native-utils 13.0.0-rc.12 → 13.0.0-rc.121

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/README.md +0 -10
  2. package/actionsExecutor/ActionExecutor.ts +16 -9
  3. package/actionsExecutor/ActionExecutorContext.tsx +196 -11
  4. package/actionsExecutor/consts.ts +4 -0
  5. package/alertUtils/alert.ts +148 -0
  6. package/alertUtils/index.ts +1 -148
  7. package/analyticsUtils/AnalyticPlayerListener.ts +18 -1
  8. package/analyticsUtils/__tests__/__snapshots__/analyticsManagerNoModule.test.js.snap +9 -9
  9. package/analyticsUtils/currentScreenProperities.ts +6 -4
  10. package/analyticsUtils/helpers/hooks.ts +1 -1
  11. package/appUtils/HooksManager/{Hook.js → Hook.ts} +39 -23
  12. package/appUtils/HooksManager/__tests__/__snapshots__/hook.test.js.snap +10 -8
  13. package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +693 -0
  14. package/appUtils/HooksManager/__tests__/hook.test.js +196 -184
  15. package/appUtils/HooksManager/__tests__/hooksManager.test.js +96 -99
  16. package/appUtils/HooksManager/{constants.js → constants.ts} +1 -1
  17. package/appUtils/HooksManager/{index.js → index.ts} +124 -113
  18. package/appUtils/HooksManager/types.ts +119 -0
  19. package/appUtils/RiverFocusManager/index.js +17 -12
  20. package/appUtils/__tests__/__snapshots__/localizationsHelper.test.ts.snap +151 -0
  21. package/appUtils/__tests__/allZappLocales.ts +79 -0
  22. package/appUtils/__tests__/{localizationsHelper.test.js → localizationsHelper.test.ts} +11 -0
  23. package/appUtils/accessibilityManager/index.ts +42 -1
  24. package/appUtils/contextKeysManager/contextResolver.ts +66 -0
  25. package/appUtils/contextKeysManager/index.ts +2 -2
  26. package/appUtils/contextKeysManager/utils/index.ts +2 -1
  27. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +9 -6
  28. package/appUtils/focusManager/index.ios.ts +14 -4
  29. package/appUtils/focusManager/index.ts +108 -69
  30. package/appUtils/focusManager/treeDataStructure/Tree/index.js +25 -3
  31. package/appUtils/focusManager/treeDataStructure/Utils/index.js +1 -3
  32. package/appUtils/focusManager/utils/__tests__/findChild.test.ts +35 -0
  33. package/appUtils/focusManager/utils/enums.ts +4 -0
  34. package/appUtils/focusManager/utils/index.ts +5 -0
  35. package/appUtils/focusManagerAux/utils/index.ts +4 -3
  36. package/appUtils/{index.js → index.ts} +1 -1
  37. package/appUtils/keyCodes/__tests__/__snapshots__/keyCodes.test.js.snap +2 -2
  38. package/appUtils/keyCodes/__tests__/keyCodes.test.js +4 -4
  39. package/appUtils/keyCodes/{index.js → index.ts} +13 -7
  40. package/appUtils/keyCodes/keys/index.ts +3 -0
  41. package/appUtils/keyCodes/{keys.android.js → keys/keyEventMapper.ts} +0 -19
  42. package/appUtils/keyCodes/keys/keys.android.ts +18 -0
  43. package/appUtils/keyCodes/keys/keys.ios.ts +25 -0
  44. package/appUtils/keyCodes/keys/keys.ts +15 -0
  45. package/appUtils/keyCodes/{keysByPlatform.js → keys/keysByPlatform.ts} +4 -0
  46. package/appUtils/keyCodes/keysByPlatform.ts +8 -0
  47. package/appUtils/keyInputHandler/KeyInputHandler.ts +68 -0
  48. package/appUtils/{localizationsHelper.js → localizationsHelper.ts} +31 -0
  49. package/appUtils/orientationHelper.ts +11 -13
  50. package/appUtils/platform/const.ts +14 -0
  51. package/appUtils/platform/platformUtils.ts +47 -18
  52. package/appUtils/playerManager/index.ts +1 -1
  53. package/appUtils/playerManager/player.ts +42 -18
  54. package/appUtils/playerManager/playerHooks/usePlayerCurrentTime.tsx +11 -7
  55. package/appUtils/playerManager/playerNative.ts +18 -2
  56. package/appUtils/playerManager/usePlayerControllerSetup.tsx +3 -3
  57. package/appUtils/playerManager/usePlayerTitleSummaryOverlay.tsx +7 -1
  58. package/arrayUtils/__tests__/__snapshots__/arrayUtils.test.ts.snap +4 -4
  59. package/cellUtils/index.ts +9 -5
  60. package/componentsUtils/__tests__/isFirstComponentGallery.test.ts +33 -0
  61. package/componentsUtils/__tests__/isFirstComponentScreenPicker.test.ts +33 -0
  62. package/componentsUtils/__tests__/isGallery.test.ts +33 -0
  63. package/componentsUtils/__tests__/isScreenPicker.test.ts +33 -0
  64. package/componentsUtils/index.ts +39 -0
  65. package/dateUtils/index.ts +19 -0
  66. package/domUtils/{cookieManager.js → cookieManager.ts} +1 -2
  67. package/equalUtils/__tests__/isEqual/combination.test.ts +263 -0
  68. package/equalUtils/index.ts +49 -30
  69. package/focusManager/FocusManager.ts +14 -2
  70. package/focusManager/index.ts +23 -4
  71. package/functionUtils/__tests__/__snapshots__/functionUtils.test.js.snap +4 -4
  72. package/functionUtils/index.ts +61 -19
  73. package/idleUtils/__tests__/withTimeout$.test.ts +37 -0
  74. package/idleUtils/index.ts +1 -1
  75. package/idleUtils/withTimeout.ts +15 -2
  76. package/index.d.ts +0 -12
  77. package/localizationUtils/index.ts +8 -13
  78. package/logger/const.ts +9 -67
  79. package/manifestUtils/__tests__/createConfig.test.js +16 -16
  80. package/manifestUtils/defaultManifestConfigurations/generalContent.js +13 -0
  81. package/manifestUtils/defaultManifestConfigurations/player.js +9 -3
  82. package/manifestUtils/fonts/index.js +5 -6
  83. package/manifestUtils/keys.js +27 -2
  84. package/manifestUtils/sharedConfiguration/screenPicker/__tests__/utils.test.js +304 -0
  85. package/manifestUtils/sharedConfiguration/screenPicker/stylesFields.js +875 -0
  86. package/manifestUtils/sharedConfiguration/screenPicker/utils.js +130 -0
  87. package/modalState/__tests__/index.test.ts +51 -0
  88. package/modalState/index.ts +33 -7
  89. package/navigationUtils/__tests__/__snapshots__/navigationUtils.test.js.snap +7 -6
  90. package/navigationUtils/__tests__/itemTypes.test.js +2 -2
  91. package/navigationUtils/__tests__/navigationUtils.test.js +2 -2
  92. package/navigationUtils/index.ts +20 -9
  93. package/numberUtils/__tests__/toPositiveNumberWithDefault.test.ts +23 -3
  94. package/numberUtils/index.ts +11 -5
  95. package/package.json +5 -10
  96. package/playerUtils/configurationGenerator.ts +9 -11
  97. package/reactHooks/advertising/index.ts +5 -5
  98. package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
  99. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +6 -8
  100. package/reactHooks/autoscrolling/useTrackedView.ts +12 -1
  101. package/reactHooks/cell-click/__tests__/index.test.js +10 -2
  102. package/reactHooks/cell-click/index.ts +7 -1
  103. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +4 -4
  104. package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +10 -11
  105. package/reactHooks/feed/useBatchLoading.ts +10 -12
  106. package/reactHooks/feed/useFeedLoader.tsx +18 -9
  107. package/reactHooks/feed/usePipesCacheReset.ts +5 -5
  108. package/reactHooks/flatList/__tests__/index.test.tsx +30 -21
  109. package/reactHooks/hookModal/hooks/useHookModalScreenData.ts +39 -0
  110. package/reactHooks/layout/__tests__/index.test.tsx +10 -10
  111. package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.native.test.js +14 -28
  112. package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.test.js +1 -1
  113. package/reactHooks/layout/useDimensions/useDimensions.ts +8 -0
  114. package/reactHooks/navigation/__mocks__/useNavigation.ts +3 -0
  115. package/reactHooks/navigation/__tests__/index.test.tsx +6 -21
  116. package/reactHooks/navigation/getTabBarHeight.ts +10 -0
  117. package/reactHooks/navigation/index.ts +41 -240
  118. package/reactHooks/navigation/useGetBottomTabBarHeight.ts +19 -0
  119. package/reactHooks/navigation/useGetNavBarTopBorderWidth.ts +14 -0
  120. package/reactHooks/navigation/useIsScreenActive.ts +17 -0
  121. package/reactHooks/navigation/useNavigationPluginData.ts +19 -0
  122. package/reactHooks/navigation/useNavigationType.ts +17 -0
  123. package/reactHooks/navigation/usePathname.ts +4 -0
  124. package/reactHooks/navigation/useProfilerLogging.ts +15 -0
  125. package/reactHooks/navigation/useRoute.ts +98 -0
  126. package/reactHooks/navigation/useUniqueRouteSuffix.ts +41 -0
  127. package/reactHooks/player/TVSeekControlller/ISeekController.ts +32 -0
  128. package/reactHooks/player/TVSeekControlller/LongPressSeekController.ts +71 -0
  129. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +258 -0
  130. package/reactHooks/player/TVSeekControlller/TapSeekController.ts +53 -0
  131. package/reactHooks/player/__tests__/{useAutoSeek.test.tsx → useAutoSeek._test.tsx} +2 -3
  132. package/reactHooks/player/const.ts +0 -4
  133. package/reactHooks/player/index.ts +0 -6
  134. package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +69 -0
  135. package/reactHooks/screen/useScreenBackgroundColor.ts +3 -15
  136. package/reactHooks/state/useRefWithInitialValue.ts +14 -0
  137. package/reactHooks/state/useStateFromSubscribe.ts +23 -0
  138. package/reactHooks/useListenEventBusEvent.ts +1 -1
  139. package/reactHooks/usePluginConfiguration.ts +1 -1
  140. package/reactHooks/useSubscriberFor.ts +4 -3
  141. package/reactUtils/__tests__/__snapshots__/reactUtilsHelpers.test.js.snap +16 -4
  142. package/reactUtils/__tests__/reactUtils.test.js +1 -37
  143. package/reactUtils/__tests__/reactUtilsHelpers.test.js +72 -71
  144. package/reactUtils/createContext/__tests__/__snapshots__/helpers.test.js.snap +13 -79
  145. package/reactUtils/createContext/__tests__/__snapshots__/{index.test.js.snap → index.test.ts.snap} +2 -2
  146. package/reactUtils/createContext/__tests__/__snapshots__/provider.test.js.snap +3 -28
  147. package/reactUtils/createContext/__tests__/__snapshots__/withConsumer.test.js.snap +3 -4
  148. package/reactUtils/createContext/__tests__/__snapshots__/withProvider.test.js.snap +7 -3
  149. package/reactUtils/createContext/__tests__/helpers.test.js +107 -121
  150. package/reactUtils/createContext/__tests__/{index.test.js → index.test.ts} +2 -2
  151. package/reactUtils/createContext/__tests__/provider.test.js +4 -6
  152. package/reactUtils/createContext/__tests__/withConsumer.test.js +12 -12
  153. package/reactUtils/createContext/__tests__/withProvider.test.js +4 -4
  154. package/reactUtils/createContext/helpers.ts +6 -1
  155. package/reactUtils/createContext/index.ts +11 -25
  156. package/reactUtils/index.ts +9 -25
  157. package/screenState/index.ts +24 -10
  158. package/services/js2native.ts +673 -0
  159. package/testUtils/index.tsx +0 -10
  160. package/theme/__mocks__/index.ts +4 -0
  161. package/theme/index.ts +1 -1
  162. package/time/BackgroundTimer.ts +55 -0
  163. package/time/Timer.ts +9 -6
  164. package/types.ts +1 -0
  165. package/utils/README.md +30 -0
  166. package/utils/chunk.ts +5 -0
  167. package/utils/index.ts +5 -0
  168. package/utils/times.ts +5 -0
  169. package/zappFrameworkUtils/localStorageHelper.ts +6 -0
  170. package/zappFrameworkUtils/loginPluginUtils.ts +6 -2
  171. package/zappFrameworkUtils/presentPluginOneTime.ts +2 -3
  172. package/zappFrameworkUtils/types.ts +11 -0
  173. package/appUtils/keyCodes/keys.ios.js +0 -46
  174. package/reactHooks/player/useAutoSeek.tsx +0 -87
  175. package/reactHooks/player/useSeek.tsx +0 -66
  176. package/reactHooks/player/useTapSeek.tsx +0 -58
  177. package/reactUtils/createContext/__tests__/index-no-react.test.js +0 -27
  178. /package/appUtils/HooksManager/{logger.js → logger.ts} +0 -0
  179. /package/appUtils/{directionHelper.js → directionHelper.ts} +0 -0
  180. /package/appUtils/keyCodes/{androidTVKeys.js → androidTVKeys.ts} +0 -0
  181. /package/appUtils/keyCodes/{keys.web.js → keys/keys.web.ts} +0 -0
  182. /package/domUtils/{logger.js → logger.ts} +0 -0
  183. /package/reactHooks/player/__tests__/{useTapSeek.test.ts → useTapSeek._test.ts} +0 -0
@@ -62,9 +62,9 @@ describe("HooksManager", () => {
62
62
  const successHandler = jest.fn();
63
63
 
64
64
  it("invokes the success handler directly", () => {
65
- hooksManager
66
- .on(HOOKS_EVENTS.COMPLETE, successHandler)
67
- .handleHooks(payload);
65
+ hooksManager.subscriber.on(HOOKS_EVENTS.COMPLETE, successHandler);
66
+
67
+ hooksManager.handleHooks(payload);
68
68
 
69
69
  expect(successHandler).toHaveBeenCalledTimes(1);
70
70
 
@@ -103,11 +103,12 @@ describe("HooksManager", () => {
103
103
  const presentScreenHandler = jest.fn();
104
104
 
105
105
  it("executes the player hook", () => {
106
- hooksManager
106
+ hooksManager.subscriber
107
107
  .on(HOOKS_EVENTS.PRESENT_SCREEN_HOOK, presentScreenHandler)
108
108
  .on(HOOKS_EVENTS.SUCCESS, successHandler)
109
- .on(HOOKS_EVENTS.COMPLETE, completeHandler)
110
- .handleHooks(payload);
109
+ .on(HOOKS_EVENTS.COMPLETE, completeHandler);
110
+
111
+ hooksManager.handleHooks(payload);
111
112
 
112
113
  expect(headlessPlayerHook.module.run).toHaveBeenCalledWith(
113
114
  payload,
@@ -115,20 +116,14 @@ describe("HooksManager", () => {
115
116
  headlessPlayerHook.configuration
116
117
  );
117
118
 
118
- expect(successHandler).toHaveBeenCalledWith(
119
- { hookPlugin: expect.objectContaining(headlessPlayerHook), payload },
120
- expect.any(Function)
121
- );
119
+ expect(successHandler.mock.calls[0]).toMatchSnapshot();
122
120
 
123
- expect(completeHandler).toHaveBeenCalledWith(
124
- { hookPlugin: expect.objectContaining(headlessPlayerHook), payload },
125
- expect.any(Function)
126
- );
121
+ expect(completeHandler.mock.calls[0]).toMatchSnapshot();
127
122
  });
128
123
  });
129
124
 
130
125
  describe("when there are preload hooks", () => {
131
- describe("hook with screen", () => {
126
+ it("hook with screen: executes", () => {
132
127
  const hookScreenId = "6e15fcbf-9414-4ea8-b7db-a287593ab6bd";
133
128
  const pluginScreenId = "1bb8ad39-a42e-4096-a134-56aadbd35c83";
134
129
 
@@ -157,36 +152,29 @@ describe("HooksManager", () => {
157
152
  }
158
153
  );
159
154
 
160
- it("executes the hook", () => {
161
- hooksManager
162
- .on(HOOKS_EVENTS.PRESENT_SCREEN_HOOK, presentScreenHandler)
163
- .on(HOOKS_EVENTS.SUCCESS, successHandler)
164
- .on(HOOKS_EVENTS.COMPLETE, completeHandler)
165
- .handleHooks(payload);
155
+ hooksManager.subscriber
156
+ .on(HOOKS_EVENTS.PRESENT_SCREEN_HOOK, presentScreenHandler)
157
+ .on(HOOKS_EVENTS.SUCCESS, successHandler)
158
+ .on(HOOKS_EVENTS.COMPLETE, completeHandler);
166
159
 
167
- expect(presentScreenHandler).toHaveBeenCalledWith(
168
- {
169
- route: `/hooks/${pluginScreenId}`,
160
+ hooksManager.handleHooks(payload);
161
+
162
+ expect(presentScreenHandler).toHaveBeenCalledWith(
163
+ {
164
+ route: `/hooks/${pluginScreenId}`,
165
+ hookPlugin: expect.objectContaining(hookScreen),
166
+ payload: {
167
+ payload,
170
168
  hookPlugin: expect.objectContaining(hookScreen),
171
- payload: {
172
- payload,
173
- hookPlugin: expect.objectContaining(hookScreen),
174
- callback: expect.any(Function),
175
- },
169
+ callback: expect.any(Function),
176
170
  },
177
- expect.any(Function)
178
- );
179
-
180
- expect(successHandler).toHaveBeenCalledWith(
181
- { payload, hookPlugin: expect.objectContaining(hookScreen) },
182
- expect.any(Function)
183
- );
184
-
185
- expect(completeHandler).toHaveBeenCalledWith(
186
- { payload, hookPlugin: expect.objectContaining(hookScreen) },
187
- expect.any(Function)
188
- );
189
- });
171
+ },
172
+ expect.any(Function)
173
+ );
174
+
175
+ expect(successHandler.mock.calls[0]).toMatchSnapshot();
176
+
177
+ expect(completeHandler.mock.calls[0]).toMatchSnapshot();
190
178
  });
191
179
  });
192
180
 
@@ -226,11 +214,12 @@ describe("HooksManager", () => {
226
214
  });
227
215
 
228
216
  it("executes the hook", () => {
229
- hooksManager
217
+ hooksManager.subscriber
230
218
  .on(HOOKS_EVENTS.PRESENT_SCREEN_HOOK, presentScreenHandler)
231
219
  .on(HOOKS_EVENTS.SUCCESS, successHandler)
232
- .on(HOOKS_EVENTS.COMPLETE, completeHandler)
233
- .handleHooks(payload);
220
+ .on(HOOKS_EVENTS.COMPLETE, completeHandler);
221
+
222
+ hooksManager.handleHooks(payload);
234
223
 
235
224
  expect(presentScreenHandler).toHaveBeenCalledTimes(2);
236
225
 
@@ -341,12 +330,13 @@ describe("HooksManager", () => {
341
330
  );
342
331
 
343
332
  it("stops the flow", () => {
344
- hooksManager
333
+ hooksManager.subscriber
345
334
  .on(HOOKS_EVENTS.PRESENT_SCREEN_HOOK, presentScreenHandler)
346
335
  .on(HOOKS_EVENTS.CANCEL, cancelHandler)
347
336
  .on(HOOKS_EVENTS.SUCCESS, successHandler)
348
- .on(HOOKS_EVENTS.COMPLETE, completeHandler)
349
- .handleHooks(payload);
337
+ .on(HOOKS_EVENTS.COMPLETE, completeHandler);
338
+
339
+ hooksManager.handleHooks(payload);
350
340
 
351
341
  expect(cancelHandler).toHaveBeenCalledWith(
352
342
  { hookPlugin: expect.any(Object), payload },
@@ -370,25 +360,28 @@ describe("HooksManager", () => {
370
360
  const payload = { foo: "bar" };
371
361
 
372
362
  it("executes the hook", () => {
373
- hooksManager
363
+ hooksManager.subscriber
374
364
  .on(HOOKS_EVENTS.SUCCESS, successHandler)
375
- .on(HOOKS_EVENTS.COMPLETE, completeHandler)
376
- .handleHooks(payload);
365
+ .on(HOOKS_EVENTS.COMPLETE, completeHandler);
377
366
 
378
- expect(successHandler).toHaveBeenCalledWith(
379
- {
380
- payload: { ...payload, identifier: "hook_plugin" },
381
- hookPlugin: expect.objectContaining(hookPlugin),
382
- },
383
- expect.any(Function)
367
+ hooksManager.handleHooks(payload);
368
+
369
+ expect(successHandler.mock.calls[0][0].payload).toMatchObject({
370
+ ...payload,
371
+ identifier: "hook_plugin",
372
+ });
373
+
374
+ expect(successHandler.mock.calls[0][0].hookPlugin).toMatchObject(
375
+ hookPlugin
384
376
  );
385
377
 
386
- expect(completeHandler).toHaveBeenCalledWith(
387
- {
388
- payload: { ...payload, identifier: "hook_plugin" },
389
- hookPlugin: expect.objectContaining(hookPlugin),
390
- },
391
- expect.any(Function)
378
+ expect(completeHandler.mock.calls[0][0].payload).toMatchObject({
379
+ ...payload,
380
+ identifier: "hook_plugin",
381
+ });
382
+
383
+ expect(completeHandler.mock.calls[0][0].hookPlugin).toMatchObject(
384
+ hookPlugin
392
385
  );
393
386
  });
394
387
  });
@@ -410,11 +403,12 @@ describe("HooksManager", () => {
410
403
  const hooksManager = HooksManager({ rivers, targetScreen, plugins });
411
404
 
412
405
  it("invokes the error handler but not the success handler", () => {
413
- hooksManager
406
+ hooksManager.subscriber
414
407
  .on(HOOKS_EVENTS.SUCCESS, successHandler)
415
408
  .on(HOOKS_EVENTS.COMPLETE, completeHandler)
416
- .on(HOOKS_EVENTS.ERROR, errorHandler)
417
- .handleHooks(payload);
409
+ .on(HOOKS_EVENTS.ERROR, errorHandler);
410
+
411
+ hooksManager.handleHooks(payload);
418
412
 
419
413
  expect(successHandler).not.toHaveBeenCalled();
420
414
 
@@ -447,12 +441,13 @@ describe("HooksManager", () => {
447
441
  const hooksManager = HooksManager({ rivers, targetScreen, plugins });
448
442
 
449
443
  it("invokes the error handler, and stops the flow", () => {
450
- hooksManager
444
+ hooksManager.subscriber
451
445
  .on(HOOKS_EVENTS.SUCCESS, successHandler)
452
446
  .on(HOOKS_EVENTS.COMPLETE, completeHandler)
453
447
  .on(HOOKS_EVENTS.ERROR, errorHandler)
454
- .on(HOOKS_EVENTS.CANCEL, cancelHandler)
455
- .handleHooks(payload);
448
+ .on(HOOKS_EVENTS.CANCEL, cancelHandler);
449
+
450
+ hooksManager.handleHooks(payload);
456
451
 
457
452
  expect(errorHandler).toHaveBeenCalledWith(
458
453
  {
@@ -507,48 +502,50 @@ describe("HooksManager", () => {
507
502
  const hooksManager = HooksManager({ rivers, targetScreen, plugins });
508
503
 
509
504
  it("executes the hook", () => {
510
- hooksManager
505
+ hooksManager.subscriber
511
506
  .on(HOOKS_EVENTS.COMPLETE, completeHandler)
512
- .on(HOOKS_EVENTS.SUCCESS, successHandler)
513
- .handleHooks(payload);
507
+ .on(HOOKS_EVENTS.SUCCESS, successHandler);
508
+
509
+ hooksManager.handleHooks(payload);
514
510
 
515
511
  expect(successHandler).toHaveBeenCalledTimes(3);
516
512
 
517
- expect(successHandler).toHaveBeenNthCalledWith(
518
- 1,
519
- {
520
- payload: { ...payload, identifier: "hook_plugin" },
521
- hookPlugin: expect.objectContaining(hookPlugin),
522
- },
523
- expect.any(Function)
513
+ expect(successHandler.mock.calls[0][0].payload).toMatchObject({
514
+ ...payload,
515
+ identifier: "hook_plugin",
516
+ });
517
+
518
+ expect(successHandler.mock.calls[0][0].hookPlugin).toMatchObject(
519
+ hookPlugin
524
520
  );
525
521
 
526
- expect(successHandler).toHaveBeenNthCalledWith(
527
- 2,
528
- {
529
- payload: { ...payload, identifier: "hook_plugin_2" },
530
- hookPlugin: expect.objectContaining(hookPlugin2),
531
- },
532
- expect.any(Function)
522
+ expect(successHandler.mock.calls[1][0].payload).toMatchObject({
523
+ ...payload,
524
+ identifier: "hook_plugin_2",
525
+ });
526
+
527
+ expect(successHandler.mock.calls[1][0].hookPlugin).toMatchObject(
528
+ hookPlugin2
533
529
  );
534
530
 
535
- expect(successHandler).toHaveBeenNthCalledWith(
536
- 3,
537
- {
538
- payload: { ...payload, identifier: "hook_plugin_3" },
539
- hookPlugin: expect.objectContaining(hookPlugin3),
540
- },
541
- expect.any(Function)
531
+ expect(successHandler.mock.calls[2][0].payload).toMatchObject({
532
+ ...payload,
533
+ identifier: "hook_plugin_3",
534
+ });
535
+
536
+ expect(successHandler.mock.calls[2][0].hookPlugin).toMatchObject(
537
+ hookPlugin3
542
538
  );
543
539
 
544
540
  expect(completeHandler).toHaveBeenCalledTimes(1);
545
541
 
546
- expect(completeHandler).toHaveBeenCalledWith(
547
- {
548
- payload: { ...payload, identifier: "hook_plugin_3" },
549
- hookPlugin: expect.objectContaining(hookPlugin3),
550
- },
551
- expect.any(Function)
542
+ expect(completeHandler.mock.calls[0][0].payload).toMatchObject({
543
+ ...payload,
544
+ identifier: "hook_plugin_3",
545
+ });
546
+
547
+ expect(completeHandler.mock.calls[0][0].hookPlugin).toMatchObject(
548
+ hookPlugin3
552
549
  );
553
550
 
554
551
  expect(hookPlugin.module.run).toHaveBeenCalledWith(
@@ -12,7 +12,7 @@ export const HOOKS_EVENTS = {
12
12
  CANCEL: "cancel",
13
13
  SUCCESS: "success",
14
14
  COMPLETE: "complete",
15
- };
15
+ } as const;
16
16
 
17
17
  export const HOOKS_TRANSITION_TYPE = {
18
18
  PUSH: "push",
@@ -10,14 +10,72 @@ import { Hook } from "./Hook";
10
10
  import { HOOKS_EVENTS, HOOKS_TYPE } from "./constants";
11
11
 
12
12
  import { hooksManagerLogger } from "./logger";
13
+ import { HookManager, HookManagerArgs } from "./types";
14
+
15
+ /**
16
+ * orders the hooks according to their weight
17
+ * @param {Array<object>} hooks to sort out
18
+ * @returns {Array<object>} sorted hooks
19
+ */
20
+ function orderHooksByWeight(hooks: Hook[]) {
21
+ return R.sortBy(R.compose(Number, R.prop("weight")), hooks);
22
+ }
23
+
24
+ function executeOnNextHook(
25
+ hooks: Hook[],
26
+ payload: object,
27
+ callback: (hookPlugin: Hook, restOfHooks: Hook[], payload: object) => void
28
+ ) {
29
+ const [nextHook, ...restOfHooks] = orderHooksByWeight(hooks);
30
+
31
+ if (nextHook) {
32
+ nextHook.execute(payload, callback(nextHook, restOfHooks, payload));
33
+ }
34
+ }
35
+
36
+ /**
37
+ * tells wether the current river is related to a player plugin, or the default player
38
+ * @param {Object} river
39
+ * @returns {boolean}
40
+ */
41
+ function riverIsPlayer(river, plugins) {
42
+ const { screenType, plugin_type } = river;
43
+
44
+ if (screenType || plugin_type) {
45
+ return screenType === "playable" || plugin_type === "player";
46
+ }
47
+
48
+ const { type } = river;
49
+
50
+ return R.compose(
51
+ R.propEq("type", "player"),
52
+ R.defaultTo({}),
53
+ R.find(R.propEq("identifier", type))
54
+ )(plugins);
55
+ }
56
+
57
+ /**
58
+ * Injects the hooks for the player
59
+ * @param _hookType type of hook
60
+ * @param plugins plugins
61
+ * @returns {Array<Object>}
62
+ */
63
+ function injectPlayerHooks(_hookType: string, plugins): Hook[] {
64
+ const playerhooks: Hook[] = R.compose(
65
+ R.sortBy(R.prop("weight")),
66
+ R.map((plugin) => ({
67
+ identifier: plugin.identifier,
68
+ weight: R.path(["module", "weight"], plugin) || 1,
69
+ })),
70
+ R.filter(R.pathEq(["module", "hasPlayerHook"], true))
71
+ )(plugins);
72
+
73
+ return playerhooks;
74
+ }
13
75
 
14
76
  /**
15
77
  * creates a hooksManager object to handle the hooks process.
16
78
  * it is based on the `subscriber` object
17
- * @param {object} options
18
- * @param {object} rivers map of rivers in the app
19
- * @param {object} targetScreen rivers which we are navigating to
20
- * @param {Array<object>} plugins array of plugins in the app
21
79
  * @returns {object} hooksManager object - see Navigator for usage
22
80
  */
23
81
  export function HooksManager({
@@ -25,8 +83,8 @@ export function HooksManager({
25
83
  targetScreen,
26
84
  plugins,
27
85
  startUpHooksData = {},
28
- }) {
29
- hooksManagerLogger.addContext({ targetScreen });
86
+ }: HookManagerArgs): HookManager {
87
+ hooksManagerLogger.addContext({ targetScreenId: targetScreen.id });
30
88
 
31
89
  function logHookEvent(func, message, data) {
32
90
  func({
@@ -35,7 +93,8 @@ export function HooksManager({
35
93
  });
36
94
  }
37
95
 
38
- const hooksManager = subscriber();
96
+ const hooksManager: Partial<HookManager> = {};
97
+ hooksManager.subscriber = subscriber();
39
98
 
40
99
  /**
41
100
  * attaches the screen data to the hook object if the hook
@@ -100,15 +159,6 @@ export function HooksManager({
100
159
  };
101
160
  }
102
161
 
103
- /**
104
- * orders the hooks according to their weight
105
- * @param {Array<object>} hooks to sort out
106
- * @returns {Array<object>} sorted hooks
107
- */
108
- function orderHooksByWeight(hooks) {
109
- return R.sortBy(R.compose(Number, R.prop("weight")), hooks);
110
- }
111
-
112
162
  /**
113
163
  * extracts the hooks form the target river. returns null if there are none
114
164
  * if there are hooks, gathers all required data and constructs a Hook object
@@ -117,10 +167,10 @@ export function HooksManager({
117
167
  * @returns {Array<Hooks>} list of hooks to go through
118
168
  */
119
169
  function getHooks(hookType, river) {
120
- const playerhooks = [];
170
+ const playerhooks: Hook[] = [];
121
171
 
122
- if (riverIsPlayer(river)) {
123
- playerhooks.push(...injectPlayerHooks(hookType));
172
+ if (riverIsPlayer(river, plugins)) {
173
+ playerhooks.push(...injectPlayerHooks(hookType, plugins));
124
174
  }
125
175
 
126
176
  let hooks = R.concat(playerhooks, R.pathOr([], ["hooks", hookType], river));
@@ -130,8 +180,10 @@ export function HooksManager({
130
180
  const { startUpHooks, setStartUpHooks } = startUpHooksData;
131
181
 
132
182
  if (startUpHooks && startUpHooks !== "in_process") {
133
- hooks.unshift(...startUpHooks);
134
- setStartUpHooks("in_process");
183
+ if (Array.isArray(startUpHooks)) {
184
+ hooks.unshift(...startUpHooks);
185
+ setStartUpHooks("in_process");
186
+ }
135
187
  }
136
188
 
137
189
  if (!R.length(hooks)) {
@@ -158,45 +210,6 @@ export function HooksManager({
158
210
  )(hooks);
159
211
  }
160
212
 
161
- /**
162
- * tells wether the current river is related to a player plugin, or the default player
163
- * @param {Object} river
164
- * @returns {boolean}
165
- */
166
- function riverIsPlayer(river) {
167
- const { screenType, plugin_type } = river;
168
-
169
- if (screenType || plugin_type) {
170
- return screenType === "playable" || plugin_type === "player";
171
- }
172
-
173
- const { type } = river;
174
-
175
- return R.compose(
176
- R.propEq("type", "player"),
177
- R.defaultTo({}),
178
- R.find(R.propEq("identifier", type))
179
- )(plugins);
180
- }
181
-
182
- /**
183
- * Injects the hooks for the player
184
- * @param {String} hookType type of hook
185
- * @returns {Array<Object>}
186
- */
187
- function injectPlayerHooks(_hookType) {
188
- const playerhooks = R.compose(
189
- R.sortBy(R.prop("weight")),
190
- R.map((plugin) => ({
191
- identifier: plugin.identifier,
192
- weight: R.path(["module", "weight"], plugin) || 1,
193
- })),
194
- R.filter(R.pathEq(["module", "hasPlayerHook"], true))
195
- )(plugins);
196
-
197
- return playerhooks;
198
- }
199
-
200
213
  /**
201
214
  * tells wether the given hook is the last one or not
202
215
  * @param {Hook} hookPlugin
@@ -209,6 +222,32 @@ export function HooksManager({
209
222
  return hookPlugin.lastHook;
210
223
  }
211
224
 
225
+ /**
226
+ * flags a hook as succeeded, and pass hook data along
227
+ * @param {Hook} hookPlugin
228
+ * @param {object} payload returned by the hook plugin
229
+ */
230
+ function completeHook(hookPlugin, payload, callback) {
231
+ logHookEvent(
232
+ hooksManagerLogger.info,
233
+ `completeHook: hook sequence completed successfully: ${hookPlugin["identifier"]}`,
234
+ {
235
+ payload,
236
+ hook: hookPlugin,
237
+ }
238
+ );
239
+
240
+ // eslint-disable-next-line
241
+ // TODO: Temporary hack to pass getLoginProtocol to other plugins to refresh in case token expired, need be deleted later
242
+ delete payload.getLoginProtocol;
243
+
244
+ hookPlugin.setStateAndNotify(HOOKS_EVENTS.COMPLETE, {
245
+ hookPlugin,
246
+ payload,
247
+ callback,
248
+ });
249
+ }
250
+
212
251
  /**
213
252
  * creates the callback to invoke in order to proceed to the next hook
214
253
  * covers the scenarios of failure & flow blocking
@@ -228,9 +267,12 @@ export function HooksManager({
228
267
  success,
229
268
  error,
230
269
  payload = initialPayload,
231
- callback,
270
+ callback: callbackArg,
232
271
  cancelled,
272
+ abort,
233
273
  }) {
274
+ let callback = callbackArg;
275
+
234
276
  if (error) {
235
277
  logHookEvent(
236
278
  hooksManagerLogger.error,
@@ -267,12 +309,15 @@ export function HooksManager({
267
309
  hookPlugin.setStateAndNotify(HOOKS_EVENTS.CANCEL, {
268
310
  hookPlugin,
269
311
  payload,
312
+ abort,
270
313
  });
271
314
 
272
315
  const isHookInHomescreen = payload?.home;
273
316
 
274
317
  const isHookFlowBlocker =
275
- hookPlugin?.module?.isFlowBlocker?.() ?? false;
318
+ typeof hookPlugin?.module?.isFlowBlocker === "function"
319
+ ? hookPlugin?.module?.isFlowBlocker()
320
+ : hookPlugin?.module?.isFlowBlocker;
276
321
 
277
322
  // TODO: We technically need to also support the case where there is more than one hook in the stack,
278
323
  // if needed we could add differentiation explicit user cancellation (when we should go to background) and other types of cancellation
@@ -301,6 +346,18 @@ export function HooksManager({
301
346
  }
302
347
  );
303
348
 
349
+ if (!callback) {
350
+ logHookEvent(
351
+ hooksManagerLogger.warn,
352
+ `hookCallback: ${hookPlugin["identifier"]} is missing \`callback\`, using hookCallback(default one)`,
353
+ {
354
+ hookPlugin,
355
+ }
356
+ );
357
+
358
+ callback = hookCallback;
359
+ }
360
+
304
361
  hookPlugin.setStateAndNotify(HOOKS_EVENTS.SUCCESS, {
305
362
  hookPlugin,
306
363
  payload,
@@ -309,37 +366,11 @@ export function HooksManager({
309
366
 
310
367
  isLastHook(hookPlugin, restOfHooks)
311
368
  ? completeHook(hookPlugin, payload, callback)
312
- : handleNextHook(restOfHooks, payload);
369
+ : executeOnNextHook(restOfHooks, payload, callback);
313
370
  }
314
371
  };
315
372
  }
316
373
 
317
- /**
318
- * flags a hook as succeeded, and pass hook data along
319
- * @param {Hook} hookPlugin
320
- * @param {object} payload returned by the hook plugin
321
- */
322
- function completeHook(hookPlugin, payload, callback) {
323
- logHookEvent(
324
- hooksManagerLogger.info,
325
- `completeHook: hook sequence completed successfully: ${hookPlugin["identifier"]}`,
326
- {
327
- payload,
328
- hook: hookPlugin,
329
- }
330
- );
331
-
332
- // eslint-disable-next-line
333
- // TODO: Temporary hack to pass getLoginProtocol to other plugins to refresh in case token expired, need be deleted later
334
- delete payload.getLoginProtocol;
335
-
336
- hookPlugin.setStateAndNotify(HOOKS_EVENTS.COMPLETE, {
337
- hookPlugin,
338
- payload,
339
- callback,
340
- });
341
- }
342
-
343
374
  /**
344
375
  * presents a screen hook by triggering an event invoking the handler with
345
376
  * the appropriate route & payload
@@ -376,9 +407,6 @@ export function HooksManager({
376
407
 
377
408
  /**
378
409
  * executes a headless hook
379
- * @param {Hook} hookPlugin to present
380
- * @param {object} payload to pass to the hook module
381
- * @param {function} callback to invoke when the hook is successful
382
410
  */
383
411
  hooksManager.executeHook = function (hookPlugin, payload, callback) {
384
412
  logHookEvent(
@@ -444,30 +472,13 @@ export function HooksManager({
444
472
  }
445
473
  };
446
474
 
447
- /**
448
- * handles the next hook in the list of provided hooks, passing the payload along
449
- * @param {Array<Hook>} hooks to process
450
- * @param {object} payload to pass to the hook
451
- */
452
- function handleNextHook(hooks, payload) {
453
- const [hookPlugin, ...restOfHooks] = orderHooksByWeight(hooks);
454
-
455
- /**
456
- * Commenting out part of the code which is trying to run the next hook
457
- * in parallel - it's not in use, and it's creating unexpected side
458
- * effects
459
- * */
460
-
461
- hookPlugin.execute(payload, hookCallback(hookPlugin, restOfHooks, payload));
462
- }
463
-
464
475
  /**
465
476
  * function exposes on the hooks manager to trigger the handling of the hooks for
466
477
  * the given targetScreen
467
478
  * @param {object} payload to send to the hooks
468
479
  * @returns {object} returns the hooks manager so methods can be chained
469
480
  */
470
- hooksManager.handleHooks = function (payload) {
481
+ hooksManager.handleHooks = function (payload: object) {
471
482
  const preloadHooks = getHooks(HOOKS_TYPE.PRELOAD, targetScreen);
472
483
 
473
484
  if (preloadHooks?.length) {
@@ -482,9 +493,9 @@ export function HooksManager({
482
493
  }
483
494
  );
484
495
 
485
- handleNextHook(preloadHooks, payload);
496
+ executeOnNextHook(preloadHooks, payload, hookCallback);
486
497
  } else {
487
- hooksManager.invokeHandler(HOOKS_EVENTS.COMPLETE, {
498
+ hooksManager.subscriber.invokeHandler(HOOKS_EVENTS.COMPLETE, {
488
499
  hookPlugin: { lastHook: true },
489
500
  payload,
490
501
  });
@@ -493,5 +504,5 @@ export function HooksManager({
493
504
  return hooksManager;
494
505
  };
495
506
 
496
- return hooksManager;
507
+ return hooksManager as HookManager;
497
508
  }