@applicaster/zapp-react-native-ui-components 13.0.0-alpha.3013227535 → 13.0.0-alpha.3044917147

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 (159) hide show
  1. package/Components/AppContainer/__tests__/AppContainer.test.js +4 -6
  2. package/Components/AudioPlayer/AudioPlayer.tsx +5 -9
  3. package/Components/AudioPlayer/AudioPlayerLayout.tsx +8 -9
  4. package/Components/AudioPlayer/__tests__/Runtime.test.js +5 -8
  5. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +54 -111
  6. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +36 -20
  7. package/Components/AudioPlayer/__tests__/artWork.test.js +3 -5
  8. package/Components/AudioPlayer/__tests__/audioPlayer.test.js +3 -5
  9. package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +7 -8
  10. package/Components/AudioPlayer/__tests__/channel.test.js +3 -5
  11. package/Components/AudioPlayer/__tests__/summary.test.js +3 -5
  12. package/Components/AudioPlayer/__tests__/title.test.js +3 -5
  13. package/Components/AudioPlayer/helpers.tsx +1 -2
  14. package/Components/BaseFocusable/index.tsx +1 -2
  15. package/Components/Cell/Cell.tsx +4 -13
  16. package/Components/Cell/CellWithFocusable.tsx +50 -59
  17. package/Components/Cell/CellWrapper.tsx +18 -0
  18. package/Components/Cell/TvOSCellComponent.tsx +20 -22
  19. package/Components/Cell/__tests__/CellWIthFocusable.test.js +13 -6
  20. package/Components/Cell/index.js +3 -1
  21. package/Components/Cell/styles.ts +17 -0
  22. package/Components/CellRendererResolver/__tests__/cellRendererResolver.test.js +46 -48
  23. package/Components/CellRendererResolver/index.ts +2 -1
  24. package/Components/ComponentResolver/__tests__/__snapshots__/componentResolver.test.js.snap +1 -42
  25. package/Components/ComponentResolver/__tests__/componentResolver.test.js +16 -22
  26. package/Components/ContentScreen/__tests__/contentScreen.test.js +3 -3
  27. package/Components/ErrorScreen/index.tsx +14 -6
  28. package/Components/Focusable/Focusable.tsx +1 -0
  29. package/Components/Focusable/FocusableTvOS.tsx +5 -1
  30. package/Components/Focusable/index.android.tsx +10 -3
  31. package/Components/FocusableCell/index.tsx +1 -1
  32. package/Components/FocusableGroup/FocusableTvOS.tsx +34 -86
  33. package/Components/FocusableGroup/index.tsx +0 -3
  34. package/Components/FocusableList/index.tsx +26 -9
  35. package/Components/FocusableScrollView/index.tsx +43 -13
  36. package/Components/GeneralContentScreen/GeneralContentScreen.tsx +3 -0
  37. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +4 -2
  38. package/Components/GeneralContentScreen/utils/useEventAlerts.ts +30 -0
  39. package/Components/HandlePlayable/HandlePlayable.tsx +21 -27
  40. package/Components/Layout/TV/LayoutBackground.tsx +28 -0
  41. package/Components/Layout/TV/NavBarContainer.tsx +19 -23
  42. package/Components/Layout/TV/ScreenContainer.tsx +8 -2
  43. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +5 -0
  44. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +2 -1
  45. package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +3 -2
  46. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +3 -2
  47. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +15 -10
  48. package/Components/Layout/TV/__tests__/index.test.tsx +8 -2
  49. package/Components/Layout/TV/index.tsx +6 -20
  50. package/Components/Layout/TV/index.web.tsx +4 -1
  51. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -3
  52. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +4 -3
  53. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +11 -7
  54. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +2 -2
  55. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/const.ts +3 -0
  56. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -6
  57. package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +2 -8
  58. package/Components/MasterCell/__tests__/__snapshots__/elementMapper.test.js.snap +4 -12
  59. package/Components/MasterCell/__tests__/__snapshots__/masterCell.test.js.snap +0 -229
  60. package/Components/MasterCell/__tests__/elementMapper.test.js +18 -5
  61. package/Components/MasterCell/__tests__/masterCell.test.js +26 -26
  62. package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +2 -2
  63. package/Components/MasterCell/utils/behaviorProvider.ts +136 -0
  64. package/Components/MasterCell/utils/index.ts +8 -134
  65. package/Components/ModalComponent/BottomSheetModalContent.tsx +66 -54
  66. package/Components/ModalComponent/Button/Item.tsx +6 -5
  67. package/Components/ModalComponent/Button/assets.ts +1 -1
  68. package/Components/ModalComponent/Button/index.tsx +45 -62
  69. package/Components/ModalComponent/Header/index.tsx +12 -11
  70. package/Components/ModalComponent/utils.ts +55 -7
  71. package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +2 -2
  72. package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +2 -2
  73. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -5
  74. package/Components/OfflineHandler/utils/index.ts +1 -1
  75. package/Components/PlayerContainer/PlayerContainer.tsx +63 -54
  76. package/Components/PlayerContainer/ProgramInfo/index.tsx +2 -2
  77. package/Components/PlayerImageBackground/index.tsx +1 -1
  78. package/Components/River/ComponentsMap/ComponentsMap.tsx +53 -68
  79. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +78 -51
  80. package/Components/River/RiverFooter.tsx +39 -9
  81. package/Components/River/RiverItem.tsx +43 -3
  82. package/Components/River/TV/index.tsx +6 -1
  83. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +107 -32
  84. package/Components/River/__tests__/__snapshots__/river.test.js.snap +20 -82
  85. package/Components/River/__tests__/componentsMap.test.js +3 -4
  86. package/Components/River/__tests__/river.test.js +75 -40
  87. package/Components/RouteManager/TestId.tsx +1 -5
  88. package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +10 -4
  89. package/Components/RouteManager/__tests__/routeManager.test.js +29 -14
  90. package/Components/RouteManager/__tests__/testId.test.js +4 -6
  91. package/Components/Screen/TV/__tests__/index.web.test.tsx +26 -0
  92. package/Components/Screen/TV/index.web.tsx +5 -6
  93. package/Components/Screen/__tests__/Screen.test.tsx +22 -14
  94. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +2 -2
  95. package/Components/Screen/hooks.ts +53 -0
  96. package/Components/Screen/index.tsx +16 -43
  97. package/Components/ScreenResolver/__tests__/screenResolver.test.js +91 -70
  98. package/Components/Tabs/Tab.tsx +5 -3
  99. package/Components/TextInputTv/index.tsx +2 -1
  100. package/Components/TopMarginApplicator/TopMarginApplicator.tsx +2 -3
  101. package/Components/TrackedView/index.tsx +1 -0
  102. package/Components/Transitioner/AnimationManager.js +15 -15
  103. package/Components/Transitioner/Scene.tsx +1 -1
  104. package/Components/Transitioner/Transitioner.tsx +3 -3
  105. package/Components/Transitioner/__tests__/Scene.test.js +25 -14
  106. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +12 -68
  107. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +2 -2
  108. package/Components/Transitioner/__tests__/transitioner.test.js +13 -4
  109. package/Components/VideoLive/PlayerLiveImageComponent.tsx +7 -3
  110. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -0
  111. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +1 -1
  112. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +46 -30
  113. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +3 -3
  114. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +45 -21
  115. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +13 -6
  116. package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +108 -0
  117. package/Components/VideoModal/ModalAnimation/const.ts +5 -0
  118. package/Components/VideoModal/ModalAnimation/index.ts +2 -0
  119. package/Components/VideoModal/ModalAnimation/utils.ts +30 -0
  120. package/Components/VideoModal/PlayerDetails.tsx +18 -10
  121. package/Components/VideoModal/PlayerWrapper.tsx +37 -24
  122. package/Components/VideoModal/VideoModal.tsx +19 -4
  123. package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +2 -40
  124. package/Components/VideoModal/utils.ts +3 -4
  125. package/Components/Viewport/ViewportAware/__tests__/__snapshots__/viewportAware.test.js.snap +24 -36
  126. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -18
  127. package/Components/Viewport/__tests__/utils.test.js +5 -4
  128. package/Components/ZappUIComponent/Placeholder.tsx +3 -1
  129. package/Components/ZappUIComponent/__tests__/{ZappUIComponent.test.js → ZappUIComponent.test.tsx} +26 -10
  130. package/Components/ZappUIComponent/index.tsx +4 -17
  131. package/Components/default-cell-renderer/__tests__/defaultCellRenderer.test.tsx +20 -17
  132. package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/__tests__/DefaultCell.test.tsx +15 -11
  133. package/Contexts/ComponentsMapOffsetContext/index.tsx +49 -0
  134. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +4 -10
  135. package/Contexts/HeaderOffsetContext/index.tsx +4 -6
  136. package/Contexts/ScreenContext/index.tsx +3 -10
  137. package/Contexts/ScreenLayoutContext/index.tsx +5 -3
  138. package/Decorators/Navigator/__tests__/navigator.test.js +16 -16
  139. package/Decorators/Navigator/index.tsx +1 -1
  140. package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +18 -24
  141. package/Decorators/RiverResolver/index.tsx +6 -8
  142. package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +29 -22
  143. package/Decorators/ZappPipesDataConnector/index.tsx +4 -30
  144. package/package.json +7 -11
  145. package/tsconfig.json +2 -3
  146. package/.babelrc +0 -8
  147. package/Components/Cell/CellStyles/FallbackCellStyle/index.js +0 -157
  148. package/Components/Cell/CellStyles/Hero/index.js +0 -111
  149. package/Components/Cell/CellStyles/ScreenSelector/index.js +0 -68
  150. package/Components/Cell/CellStyles/cellStylesResolver.ts +0 -19
  151. package/Components/Cell/CellStyles/colors.js +0 -40
  152. package/Components/Cell/CellStyles/index.js +0 -15
  153. package/Components/CellRendererResolver/__tests__/__snapshots__/cellRendererResolver.test.js.snap +0 -53
  154. package/Components/RouteManager/__tests__/__snapshots__/testId.test.js.snap +0 -17
  155. package/Components/ScreenResolver/__tests__/__snapshots__/screenResolver.test.js.snap +0 -17
  156. package/Components/ZappUIComponent/__tests__/__snapshots__/ZappUIComponent.test.js.snap +0 -91
  157. package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +0 -338
  158. package/Decorators/Navigator/__tests__/__snapshots__/navigator.test.js.snap +0 -18
  159. package/Decorators/RiverResolver/__tests__/__snapshots__/riverResolver.test.tsx.snap +0 -28
