@applicaster/zapp-react-native-utils 16.0.0-alpha.1833861900 → 16.0.0-alpha.1852433906

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 (245) hide show
  1. package/actionUtils/index.ts +3 -1
  2. package/actionsExecutor/ActionExecutor.ts +57 -12
  3. package/actionsExecutor/ActionExecutorContext.tsx +113 -314
  4. package/actionsExecutor/__tests__/ActionExecutor.test.ts +71 -0
  5. package/actionsExecutor/__tests__/StorageActions.test.ts +98 -0
  6. package/actionsExecutor/__tests__/feedDecorator.test.ts +91 -0
  7. package/actionsExecutor/__tests__/screenToggleFlag.test.ts +90 -0
  8. package/actionsExecutor/actions/__tests__/dismissBottomSheet.test.ts +25 -0
  9. package/actionsExecutor/actions/__tests__/goBack.test.ts +62 -0
  10. package/actionsExecutor/actions/__tests__/goHome.test.ts +19 -0
  11. package/actionsExecutor/actions/__tests__/loadItemsFromSource.test.ts +88 -0
  12. package/actionsExecutor/actions/__tests__/navigateToScreen.test.ts +267 -0
  13. package/actionsExecutor/actions/__tests__/openBottomSheet.customContent.test.ts +100 -0
  14. package/actionsExecutor/actions/__tests__/openBottomSheet.inlineItems.test.ts +372 -0
  15. package/actionsExecutor/actions/__tests__/presentScreen.test.ts +127 -0
  16. package/actionsExecutor/actions/__tests__/showAlert.test.ts +49 -0
  17. package/actionsExecutor/actions/__tests__/showToast.test.ts +88 -0
  18. package/actionsExecutor/actions/appRestart.ts +24 -0
  19. package/actionsExecutor/actions/confirmDialog.ts +53 -0
  20. package/actionsExecutor/actions/dismissBottomSheet.ts +23 -0
  21. package/actionsExecutor/actions/goBack.ts +60 -0
  22. package/actionsExecutor/actions/goHome.ts +31 -0
  23. package/actionsExecutor/actions/index.ts +42 -0
  24. package/actionsExecutor/actions/localStorageRemove.ts +27 -0
  25. package/actionsExecutor/actions/localStorageSet.ts +28 -0
  26. package/actionsExecutor/actions/localStorageToggleFlag.ts +28 -0
  27. package/actionsExecutor/actions/navigateToScreen.ts +121 -0
  28. package/actionsExecutor/actions/openBottomSheet.ts +340 -0
  29. package/actionsExecutor/actions/presentScreen.ts +78 -0
  30. package/actionsExecutor/actions/refreshComponent.ts +85 -0
  31. package/actionsExecutor/actions/screenSetVariable.ts +35 -0
  32. package/actionsExecutor/actions/screenToggleFlag.ts +36 -0
  33. package/actionsExecutor/actions/sendCloudEvent.ts +93 -0
  34. package/actionsExecutor/actions/sessionStorageRemove.ts +19 -0
  35. package/actionsExecutor/actions/sessionStorageSet.ts +20 -0
  36. package/actionsExecutor/actions/sessionStorageToggleFlag.ts +15 -0
  37. package/actionsExecutor/actions/showAlert.ts +51 -0
  38. package/actionsExecutor/actions/showToast.ts +87 -0
  39. package/actionsExecutor/actions/switchLayout.ts +40 -0
  40. package/actionsExecutor/consts.ts +27 -0
  41. package/actionsExecutor/feedDecorator.ts +12 -6
  42. package/actionsExecutor/types.ts +59 -0
  43. package/analyticsUtils/AnalyticsEvents/sendMenuClickEvent.ts +2 -2
  44. package/analyticsUtils/PlayerAnalyticsManager.ts +1 -1
  45. package/analyticsUtils/__tests__/analyticsMapper.test.ts +35 -0
  46. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testACP_events.json +1 -1
  47. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testBlockUnlistedParams_rules.json +1 -1
  48. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testEmptyRenameKeepsName_events.json +4 -0
  49. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testEmptyRenameKeepsName_rules.json +6 -0
  50. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testEventRegex_events.json +3 -9
  51. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testIgnoreOrdering_events.json +18 -0
  52. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testIgnoreOrdering_rules.json +16 -0
  53. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexEventNoFallback_events.json +4 -0
  54. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexEventNoFallback_rules.json +6 -0
  55. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexMultiGroupRename_events.json +4 -0
  56. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexMultiGroupRename_rules.json +6 -0
  57. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexNonNamedFullMatch_events.json +4 -0
  58. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexNonNamedFullMatch_rules.json +6 -0
  59. package/analyticsUtils/__tests__/fixtures/index.js +20 -0
  60. package/analyticsUtils/analyticsMapper.ts +4 -1
  61. package/appUtils/HooksManager/index.ts +9 -0
  62. package/appUtils/contextKeysManager/__tests__/getKey/failure.test.ts +2 -23
  63. package/appUtils/contextKeysManager/__tests__/getKey/success/fullSearch.test.ts +1 -25
  64. package/appUtils/contextKeysManager/__tests__/getKey/success/searchInSecure.test.ts +1 -7
  65. package/appUtils/contextKeysManager/__tests__/removeKey/failure.test.ts +1 -26
  66. package/appUtils/contextKeysManager/__tests__/removeKey/success.test.ts +0 -6
  67. package/appUtils/contextKeysManager/__tests__/setKey/failure/failedToSaveInStorage.test.ts +0 -40
  68. package/appUtils/contextKeysManager/__tests__/setKey/failure/invalidKey.test.ts +4 -4
  69. package/appUtils/contextKeysManager/__tests__/setKey/{success/saveItemAndReference.test.ts → success.test.ts} +2 -42
  70. package/appUtils/contextKeysManager/index.ts +29 -130
  71. package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +142 -59
  72. package/appUtils/playerManager/OverlayObserver/__tests__/getUpcomingQueue.test.ts +67 -0
  73. package/appUtils/playerManager/OverlayObserver/__tests__/liveContent.test.ts +205 -0
  74. package/appUtils/playerManager/OverlayObserver/__tests__/utils.test.ts +56 -0
  75. package/appUtils/playerManager/OverlayObserver/getUpcomingQueue.android.tv.ts +4 -0
  76. package/appUtils/playerManager/OverlayObserver/getUpcomingQueue.ios.tv.ts +4 -0
  77. package/appUtils/playerManager/OverlayObserver/getUpcomingQueue.ts +24 -0
  78. package/appUtils/playerManager/OverlayObserver/getUpcomingQueue.web.ts +4 -0
  79. package/appUtils/playerManager/OverlayObserver/utils.ts +51 -20
  80. package/appUtils/playerManager/__tests__/playerContent.test.ts +403 -0
  81. package/appUtils/playerManager/__tests__/playerDiagnostics.test.ts +62 -0
  82. package/appUtils/playerManager/__tests__/playerFactory.test.ts +1 -1
  83. package/appUtils/playerManager/__tests__/playerNative.test.ts +114 -0
  84. package/appUtils/playerManager/__tests__/playerNativeCommand.test.ts +62 -0
  85. package/appUtils/playerManager/__tests__/playerToolbox.test.ts +281 -0
  86. package/appUtils/playerManager/__tests__/usePlayerContent.test.tsx +64 -0
  87. package/appUtils/playerManager/__tests__/usePlayerControllerSetup.test.tsx +62 -0
  88. package/appUtils/playerManager/{conts.ts → const.ts} +33 -0
  89. package/appUtils/playerManager/index.ts +8 -1
  90. package/appUtils/playerManager/player.ts +140 -3
  91. package/appUtils/playerManager/playerFactory.ts +1 -1
  92. package/appUtils/playerManager/playerNative.ts +28 -4
  93. package/appUtils/playerManager/playerNativeCommand.ts +3 -6
  94. package/appUtils/playerManager/playerToolbox.ts +196 -0
  95. package/appUtils/playerManager/usePlayerContent.tsx +43 -0
  96. package/appUtils/playerManager/usePlayerControllerSetup.tsx +7 -1
  97. package/appUtils/playerManager/userLanguagePreference.ts +1 -1
  98. package/arrayUtils/__tests__/{anyThruthy.test.ts → anyTruthy.test.ts} +8 -0
  99. package/arrayUtils/__tests__/arrayUtils.test.ts +165 -108
  100. package/arrayUtils/__tests__/isEmptyArray.test.ts +11 -0
  101. package/arrayUtils/__tests__/isFilledArray.test.ts +12 -0
  102. package/arrayUtils/__tests__/isFirst.test.ts +17 -0
  103. package/arrayUtils/__tests__/isIndexInRange.test.ts +14 -0
  104. package/arrayUtils/__tests__/isLast.test.ts +31 -0
  105. package/arrayUtils/__tests__/makeListOf.test.ts +31 -0
  106. package/arrayUtils/__tests__/makeListOfIndexes.test.ts +20 -0
  107. package/arrayUtils/__tests__/reorderByIds.test.ts +63 -0
  108. package/arrayUtils/__tests__/sample.test.ts +61 -0
  109. package/arrayUtils/index.ts +119 -20
  110. package/bottomSheet/__tests__/scrollContext.test.tsx +35 -0
  111. package/bottomSheet/index.ts +17 -0
  112. package/cellUtils/__tests__/getButtonsEnabled.test.ts +28 -0
  113. package/cellUtils/__tests__/getCellNavigationEnabled.test.ts +36 -0
  114. package/cellUtils/__tests__/getIsCellNavigationEnabled.test.ts +35 -0
  115. package/cellUtils/__tests__/isCellNavigationEnabled.test.ts +21 -0
  116. package/cellUtils/index.ts +73 -8
  117. package/colorUtils/__tests__/isTransparentColor.test.ts +76 -0
  118. package/colorUtils/__tests__/isValidColor.test.ts +70 -0
  119. package/colorUtils/index.ts +50 -0
  120. package/configurationUtils/__tests__/manifestKeyParser.test.ts +21 -0
  121. package/configurationUtils/__tests__/modalBlocksParser.test.ts +403 -0
  122. package/configurationUtils/manifestKeyParser.ts +50 -10
  123. package/configurationUtils/modalBlocksParser.ts +252 -0
  124. package/entryActions/__tests__/buildEntryActions.test.ts +235 -0
  125. package/entryActions/aliasPresentation.ts +108 -0
  126. package/entryActions/buildEntryActions.ts +167 -0
  127. package/entryActions/index.ts +15 -0
  128. package/entryActions/types.ts +39 -0
  129. package/focusManager/FocusManager.ts +26 -0
  130. package/focusManager/__tests__/FocusManager.test.ts +9 -0
  131. package/localizationUtils/index.ts +12 -6
  132. package/logger/__tests__/xrayToolbox.test.ts +69 -0
  133. package/logger/xrayToolbox.ts +67 -0
  134. package/manifestUtils/__tests__/player.audioControls.test.js +158 -0
  135. package/manifestUtils/_internals/index.js +14 -3
  136. package/manifestUtils/defaultManifestConfigurations/generalContent.js +41 -0
  137. package/manifestUtils/defaultManifestConfigurations/player.js +357 -20
  138. package/manifestUtils/fieldUtils/__tests__/fieldUtils.test.js +84 -0
  139. package/manifestUtils/fieldUtils/index.js +125 -0
  140. package/manifestUtils/index.js +3 -0
  141. package/manifestUtils/keys.js +16 -2
  142. package/manifestUtils/mobileAction/button/index.js +16 -0
  143. package/manifestUtils/mobileAction/container/__tests__/mobileActionButtonsContainer.test.js +21 -0
  144. package/manifestUtils/mobileAction/container/index.js +3 -1
  145. package/manifestUtils/mobileAction/groups/__tests__/buildMobileActionButtonGroups.test.js +1 -1
  146. package/manifestUtils/mobileAction/groups/defaults.js +5 -2
  147. package/manifestUtils/modalBlocks.js +304 -0
  148. package/manifestUtils/platformIsTV.js +1 -0
  149. package/modalState/ContentViewModel.ts +113 -0
  150. package/modalState/EditableCollection.ts +17 -0
  151. package/modalState/EditableCollectionRegistry.ts +51 -0
  152. package/modalState/ModalOrchestrator.ts +213 -0
  153. package/modalState/RemoteEditableCollection.ts +235 -0
  154. package/modalState/__tests__/ContentViewModel.editable.test.ts +69 -0
  155. package/modalState/__tests__/ContentViewModel.test.ts +165 -0
  156. package/modalState/__tests__/EditableCollectionRegistry.test.ts +112 -0
  157. package/modalState/__tests__/ModalOrchestrator.phase3.test.ts +86 -0
  158. package/modalState/__tests__/RemoteEditableCollection.test.ts +415 -0
  159. package/modalState/__tests__/index.test.ts +30 -1
  160. package/modalState/__tests__/useBottomSheetContent.test.ts +349 -0
  161. package/modalState/__tests__/useModalStoreState.test.ts +142 -0
  162. package/modalState/index.ts +37 -83
  163. package/modalState/store.ts +109 -0
  164. package/modalState/types.ts +173 -0
  165. package/modalState/useBottomSheetContent.ts +109 -0
  166. package/navigationUtils/xrayNavigator.ts +12 -0
  167. package/numberUtils/__tests__/isMinusZero.test.ts +20 -0
  168. package/numberUtils/__tests__/isZero.test.ts +27 -0
  169. package/numberUtils/__tests__/requireNumber.test.ts +50 -0
  170. package/numberUtils/__tests__/toNumber.test.ts +27 -0
  171. package/numberUtils/__tests__/toNumberWithDefault.test.ts +64 -0
  172. package/numberUtils/__tests__/toNumberWithDefaultZero.test.ts +48 -0
  173. package/numberUtils/index.ts +27 -8
  174. package/package.json +3 -2
  175. package/pipesUtils/__tests__/buildUrlWithQuery.test.ts +33 -0
  176. package/pipesUtils/__tests__/withPipesEndpoint.test.tsx +56 -0
  177. package/pipesUtils/index.ts +1 -0
  178. package/pipesUtils/withPipesEndpoint.tsx +54 -0
  179. package/playerUtils/__tests__/contentDataKeys.test.ts +297 -0
  180. package/playerUtils/__tests__/resolvePlayerActions.test.ts +138 -0
  181. package/playerUtils/__tests__/resolvePlayerTitleSubtitle.test.ts +180 -0
  182. package/playerUtils/contentDataKeys.ts +134 -0
  183. package/playerUtils/index.ts +37 -16
  184. package/playerUtils/isAudioItem.ts +26 -0
  185. package/playerUtils/resolvePlayerActions.ts +71 -0
  186. package/playerUtils/resolvePlayerTitleSubtitle.ts +76 -0
  187. package/pluginUtils/__tests__/pluginUtils.test.js +32 -0
  188. package/pluginUtils/index.ts +29 -0
  189. package/quickBrickAssets/__tests__/index.test.ts +18 -0
  190. package/quickBrickAssets/index.ts +35 -0
  191. package/reactHooks/__tests__/getPluginConfiguration.test.ts +82 -0
  192. package/reactHooks/actions/index.ts +124 -3
  193. package/reactHooks/cell-click/__tests__/index.test.js +64 -0
  194. package/reactHooks/cell-click/index.ts +39 -24
  195. package/reactHooks/connection/index.tsx +8 -5
  196. package/reactHooks/feed/__mocks__/useMarkPipesDataStale.ts +4 -0
  197. package/reactHooks/feed/__tests__/feedInvalidation.test.tsx +338 -0
  198. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +8 -2
  199. package/reactHooks/feed/__tests__/useInflatedUrl.test.tsx +25 -0
  200. package/reactHooks/feed/__tests__/useMarkPipesDataStale.test.tsx +243 -0
  201. package/reactHooks/feed/index.ts +5 -1
  202. package/reactHooks/feed/useBatchLoading.ts +9 -1
  203. package/reactHooks/feed/useFeedLoader.tsx +28 -1
  204. package/reactHooks/feed/useLoadPipesDataDispatch.ts +12 -11
  205. package/reactHooks/feed/useMarkPipesDataStale.ts +97 -0
  206. package/reactHooks/index.ts +2 -0
  207. package/reactHooks/layout/index.ts +1 -1
  208. package/reactHooks/navigation/__mocks__/index.ts +4 -0
  209. package/reactHooks/navigation/__tests__/index.test.tsx +176 -1
  210. package/reactHooks/navigation/__tests__/useIsScreenActive.test.ts +42 -0
  211. package/reactHooks/navigation/__tests__/usePresentScreen.test.ts +154 -0
  212. package/reactHooks/navigation/index.ts +3 -1
  213. package/reactHooks/navigation/useIsScreenActive.ts +29 -8
  214. package/reactHooks/navigation/usePresentScreen.ts +157 -0
  215. package/reactHooks/navigation/useRoute.ts +22 -5
  216. package/reactHooks/state/useComponentScreenState.ts +1 -1
  217. package/reactHooks/usePluginConfiguration.ts +88 -47
  218. package/reactHooks/utils/__tests__/index.test.js +22 -2
  219. package/reactHooks/utils/index.ts +13 -2
  220. package/riverComponetsMeasurementProvider/index.tsx +15 -9
  221. package/stringUtils/__tests__/stringUtils.test.js +42 -0
  222. package/stringUtils/index.ts +2 -2
  223. package/uiActionsRegistrator/__tests__/resolveActionIdentifiers.test.ts +93 -0
  224. package/uiActionsRegistrator/__tests__/subscribe.test.ts +133 -0
  225. package/uiActionsRegistrator/__tests__/usableActionItems.test.ts +52 -0
  226. package/uiActionsRegistrator/index.ts +25 -0
  227. package/uiActionsRegistrator/registry.ts +351 -0
  228. package/uiActionsRegistrator/resolveActionIdentifiers.ts +100 -0
  229. package/uiActionsRegistrator/usableActionItems.ts +66 -0
  230. package/zappFrameworkUtils/__tests__/localStorageHelper.test.ts +146 -0
  231. package/zappFrameworkUtils/localStorageHelper.ts +19 -15
  232. package/appUtils/contextKeysManager/__tests__/getKey/success/byReference.test.ts +0 -56
  233. package/appUtils/contextKeysManager/__tests__/getKeyByReference/failure.test.ts +0 -265
  234. package/appUtils/contextKeysManager/__tests__/getKeyByReference/success.test.ts +0 -303
  235. package/appUtils/contextKeysManager/__tests__/removeReferenceForKey/failure.test.ts +0 -82
  236. package/appUtils/contextKeysManager/__tests__/removeReferenceForKey/success.test.ts +0 -41
  237. package/appUtils/contextKeysManager/__tests__/setKey/success/saveItemButNotReference.test.ts +0 -208
  238. package/appUtils/contextKeysManager/__tests__/setReferenceForKey/failure.test.ts +0 -93
  239. package/appUtils/contextKeysManager/__tests__/setReferenceForKey/success.test.ts +0 -45
  240. package/appUtils/playerManager/usePlayerTitleSummaryOverlay.tsx +0 -56
  241. package/playerUtils/__tests__/getPlayerActionButtons.test.ts +0 -54
  242. package/playerUtils/getPlayerActionButtons.ts +0 -17
  243. package/reactHooks/feed/__mocks__/usePipesCacheReset.ts +0 -1
  244. package/reactHooks/feed/usePipesCacheReset.ts +0 -44
  245. /package/reactHooks/actions/__tests__/{index.test.js → index.test.tsx} +0 -0
