@applicaster/zapp-react-native-ui-components 14.0.0-alpha.2175196485 → 14.0.0-alpha.2292190333

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 (74) hide show
  1. package/Components/AudioPlayer/mobile/Layout.tsx +1 -1
  2. package/Components/AudioPlayer/tv/helpers.tsx +10 -3
  3. package/Components/BaseFocusable/index.tsx +23 -12
  4. package/Components/Cell/__tests__/CellWIthFocusable.test.js +3 -2
  5. package/Components/Cell/index.js +1 -1
  6. package/Components/ComponentResolver/index.ts +1 -1
  7. package/Components/FeedLoader/FeedLoader.tsx +6 -15
  8. package/Components/FeedLoader/FeedLoaderHOC.tsx +21 -0
  9. package/Components/FeedLoader/index.js +2 -8
  10. package/Components/Focusable/FocusableiOS.tsx +1 -1
  11. package/Components/Focusable/Touchable.tsx +6 -3
  12. package/Components/Focusable/index.android.tsx +11 -4
  13. package/Components/Focusable/index.tsx +1 -1
  14. package/Components/FocusableList/FocusableItem.tsx +22 -3
  15. package/Components/FocusableList/FocusableListItemWrapper.tsx +2 -1
  16. package/Components/FocusableList/index.tsx +14 -7
  17. package/Components/FreezeWithCallback/__tests__/index.test.tsx +67 -43
  18. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +42 -59
  19. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +13 -10
  20. package/Components/Layout/TV/LayoutBackground.tsx +1 -1
  21. package/Components/Layout/TV/__tests__/index.test.tsx +0 -1
  22. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
  23. package/Components/MasterCell/DefaultComponents/Button.tsx +1 -1
  24. package/Components/MasterCell/DefaultComponents/Image/hoc/withDimensions.tsx +1 -1
  25. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +1 -1
  26. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +10 -10
  27. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +18 -18
  28. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/index.test.tsx +10 -10
  29. package/Components/MasterCell/utils/behaviorProvider.ts +82 -14
  30. package/Components/MasterCell/utils/index.ts +11 -5
  31. package/Components/OfflineHandler/__tests__/index.test.tsx +26 -35
  32. package/Components/PlayerContainer/ErrorDisplay/index.ts +1 -1
  33. package/Components/PlayerContainer/ProgramInfo/index.tsx +1 -1
  34. package/Components/PlayerContainer/index.ts +1 -1
  35. package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +378 -0
  36. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +2 -2
  37. package/Components/River/RefreshControl.tsx +11 -17
  38. package/Components/River/TV/River.tsx +2 -17
  39. package/Components/River/TV/index.tsx +3 -1
  40. package/Components/River/TV/withPipesV1DataLoader.tsx +43 -0
  41. package/Components/River/TV/withRiverDataLoader.tsx +17 -0
  42. package/Components/River/__tests__/river.test.js +12 -26
  43. package/Components/River/index.tsx +1 -1
  44. package/Components/Screen/__tests__/Screen.test.tsx +28 -29
  45. package/Components/Tabs/Tabs.tsx +2 -3
  46. package/Components/Touchable/__tests__/touchable.test.tsx +12 -17
  47. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +3 -9
  48. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +24 -8
  49. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -5
  50. package/Contexts/ConfigutaionContext/__tests__/ConfigurationProvider.test.tsx +3 -3
  51. package/Contexts/ScreenContext/index.tsx +46 -6
  52. package/Decorators/ConfigurationWrapper/__tests__/withConfigurationProvider.test.tsx +3 -3
  53. package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +221 -209
  54. package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +14 -16
  55. package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -20
  56. package/Decorators/RiverFeedLoader/index.tsx +22 -4
  57. package/Decorators/RiverFeedLoader/utils/index.ts +0 -18
  58. package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +3 -6
  59. package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -0
  60. package/Decorators/ZappPipesDataConnector/__tests__/NullFeedResolver.test.tsx +78 -0
  61. package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +205 -0
  62. package/Decorators/ZappPipesDataConnector/__tests__/StaticFeedResolver.test.tsx +251 -0
  63. package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +368 -0
  64. package/Decorators/ZappPipesDataConnector/__tests__/utils.test.ts +39 -0
  65. package/Decorators/ZappPipesDataConnector/index.tsx +26 -293
  66. package/Decorators/ZappPipesDataConnector/resolvers/NullFeedResolver.tsx +25 -0
  67. package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +87 -0
  68. package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +266 -0
  69. package/Decorators/ZappPipesDataConnector/types.ts +29 -0
  70. package/Decorators/ZappPipesDataConnector/utils/mongoFilter.ts +738 -0
  71. package/Decorators/ZappPipesDataConnector/utils/useFilter.tsx +136 -0
  72. package/events/index.ts +1 -0
  73. package/package.json +5 -6
  74. package/Components/River/__tests__/__snapshots__/river.test.js.snap +0 -27