@@ -1,31 +1,46 @@
1
1
  import React from "react";
2
- import { shallow } from "enzyme";
3
- import { shallowToJson } from "enzyme-to-json";
2
+ import { render } from "@testing-library/react-native";
4
3
 
5
- const pathname = "/river/A1234";
6
- const screenData = { id: "A1234" };
4
+ import { RouteManager } from "../";
5
+
6
+ const mockPathname = "/river/A1234";
7
+ const mockScreenData = { id: "A1234" };
7
8
 
8
9
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
9
- useRoute: jest.fn(() => ({ pathname: pathname, screenData: screenData })),
10
+ useRoute: jest.fn(() => ({
11
+ pathname: mockPathname,
12
+ screenData: mockScreenData,
13
+ })),
10
14
  }));
11
15
 
12
- const {
13
- ScreenResolver,
14
- } = require("@applicaster/zapp-react-native-ui-components/Components/ScreenResolver");
16
+ jest.mock(
17
+ "@applicaster/zapp-react-native-ui-components/Components/ScreenResolver",
18
+ () => {
19
+ const { View } = jest.requireActual("react-native");
15
20
 
16
- const { RouteManager } = require("../index");
21
+ return {
22
+ ScreenResolver: (props) => <View testID="screen-resolver" {...props} />,
23
+ };
24
+ }
25
+ );
17
26
 
