@applicaster/zapp-react-native-utils 15.0.0-rc.98 → 15.1.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) 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/README.md +1 -1
  5. package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +188 -0
  6. package/appUtils/HooksManager/__tests__/hooksManager.test.js +2 -16
  7. package/appUtils/HooksManager/index.ts +45 -10
  8. package/appUtils/RiverFocusManager/{index.ts → index.js} +18 -25
  9. package/appUtils/accessibilityManager/const.ts +0 -4
  10. package/appUtils/accessibilityManager/utils.ts +1 -0
  11. package/appUtils/contextKeysManager/__tests__/getKeys/failure.test.ts +2 -7
  12. package/appUtils/contextKeysManager/__tests__/getKeys/success.test.ts +0 -48
  13. package/appUtils/contextKeysManager/contextResolver.ts +22 -51
  14. package/appUtils/contextKeysManager/index.ts +10 -65
  15. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +0 -3
  16. package/appUtils/focusManager/index.ios.ts +4 -43
  17. package/appUtils/focusManagerAux/utils/index.ts +3 -5
  18. package/appUtils/focusManagerAux/utils/utils.ios.ts +3 -199
  19. package/appUtils/keyCodes/keys/keys.web.ts +4 -1
  20. package/appUtils/localizationsHelper.ts +4 -0
  21. package/appUtils/orientationHelper.ts +4 -2
  22. package/appUtils/platform/platformUtils.ts +1 -1
  23. package/appUtils/playerManager/index.ts +9 -0
  24. package/appUtils/playerManager/player.ts +1 -5
  25. package/appUtils/playerManager/playerNative.ts +22 -30
  26. package/appUtils/playerManager/usePlayer.tsx +5 -3
  27. package/appUtils/playerManager/usePlayerState.tsx +2 -14
  28. package/cellUtils/__tests__/cellUtils.test.ts +39 -0
  29. package/cellUtils/index.ts +11 -1
  30. package/cloudEventsUtils/index.ts +1 -65
  31. package/configurationUtils/__tests__/manifestKeyParser.test.ts +26 -26
  32. package/dateUtils/__tests__/dayjs.test.ts +0 -3
  33. package/dateUtils/index.ts +2 -0
  34. package/focusManager/aux/index.ts +1 -1
  35. package/headersUtils/__tests__/headersUtils.test.js +1 -11
  36. package/headersUtils/index.ts +1 -2
  37. package/manifestUtils/defaultManifestConfigurations/player.js +7 -75
  38. package/manifestUtils/platformIsTV.js +13 -0
  39. package/manifestUtils/tvAction/container/index.js +1 -1
  40. package/numberUtils/__tests__/toNumber.test.ts +0 -12
  41. package/numberUtils/index.ts +1 -19
  42. package/package.json +4 -4
  43. package/pluginUtils/index.ts +4 -9
  44. package/reactHooks/advertising/index.ts +2 -2
  45. package/reactHooks/app/__tests__/useAppState.test.ts +1 -1
  46. package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
  47. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +2 -1
  48. package/reactHooks/casting/index.ts +1 -0
  49. package/reactHooks/casting/useIsCasting.tsx +57 -0
  50. package/reactHooks/cell-click/__tests__/index.test.js +3 -1
  51. package/reactHooks/componentsMap/index.ts +55 -0
  52. package/reactHooks/configuration/__tests__/index.test.tsx +1 -1
  53. package/reactHooks/connection/__tests__/index.test.js +1 -1
  54. package/reactHooks/debugging/__tests__/index.test.js +4 -4
  55. package/reactHooks/device/useIsTablet.tsx +19 -14
  56. package/reactHooks/device/useMemoizedIsTablet.ts +3 -3
  57. package/reactHooks/events/index.ts +20 -0
  58. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +23 -32
  59. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +19 -19
  60. package/reactHooks/feed/__tests__/useEntryScreenId.test.tsx +1 -4
  61. package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +30 -42
  62. package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +1 -1
  63. package/reactHooks/feed/__tests__/useInflatedUrl.test.tsx +1 -1
  64. package/reactHooks/feed/useBatchLoading.ts +1 -7
  65. package/reactHooks/feed/useEntryScreenId.ts +2 -2
  66. package/reactHooks/feed/useInflatedUrl.ts +1 -1
  67. package/reactHooks/feed/usePipesCacheReset.ts +1 -3
  68. package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +16 -13
  69. package/reactHooks/index.ts +2 -0
  70. package/reactHooks/layout/__tests__/index.test.tsx +1 -1
  71. package/reactHooks/layout/__tests__/useLayoutVersion.test.tsx +1 -1
  72. package/reactHooks/layout/useDimensions/__tests__/{useDimensions.test.tsx → useDimensions.test.ts} +25 -105
  73. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -2
  74. package/reactHooks/navigation/__tests__/index.test.tsx +4 -2
  75. package/reactHooks/navigation/index.ts +6 -7
  76. package/reactHooks/navigation/useRoute.ts +6 -8
  77. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +10 -27
  78. package/reactHooks/player/__tests__/useAutoSeek._test.tsx +1 -1
  79. package/reactHooks/player/__tests__/useTapSeek._test.ts +1 -1
  80. package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +1 -1
  81. package/reactHooks/resolvers/__tests__/useComponentResolver.test.tsx +1 -1
  82. package/reactHooks/resolvers/useCellResolver.ts +2 -6
  83. package/reactHooks/resolvers/useComponentResolver.ts +13 -9
  84. package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +2 -2
  85. package/reactHooks/screen/__tests__/useCurrentScreenIsHook.test.ts +103 -0
  86. package/reactHooks/screen/__tests__/useCurrentScreenIsStartupHook.test.ts +94 -0
  87. package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +1 -1
  88. package/reactHooks/screen/__tests__/useScreenData.test.tsx +1 -1
  89. package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +4 -12
  90. package/reactHooks/screen/index.ts +6 -0
  91. package/reactHooks/screen/useCurrentScreenIsHook.ts +9 -0
  92. package/reactHooks/screen/useCurrentScreenIsStartupHook.ts +8 -0
  93. package/reactHooks/screen/useIsStandaloneFullscreen.ts +12 -0
  94. package/reactHooks/screen/useTargetScreenData.ts +2 -4
  95. package/reactHooks/state/__tests__/useComponentScreenState.test.ts +246 -0
  96. package/reactHooks/state/index.ts +2 -0
  97. package/reactHooks/state/useComponentScreenState.ts +45 -0
  98. package/reactHooks/state/useRivers.ts +1 -1
  99. package/reactHooks/usePluginConfiguration.ts +2 -2
  100. package/reactHooks/utils/__tests__/index.test.js +1 -1
  101. package/rectUtils/index.ts +2 -2
  102. package/screenPickerUtils/index.ts +5 -0
  103. package/screenState/__tests__/index.test.ts +1 -1
  104. package/stringUtils/index.ts +1 -1
  105. package/testUtils/index.tsx +21 -30
  106. package/typeGuards/index.ts +0 -4
  107. package/utils/__tests__/clone.test.ts +158 -0
  108. package/utils/clone.ts +7 -0
  109. package/utils/index.ts +1 -13
  110. package/utils/path.ts +3 -6
  111. package/utils/pathOr.ts +1 -5
  112. package/zappFrameworkUtils/HookCallback/callbackNavigationAction.ts +1 -1
  113. package/zappFrameworkUtils/HookCallback/hookCallbackManifestExtensions.config.js +1 -1
  114. package/zappFrameworkUtils/loginPluginUtils.ts +1 -1
  115. package/adsUtils/__tests__/createVMAP.test.ts +0 -419
  116. package/appDataUtils/__tests__/urlScheme.test.ts +0 -678
  117. package/appUtils/focusManagerAux/utils/index.ios.ts +0 -122
  118. package/cloudEventsUtils/__tests__/index.test.ts +0 -529
  119. package/enumUtils/__tests__/getEnumKeyByEnumValue.test.ts +0 -207
  120. package/errorUtils/__tests__/GeneralError.test.ts +0 -97
  121. package/errorUtils/__tests__/HttpStatusCode.test.ts +0 -344
  122. package/errorUtils/__tests__/MissingPluginError.test.ts +0 -113
  123. package/errorUtils/__tests__/NetworkError.test.ts +0 -202
  124. package/errorUtils/__tests__/getParsedResponse.test.ts +0 -188
  125. package/errorUtils/__tests__/invariant.test.ts +0 -112
  126. package/numberUtils/__tests__/toPositiveNumber.test.ts +0 -165
  127. package/reactHooks/analytics/__tests__/useSendAnalyticsOnPress.test.ts +0 -537
  128. package/reactHooks/dev/__tests__/useReRenderLog.test.ts +0 -188
  129. package/reactHooks/ui/__tests__/useFadeOutWhenBlurred.test.ts +0 -580
  130. package/rectUtils/__tests__/index.test.ts +0 -549
  131. package/screenPickerUtils/__tests__/index.test.ts +0 -333
  132. package/searchUtils/const.ts +0 -7
  133. package/searchUtils/index.ts +0 -3
  134. package/time/__tests__/BackgroundTimer.test.ts +0 -156
  135. package/time/__tests__/Timer.test.ts +0 -236
  136. package/typeGuards/__tests__/isString.test.ts +0 -21
  137. package/utils/__tests__/mergeRight.test.ts +0 -48
  138. package/utils/__tests__/selectors.test.ts +0 -124
  139. package/utils/mergeRight.ts +0 -5
  140. package/utils/selectors.ts +0 -46