@@ -0,0 +1,43 @@
1
+ import React, { useMemo } from "react";
2
+ import { path } from "ramda";
3
+
4
+ import {
5
+ useFeedLoader,
6
+ useRivers,
7
+ } from "@applicaster/zapp-react-native-utils/reactHooks";
8
+
9
+ type Props = {
10
+ screenId: string;
11
+ screenData: ZappRiver | ZappEntry;
12
+ feedUrl?: string;
13
+ river?: ZappRiver | ZappEntry;
14
+ };
15
+
16
+ export const withPipesV1DataLoader = (
17
+ WrappedComponent: React.ComponentType<any>
18
+ ) => {
19
+ return function WithPipesV1DataLoaderComponent(props: Props) {
20
+ const { screenId, feedUrl } = props;
21
+
22
+ const rivers = useRivers();
23
+
24
+ const river = React.useMemo(() => rivers?.[screenId], [screenId]);
25
+
26
+ const screenData = React.useMemo(
27
+ () => props.screenData || props.river || river,
28
+ [screenId]
29
+ );
30
+
31
+ const connectedScreenUrl = useMemo(() => {
32
+ // Avoid using feedUrl or content.src on layouts v2
33
+
34
+ return feedUrl || path(["content", "src"], screenData);
35
+ }, [feedUrl, screenData]);
36
+
37
+ const { data: feedData } = useFeedLoader({
38
+ feedUrl: connectedScreenUrl,
39
+ });
40
+
41
+ return <WrappedComponent {...props} feedData={feedData} />;
42
+ };
43
+ };
@@ -0,0 +1,17 @@
1
+ import { useLayoutVersion } from "@applicaster/zapp-react-native-utils/reactHooks";
2
+ import React from "react";
3
+ import { withPipesV1DataLoader } from "./withPipesV1DataLoader";
4
+
5
+ export const withRiverDataLoader = (
6
+ WrappedComponent: React.ComponentType<any>
7
+ ) => {
8
+ return function WithRiverDataLoaderComponent(props) {
9
+ const isV2 = useLayoutVersion({ isV2: true });
10
+
11
+ if (isV2) {
12
+ return <WrappedComponent {...props} />;
13
+ }
14
+
15
+ return withPipesV1DataLoader(WrappedComponent)(props);
16
+ };
17
+ };
@@ -1,20 +1,10 @@
1
1
  import React from "react";
