@applicaster/zapp-react-native-utils 15.0.0-rc.99 → 15.1.0-alpha.4285753931

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 (165) hide show
  1. package/actionsExecutor/ActionExecutorContext.tsx +51 -5
  2. package/actionsExecutor/feedDecorator.ts +6 -6
  3. package/adsUtils/index.ts +2 -2
  4. package/analyticsUtils/AnalyticsEvents/sendMenuClickEvent.ts +2 -2
  5. package/analyticsUtils/PlayerAnalyticsManager.ts +11 -1
  6. package/analyticsUtils/README.md +1 -1
  7. package/analyticsUtils/__tests__/analyticsMapper.test.ts +35 -0
  8. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testACP_events.json +1 -1
  9. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testBlockUnlistedParams_rules.json +1 -1
  10. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testEmptyRenameKeepsName_events.json +4 -0
  11. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testEmptyRenameKeepsName_rules.json +6 -0
  12. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testEventRegex_events.json +3 -9
  13. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testIgnoreOrdering_events.json +18 -0
  14. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testIgnoreOrdering_rules.json +16 -0
  15. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexEventNoFallback_events.json +4 -0
  16. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexEventNoFallback_rules.json +6 -0
  17. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexMultiGroupRename_events.json +4 -0
  18. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexMultiGroupRename_rules.json +6 -0
  19. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexNonNamedFullMatch_events.json +4 -0
  20. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexNonNamedFullMatch_rules.json +6 -0
  21. package/analyticsUtils/__tests__/fixtures/index.js +20 -0
  22. package/analyticsUtils/analyticsMapper.ts +4 -1
  23. package/analyticsUtils/playerAnalyticsTracker.ts +26 -3
  24. package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +188 -0
  25. package/appUtils/HooksManager/__tests__/hooksManager.test.js +2 -16
  26. package/appUtils/HooksManager/index.ts +47 -17
  27. package/appUtils/RiverFocusManager/{index.ts → index.js} +18 -25
  28. package/appUtils/accessibilityManager/const.ts +0 -4
  29. package/appUtils/accessibilityManager/utils.ts +1 -0
  30. package/appUtils/contextKeysManager/__tests__/getKeys/failure.test.ts +2 -7
  31. package/appUtils/contextKeysManager/__tests__/getKeys/success.test.ts +0 -48
  32. package/appUtils/contextKeysManager/contextResolver.ts +22 -51
  33. package/appUtils/contextKeysManager/index.ts +10 -65
  34. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +0 -3
  35. package/appUtils/focusManager/index.ios.ts +4 -43
  36. package/appUtils/focusManagerAux/utils/index.ts +3 -5
  37. package/appUtils/focusManagerAux/utils/utils.ios.ts +3 -199
  38. package/appUtils/keyCodes/keys/keys.web.ts +4 -1
  39. package/appUtils/localizationsHelper.ts +4 -0
  40. package/appUtils/orientationHelper.ts +4 -2
  41. package/appUtils/platform/platformUtils.ts +1 -1
  42. package/appUtils/playerManager/__tests__/playerFactory.test.ts +150 -0
  43. package/appUtils/playerManager/index.ts +9 -0
  44. package/appUtils/playerManager/player.ts +1 -5
  45. package/appUtils/playerManager/playerFactory.ts +17 -34
  46. package/appUtils/playerManager/playerNative.ts +22 -30
  47. package/appUtils/playerManager/usePlayer.tsx +5 -3
  48. package/appUtils/playerManager/usePlayerState.tsx +2 -14
  49. package/cellUtils/__tests__/cellUtils.test.ts +39 -0
  50. package/cellUtils/index.ts +11 -1
  51. package/cloudEventsUtils/index.ts +1 -65
  52. package/configurationUtils/__tests__/manifestKeyParser.test.ts +26 -26
  53. package/dateUtils/__tests__/dayjs.test.ts +0 -3
  54. package/dateUtils/index.ts +2 -0
  55. package/focusManager/aux/index.ts +1 -1
  56. package/headersUtils/__tests__/headersUtils.test.js +1 -11
  57. package/headersUtils/index.ts +1 -2
  58. package/manifestUtils/defaultManifestConfigurations/player.js +7 -75
  59. package/manifestUtils/tvAction/container/index.js +1 -1
  60. package/numberUtils/__tests__/toNumber.test.ts +0 -12
  61. package/numberUtils/index.ts +1 -19
  62. package/package.json +4 -4
  63. package/pipesUtils/__tests__/buildUrlWithQuery.test.ts +33 -0
  64. package/pipesUtils/__tests__/withPipesEndpoint.test.tsx +56 -0
  65. package/pipesUtils/index.ts +1 -0
  66. package/pipesUtils/withPipesEndpoint.tsx +54 -0
  67. package/playerUtils/index.ts +24 -2
  68. package/pluginUtils/index.ts +4 -9
  69. package/reactHooks/advertising/index.ts +2 -2
  70. package/reactHooks/app/__tests__/useAppState.test.ts +1 -1
  71. package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
  72. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +2 -1
  73. package/reactHooks/casting/index.ts +1 -0
  74. package/reactHooks/casting/useIsCasting.tsx +57 -0
  75. package/reactHooks/cell-click/__tests__/index.test.js +3 -1
  76. package/reactHooks/componentsMap/index.ts +55 -0
  77. package/reactHooks/configuration/__tests__/index.test.tsx +1 -1
  78. package/reactHooks/connection/__tests__/index.test.js +1 -1
  79. package/reactHooks/debugging/__tests__/index.test.js +4 -4
  80. package/reactHooks/device/useIsTablet.tsx +19 -14
  81. package/reactHooks/device/useMemoizedIsTablet.ts +3 -3
  82. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +23 -32
  83. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +19 -19
  84. package/reactHooks/feed/__tests__/useEntryScreenId.test.tsx +1 -4
  85. package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +30 -42
  86. package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +1 -1
  87. package/reactHooks/feed/__tests__/useInflatedUrl.test.tsx +1 -1
  88. package/reactHooks/feed/useBatchLoading.ts +1 -7
  89. package/reactHooks/feed/useEntryScreenId.ts +2 -2
  90. package/reactHooks/feed/useInflatedUrl.ts +1 -1
  91. package/reactHooks/feed/usePipesCacheReset.ts +1 -3
  92. package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +16 -13
  93. package/reactHooks/layout/__tests__/index.test.tsx +1 -1
  94. package/reactHooks/layout/__tests__/useLayoutVersion.test.tsx +1 -1
  95. package/reactHooks/layout/useDimensions/__tests__/{useDimensions.test.tsx → useDimensions.test.ts} +25 -105
  96. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -2
  97. package/reactHooks/navigation/__tests__/index.test.tsx +4 -2
  98. package/reactHooks/navigation/index.ts +6 -7
  99. package/reactHooks/navigation/useRoute.ts +6 -8
  100. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +10 -27
  101. package/reactHooks/player/__tests__/useAutoSeek._test.tsx +1 -1
  102. package/reactHooks/player/__tests__/useTapSeek._test.ts +1 -1
  103. package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +1 -1
  104. package/reactHooks/resolvers/__tests__/useComponentResolver.test.tsx +1 -1
  105. package/reactHooks/resolvers/useCellResolver.ts +2 -6
  106. package/reactHooks/resolvers/useComponentResolver.ts +13 -9
  107. package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +2 -2
  108. package/reactHooks/screen/__tests__/useCurrentScreenIsHook.test.ts +103 -0
  109. package/reactHooks/screen/__tests__/useCurrentScreenIsStartupHook.test.ts +94 -0
  110. package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +1 -1
  111. package/reactHooks/screen/__tests__/useScreenData.test.tsx +1 -1
  112. package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +4 -12
  113. package/reactHooks/screen/index.ts +6 -0
  114. package/reactHooks/screen/useCurrentScreenIsHook.ts +9 -0
  115. package/reactHooks/screen/useCurrentScreenIsStartupHook.ts +8 -0
  116. package/reactHooks/screen/useIsStandaloneFullscreen.ts +12 -0
  117. package/reactHooks/screen/useTargetScreenData.ts +2 -4
  118. package/reactHooks/state/__tests__/useComponentScreenState.test.ts +246 -0
  119. package/reactHooks/state/index.ts +2 -0
  120. package/reactHooks/state/useComponentScreenState.ts +45 -0
  121. package/reactHooks/state/useRivers.ts +1 -1
  122. package/reactHooks/usePluginConfiguration.ts +2 -2
  123. package/reactHooks/utils/__tests__/index.test.js +1 -1
  124. package/reactHooks/videoModal/hooks/useVideoModalScreenData.tsx +22 -4
  125. package/rectUtils/index.ts +2 -2
  126. package/riverComponetsMeasurementProvider/index.tsx +13 -13
  127. package/screenPickerUtils/index.ts +5 -0
  128. package/screenState/__tests__/index.test.ts +1 -1
  129. package/stringUtils/index.ts +1 -1
  130. package/testUtils/index.tsx +21 -30
  131. package/typeGuards/index.ts +0 -4
  132. package/utils/__tests__/clone.test.ts +158 -0
  133. package/utils/clone.ts +7 -0
  134. package/utils/index.ts +1 -13
  135. package/utils/path.ts +3 -6
  136. package/utils/pathOr.ts +1 -5
  137. package/zappFrameworkUtils/HookCallback/callbackNavigationAction.ts +2 -2
  138. package/zappFrameworkUtils/HookCallback/hookCallbackManifestExtensions.config.js +1 -1
  139. package/zappFrameworkUtils/loginPluginUtils.ts +1 -1
  140. package/adsUtils/__tests__/createVMAP.test.ts +0 -419
  141. package/appDataUtils/__tests__/urlScheme.test.ts +0 -678
  142. package/appUtils/focusManagerAux/utils/index.ios.ts +0 -122
  143. package/cloudEventsUtils/__tests__/index.test.ts +0 -529
  144. package/enumUtils/__tests__/getEnumKeyByEnumValue.test.ts +0 -207
  145. package/errorUtils/__tests__/GeneralError.test.ts +0 -97
  146. package/errorUtils/__tests__/HttpStatusCode.test.ts +0 -344
  147. package/errorUtils/__tests__/MissingPluginError.test.ts +0 -113
  148. package/errorUtils/__tests__/NetworkError.test.ts +0 -202
  149. package/errorUtils/__tests__/getParsedResponse.test.ts +0 -188
  150. package/errorUtils/__tests__/invariant.test.ts +0 -112
  151. package/numberUtils/__tests__/toPositiveNumber.test.ts +0 -165
  152. package/reactHooks/analytics/__tests__/useSendAnalyticsOnPress.test.ts +0 -537
  153. package/reactHooks/dev/__tests__/useReRenderLog.test.ts +0 -188
  154. package/reactHooks/ui/__tests__/useFadeOutWhenBlurred.test.ts +0 -580
  155. package/rectUtils/__tests__/index.test.ts +0 -549
  156. package/screenPickerUtils/__tests__/index.test.ts +0 -333
  157. package/searchUtils/const.ts +0 -7
  158. package/searchUtils/index.ts +0 -3
  159. package/time/__tests__/BackgroundTimer.test.ts +0 -156
  160. package/time/__tests__/Timer.test.ts +0 -236
  161. package/typeGuards/__tests__/isString.test.ts +0 -21
  162. package/utils/__tests__/mergeRight.test.ts +0 -48
  163. package/utils/__tests__/selectors.test.ts +0 -124
  164. package/utils/mergeRight.ts +0 -5
  165. package/utils/selectors.ts +0 -46