@@ -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
 
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { View } from "react-native";
3
- import { cleanup, renderHook } from "@testing-library/react-native";
3
+ import { cleanup, renderHook } from "@testing-library/react-hooks";
4
4
  import configureStore from "redux-mock-store";
5
5
  import { Provider } from "react-redux";
6
6
 
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { renderHook, cleanup } from "@testing-library/react-native";
2
+ import { renderHook, cleanup } from "@testing-library/react-hooks";
3
3
  import configureStore from "redux-mock-store";
4
4
  import { Provider } from "react-redux";
5
5
 
@@ -3,10 +3,7 @@ import memoizee from "memoizee";
3
3
  import * as R from "ramda";
4
4
 
5
5
  import { CellRendererResolver } from "@applicaster/zapp-react-native-ui-components/Components/CellRendererResolver";
6
- import {
7
- usePlugins,
8
- useCellStyles,
9
- } from "@applicaster/zapp-react-native-redux";
6
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
10
7
  import { useDimensions } from "../layout";
11
8
  import { useIsRTL } from "../../localizationUtils";
12
9
 
@@ -56,8 +53,7 @@ export function useCellResolver({
56
53
  updateForInactiveScreens: false,
57
54
  });
58
55
 
59
- const plugins = usePlugins();
60
- const cellStyles = useCellStyles();
56
+ const { plugins, cellStyles } = usePickFromState(["plugins", "cellStyles"]);
61
57
  const isRTL = useIsRTL();