2
- import { render, screen } from "@testing-library/react-native";
3
- import configureStore from "redux-mock-store";
2
+ import { screen } from "@testing-library/react-native";
4
3
  import { renderWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
5
- import { Provider } from "react-redux";
6
4
 
7
- import { River } from "../";
8
5
  import { ScreenResolver } from "../../ScreenResolver";
9
6
  import { RiverComponent } from "../River";
10
7
 
11
- jest.mock(
12
- "@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive",
13
- () => ({
14
- useIsScreenActive: jest.fn(() => true),
15
- })
16
- );
17
-
18
8
  jest.mock(
19
9
  "@applicaster/zapp-react-native-ui-components/Components/GeneralContentScreen",
20
10
  () => {
@@ -46,6 +36,13 @@ jest.mock(
46
36
  })
47
37
  );
48
38
 
39
+ jest.mock(
40
+ "@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive",
41
+ () => ({
42
+ useIsScreenActive: jest.fn(() => true),
43
+ })
44
+ );
45
+
49
46
  const river = {
50
47
  home: true,
51
48
  id: "A1234",
@@ -89,28 +86,17 @@ const riverProps = {
89
86
 
90
87
  const appData = { layoutVersion: "v1" };
91
88
 
92
- const store = configureStore()({ rivers, appData });
89
+ const store = { rivers, appData };
93
90
 
94
91
  describe("When River has a general_content type", () => {
95
92
  it("renders GeneralContentScreen correctly", () => {
96
- const { getByTestId } = render(
97
- <Provider store={store}>
98
- <RiverComponent {...riverProps} />
99
- </Provider>
93
+ const { getByTestId } = renderWithProviders(
94
+ <RiverComponent {...riverProps} />,
95
+ store
100
96
  );
101
97
 
102
98
  expect(getByTestId("general-content-screen")).toBeTruthy();
103
99
  });
104
-
105
- it("renders River component correctly", () => {
106
- const wrapper = render(
107
- <Provider store={store}>
108
- <River screenId="A1234" />
109
- </Provider>
110
- );
111
-
112
- expect(wrapper.toJSON()).toMatchSnapshot();
113
- });
114
100
  });
115
101
 
116
102
  describe("When River has any other type other than general_content", () => {
@@ -1,5 +1,5 @@
1
1
  import * as R from "ramda";
2
- import { connectToStore } from "@applicaster/zapp-react-native-redux";
2
+ import { connectToStore } from "@applicaster/zapp-react-native-redux/utils/connectToStore";
3
3
 
4
4
  import { withRiver } from "../../Decorators/RiverResolver";
5
5
  import { withNavigator } from "../../Decorators/Navigator";
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { View } from "react-native";
3
- import { act, create } from "react-test-renderer";
3
+ import { render } from "@testing-library/react-native";
4
4
 
5
5
  const Mocked_RouteManager = jest.fn((props) => (
6
6
  <View testID="routeManager" {...props} />
@@ -68,12 +68,33 @@ jest.mock(
68
68
  })
69
69
  );
70
70
 
71
+ jest.mock(
72
+ "@applicaster/zapp-react-native-utils/reactHooks/state/useRivers",
73
+ () => ({
74
+ useRivers: jest.fn(() => ({
75
+ rivers: [{ id: "testId", name: "Test River" }],
76
+ })),
77
+ })
78
+ );
79
+
71
80
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
72
81
  isNavBarVisible: mockIsNavBarVisible,
73
82
  useIsScreenActive: jest.fn().mockReturnValue(true),
83
+ useNavigation: jest.fn(() => ({
84
+ canGoBack: () => false,
85
+ currentRoute: "/river/testId",
86
+ activeRiver: { id: "testId" },
87
+ screenData: { id: "testId" },
88
+ data: { screen: { id: "testId" } },
89
+ })),
90
+ useRoute: jest.fn(() => ({
91
+ pathname: "/river/testId",
92
+ screenData: { id: "testId" },
93
+ })),
74
94
  }));
75
95
 
76
96
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
97
+ ...jest.requireActual("@applicaster/zapp-react-native-utils/reactHooks"),
77
98
  useCurrentScreenData: jest.fn(() => ({
78
99
  id: "testId",
79
100
  })),
@@ -84,17 +105,6 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
84
105
  id: "testId",
85
106
  navigations: [{ id: "testId", category: "nav_bar" }],
86
107
  })),
87
- useNavigation: jest.fn(() => ({
88
- canGoBack: () => false,
89
- currentRoute: "/river/testId",
90
- activeRiver: { id: "testId" },
91
- screenData: { id: "testId" },
92
- data: { screen: { id: "testId" } },
93
- })),
94
- useRoute: jest.fn(() => ({
95
- pathname: "/river/testId",
96
- screenData: { id: "testId" },
97
- })),
98
108
  useDimensions: jest.fn(() => ({
99
109
  width: 1920,
100
110
  height: 1080,
@@ -102,10 +112,11 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
102
112
  useIsTablet: jest.fn(() => false),
103
113
  }));