@@ -0,0 +1,267 @@
1
+ import { createNavigateToScreenAction } from "../navigateToScreen";
2
+ import { ActionResult } from "../../ActionExecutor";
3
+
4
+ const river = { id: "screen-id", type: "parent-lock" } as unknown as ZappRiver;
5
+
6
+ const rivers = { "screen-id": river } as Record<string, ZappRiver>;
7
+
8
+ const contentTypes = {
9
+ parentLock: { screen_id: "screen-id" },
10
+ } as unknown as ZappContentTypes;
11
+
12
+ function createNavigator() {
13
+ return {
14
+ push: jest.fn(),
15
+ replace: jest.fn(),
16
+ replaceTop: jest.fn(),
17
+ } as unknown as QuickBrickAppNavigator;
18
+ }
19
+
20
+ describe("navigateToScreen navigationOptions", () => {
21
+ it("forwards navigationOptions to push when navigating to a screen", async () => {
22
+ const navigator = createNavigator();
23
+
24
+ const action = {
25
+ type: "navigateToScreen",
26
+ options: {
27
+ typeMapping: "parentLock",
28
+ navigationAction: "push",
29
+ navigationOptions: { pinFlow: "set-pin" },
30
+ },
31
+ };
32
+
33
+ const result = await createNavigateToScreenAction(
34
+ navigator,
35
+ rivers,
36
+ contentTypes
37
+ )(action);
38
+
39
+ expect(navigator.push).toHaveBeenCalledWith(river, {
40
+ pinFlow: "set-pin",
41
+ });
42
+
43
+ expect(result).toBe(ActionResult.Success);
44
+ });
45
+
46
+ it("forwards navigationOptions to replace when navigating to a screen", async () => {
47
+ const navigator = createNavigator();
48
+
49
+ const action = {
50
+ type: "navigateToScreen",
51
+ options: {
52
+ typeMapping: "parentLock",
53
+ navigationOptions: { pinFlow: "change-pin" },
54
+ },
55
+ };
56
+
57
+ await createNavigateToScreenAction(navigator, rivers, contentTypes)(action);
58
+
59
+ expect(navigator.replace).toHaveBeenCalledWith(river, {
60
+ pinFlow: "change-pin",
61
+ });
62
+ });
63
+
64
+ it("forwards navigationOptions to push when navigating with an entry", async () => {
65
+ const navigator = createNavigator();
66
+ const entry = { id: "entry-id" } as unknown as ZappEntry;
67
+
68
+ const action = {
69
+ type: "navigateToScreen",
70
+ options: {
71
+ typeMapping: "parentLock",
72
+ navigationAction: "push",
73
+ entry,
74
+ navigationOptions: { pinFlow: "set-pin" },
75
+ },
76
+ };
77
+
78
+ await createNavigateToScreenAction(navigator, rivers, contentTypes)(action);
79
+
80
+ expect(navigator.push).toHaveBeenCalledWith(
81
+ { id: "entry-id", type: { value: "parentLock" } },
82
+ { pinFlow: "set-pin" }
83
+ );
84
+ });
85
+
86
+ it("forwards navigationOptions to replace when navigating with an entry", async () => {
87
+ const navigator = createNavigator();
88
+ const entry = { id: "entry-id" } as unknown as ZappEntry;
89
+
90
+ const action = {
91
+ type: "navigateToScreen",
92
+ options: {
93
+ typeMapping: "parentLock",
94
+ entry,
95
+ navigationOptions: { pinFlow: "change-pin" },
96
+ },
97
+ };
98
+
99
+ await createNavigateToScreenAction(navigator, rivers, contentTypes)(action);
100
+
101
+ expect(navigator.replace).toHaveBeenCalledWith(
102
+ { id: "entry-id", type: { value: "parentLock" } },
103
+ { pinFlow: "change-pin" }
104
+ );
105
+
106
+ expect(navigator.replaceTop).not.toHaveBeenCalled();
107
+ });
108
+
109
+ // Regression guard: the no-options path must keep working unchanged.
110
+ it("still navigates when no navigationOptions are configured", async () => {
111
+ const navigator = createNavigator();
112
+
113
+ const action = {
114
+ type: "navigateToScreen",
115
+ options: {
116
+ typeMapping: "parentLock",
117
+ navigationAction: "push",
118
+ },
119
+ };
120
+
121
+ const result = await createNavigateToScreenAction(
122
+ navigator,
123
+ rivers,
124
+ contentTypes
125
+ )(action);
126
+
127
+ expect(navigator.push).toHaveBeenCalledTimes(1);
128
+ expect((navigator.push as jest.Mock).mock.calls[0][0]).toBe(river);
129
+ expect(result).toBe(ActionResult.Success);
130
+ });
131
+ });
132
+
133
+ describe("navigateToScreen target resolution", () => {
134
+ function run(options, context?) {
135
+ const navigator = createNavigator();
136
+
137
+ const result = createNavigateToScreenAction(
138
+ navigator,
139
+ rivers,
140
+ contentTypes
141
+ )({ type: "navigateToScreen", options }, context);
142
+
143
+ return { navigator, result };
144
+ }
145
+
146
+ it("overrides entry.type with typeMapping when both are provided", async () => {
147
+ const entry = {
148
+ id: "entry-id",
149
+ type: { value: "video" },
150
+ } as unknown as ZappEntry;
151
+
152
+ const { navigator, result } = run({
153
+ typeMapping: "parentLock",
154
+ navigationAction: "push",
155
+ entry,
156
+ });
157
+
158
+ expect(await result).toBe(ActionResult.Success);
159
+
160
+ expect(navigator.push).toHaveBeenCalledWith(
161
+ { id: "entry-id", type: { value: "parentLock" } },
162
+ undefined
163
+ );
164
+
165
+ expect(entry.type).toEqual({ value: "video" });
166
+ });
167
+
168
+ it("navigates with the entry's own type when typeMapping is not provided", async () => {
169
+ const entry = {
170
+ id: "entry-id",
171
+ type: { value: "video" },
172
+ } as unknown as ZappEntry;
173
+
174
+ const { navigator, result } = run({ navigationAction: "push", entry });
175
+
176
+ expect(await result).toBe(ActionResult.Success);
177
+
178
+ expect(navigator.push).toHaveBeenCalledWith(
179
+ { id: "entry-id", type: { value: "video" } },
180
+ undefined
181
+ );
182
+ });
183
+
184
+ it("resolves the context entry when entry is @{entry/} and typeMapping is not provided", async () => {
185
+ const entry = {
186
+ id: "context-entry-id",
187
+ type: { value: "video" },
188
+ } as unknown as ZappEntry;
189
+
190
+ const { navigator, result } = run({ entry: "@{entry/}" }, { entry });
191
+
192
+ expect(await result).toBe(ActionResult.Success);
193
+
194
+ expect(navigator.replace).toHaveBeenCalledWith(
195
+ { id: "context-entry-id", type: { value: "video" } },
196
+ undefined
197
+ );
198
+ });
199
+
200
+ it("returns an error when neither typeMapping nor entry type is provided", async () => {
201
+ const entry = { id: "entry-id" } as unknown as ZappEntry;
202
+
203
+ const { navigator, result } = run({ navigationAction: "push", entry });
204
+
205
+ expect(await result).toBe(ActionResult.Error);
206
+ expect(navigator.push).not.toHaveBeenCalled();
207
+ expect(navigator.replace).not.toHaveBeenCalled();
208
+ });
209
+
210
+ it("returns an error when neither typeMapping nor entry is provided", async () => {
211
+ const { navigator, result } = run({ navigationAction: "push" });
212
+
213
+ expect(await result).toBe(ActionResult.Error);
214
+ expect(navigator.push).not.toHaveBeenCalled();
215
+ });
216
+
217
+ it("returns an error when typeMapping has no screen_id mapping", async () => {
218
+ const callback = jest.fn();
219
+
220
+ const { navigator, result } = run(
221
+ { typeMapping: "unknownType", navigationAction: "push" },
222
+ { callback }
223
+ );
224
+
225
+ expect(await result).toBe(ActionResult.Error);
226
+ expect(navigator.push).not.toHaveBeenCalled();
227
+ expect(callback).not.toHaveBeenCalled();
228
+ });
229
+
230
+ it("returns an error when the mapped screen_id has no river", async () => {
231
+ const navigator = createNavigator();
232
+ const callback = jest.fn();
233
+
234
+ const result = await createNavigateToScreenAction(navigator, rivers, {
235
+ orphan: { screen_id: "missing-screen-id" },
236
+ } as unknown as ZappContentTypes)(
237
+ {
238
+ type: "navigateToScreen",
239
+ options: { typeMapping: "orphan", navigationAction: "push" },
240
+ },
241
+ { callback }
242
+ );
243
+
244
+ expect(result).toBe(ActionResult.Error);
245
+ expect(navigator.push).not.toHaveBeenCalled();
246
+ expect(callback).not.toHaveBeenCalled();
247
+ });
248
+
249
+ it("aborts the action pipeline before navigating to a resolved river", async () => {
250
+ const callback = jest.fn();
251
+
252
+ const { navigator, result } = run(
253
+ { typeMapping: "parentLock" },
254
+ { callback }
255
+ );
256
+
257
+ expect(await result).toBe(ActionResult.Success);
258
+
259
+ expect(callback).toHaveBeenCalledWith({
260
+ success: false,
261
+ error: null,
262
+ abort: true,
263
+ });
264
+
265
+ expect(navigator.replace).toHaveBeenCalledWith(river, undefined);
266
+ });
267
+ });
@@ -0,0 +1,100 @@
1
+ import { openBottomSheetAction } from "../openBottomSheet";
2
+ import { ActionResult } from "../../ActionExecutor";
3
+ import { openBottomSheetModal } from "../../../modalState/store";
4
+ import { modalOrchestrator } from "../../../modalState/ModalOrchestrator";
5
+
6
+ jest.mock("../../../modalState/store", () => ({
7
+ openBottomSheetModal: jest.fn(),
8
+ }));
9
+
10
+ jest.mock("../../../modalState/ModalOrchestrator", () => ({
11
+ modalOrchestrator: {
12
+ open: jest.fn(),
13
+ },
14
+ isPresentSubMenuAction: jest.requireActual("../../../modalState/types")
15
+ .isPresentSubMenuAction,
16
+ }));
17
+
18
+ describe("openBottomSheetAction custom content", () => {
19
+ beforeEach(() => {
20
+ jest.clearAllMocks();
21
+ });
22
+
23
+ it("opens default sheet with contentComponent body props", async () => {
24
+ const CustomContent = function CustomContent() {
25
+ return null;
26
+ };
27
+
28
+ const result = await openBottomSheetAction({
29
+ type: "openBottomSheet",
30
+ options: {
31
+ header: { title: "Create Playlist" },
32
+ content: {
33
+ component: CustomContent,
34
+ props: {
35
+ inputLabel: "Name your playlist",
36
+ buttonLabel: "Create",
37
+ defaultValue: "",
38
+ submitAction: { type: "sendCloudEvent", options: {} },
39
+ },
40
+ },
41
+ },
42
+ } as any);
43
+
44
+ expect(result).toBe(ActionResult.Success);
45
+ expect(openBottomSheetModal).toHaveBeenCalledTimes(1);
46
+ expect(modalOrchestrator.open).not.toHaveBeenCalled();
47
+
48
+ const args = (openBottomSheetModal as jest.Mock).mock.calls[0][0];
49
+ // Default ModalComponent provides the standard header
50
+ expect(args.ModalBottomSheetContent).toBeUndefined();
51
+
52
+ expect(args.modalBottomSheetContentProps).toMatchObject({
53
+ title: "Create Playlist",
54
+ contentComponent: CustomContent,
55
+ contentComponentProps: {
56
+ inputLabel: "Name your playlist",
57
+ buttonLabel: "Create",
58
+ defaultValue: "",
59
+ },
60
+ });
61
+ });
62
+
63
+ it("passes themePluginId through to the name sheet", async () => {
64
+ const CustomContent = function CustomContent() {
65
+ return null;
66
+ };
67
+
68
+ await openBottomSheetAction({
69
+ type: "openBottomSheet",
70
+ options: {
71
+ header: { title: "Create New Playlist" },
72
+ themePluginId: "playlist-experience",
73
+ content: {
74
+ component: CustomContent,
75
+ props: { buttonLabel: "Create" },
76
+ },
77
+ },
78
+ } as any);
79
+
80
+ const args = (openBottomSheetModal as jest.Mock).mock.calls[0][0];
81
+
82
+ expect(args.modalBottomSheetContentProps.themePluginId).toBe(
83
+ "playlist-experience"
84
+ );
85
+ });
86
+
87
+ it("returns Error when neither list data nor content.component is provided", async () => {
88
+ const result = await openBottomSheetAction({
89
+ type: "openBottomSheet",
90
+ options: {
91
+ header: { title: "Empty" },
92
+ content: {},
93
+ },
94
+ } as any);
95
+
96
+ expect(result).toBe(ActionResult.Error);
97
+ expect(openBottomSheetModal).not.toHaveBeenCalled();
98
+ expect(modalOrchestrator.open).not.toHaveBeenCalled();
99
+ });
100
+ });