18
27
  describe("<RouteManager />", () => {
19
- const wrapper = shallow(
20
- <RouteManager pathname={pathname} screenData={screenData} />
21
- );
28
+ let wrapper;
29
+
30
+ beforeEach(() => {
31
+ jest.clearAllMocks();
32
+
33
+ wrapper = render(
34
+ <RouteManager pathname={mockPathname} screenData={mockScreenData} />
35
+ );
36
+ });
22
37
 
23
38
  it("renders correctly", () => {
24
- expect(shallowToJson(wrapper)).toMatchSnapshot();
39
+ expect(wrapper.toJSON()).toMatchSnapshot();
25
40
  });
26
41
 
27
42
  it("passes the correct props to ScreenResolver", () => {
28
- expect(wrapper.find(ScreenResolver).props()).toEqual({
43
+ expect(wrapper.getByTestId("screen-resolver").props).toMatchObject({
29
44
  pathname: "/river/A1234",
30
45
  screenType: "river",
31
46
  screenId: "A1234",
@@ -2,8 +2,8 @@
2
2
  /* eslint-disable react/prop-types */
3
3
  import React from "react";
4
4
  import { View, Text } from "react-native";
5
- import { shallow } from "enzyme";
6
- import { shallowToJson } from "enzyme-to-json";
5
+
6
+ import { render } from "@testing-library/react-native";
7
7
 
8
8
  import { TestId } from "../TestId";
9
9
 
@@ -17,14 +17,12 @@ const screenId = "A1234";
17
17
 
18
18
  describe("TestId", () => {
19
19
  it("renders correctly and assigns the testID to a wrapping view", () => {
20
- const wrapper = shallow(
20
+ const wrapper = render(
21
21
  <TestId screenId={screenId}>
22
22
  <TestComponent name="dev test" />
23
23
  </TestId>
24
24
  );
25
25
 
26
- expect(shallowToJson(wrapper)).toMatchSnapshot();
27
- expect(wrapper.find(View).prop("testID")).toEqual(screenId);
28
- expect(wrapper.find(View).prop("accessibilityLabel")).toEqual(screenId);
26
+ expect(wrapper.getByTestId(screenId)).toBeTruthy();
29
27
  });
30
28
  });
@@ -0,0 +1,26 @@
1
+ const {
2
+ useScreenBackgroundColor,
3
+ } = require("@applicaster/zapp-react-native-utils/reactHooks/screen");
4
+
5
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen", () => ({
6
+ useScreenBackgroundColor: jest.fn(),
7
+ useNavbarState: jest.fn().mockReturnValue({ visible: true }),
8
+ }));
9
+
10
+ describe("TV Screen Component", () => {
11
+ it("uses the useScreenBackgroundColor hook with the correct screen ID", () => {
12
+ useScreenBackgroundColor.mockReturnValue("#FF0000");
13
+
14
+ expect(useScreenBackgroundColor("test-screen-id")).toBe("#FF0000");
15
+
16
+ // Verify the hook was called with the correct screen ID
17
+ expect(useScreenBackgroundColor).toHaveBeenCalledWith("test-screen-id");
18
+ });
19
+
20
+ it("returns 'transparent' when the screen background color is not defined", () => {
21
+ useScreenBackgroundColor.mockReturnValue("transparent");
22
+
23
+ // Verify the hook returns 'transparent'
24
+ expect(useScreenBackgroundColor("test-screen-id")).toBe("transparent");
25
+ });
26
+ });
@@ -92,6 +92,10 @@ const getNavigations = ({
92
92
  return fallbackNavigations;
93
93
  };
94
94
 
95
+ const onRelease = () => {
96
+ focusManager.setInitialFocus();
97
+ };
98
+
95
99
  export const Screen = ({ route, Components }: Props) => {
96
100
  if (isNilOrEmpty(route)) {
97
101
  throw Error("Required props: route is missing");
@@ -152,12 +156,7 @@ export const Screen = ({ route, Components }: Props) => {
152
156
  const isScreenActive = useIsScreenActive();
153
157
 
154
158
  return (
155
- <FreezeWithCallback
156
- freeze={!isScreenActive}
157
- onRelease={() => {
158
- focusManager.setInitialFocus();
159
- }}
160
- >
159
+ <FreezeWithCallback freeze={!isScreenActive} onRelease={onRelease}>
161
160
  <View style={[styles.container, { backgroundColor }]}>
162
161
  <NavBarContainer isVisible={isNavBarVisible} onReady={noop}>
163
162
  <NavBar
@@ -68,21 +68,21 @@ jest.mock(
68
68
  })
69
69
  );
70
70
 
71
- jest.mock(
72
- "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenData",
73
- () => ({
74
- useScreenData: jest.fn(() => ({
75
- id: "testId",
76
- navigations: [{ id: "testId", category: "nav_bar" }],
77
- })),
78
- })
79
- );
80
-
81
71
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
82
72
  isNavBarVisible: mockIsNavBarVisible,
83
- useRoute: jest.fn(() => ({
84
- pathname: "/river/testId",
85
- screenData: { id: "testId" },
73
+ useIsScreenActive: jest.fn().mockReturnValue(true),
74
+ }));
75
+
76
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
77
+ useCurrentScreenData: jest.fn(() => ({
78
+ id: "testId",
79
+ })),
80
+ useNavbarState: jest.fn(() => ({
81
+ title: "Test Title",
82
+ })),
83
+ useScreenData: jest.fn(() => ({
84
+ id: "testId",
85
+ navigations: [{ id: "testId", category: "nav_bar" }],
86
86
  })),
87
87
  useNavigation: jest.fn(() => ({
88
88
  canGoBack: () => false,
@@ -91,7 +91,15 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
91
91
  screenData: { id: "testId" },
92
92
  data: { screen: { id: "testId" } },
93
93
  })),
94
- useIsScreenActive: jest.fn().mockReturnValue(true),
94
+ useRoute: jest.fn(() => ({
95
+ pathname: "/river/testId",
96
+ screenData: { id: "testId" },
97
+ })),
98
+ useDimensions: jest.fn(() => ({
99
+ width: 1920,
100
+ height: 1080,
101
+ })),
102
+ useIsTablet: jest.fn(() => false),
95
103
  }));
96
104
 
97
105
  jest.mock("@applicaster/zapp-react-native-redux/hooks/usePickFromState", () => {
@@ -16,7 +16,7 @@ exports[`<Screen Component /> when the navbar should be hidden renders correctly
16
16
  pathname="/river/testId"
17
17
  selected="testId"
18
18
  testID="navBar"
19
- title=""
19
+ title="Test Title"
20
20
  />
21
21
  <View>
22
22
  <View
@@ -48,7 +48,7 @@ exports[`<Screen Component /> when the navbar should show renders correctly 1`]
48
48
  pathname="/river/testId"
49
49
  selected="testId"
50
50
  testID="navBar"
51
- title=""
51
+ title="Test Title"
52
52
  />
53
53
  <View>
54
54
  <View
@@ -0,0 +1,53 @@
1
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
2
+ import {
3
+ useGetScreenOrientation,
4
+ isOrientationCompatible,
5
+ } from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
6
+ import {
7
+ useCurrentScreenData,
8
+ useDimensions,
9
+ useRoute,
10
+ useIsTablet,
11
+ } from "@applicaster/zapp-react-native-utils/reactHooks";
12
+ import { useMemo, useEffect, useState } from "react";
13
+
14
+ export const useWaitForValidOrientation = () => {
15
+ const { width: screenWidth, height } = useDimensions("screen", {
16
+ fullDimensions: true,
17
+ updateForInactiveScreens: false,
18
+ });
19
+
20
+ const currentScreenData = useCurrentScreenData();
21
+
22
+ const { screenData } = useRoute();
23
+
24
+ const [readyState, setReadyState] = useState(false);
25
+
26
+ const isTablet = useIsTablet();
27
+
28
+ const { appData } = usePickFromState(["appData"]);
29
+ const isTabletPortrait = appData?.isTabletPortrait;
30
+
31
+ const layoutData = useMemo(
32
+ () => ({ isTablet, isTabletPortrait, width: screenWidth, height }),
33
+ [isTablet, isTabletPortrait, screenWidth, height]
34
+ );
35
+
36
+ const targetScreenData =
37
+ currentScreenData || (screenData as any)?.targetScreen || screenData;
38
+
39
+ const orientation = useGetScreenOrientation(targetScreenData);
40
+
41
+ const isReadyForDisplay = isOrientationCompatible({
42
+ orientation,
43
+ layoutData,
44
+ });
45
+
46
+ useEffect(() => {
47
+ if (isReadyForDisplay && !readyState) {
48
+ setReadyState(true);
49
+ }
50
+ }, [readyState, orientation, layoutData]);
51
+
52
+ return readyState;
53
+ };
@@ -2,31 +2,27 @@
2
2
  import React from "react";
3
3
  import { View } from "react-native";
4
4
  import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
5
- import {
6
- isOrientationCompatible,
7
- useGetScreenOrientation,
8
- } from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
9
5
 
10
6
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
11
7
  import { getComponentModule } from "@applicaster/zapp-react-native-utils/pluginUtils";
12
8
  import {
13
- shouldNavBarDisplayMenu,
14
9
  getNavBarProps,
15
10
  getScreenId,
11
+ shouldNavBarDisplayMenu,
16
12
  } from "@applicaster/zapp-react-native-utils/navigationUtils";
17
13
  import {
18
- useDimensions,
19
- useRoute,
20
14
  useCurrentScreenData,
21
15
  useNavbarState,
22
- useScreenData,
23
16
  useNavigation,
17
+ useRoute,
18
+ useScreenData,
24
19
  } from "@applicaster/zapp-react-native-utils/reactHooks";
25
20
  import { getNavigationPluginModule } from "@applicaster/zapp-react-native-app/App/Layout/layoutHelpers";
26
21
 
27
22
  import { RouteManager } from "../RouteManager";
28
23
  import { useScreenConfiguration } from "../River/useScreenConfiguration";
29
24
  import { isValidColor } from "./utils";
25
+ import { useWaitForValidOrientation } from "./hooks";
30
26
 
31
27
  const screenStyles = {
32
28
  flex: 1,
@@ -50,15 +46,6 @@ export function Screen(_props: Props) {
50
46
  const currentScreenData = useCurrentScreenData();
51
47
  const { backgroundColor } = useScreenConfiguration(currentScreenData.id);
52
48
 
53
- const {
54
- width: screenWidth,
55
- height,
56
- deviceInfo,
57
- } = useDimensions("screen", {
58
- updateForInactiveScreens: false,
59
- fullDimensions: true,
60
- });
61
-
62
49
  const { screenData, pathname } = useRoute();
63
50
 
64
51
  const currentRiver = useScreenData(
@@ -67,13 +54,6 @@ export function Screen(_props: Props) {
67
54
 
68
55
  const { title } = useNavbarState();
69
56
 
70
- const isTablet = deviceInfo?.isTablet;
71
-
72
- const { appData } = usePickFromState(["appData"]);
73
- const isTabletPortrait = appData?.isTabletPortrait;
74
-
75
- const layoutData = { isTablet, isTabletPortrait, width: screenWidth, height };
76
-
77
57
  const hasMenu = shouldNavBarDisplayMenu(currentRiver, plugins);
78
58
 
79
59
  const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(
@@ -109,30 +89,23 @@ export function Screen(_props: Props) {
109
89
  [theme.app_background_color, backgroundColor]
110
90
  );
111
91
 
112
- const targetScreenData =
113
- currentScreenData || (screenData as any)?.targetScreen || screenData;
114
-
115
- const orientation = useGetScreenOrientation(targetScreenData);
92
+ // Set ready state when screen is rotated to desired orientation
93
+ const isReady = useWaitForValidOrientation();
116
94
 
117
95
  // We prevent rendering of the screen until UI is actually rotated to screen desired orientation.
118
96
  // This saves unnecessary re-renders and user will not see distorted aspect screen.
119
- if (
120
- !isOrientationCompatible({
121
- orientation,
122
- layoutData,
123
- })
124
- ) {
125
- return <View style={style} />;
126
- }
127
-
128
97
  return (
129
98
  <View style={style}>
130
- {navBarProps && <NavBar {...navBarProps} hasMenu={hasMenu} />}
131
-
132
- <OfflineFallbackScreen>
133
- {/* @TODO RouteManager doesn't use props, can they be removed ? */}
134
- <RouteManager pathname={pathname} screenData={screenData} />
135
- </OfflineFallbackScreen>
99
+ {isReady ? (
100
+ <>
101
+ {navBarProps ? <NavBar {...navBarProps} hasMenu={hasMenu} /> : null}
102
+
103
+ <OfflineFallbackScreen>
104
+ {/* @TODO RouteManager doesn't use props, can they be removed ? */}
105
+ <RouteManager pathname={pathname} screenData={screenData} />
106
+ </OfflineFallbackScreen>
107
+ </>
108
+ ) : null}
136
109
  </View>
137
110
  );
138
111
  }
@@ -1,161 +1,180 @@
1
1
  import React from "react";
2
2
  import { View } from "react-native";
3
- import { shallow } from "enzyme";
4
- import { shallowToJson } from "enzyme-to-json";
3
+ import { renderWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
4
+
5
5
  const pluginConfiguration = { foo: "bar" };
6
6
 
7
- const ScreenType1 = jest.fn(() => <View />);
8
- const ScreenType2 = jest.fn(() => <View />);
9
- const PlayerController = jest.fn(() => <View />);
7
+ const MockModuleView = (testID) => {
8
+ // eslint-disable-next-line react/display-name
9
+ return function (props) {
10
+ return <View testID={testID} {...props} />;
11
+ };
12
+ };
13
+
14
+ const ScreenType1 = MockModuleView("screen_type_1");
15
+ const ScreenType2 = MockModuleView("screen_type_2");
16
+ const PlayerController = MockModuleView("player_controller");
10
17
 
11
18
  const mockScreenType3 = {
12
- module: jest.fn(() => <View />),
19
+ module: MockModuleView("screen_type_3"),
13
20
  name: "ScreenType3",
14
21
  type: "screen_type_3",
15
22
  configuration: pluginConfiguration,
16
23
  };
17
24
 
18
25
  const mockScreenType4 = {
19
- module: jest.fn(() => <View />),
26
+ module: MockModuleView("screen_type_4"),
20
27
  name: "ScreenType4",
21
28
  type: "screen_type_4",
22
29
  };
23
30
 
24
31
  const mockPlayerPlugin = {
25
- module: jest.fn(() => <View />),
32
+ module: MockModuleView("player_plugin"),
26
33
  name: "playerPlugin",
27
34
  type: "player",
28
35
  };
29
36
 
30
37
  const mockScreenPlugin = {
31
- module: jest.fn(() => <View />),
38
+ module: MockModuleView("screen_plugin"),
32
39
  type: "general",
33
40
  name: "Screen plugin",
34
41
  identifier: "screen-plugin",
35
42
  };
36
43
 
37
44
  const mockPluginWithConfig = {
38
- module: jest.fn(() => <View />),
45
+ module: MockModuleView("plugin_with_config"),
39
46
  type: "general",
40
47
  name: "Plugin with config",
41
48
  identifier: "plugin-with-config",
42
49
  configuration: pluginConfiguration,
43
50
  };
44
51
 
45
- const components = { ScreenType1, ScreenType2, PlayerController };
46
-
47
- const mockWithAnalytics = {
48
- sendOnClickEvent: jest.fn(),
49
- sendMenuClickEvent: jest.fn(),
50
- sendMenuToggleEvent: jest.fn(),
51
- sendBackButtonClickEvent: jest.fn(),
52
- sendOnNavItemClickEvent: jest.fn(),
53
- sendHeaderClickEvent: jest.fn(),
54
- sendHardwareBackButtonClickEvent: jest.fn(),
55
- sendScreenEvent: jest.fn(),
52
+ const mockComponents = { ScreenType1, ScreenType2, PlayerController };
53
+
54
+ const mockState = {
55
+ components: mockComponents,
56
+ plugins: [
57
+ mockScreenType3,
58
+ mockScreenType4,
59
+ mockPlayerPlugin,
60
+ mockScreenPlugin,
61
+ mockPluginWithConfig,
62
+ ],
63
+ rivers: {
64
+ A1234: {},
65
+ },
56
66
  };
57
67
 
58
- const mockUsePickFromState = jest.fn(() => {
59
- return {
60
- components,
61
- plugins: {
62
- ScreenType3: mockScreenType3,
63
- ScreenType4: mockScreenType4,
64
- playerPlugin: mockPlayerPlugin,
65
- ScreenPlugin: mockScreenPlugin,
66
- PluginWithConfig: mockPluginWithConfig,
67
- },
68
- };
69
- });
70
-
71
- jest.mock("@applicaster/zapp-react-native-utils/analyticsUtils", () => ({
72
- useAnalytics: jest.fn().mockReturnValue(mockWithAnalytics),
73
- }));
68
+ jest.mock(
69
+ "@applicaster/zapp-react-native-utils/analyticsUtils/helpers/hooks",
70
+ () => ({
71
+ useScreenAnalytics: jest.fn(),
72
+ })
73
+ );
74
74
 
75
- jest.mock("@applicaster/zapp-react-native-redux/hooks", () => ({
76
- usePickFromState: mockUsePickFromState,
77
- }));
75
+ jest.mock(
76
+ "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation",
77
+ () => ({
78
+ useNavigation: jest.fn(() => ({
79
+ closeVideoModal: jest.fn(),
80
+ videoModalState: {
81
+ mode: "test",
82
+ },
83
+ })),
84
+ })
85
+ );
78
86
 
79
- const mockUseScreenAnalytics = jest.fn();
87
+ jest.mock(
88
+ "@applicaster/zapp-react-native-utils/reactHooks/navigation/useRoute",
89
+ () => ({
90
+ useRoute: jest.fn(() => ({ screenId: "1234" })),
91
+ })
92
+ );
80
93
 
81
94
  jest.mock(
82
- "@applicaster/zapp-react-native-utils/analyticsUtils/helpers/hooks",
95
+ "@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive",
83
96
  () => ({
84
- useScreenAnalytics: mockUseScreenAnalytics,
97
+ useIsScreenActive: () => ({
98
+ isScreenActive: true,
99
+ }),
85
100
  })
86
101
  );
87
102
 
88
- jest.mock("react-redux", () => ({
89
- ...jest.requireActual("react-redux"),
90
- useDispatch: jest.fn(() => () => {}),
91
- }));
103
+ jest.mock("../../PlayerContainer", () => {
104
+ const { View } = jest.requireActual("react-native");
92
105
 
93
- jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
94
- useNavigation: jest.fn(() => ({
95
- videoModalState: {
96
- mode: "test",
97
- },
98
- })),
99
- useRoute: jest.fn(() => ({ screenId: "1234" })),
100
- }));
106
+ return {
107
+ PlayerContainer: (props) => (
108
+ <View {...props}>
109
+ <props.Player />
110
+ </View>
111
+ ),
112
+ };
113
+ });
101
114
 
102
- const { ScreenResolverComponent: ScreenResolver } = require("..");
115
+ const getWrapper = (screenId, screenType, screenData) => {
116
+ const ScreenResolver = require("../").ScreenResolverComponent;
103
117
 
104
- const getWrapper = (screenId, screenType, screenData) =>
105
- shallow(
118
+ return renderWithProviders(
106
119
  <ScreenResolver
107
120
  {...{
108
121
  screenId,
109
122
  screenType,
110
123
  screenData,
111
124
  }}
112
- />
125
+ />,
126
+ mockState
113
127
  );
128
+ };
114
129
 
115
130
  describe("<ScreenResolver />", () => {
116
131
  it("renders correctly", () => {
117
132
  const wrapper = getWrapper("1234", "screen_type_1", {});
118
133
 
119
- expect(shallowToJson(wrapper)).toMatchSnapshot();
134
+ expect(wrapper.getByTestId("screen_type_1")).toBeDefined();
120
135
  });
121
136
 
122
137
  it("picks screen from plugins if it exists", () => {
123
138
  const wrapper = getWrapper("A1234", "screen_type_3", {});
124
139
 
125
- expect(wrapper.find(mockScreenType3.module)).toHaveProperty("length", 1);
140
+ expect(wrapper.getByTestId("screen_type_3")).toBeDefined();
126
141
  });
127
142
 
128
143
  it("picks the screen from its identifier if it exists", () => {
129
144
  const wrapper = getWrapper("A1234", "screen-plugin", {});
130
145
 
131
- expect(wrapper.find(mockScreenPlugin.module)).toHaveProperty("length", 1);
146
+ expect(wrapper.getByTestId("screen_plugin")).toBeDefined();
132
147
  });
133
148
 
134
149
  it("picks screen from components if it doesn't exist in plugins", () => {
135
150
  const wrapper = getWrapper("A1234", "screen_type_2", {});
136
151
 
137
- expect(wrapper.find(ScreenType2)).toHaveProperty("length", 1);
152
+ expect(wrapper.getByTestId("screen_type_2")).toBeDefined();
138
153
  });
139
154
 
140
155
  it("renders the screen and passes screenId & locationState as props", () => {
141
156
  const wrapper = getWrapper("A1234", "screen_type_3", "foo");
142
157
 
143
- const screenWrapper = wrapper.find(mockScreenType3.module);
158
+ const screenWrapper = wrapper.getByTestId("screen_type_3");
144
159
 
145
- expect(screenWrapper.prop("screenId")).toEqual("A1234");
146
- expect(screenWrapper.prop("screenData")).toEqual("foo");
160
+ expect(screenWrapper.props).toMatchObject({
161
+ screenId: "A1234",
162
+ screenData: "foo",
163
+ });
147
164
  });
148
165
 
149
166
  it("renders null if the screen is not found", () => {
150
167
  const wrapper = getWrapper(null, "screen_type_5", {});
151
168
 
152
- expect(wrapper.getElement()).toBe(null);
169
+ expect(wrapper.queryAllByTestId("screen_type_5")).toBeEmpty();
153
170
  });
154
171
 
155
172
  it("injects the plugin configuration if it exists", () => {
156
173
  const wrapper = getWrapper("A1234", "plugin-with-config", {});
157
174
 
158
- expect(wrapper.find(mockPluginWithConfig.module).props()).toHaveProperty(
175
+ const screenWrapper = wrapper.getByTestId("plugin_with_config");
176
+
177
+ expect(screenWrapper.props).toHaveProperty(
159
178
  "configuration",
160
179
  expect.objectContaining(pluginConfiguration)
161
180
  );
@@ -164,7 +183,9 @@ describe("<ScreenResolver />", () => {
164
183
  it("injects the plugin configuration if it exists, even when plugin is resolved by type", () => {
165
184
  const wrapper = getWrapper("A1234", "screen_type_3", {});
166
185
 
167
- expect(wrapper.find(mockScreenType3.module).props()).toHaveProperty(
186
+ const screenWrapper = wrapper.getByTestId("screen_type_3");
187
+
188
+ expect(screenWrapper.props).toHaveProperty(
168
189
  "configuration",
169
190
  expect.objectContaining(pluginConfiguration)
170
191
  );
@@ -172,6 +193,6 @@ describe("<ScreenResolver />", () => {
172
193
 
173
194
  it("wraps the player with the playerController component when the screenType is playable", () => {
174
195
  const wrapper = getWrapper("A1234", "playable", {});
175
- expect(shallowToJson(wrapper)).toMatchSnapshot();
196
+ expect(wrapper.getByTestId("player_plugin")).toBeDefined();
176
197
  });
177
198
  });
@@ -1,11 +1,11 @@
1
1
  /* eslint-disable react-native/no-unused-styles */
2
2
  import React from "react";
3
3
  import * as R from "ramda";
4
- import { View, Text, StyleSheet, TouchableWithoutFeedback } from "react-native";
4
+ import { StyleSheet, Text, TouchableWithoutFeedback, View } from "react-native";
5
5
  import { useConfiguration } from "@applicaster/zapp-react-native-utils/reactHooks/configuration";
6
6
  import {
7
- getStyleForPlatform,
8
7
  applyStringTransformation,
8
+ getStyleForPlatform,
9
9
  } from "@applicaster/zapp-react-native-utils/configurationUtils";
10
10
 
11
11
  type Props = {
@@ -148,7 +148,9 @@ const Tab = ({ title, selected, handleOnPress }: Props, ref: any) => {
148
148
  <Text numberOfLines={1} style={styles.label}>
149
149
  {tabTitle}
150
150
  </Text>
151
- {selected && <View testID="underline" style={styles.underline} />}
151
+ {selected ? (
152
+ <View testID="underline" style={styles.underline} />
153
+ ) : null}
152
154
  </View>
153
155
  </View>
154
156
  </TouchableWithoutFeedback>