104
114
 
105
- jest.mock("@applicaster/zapp-react-native-redux/hooks/usePickFromState", () => {
115
+ jest.mock("@applicaster/zapp-react-native-redux/hooks", () => {
106
116
  const View = jest.requireActual("react-native").View;
107
117
 
108
118
  return {
119
+ ...jest.requireActual("@applicaster/zapp-react-native-redux/hooks"),
109
120
  usePickFromState: () => ({
110
121
  plugins: [
111
122
  {
@@ -141,8 +152,6 @@ const screenProps = {
141
152
  const { Screen } = require("..");
142
153
 
143
154
  describe("<Screen Component />", () => {
144
- let wrapper;
145
-
146
155
  beforeEach(() => {
147
156
  allowedOrientationsForScreen.mockClear();
148
157
  getOrientation.mockClear();
@@ -150,26 +159,16 @@ describe("<Screen Component />", () => {
150
159
  });
151
160
 
152
161
  describe("when the navbar should show", () => {
153
- act(() => {
154
- wrapper = create(<Screen {...screenProps} />);
155
- });
156
-
157
162
  it("renders correctly", () => {
158
- expect(wrapper.toJSON()).toMatchSnapshot();
163
+ const { toJSON } = render(<Screen {...screenProps} />);
164
+ expect(toJSON()).toMatchSnapshot();
159
165
  });
160
166
  });
161
167
 
162
168
  describe("when the navbar should be hidden", () => {
163
- beforeEach(() => {
164
- wrapper = create(<Screen {...screenProps} />);
165
- });
166
-
167
169
  it("renders correctly", () => {
168
- act(() => {
169
- wrapper = create(<Screen {...screenProps} />);
170
- });
171
-
172
- expect(wrapper.toJSON()).toMatchSnapshot();
170
+ const { toJSON } = render(<Screen {...screenProps} />);
171
+ expect(toJSON()).toMatchSnapshot();
173
172
  });
174
173
  });
175
174
  });
@@ -158,12 +158,11 @@ const TabsComponent = ({
158
158
 
159
159
  const renderItem = React.useCallback(
160
160
  ({ item, index, item: { id } }: RenderItemProps) => (
161
- <>
161
+ <React.Fragment key={id}>
162
162
  <Tab
163
163
  ref={(ref) => {
164
164
  tabRefs.current[index] = ref;
165
165
  }}
166
- key={id}
167
166
  {...{
168
167
  title: getTitle(item),
169
168
  id,
@@ -177,7 +176,7 @@ const TabsComponent = ({
177
176
  {display_mode === "fractional" &&
178
177
  index !== tabs?.length - 1 &&
179
178
  renderGutter()}
180
- </>
179
+ </React.Fragment>
181
180
  ),
182
181
  [tabs, display_mode, configuration, onTabPress, getTitle, getSelectedItem]
183
182
  );
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { View, TouchableOpacity } from "react-native";
3
- import { create, act } from "react-test-renderer";
3
+ import { render } from "@testing-library/react-native";
4
4
 
5
5
  import { Touchable } from "..";
6
6
 
@@ -23,38 +23,31 @@ describe("<Touchable />", () => {
23
23
  });
24
24
 
25
25
  it("has accessible flag set to false", () => {
26
- let wrapper;
26
+ const { toJSON, UNSAFE_getByType } = render(<Touchable {...props} />);
27
27
 
28
- act(() => {
29
- wrapper = create(<Touchable {...props} />);
30
- });
31
-
32
- const touchableWrapper = wrapper.root.findByType(TouchableOpacity);
33
- expect(wrapper.toJSON()).toMatchSnapshot();
28
+ const touchableWrapper = UNSAFE_getByType(TouchableOpacity);
29
+ expect(toJSON()).toMatchSnapshot();
34
30
  expect(touchableWrapper.props).toHaveProperty("accessible", false);
35
31
  });
36
32
  });
37
33
 
38
34
  describe("when not running in automated tests environment", () => {
39
- let wrapper;
40
-
41
- act(() => {
42
- wrapper = create(<Touchable {...props} />);
43
- });
44
-
45
- const touchableWrapper = wrapper.root.findByType(TouchableOpacity);
46
-
47
35
  beforeEach(props.onPress.mockClear);
48
36
 
49
37
  it("renders correctly", () => {
50
- expect(wrapper.toJSON()).toMatchSnapshot();
38
+ const { toJSON } = render(<Touchable {...props} />);
39
+ expect(toJSON()).toMatchSnapshot();
51
40
  });
52
41
 
53
42
  it("has accessible flag set to true", () => {
43
+ const { UNSAFE_getByType } = render(<Touchable {...props} />);
44
+ const touchableWrapper = UNSAFE_getByType(TouchableOpacity);
54
45
  expect(touchableWrapper.props).toHaveProperty("accessible", true);
55
46
  });
56
47
 
57
48
  it("assigns testID and accessibilityLabel props correctly", () => {
49
+ const { UNSAFE_getByType } = render(<Touchable {...props} />);
50
+ const touchableWrapper = UNSAFE_getByType(TouchableOpacity);
58
51
  expect(touchableWrapper.props).toHaveProperty("testID", props.testID);
59
52
 
60
53
  expect(touchableWrapper.props).toHaveProperty(
@@ -64,6 +57,8 @@ describe("<Touchable />", () => {
64
57
  });
65
58
 
66
59
  it("calls the onPress event when it is pressed", () => {
60
+ const { UNSAFE_getByType } = render(<Touchable {...props} />);
61
+ const touchableWrapper = UNSAFE_getByType(TouchableOpacity);
67
62
  touchableWrapper.props.onPress();
68
63
  expect(props.onPress).toHaveBeenCalledTimes(1);
69
64
  });
@@ -1,9 +1,8 @@
1
1
  import React from "react";
2
- import { Animated, Platform, StyleSheet, View } from "react-native";
2
+ import { Animated, StyleSheet, View } from "react-native";
3
3
 
4
4
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
5
5
  import {
6
- GestureHandlerRootView,
7
6
  NativeViewGestureHandler,
8
7
  PanGestureHandler,
9
8
  State,
@@ -357,15 +356,10 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
357
356
  };
358
357
  }, [playerAnimationState, isAudioItem, isMinimizedModal]);
359
358
 
360
- const Wrapper = React.useMemo(
361
- () => (Platform.OS === "android" ? GestureHandlerRootView : View),
362
- []
363
- );
364
-
365
359
  const scrollEnabled = isMaximizedModal && isNotMinimizeMaximazeAnimation;
366
360
 
367
361
  return (
368
- <Wrapper style={generalStyles.container}>
362
+ <View style={generalStyles.container}>
369
363
  <TapGestureHandler
370
364
  maxDurationMs={100000}
371
365
  ref={tapHandlerRef}
@@ -405,7 +399,7 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
405
399
  </PanGestureHandler>
406
400
  </View>
407
401
  </TapGestureHandler>
408
- </Wrapper>
402
+ </View>
409
403
  );
410
404
  };
411
405
 
@@ -11,6 +11,7 @@ import { isLive } from "@applicaster/zapp-react-native-utils/playerUtils";
11
11
 
12
12
  import { PROGRESS_BAR_HEIGHT } from "./utils";
13
13
  import { useConfiguration } from "../utils";
14
+ import { useIsTabletLandscape } from "@applicaster/zapp-react-native-utils/reactHooks/device/useMemoizedIsTablet";
14
15
 
15
16
  export enum PlayerAnimationStateEnum {
16
17
  minimize = "minimize",
@@ -102,14 +103,6 @@ const Provider = ({ children }: { children: React.ReactNode }) => {
102
103
  setStartComponentsAnimation(false);
103
104
  }, []);
104
105
 
105
- useEffect(() => {
106
- // Reset player animation state when video modal is closed
107
- if (!visible) {
108
- resetPlayerAnimationState();
109
- yTranslate.current?.setValue(Dimensions.get("window").height);
110
- }
111
- }, [visible, resetPlayerAnimationState]);
112
-
113
106
  // Animated values
114
107
  const lastScrollY = React.useRef(new Animated.Value(0)).current;
115
108
  const dragScrollY = React.useRef(new Animated.Value(0)).current;
@@ -122,6 +115,29 @@ const Provider = ({ children }: { children: React.ReactNode }) => {
122
115
  const { bottom: bottomSafeArea } = useSafeAreaInsets();
123
116
  const bottomTabBarHeight = useGetBottomTabBarHeight();
124
117
  const startComponentsAnimationDistance = Math.round((height * 60) / 100);
118
+ const isTabletLandscape = useIsTabletLandscape();
119
+ const windowDimensions = Dimensions.get("window");
120
+
121
+ useEffect(() => {
122
+ // Reset player animation state when video modal is closed
123
+ if (!visible) {
124
+ resetPlayerAnimationState();
125
+
126
+ if (!isTabletLandscape) {
127
+ // restore to portrait ( in portrait mode height is bigger)
128
+ if (windowDimensions.height > windowDimensions.width) {
129
+ yTranslate.current?.setValue(windowDimensions.height);
130
+ }
131
+ } else {
132
+ yTranslate.current?.setValue(windowDimensions.height);
133
+ }
134
+ }
135
+ }, [
136
+ visible,
137
+ resetPlayerAnimationState,
138
+ windowDimensions.height,
139
+ isTabletLandscape,
140
+ ]);
125
141
 
126
142
  React.useEffect(() => {
127
143
  if (visible && mode === "MAXIMIZED" && height !== safeAreaFrameHeight) {
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import renderer from "react-test-renderer";
2
+ import { render } from "@testing-library/react-native";
3
3
 
4
4
  const props = {
5
5
  entry: {},
@@ -42,16 +42,16 @@ const { PlayerDetails } = require("../PlayerDetails");
42
42
 
43
43
  describe("PlayerDetails", () => {
44
44
  it("renders properly", () => {
45
- const element = renderer.create(<PlayerDetails {...props} />);
45
+ const { toJSON } = render(<PlayerDetails {...props} />);
46
46
 
47
- expect(element).toMatchSnapshot();
47
+ expect(toJSON()).toMatchSnapshot();
48
48
  });
49
49
 
50
50
  it("renders properly on tablet in landscape orientation", () => {
51
- const element = renderer.create(
51
+ const { toJSON } = render(
52
52
  <PlayerDetails {...props} isTabletLandscape={true} />
53
53
  );
54
54
 
55
- expect(element).toMatchSnapshot();
55
+ expect(toJSON()).toMatchSnapshot();
56
56
  });
57
57
  });
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import TestRenderer from "react-test-renderer";
2
+ import { render } from "@testing-library/react-native";
3
3
  import { View } from "react-native";
4
4
  import { useConfiguration } from "@applicaster/zapp-react-native-utils/reactHooks/configuration";
5
5
 
@@ -14,12 +14,12 @@ describe("withConfigurationProvider", () => {
14
14
  };
15
15
 
16
16
  it("provides configuration to children", () => {
17
- const wrapper = TestRenderer.create(
17
+ const { toJSON } = render(
18
18
  <ConfigurationProvider configuration={{ target: "foobar" }}>
19
19
  <TestComponent />
20
20
  </ConfigurationProvider>
21
21
  );
22
22
 
23
- expect(wrapper.toJSON()).toMatchSnapshot();
23
+ expect(toJSON()).toMatchSnapshot();
24
24
  });
25
25
  });
@@ -13,7 +13,8 @@ import {
13
13
  } from "@applicaster/zapp-react-native-utils/reactHooks";
14
14
  import { useModalNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ModalNavigationContext";
15
15
  import { useNestedNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NestedNavigationContext";
16
- import { create, StoreApi, UseBoundStore } from "zustand";
16
+ import { create } from "zustand";
17
+ import { subscribeWithSelector } from "zustand/middleware";
17
18
  import { useShallow } from "zustand/react/shallow";
18
19
  import { Animated } from "react-native";
19
20
 
@@ -39,11 +40,26 @@ interface NavBarState {
39
40
  setSummary: (subtitle: string) => void;
40
41
  }
41
42
 
42
- type ScreenContextType = {
43
- _navBarStore: UseBoundStore<StoreApi<NavBarStoreState>>;
44
- navBar: NavBarState;
45
- legacyFormatScreenData: LegacyNavigationScreenData | null;
46
- };
43
+ const createStateStore = () =>
44
+ create(
45
+ subscribeWithSelector<ScreenStateStore>((set) => ({
46
+ data: {},
47
+ setValue: (key, value) =>
48
+ set((state) => ({
49
+ data: {
50
+ ...state.data,
51
+ [key]: value,
52
+ },
53
+ })),
54
+ removeValue: (key) =>
55
+ set((state) => {
56
+ const newData = { ...state.data };
57
+ delete newData[key];
58
+
59
+ return { data: newData };
60
+ }),
61
+ }))
62
+ );
47
63
 
48
64
  const createStore = () =>
49
65
  create<NavBarStoreState>((set) => ({
@@ -65,7 +81,15 @@ const createStore = () =>
65
81
  },
66
82
  }));
67
83
 
84
+ type ScreenContextType = {
85
+ _navBarStore: ReturnType<typeof createStore>;
86
+ _stateStore: ReturnType<typeof createStateStore>;
87
+ navBar: NavBarState;
88
+ legacyFormatScreenData: LegacyNavigationScreenData | null;
89
+ };
90
+
68
91
  export const ScreenContext = createContext<ScreenContextType>({
92
+ _stateStore: createStateStore(),
69
93
  _navBarStore: createStore(),
70
94
  navBar: {
71
95
  visible: true,
@@ -103,6 +127,21 @@ export function ScreenContextProvider({
103
127
  null
104
128
  );
105
129
 
130
+ const screenStateRef = useRef<null | ReturnType<typeof createStateStore>>(
131
+ null
132
+ );
133
+
134
+ const getScreenState = useCallback(() => {
135
+ if (screenStateRef.current !== null) {
136
+ return screenStateRef.current;
137
+ }
138
+
139
+ const stateStore = createStateStore();
140
+ screenStateRef.current = stateStore;
141
+
142
+ return stateStore;
143
+ }, []);
144
+
106
145
  const getScreenNavBarState = useCallback(() => {
107
146
  if (screenNavBarStateRef.current !== null) {
108
147
  return screenNavBarStateRef.current;
@@ -163,6 +202,7 @@ export function ScreenContextProvider({
163
202
  value={useMemo(
164
203
  () => ({
165
204
  _navBarStore: getScreenNavBarState(),
205
+ _stateStore: getScreenState(),
166
206
  navBar: navBarState,
167
207
  legacyFormatScreenData: routeScreenData,
168
208
  }),
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import TestRenderer from "react-test-renderer";
2
+ import { render } from "@testing-library/react-native";
3
3
  import { useConfiguration } from "@applicaster/zapp-react-native-utils/reactHooks/configuration";
4
4
  import { View } from "react-native";
5
5
  import { withConfigurationProvider } from "@applicaster/zapp-react-native-ui-components/Decorators/ConfigurationWrapper";
@@ -15,12 +15,12 @@ describe("withConfigurationProvider", () => {
15
15
  it("correctly passes all the configuration keys child component", () => {
16
16
  const Component = withConfigurationProvider(TestComponent);
17
17
 
18
- const wrapper = TestRenderer.create(
18
+ const { toJSON } = render(
19
19
  <Component
20
20
  screenData={{ styles: {}, general: {}, data: { source: "test" } }}
21
21
  />
22
22
  );
23
23
 
24
- expect(wrapper.toJSON()).toMatchSnapshot();
24
+ expect(toJSON()).toMatchSnapshot();
25
25
  });
26
26
  });