@@ -1,4 +1,4 @@
1
- import { renderHook } from "@testing-library/react-native";
1
+ import { renderHook } from "@testing-library/react-hooks";
2
2
  import * as R from "ramda";
3
3
  import * as zappPipesModule from "@applicaster/zapp-react-native-redux/ZappPipes";
4
4
  import * as reactReduxModules from "react-redux";
@@ -50,16 +50,6 @@ const mockZappPipesData = {
50
50
  url: "test://testfakeurl",
51
51
  };
52
52
 
53
- const createWrapper = (
54
- getStore: () => any
55
- ): React.FC<{ children: React.ReactNode }> => {
56
- const Wrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (
57
- <WrappedWithProviders store={getStore()}>{children}</WrappedWithProviders>
58
- );
59
-
60
- return Wrapper;
61
- };
62
-
63
53
  describe("useFeedLoader", () => {
64
54
  describe("with cached feed url", () => {
65
55
  const store = {
@@ -67,7 +57,11 @@ describe("useFeedLoader", () => {
67
57
  zappPipes: { "test://testfakeurl": mockZappPipesData },
68
58
  };
69
59
 
70
- const wrapper = createWrapper(() => store);
60
+ const wrapper: React.FC<any> = ({ children, ...props }) => (
61
+ <WrappedWithProviders store={props.store || store}>
62
+ {children}
63
+ </WrappedWithProviders>
64
+ );
71
65
 
72
66
  it("returns cached feed", () => {
73
67
  const { result } = renderHook(
@@ -115,6 +109,12 @@ describe("useFeedLoader", () => {
115
109
  describe("without cached feeds", () => {
116
110
  const feedUrl = "test://testfakeurl2";
117
111
 
112
+ const wrapper: React.FC<any> = ({ children, ...props }) => (
113
+ <WrappedWithProviders store={props.store}>
114
+ {children}
115
+ </WrappedWithProviders>
116
+ );
117
+
118
118
  it("It loads data for new url and returns it", () => {
119
119
  const useDispatchSpy = jest
120
120
  .spyOn(reactReduxModules, "useDispatch")
@@ -129,12 +129,9 @@ describe("useFeedLoader", () => {
129
129
  zappPipes: { "test://testfakeurl": "foobar" },
130
130
  };
131
131
 
132
- let store = initialStore;
133
- const wrapper = createWrapper(() => store);
134
-
135
132
  const { result, rerender } = renderHook(
136
- ({ feedUrl: url }) => useFeedLoader({ feedUrl: url }),
137
- { wrapper, initialProps: { feedUrl } }
133
+ () => useFeedLoader({ feedUrl: "test://testfakeurl2" }),
134
+ { wrapper, initialProps: { store: initialStore } }
138
135
  );
139
136
 
140
137
  expect(result.current.data).toBeNull();
@@ -153,8 +150,7 @@ describe("useFeedLoader", () => {
153
150
  zappPipes: { "test://testfakeurl2": mockZappPipesData },
154
151
  };
155
152
 
156
- store = store2;
157
- rerender({ feedUrl });
153
+ rerender({ store: store2 });
158
154
 
159
155
  expect(R.omit(["reloadData", "loadNext"], result.current)).toEqual(
160
156
  mockZappPipesData
@@ -178,12 +174,9 @@ describe("useFeedLoader", () => {
178
174
  zappPipes: { "test://testfakeurl": "foobar" },
179
175
  };
180
176
 
181
- let store = initialStore;
182
- const wrapper = createWrapper(() => store);
183
-
184
177
  const { result, rerender } = renderHook(
185
- ({ feedUrl: url }) => useFeedLoader({ feedUrl: url }),
186
- { wrapper, initialProps: { feedUrl } }
178
+ () => useFeedLoader({ feedUrl: "test://testfakeurl2" }),
179
+ { wrapper, initialProps: { store: initialStore } }
187
180
  );
188
181
 
189
182
  expect(result.current.data).toBeNull();
@@ -205,8 +198,7 @@ describe("useFeedLoader", () => {
205
198
  zappPipes: { "test://testfakeurl2": mockZappPipesData },
206
199
  };
207
200
 
208
- store = store2;
209
- rerender({ feedUrl });
201
+ rerender({ store: store2 });
210
202
 
211
203
  loadPipesDataSpy.mockRestore();
212
204
  useDispatchSpy.mockRestore();
@@ -217,6 +209,12 @@ describe("useFeedLoader", () => {
217
209
  const feedUrl = "test://testfakeurl";
218
210
  const feedUrlWithNext = "test://withnexttestfakeurl";
219
211
 
212
+ const wrapper: React.FC<any> = ({ children, ...props }) => (
213
+ <WrappedWithProviders store={props.store || {}}>
214
+ {children}
215
+ </WrappedWithProviders>
216
+ );
217
+
220
218
  describe("reloadData", () => {
221
219
  it("Tries to reload data in the redux store", () => {
222
220
  const loadPipesDataSpy = jest
@@ -232,17 +230,10 @@ describe("useFeedLoader", () => {
232
230
  zappPipes: { [feedUrl]: "foobar" },
233
231
  };
234
232
 
235
- const store = initialStore;
236
-
237
- const wrapper = createWrapper(() => store);
238
-
239
- const { result } = renderHook(
240
- ({ feedUrl: url }) => useFeedLoader({ feedUrl: url }),
241
- {
242
- wrapper,
243
- initialProps: { feedUrl },
244
- }
245
- );
233
+ const { result } = renderHook(() => useFeedLoader({ feedUrl }), {
234
+ wrapper,
235
+ initialProps: { store: initialStore },
236
+ });
246
237
 
247
238
  const { reloadData } = result.current;
248
239
 
@@ -288,14 +279,11 @@ describe("useFeedLoader", () => {
288
279
  zappPipes: { [feedUrlWithNext]: { data: { next: nextUrl } } },
289
280
  };
290
281
 
291
- const store = initialStore;
292
- const wrapper = createWrapper(() => store);
293
-
294
282
  const { result } = renderHook(
295
- ({ feedUrl: url }) => useFeedLoader({ feedUrl: url }),
283
+ () => useFeedLoader({ feedUrl: feedUrlWithNext }),
296
284
  {
297
285
  wrapper,
298
- initialProps: { feedUrl: feedUrlWithNext },
286
+ initialProps: { store: initialStore },
299
287
  }
300
288
  );
301
289
 
@@ -1,4 +1,4 @@
1
- import { renderHook } from "@testing-library/react-native";
1
+ import { renderHook } from "@testing-library/react-hooks";
2
2
 
3
3
  jest.useFakeTimers();
4
4
 
@@ -214,7 +214,7 @@ describe("getSearchContext", () => {
214
214
  });
215
215
 
216
216
  describe("useGetUrlInflater", () => {
217
- const { renderHook } = require("@testing-library/react-native");
217
+ const { renderHook } = require("@testing-library/react-hooks");
218
218
 
219
219
  it("returns original url when mapping is not provided", () => {
220
220
  const { result } = renderHook(() => useGetUrlInflater(), {
@@ -151,13 +151,7 @@ export const useBatchLoading = (
151
151
  }
152
152
  }
153
153
  });
154
- }, [
155
- batchComponents,
156
- feeds,
157
- getUrl,
158
- loadPipesDataDispatcher,
159
- options.riverId,
160
- ]);
154
+ }, [feedUrls, feeds, loadPipesDataDispatcher]);
161
155
 
162
156
  React.useEffect(() => {
163
157
  runBatchLoading();
@@ -1,7 +1,7 @@
1
- import { useContentTypes } from "@applicaster/zapp-react-native-redux";
1
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
2
2
 
3
3
  export const useEntryScreenId = (entry?: ZappEntry): string | undefined => {
4
- const contentTypes = useContentTypes();
4
+ const { contentTypes } = usePickFromState("contentTypes");
5
5
 
6
6
  if (!entry) {
7
7
  return;
@@ -45,7 +45,7 @@ interface GetInflatedDataSourceUrl {
45
45
  (properties: {
46
46
  source?: string;
47
47
  contexts: {
48
- entry?: ZappEntry;
48
+ entry?: ZappEntry & { parent?: ZappEntry };
49
49
  screen?: ZappRiver;
50
50
  search?: object | string;
51
51
  };
@@ -34,9 +34,7 @@ export const usePipesCacheReset = (riverId, riverComponents) => {
34
34
  component
35
35
  );
36
36
 
37
- if (url) {
38
- dispatch(clearPipesData(url, { riverId }));
39
- }
37
+ dispatch(clearPipesData(url, { riverId }));
40
38
  }
41
39
  });
42
40
  };
@@ -1,8 +1,10 @@
1
1
  import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
2
2
  import React from "react";
3
3
 
4
+ type Return = (index: number) => void;
5
+
4
6
  type Predicate = (
5
- entryLength: number,
7
+ entry: ZappUIComponentProps["zappPipesData"]["data"]["entry"],
6
8
  index: number,
7
9
  numberOfColumns: number
8
10
  ) => boolean;
@@ -10,15 +12,19 @@ type Predicate = (
10
12
  type Props = {
11
13
  ifNeeded: Predicate;
12
14
  loadNextData: () => void;
13
- entryLength: number;
15
+ entry: ZappUIComponentProps["zappPipesData"]["data"]["entry"];
14
16
  numberOfColumns?: number;
15
17
  };
16
18
 
17
19
  const handleLoadNextPage =
18
20
  (
19
- ifNeeded: Predicate,
21
+ ifNeeded: (
22
+ entry: ZappEntry[],
23
+ index: number,
24
+ numberOfColumns?: number
25
+ ) => boolean,
20
26
  loadNextData: () => void,
21
- entryLength: number,
27
+ entry: ZappEntry[],
22
28
  numberOfColumns
23
29
  ) =>
24
30
  (index: number) => {
@@ -26,7 +32,7 @@ const handleLoadNextPage =
26
32
  * Lazy-Loading, invoke nextLoadData if we reach the end of the List
27
33
  */
28
34
 
29
- if (ifNeeded(entryLength, index, numberOfColumns)) {
35
+ if (ifNeeded(entry, index, numberOfColumns)) {
30
36
  loadNextData();
31
37
  }
32
38
  };
@@ -34,14 +40,11 @@ const handleLoadNextPage =
34
40
  export const useLoadNextPageIfNeeded = ({
35
41
  ifNeeded,
36
42
  loadNextData = noop,
37
- entryLength,
43
+ entry,
38
44
  numberOfColumns = 0,
39
- }: Props) => {
40
- const memoFn = React.useMemo(
41
- () =>
42
- handleLoadNextPage(ifNeeded, loadNextData, entryLength, numberOfColumns),
43
- [ifNeeded, loadNextData, entryLength, numberOfColumns]
45
+ }: Props): Return => {
46
+ return React.useCallback(
47
+ handleLoadNextPage(ifNeeded, loadNextData, entry, numberOfColumns),
48
+ [ifNeeded, loadNextData, entry, numberOfColumns]
44
49
  );
45
-
46
- return memoFn;
47
50
  };
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
 
3
- import { cleanup, renderHook } from "@testing-library/react-native";
3
+ import { cleanup, renderHook } from "@testing-library/react-hooks";
4
4
  import { Provider } from "react-redux";
5
5
  import configureStore from "redux-mock-store";
6
6
 
@@ -1,4 +1,4 @@
1
- import { renderHook } from "@testing-library/react-native";
1
+ import { renderHook } from "@testing-library/react-hooks";
2
2
  import configureStore from "redux-mock-store";
3
3
 
4
4
  const mockStore = configureStore();
@@ -1,10 +1,16 @@
1
- import React from "react";
2
- import { renderHook } from "@testing-library/react-native";
1
+ import { renderHook } from "@testing-library/react-hooks";
3
2
  import { Dimensions, StatusBar } from "react-native";
4
3
  import { useDimensions } from "../useDimensions";
4
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux";
5
5
 
6
6
  import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive";
7
- import { WrappedWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
7
+
8
+ jest.mock("@applicaster/zapp-react-native-redux/hooks", () => {
9
+ return {
10
+ ...jest.requireActual("@applicaster/zapp-react-native-redux/hooks"),
11
+ usePickFromState: jest.fn(),
12
+ };
13
+ });
8
14
 
9
15
  jest.mock(
10
16
  "@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive",
@@ -36,22 +42,12 @@ describe("useDimensions", () => {
36
42
 
37
43
  beforeEach(() => {
38
44
  StatusBar.currentHeight = 20;
45
+ (usePickFromState as jest.Mock).mockReturnValue({ appData: mockAppData });
39
46
  });
40
47
 
41
48
  it("returns correct initial dimensions", () => {
42
- const { result } = renderHook(
43
- () => useDimensions("window", { fullDimensions: false }),
44
- {
45
- wrapper: ({ children }) => (
46
- <WrappedWithProviders
47
- store={{
48
- appData: mockAppData,
49
- }}
50
- >
51
- {children}
52
- </WrappedWithProviders>
53
- ),
54
- }
49
+ const { result } = renderHook(() =>
50
+ useDimensions("window", { fullDimensions: false })
55
51
  );
56
52
 
57
53
  expect(result.current).toMatchObject({
@@ -60,17 +56,7 @@ describe("useDimensions", () => {
60
56
  });
61
57
 
62
58
  it("calls handler on mount", () => {
63
- renderHook(() => useDimensions("window", { fullDimensions: false }), {
64
- wrapper: ({ children }) => (
65
- <WrappedWithProviders
66
- store={{
67
- appData: mockAppData,
68
- }}
69
- >
70
- {children}
71
- </WrappedWithProviders>
72
- ),
73
- });
59
+ renderHook(() => useDimensions("window", { fullDimensions: false }));
74
60
 
75
61
  expect(Dimensions.addEventListener).toHaveBeenCalledWith(
76
62
  "change",
@@ -79,23 +65,12 @@ describe("useDimensions", () => {
79
65
  });
80
66
 
81
67
  it("calls handler on isActive change", () => {
82
- const { rerender } = renderHook(
83
- () => useDimensions("window", { fullDimensions: false }),
84
- {
85
- wrapper: ({ children }) => (
86
- <WrappedWithProviders
87
- store={{
88
- appData: mockAppData,
89
- }}
90
- >
91
- {children}
92
- </WrappedWithProviders>
93
- ),
94
- }
68
+ const { rerender } = renderHook(() =>
69
+ useDimensions("window", { fullDimensions: false })
95
70
  );
96
71
 
97
72
  (useIsScreenActive as jest.Mock).mockReturnValue(false);
98
- rerender({});
73
+ rerender();
99
74
 
100
75
  expect(Dimensions.addEventListener).toHaveBeenCalledWith(
101
76
  "change",
@@ -104,19 +79,8 @@ describe("useDimensions", () => {
104
79
  });
105
80
 
106
81
  it("handles fullDimensions option", () => {
107
- const { result } = renderHook(
108
- () => useDimensions("window", { fullDimensions: true }),
109
- {
110
- wrapper: ({ children }) => (
111
- <WrappedWithProviders
112
- store={{
113
- appData: mockAppData,
114
- }}
115
- >
116
- {children}
117
- </WrappedWithProviders>
118
- ),
119
- }
82
+ const { result } = renderHook(() =>
83
+ useDimensions("window", { fullDimensions: true })
120
84
  );
121
85
 
122
86
  expect(result.current).toMatchObject({
@@ -127,19 +91,8 @@ describe("useDimensions", () => {
127
91
  });
128
92
 
129
93
  it("handles excludeStatusBar option", () => {
130
- const { result } = renderHook(
131
- () => useDimensions("window", { excludeStatusBar: true }),
132
- {
133
- wrapper: ({ children }) => (
134
- <WrappedWithProviders
135
- store={{
136
- appData: mockAppData,
137
- }}
138
- >
139
- {children}
140
- </WrappedWithProviders>
141
- ),
142
- }
94
+ const { result } = renderHook(() =>
95
+ useDimensions("window", { excludeStatusBar: true })
143
96
  );
144
97
 
145
98
  expect(result.current.height).toBe(
@@ -148,19 +101,8 @@ describe("useDimensions", () => {
148
101
  });
149
102
 
150
103
  it("handles rounded option", () => {
151
- const { result } = renderHook(
152
- () => useDimensions("window", { rounded: true }),
153
- {
154
- wrapper: ({ children }) => (
155
- <WrappedWithProviders
156
- store={{
157
- appData: mockAppData,
158
- }}
159
- >
160
- {children}
161
- </WrappedWithProviders>
162
- ),
163
- }
104
+ const { result } = renderHook(() =>
105
+ useDimensions("window", { rounded: true })
164
106
  );
165
107
 
166
108
  expect(result.current.width).toBe(Math.ceil(mockDimensions.width));
@@ -168,19 +110,8 @@ describe("useDimensions", () => {
168
110
  });
169
111
 
170
112
  it("handles deviceInfo option", () => {
171
- const { result } = renderHook(
172
- () => useDimensions("window", { deviceInfo: true }),
173
- {
174
- wrapper: ({ children }) => (
175
- <WrappedWithProviders
176
- store={{
177
- appData: mockAppData,
178
- }}
179
- >
180
- {children}
181
- </WrappedWithProviders>
182
- ),
183
- }
113
+ const { result } = renderHook(() =>
114
+ useDimensions("window", { deviceInfo: true })
184
115
  );
185
116
 
186
117
  expect(result.current.deviceInfo).toMatchObject({
@@ -190,18 +121,7 @@ describe("useDimensions", () => {
190
121
 
191
122
  it("logs deprecation warning when fullDimensions is boolean", () => {
192
123
  const consoleWarnSpy = jest.spyOn(console, "warn").mockImplementation();
193
-
194
- renderHook(() => useDimensions("window", true), {
195
- wrapper: ({ children }) => (
196
- <WrappedWithProviders
197
- store={{
198
- appData: mockAppData,
199
- }}
200
- >
201
- {children}
202
- </WrappedWithProviders>
203
- ),
204
- });
124
+ renderHook(() => useDimensions("window", true));
205
125
 
206
126
  expect(consoleWarnSpy).toHaveBeenCalledWith(
207
127
  "Deprecation Warning\nSecond argument is now the options object. {fullDimensions: boolean, ...}"
@@ -3,7 +3,7 @@ import { useLayoutEffect, useMemo, useRef, useState } from "react";
3
3
  import * as R from "ramda";
4
4
 
5
5
  import { Dimensions, Platform, StatusBar } from "react-native";
6
- import { useAppData } from "@applicaster/zapp-react-native-redux/hooks";
6
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
7
7
 
8
8
  import { isTV } from "../../../reactUtils";
9
9
 
@@ -37,7 +37,7 @@ export const useDimensions: UseDimensions = (
37
37
  ) => {
38
38
  const statusBarHeight = StatusBar?.currentHeight;
39
39
  const isActive = useIsScreenActive();
40
- const appData = useAppData();
40
+ const { appData } = usePickFromState(["appData"]);
41
41
 
42
42
  if (typeof fullDimensions === "boolean") {
43
43
  // eslint-disable-next-line no-console
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
3
- import { renderHook } from "@testing-library/react-native";
3
+ import { renderHook } from "@testing-library/react-hooks";
4
4
  import { isNavBarVisible, useRoute } from "../";
5
5
  import { Provider } from "react-redux";
6
6
  import configureMockStore from "redux-mock-store";
@@ -86,11 +86,11 @@ const hookModalContextState = {
86
86
  };
87
87
 
88
88
  const hooksModalPathname = `${ROUTE_TYPES.HOOKS_MODAL}/${hookModalContextState.state.screenData.payload.id}`;
89
- const videoModalPathname = `${ROUTE_TYPES.VIDEO_MODAL}/${videoModalNavigator.videoModalState.item.id}`;
90
89
 
91
90
  jest.mock(
92
91
  "@applicaster/zapp-react-native-ui-components/Contexts/ZappHookModalContext",
93
92
  () => {
93
+ // Define state inside mock factory to avoid hoisting issues
94
94
  const mockState = {
95
95
  isRunningInBackground: false,
96
96
  setIsRunningInBackground: jest.fn(),
@@ -111,6 +111,7 @@ jest.mock(
111
111
  return selector ? selector(mockState) : mockState;
112
112
  }) as jest.MockedFunction<any> & { getState: () => typeof mockState };
113
113
 
114
+ // Add getState method to the mock hook (Zustand stores have this)
114
115
  mockHook.getState = jest.fn(() => mockState);
115
116
 
116
117
  return {
@@ -120,6 +121,7 @@ jest.mock(
120
121
  }
121
122
  );
122
123
 
124
+ const videoModalPathname = `${ROUTE_TYPES.VIDEO_MODAL}/${videoModalNavigator.videoModalState.item.id}`;
123
125
  const mockStore = configureMockStore();
124
126
 
125
127
  const store = mockStore({
@@ -4,7 +4,7 @@ import { shallow } from "zustand/shallow";
4
4
 
5
5
  import {
6
6
  useContentTypes,
7
- usePlugins,
7
+ usePickFromState,
8
8
  } from "@applicaster/zapp-react-native-redux/hooks";
9
9
  import { HooksManager } from "@applicaster/zapp-react-native-utils/appUtils/HooksManager";
10
10
 
@@ -17,8 +17,6 @@ import { useConnectionInfo } from "../connection";
17
17
  import { isTV, isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
18
18
  import { pick } from "@applicaster/zapp-react-native-utils/utils";
19
19
  import { useNavbarState } from "../screen";
20
- import { useRivers } from "../state";
21
- import { useLayoutVersion } from "../layout";
22
20
 
23
21
  export { useNavigation } from "./useNavigation";
24
22
 
@@ -181,10 +179,11 @@ export const useZappHooksForEntry = (
181
179
  shallow
182
180
  );
183
181
 
184
- const plugins = usePlugins();
185
- const rivers = useRivers();
186
-
187
- const layoutVersion = useLayoutVersion();
182
+ const {
183
+ appData: { layoutVersion },
184
+ rivers,
185
+ plugins,
186
+ } = usePickFromState(["appData", "rivers", "plugins"]);
188
187
 
189
188
  const contentTypes = useContentTypes();
190
189
 
@@ -3,10 +3,7 @@
3
3
 
4
4
  import { useContext } from "react";
5
5
 
6
- import {
7
- useContentTypes,
8
- usePlugins,
9
- } from "@applicaster/zapp-react-native-redux/hooks";
6
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
10
7
 
11
8
  import { legacyScreenData } from "@applicaster/quick-brick-core/App/NavigationProvider/utils";
12
9
 
@@ -17,7 +14,6 @@ import { useNavigation } from "./useNavigation";
17
14
  import { useModalStoreState } from "../../modalState";
18
15
  import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
19
16
  import { usePathname } from "./usePathname";
20
- import { useRivers } from "../state";
21
17
 
22
18
  // starts with modal/
23
19
  const isModalPathname = (pathname: string) => /^modal\//.test(pathname);
@@ -46,9 +42,11 @@ export const useRoute = (
46
42
  ? legacyScreenData(screenContext)
47
43
  : screenContext;
48
44
 
49
- const plugins = usePlugins();
50
- const rivers = useRivers();
51
- const contentTypes = useContentTypes();
45
+ const { plugins, contentTypes, rivers } = usePickFromState([
46
+ "plugins",
47
+ "rivers",
48
+ "contentTypes",
49
+ ]);
52
50
 
53
51
  const modalState = useModalStoreState();
54
52
 
@@ -147,34 +147,17 @@ export class TVSeekController
147
147
 
148
148
  let targetPos = currentPos;
149
149
 
150
- const isLive = this.playerController.isLive();
151
-
152
- if (isLive) {
153
- if (this.currentSeekType === SEEK_TYPE.REWIND) {
154
- targetPos = Math.min(
155
- currentPos + offset,
156
- this.playerController.getSeekableDuration()
157
- );
158
- } else if (this.currentSeekType === SEEK_TYPE.FORWARD) {
159
- targetPos = Math.max(0, currentPos - offset);
160
- } else {
161
- log_warning(
162
- `TVSeekController: handleDelayedSeek - invalid seek type: ${this.currentSeekType}`
163
- );
164
- }
150
+ if (this.currentSeekType === SEEK_TYPE.FORWARD) {
151
+ targetPos = Math.min(
152
+ currentPos + offset,
153
+ this.playerController.getSeekableDuration()
154
+ );
155
+ } else if (this.currentSeekType === SEEK_TYPE.REWIND) {
156
+ targetPos = Math.max(0, currentPos - offset);
165
157
  } else {
166
- if (this.currentSeekType === SEEK_TYPE.FORWARD) {
167
- targetPos = Math.min(
168
- currentPos + offset,
169
- this.playerController.getSeekableDuration()
170
- );
171
- } else if (this.currentSeekType === SEEK_TYPE.REWIND) {
172
- targetPos = Math.max(0, currentPos - offset);
173
- } else {
174
- log_warning(
175
- `TVSeekController: handleDelayedSeek - invalid seek type: ${this.currentSeekType}`
176
- );
177
- }
158
+ log_warning(
159
+ `TVSeekController: handleDelayedSeek - invalid seek type: ${this.currentSeekType}`
160
+ );
178
161
  }
179
162
 
180
163
  log_debug(
@@ -1,4 +1,4 @@
1
- import { act, renderHook } from "@testing-library/react-native";
1
+ import { act, renderHook } from "@testing-library/react-hooks";
2
2
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager";
3
3
 
4
4
  import { ON_HOLD_INTERVAL, SEEK_TYPE, SKIP_TIME_BASE } from "../const";
@@ -1,4 +1,4 @@
1
- import { renderHook } from "@testing-library/react-native";
1
+ import { renderHook } from "@testing-library/react-hooks";
2
2
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager";
3
3
  import { useTapSeek } from "../useTapSeek";
4
4