62
58
 
63
59
  const options = {
@@ -1,12 +1,10 @@
1
1
  /// <reference types="@applicaster/applicaster-types" />
2
2
  import * as React from "react";
3
3
 
4
+ import { coreLogger } from "@applicaster/zapp-react-native-utils/logger";
5
+
4
6
  import { findComponentByType } from "@applicaster/zapp-react-native-utils/pluginUtils";
5
- import {
6
- usePlugins,
7
- useAppSelector,
8
- selectComponents,
9
- } from "@applicaster/zapp-react-native-redux";
7
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
10
8
 
11
9
  type Decorator = (component: React.Component<any>) => React.Component<any>;
12
10
  type Watcher = Array<any>;
@@ -19,11 +17,9 @@ export function useComponentResolver(
19
17
  { componentType, decorators }: Props,
20
18
  watchers?: Watcher
21
19
  ): React.ComponentType<any> {
22
- const plugins = usePlugins();
23
-
24
- const components = useAppSelector(selectComponents);
20
+ const { plugins, components } = usePickFromState(["plugins", "components"]);
25
21
 
26
- return React.useMemo(
22
+ const component = React.useMemo(
27
23
  () =>
28
24
  findComponentByType({
29
25
  components,
@@ -33,4 +29,12 @@ export function useComponentResolver(
33
29
  }),
34
30
  watchers
35
31
  );
32
+
33
+ if (!component) {
34
+ coreLogger.warn({
35
+ message: `useComponentResolver: Component of type ${componentType} not found`,
36
+ });
37
+ }
38
+
39
+ return component;
36
40
  }
@@ -1,8 +1,8 @@
1
1
  import * as React from "react";
2
2
  import { Provider } from "react-redux";
3
- import { renderHook } from "@testing-library/react-native";
3
+ import { renderHook } from "@testing-library/react-hooks";
4
4
  import configureStore from "redux-mock-store";
5
- import { thunk } from "redux-thunk";
5
+ import thunk from "redux-thunk";
6
6
 
7
7
  const mockStore = configureStore([thunk]);
8
8
 
@@ -0,0 +1,103 @@
1
+ import { renderHook } from "@testing-library/react-native";
2
+ import { useCurrentScreenIsHook } from "../useCurrentScreenIsHook";
3
+
4
+ import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
5
+ import { last } from "@applicaster/zapp-react-native-utils/utils";
6
+ import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
7
+
8
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks");
9
+ jest.mock("@applicaster/zapp-react-native-utils/utils");
10
+ jest.mock("@applicaster/zapp-react-native-utils/booleanUtils");
11
+
12
+ const mockUseNavigation = useNavigation as jest.Mock;
13
+ const mockLast = last as jest.Mock;
14
+ const mockToBoolean = toBooleanWithDefaultFalse as jest.Mock;
15
+
16
+ describe("useCurrentScreenIsHook", () => {
17
+ beforeEach(() => {
18
+ jest.clearAllMocks();
19
+
20
+ // sensible defaults
21
+ mockUseNavigation.mockReturnValue({ mainStack: [] });
22
+ mockLast.mockReturnValue(undefined);
23
+ mockToBoolean.mockReturnValue(false);
24
+ });
25
+
26
+ it("returns true when last route includes 'hook'", () => {
27
+ const stack = [{ route: "some-hook-screen" }];
28
+
29
+ mockUseNavigation.mockReturnValue({ mainStack: stack });
30
+ mockLast.mockReturnValue(stack[0]);
31
+ mockToBoolean.mockReturnValue(true);
32
+
33
+ const { result } = renderHook(() => useCurrentScreenIsHook());
34
+
35
+ expect(mockLast).toHaveBeenCalledWith(stack);
36
+ expect(mockToBoolean).toHaveBeenCalledWith(true);
37
+ expect(result.current).toBe(true);
38
+ });
39
+
40
+ it("returns false when last route does not include 'hook'", () => {
41
+ const stack = [{ route: "home-screen" }];
42
+
43
+ mockUseNavigation.mockReturnValue({ mainStack: stack });
44
+ mockLast.mockReturnValue(stack[0]);
45
+ mockToBoolean.mockReturnValue(false);
46
+
47
+ const { result } = renderHook(() => useCurrentScreenIsHook());
48
+
49
+ expect(mockToBoolean).toHaveBeenCalledWith(false);
50
+ expect(result.current).toBe(false);
51
+ });
52
+
53
+ it("returns false when route is undefined", () => {
54
+ const stack = [{}];
55
+
56
+ mockUseNavigation.mockReturnValue({ mainStack: stack });
57
+ mockLast.mockReturnValue(stack[0]);
58
+ mockToBoolean.mockReturnValue(false);
59
+
60
+ const { result } = renderHook(() => useCurrentScreenIsHook());
61
+
62
+ expect(mockToBoolean).toHaveBeenCalledWith(undefined);
63
+ expect(result.current).toBe(false);
64
+ });
65
+
66
+ it("returns false when last(mainStack) is undefined (empty stack)", () => {
67
+ mockUseNavigation.mockReturnValue({ mainStack: [] });
68
+ mockLast.mockReturnValue(undefined);
69
+ mockToBoolean.mockReturnValue(false);
70
+
71
+ const { result } = renderHook(() => useCurrentScreenIsHook());
72
+
73
+ expect(mockLast).toHaveBeenCalledWith([]);
74
+ expect(mockToBoolean).toHaveBeenCalledWith(undefined);
75
+ expect(result.current).toBe(false);
76
+ });
77
+
78
+ it("uses default empty array when mainStack is undefined", () => {
79
+ mockUseNavigation.mockReturnValue({});
80
+ mockLast.mockReturnValue(undefined);
81
+ mockToBoolean.mockReturnValue(false);
82
+
83
+ const { result } = renderHook(() => useCurrentScreenIsHook());
84
+
85
+ expect(mockLast).toHaveBeenCalledWith([]);
86
+ expect(result.current).toBe(false);
87
+ });
88
+
89
+ it("passes correct boolean result from includes('hook')", () => {
90
+ const stack = [{ route: "hook" }];
91
+
92
+ mockUseNavigation.mockReturnValue({ mainStack: stack });
93
+ mockLast.mockReturnValue(stack[0]);
94
+
95
+ // simulate actual includes result flowing through
96
+ mockToBoolean.mockImplementation((val) => Boolean(val));
97
+
98
+ const { result } = renderHook(() => useCurrentScreenIsHook());
99
+
100
+ expect(mockToBoolean).toHaveBeenCalledWith(true);
101
+ expect(result.current).toBe(true);
102
+ });
103
+ });
@@ -0,0 +1,94 @@
1
+ import { renderHook } from "@testing-library/react-native";
2
+ import { useCurrentScreenIsStartupHook } from "../useCurrentScreenIsStartupHook";
3
+
4
+ import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
5
+ import { isFilledArray } from "@applicaster/zapp-react-native-utils/arrayUtils";
6
+
7
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks");
8
+ jest.mock("@applicaster/zapp-react-native-utils/arrayUtils");
9
+
10
+ const mockUseNavigation = useNavigation as jest.Mock;
11
+ const mockIsFilledArray = isFilledArray as jest.Mock;
12
+
13
+ describe("useCurrentScreenIsStartupHook", () => {
14
+ beforeEach(() => {
15
+ jest.clearAllMocks();
16
+ });
17
+
18
+ it("returns true when startUpHooks is a filled array", () => {
19
+ mockUseNavigation.mockReturnValue({
20
+ startUpHooks: ["hook1"],
21
+ });
22
+
23
+ mockIsFilledArray.mockReturnValue(true);
24
+
25
+ const { result } = renderHook(() => useCurrentScreenIsStartupHook());
26
+
27
+ expect(result.current).toBe(true);
28
+ expect(mockIsFilledArray).toHaveBeenCalledWith(["hook1"]);
29
+ });
30
+
31
+ it('returns true when startUpHooks is "in_process"', () => {
32
+ mockUseNavigation.mockReturnValue({
33
+ startUpHooks: "in_process",
34
+ });
35
+
36
+ mockIsFilledArray.mockReturnValue(false);
37
+
38
+ const { result } = renderHook(() => useCurrentScreenIsStartupHook());
39
+
40
+ expect(result.current).toBe(true);
41
+ expect(mockIsFilledArray).toHaveBeenCalledWith("in_process");
42
+ });
43
+
44
+ it("returns false when startUpHooks is empty array", () => {
45
+ mockUseNavigation.mockReturnValue({
46
+ startUpHooks: [],
47
+ });
48
+
49
+ mockIsFilledArray.mockReturnValue(false);
50
+
51
+ const { result } = renderHook(() => useCurrentScreenIsStartupHook());
52
+
53
+ expect(result.current).toBe(false);
54
+ expect(mockIsFilledArray).toHaveBeenCalledWith([]);
55
+ });
56
+
57
+ it("returns false when startUpHooks is undefined", () => {
58
+ mockUseNavigation.mockReturnValue({
59
+ startUpHooks: undefined,
60
+ });
61
+
62
+ mockIsFilledArray.mockReturnValue(false);
63
+
64
+ const { result } = renderHook(() => useCurrentScreenIsStartupHook());
65
+
66
+ expect(result.current).toBe(false);
67
+ expect(mockIsFilledArray).toHaveBeenCalledWith(undefined);
68
+ });
69
+
70
+ it("returns false when startUpHooks is null", () => {
71
+ mockUseNavigation.mockReturnValue({
72
+ startUpHooks: null,
73
+ });
74
+
75
+ mockIsFilledArray.mockReturnValue(false);
76
+
77
+ const { result } = renderHook(() => useCurrentScreenIsStartupHook());
78
+
79
+ expect(result.current).toBe(false);
80
+ expect(mockIsFilledArray).toHaveBeenCalledWith(null);
81
+ });
82
+
83
+ it("prioritizes filled array over string comparison", () => {
84
+ mockUseNavigation.mockReturnValue({
85
+ startUpHooks: ["hook1"],
86
+ });
87
+
88
+ mockIsFilledArray.mockReturnValue(true);
89
+
90
+ const { result } = renderHook(() => useCurrentScreenIsStartupHook());
91
+
92
+ expect(result.current).toBe(true);
93
+ });
94
+ });
@@ -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.mock(
4
4
  "@applicaster/zapp-react-native-ui-components/Components/River/useScreenConfiguration",