@applicaster/zapp-react-native-ui-components 14.0.0-alpha.1661204539 → 14.0.0-alpha.1887720441
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.
- package/Components/AnimatedInOut/index.tsx +5 -3
- package/Components/AudioPlayer/index.tsx +15 -0
- package/Components/AudioPlayer/mobile/Layout.tsx +66 -0
- package/Components/AudioPlayer/{__tests__/__snapshots__/audioPlayer.test.js.snap → mobile/__tests__/__snapshots__/audioPlayerMobileLayout.test.js.snap} +2 -2
- package/Components/AudioPlayer/mobile/__tests__/audioPlayerMobileLayout.test.js +18 -0
- package/Components/AudioPlayer/mobile/index.tsx +18 -0
- package/Components/AudioPlayer/tv/Artwork.tsx +41 -0
- package/Components/AudioPlayer/{Channel.tsx → tv/Channel.tsx} +7 -7
- package/Components/AudioPlayer/tv/Layout.tsx +168 -0
- package/Components/AudioPlayer/{Runtime.tsx → tv/Runtime.tsx} +9 -2
- package/Components/AudioPlayer/{Summary.tsx → tv/Summary.tsx} +17 -10
- package/Components/AudioPlayer/tv/Title.tsx +46 -0
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/Runtime.test.js.snap +4 -4
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/artWork.test.js.snap +9 -4
- package/Components/AudioPlayer/tv/__tests__/__snapshots__/audioPlayer.test.js.snap +164 -0
- package/Components/AudioPlayer/tv/__tests__/__snapshots__/channel.test.js.snap +19 -0
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/summary.test.js.snap +2 -3
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/title.test.js.snap +2 -3
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/audioPlayer.test.js +7 -3
- package/Components/AudioPlayer/{helpers.tsx → tv/helpers.tsx} +13 -7
- package/Components/AudioPlayer/{AudioPlayer.tsx → tv/index.tsx} +18 -57
- package/Components/AudioPlayer/types.ts +40 -0
- package/Components/Cell/index.js +7 -3
- package/Components/ComponentResolver/index.ts +1 -1
- package/Components/FeedLoader/index.js +1 -1
- package/Components/Focusable/Focusable.tsx +5 -3
- package/Components/Focusable/FocusableTvOS.tsx +3 -3
- package/Components/Focusable/FocusableiOS.tsx +2 -2
- package/Components/Focusable/__tests__/index.android.test.tsx +3 -0
- package/Components/Focusable/index.android.tsx +12 -8
- package/Components/Focusable/index.tsx +1 -1
- package/Components/FocusableList/index.tsx +4 -0
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +0 -2
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +42 -59
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +12 -8
- package/Components/HandlePlayable/HandlePlayable.tsx +25 -9
- package/Components/Layout/TV/LayoutBackground.tsx +1 -1
- package/Components/MasterCell/DefaultComponents/Button.tsx +1 -1
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -27
- package/Components/MasterCell/DefaultComponents/Image/hoc/withDimensions.tsx +1 -1
- package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +1 -1
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +1 -0
- package/Components/MasterCell/elementMapper.tsx +1 -2
- package/Components/MasterCell/index.tsx +1 -1
- package/Components/MasterCell/utils/behaviorProvider.ts +12 -67
- package/Components/MasterCell/utils/index.ts +3 -13
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +13 -18
- package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +9 -0
- package/Components/OfflineHandler/__tests__/index.test.tsx +20 -22
- package/Components/PlayerContainer/ErrorDisplay/index.ts +1 -1
- package/Components/PlayerContainer/PlayerContainer.tsx +62 -66
- package/Components/PlayerContainer/ProgramInfo/index.tsx +1 -1
- package/Components/PlayerContainer/index.ts +1 -1
- package/Components/PlayerImageBackground/index.tsx +1 -1
- package/Components/River/ComponentsMap/ComponentsMap.tsx +1 -6
- package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +379 -0
- package/Components/River/ComponentsMap/hooks/useLoadingState.ts +2 -2
- package/Components/River/RefreshControl.tsx +6 -4
- package/Components/River/RiverItem.tsx +8 -8
- package/Components/River/TV/River.tsx +2 -20
- package/Components/River/TV/index.tsx +3 -1
- package/Components/River/TV/withPipesV1DataLoader.tsx +43 -0
- package/Components/River/TV/withRiverDataLoader.tsx +17 -0
- package/Components/River/TV/withTVEventHandler.tsx +1 -1
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -6
- package/Components/River/index.tsx +1 -1
- package/Components/Screen/__tests__/Screen.test.tsx +23 -12
- package/Components/ScreenRevealManager/ScreenRevealManager.ts +76 -0
- package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +107 -0
- package/Components/ScreenRevealManager/__tests__/withScreenRevealManager.test.tsx +96 -0
- package/Components/ScreenRevealManager/index.ts +1 -0
- package/Components/ScreenRevealManager/withScreenRevealManager.tsx +79 -0
- package/Components/Tabs/TV/Tabs.android.tsx +0 -2
- package/Components/TopMarginApplicator/TopMarginApplicator.tsx +16 -15
- package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +34 -0
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +15 -9
- package/Components/VideoLive/animationUtils.ts +3 -3
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +32 -8
- package/Components/VideoModal/PlayerDetails.tsx +24 -2
- package/Components/VideoModal/PlayerWrapper.tsx +26 -142
- package/Components/VideoModal/VideoModal.tsx +3 -17
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -7
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +44 -180
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +17 -55
- package/Components/VideoModal/hooks/index.ts +0 -2
- package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +15 -26
- package/Components/VideoModal/hooks/useModalSize.ts +18 -2
- package/Components/VideoModal/utils.ts +6 -0
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -16
- package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +84 -24
- package/Components/Viewport/VisibilitySensor/VisibilitySensor.tsx +3 -3
- package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/index.ts +3 -3
- package/Decorators/ConfigurationWrapper/withConfigurationProvider.tsx +2 -2
- package/Decorators/RiverFeedLoader/index.tsx +2 -8
- package/Decorators/RiverFeedLoader/utils/index.ts +2 -7
- package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +3 -6
- package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -0
- package/Decorators/ZappPipesDataConnector/__tests__/NullFeedResolver.test.tsx +78 -0
- package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +205 -0
- package/Decorators/ZappPipesDataConnector/__tests__/StaticFeedResolver.test.tsx +251 -0
- package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +368 -0
- package/Decorators/ZappPipesDataConnector/__tests__/utils.test.ts +39 -0
- package/Decorators/ZappPipesDataConnector/index.tsx +27 -308
- package/Decorators/ZappPipesDataConnector/resolvers/NullFeedResolver.tsx +25 -0
- package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +87 -0
- package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +241 -0
- package/Decorators/ZappPipesDataConnector/types.ts +29 -0
- package/index.d.ts +0 -1
- package/package.json +5 -10
- package/Components/AudioPlayer/Artwork.tsx +0 -35
- package/Components/AudioPlayer/AudioPlayerLayout.tsx +0 -202
- package/Components/AudioPlayer/Title.tsx +0 -39
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +0 -66
- package/Components/AudioPlayer/__tests__/__snapshots__/channel.test.js.snap +0 -28
- package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +0 -26
- package/Components/AudioPlayer/index.ts +0 -1
- package/Components/VideoModal/hooks/useBackgroundColor.ts +0 -10
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/Runtime.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/artWork.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/channel.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/summary.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/title.test.js +0 -0
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
3
|
-
import TestRenderer, { act } from "react-test-renderer";
|
|
2
|
+
import { act, render } from "@testing-library/react-native";
|
|
4
3
|
import { ViewportEvents } from "../../ViewportEvents";
|
|
4
|
+
import ReactNative from "react-native";
|
|
5
|
+
|
|
6
|
+
const { ScrollView } = ReactNative;
|
|
5
7
|
|
|
6
8
|
const TestComponent = () => <ScrollView />;
|
|
7
9
|
|
|
8
|
-
jest.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
jest.spyOn(ReactNative, "findNodeHandle").mockImplementation(() => 1234);
|
|
11
|
+
|
|
12
|
+
ReactNative.UIManager.measureLayout = jest.fn(
|
|
13
|
+
(handle, parent, error, success) => {
|
|
14
|
+
success(100, 100, 400, 400);
|
|
15
|
+
}
|
|
16
|
+
);
|
|
12
17
|
|
|
13
18
|
const viewportEventsManager = new ViewportEvents(true);
|
|
14
19
|
|
|
@@ -23,32 +28,49 @@ const event = {
|
|
|
23
28
|
};
|
|
24
29
|
|
|
25
30
|
describe("<ViewportTracker />", () => {
|
|
26
|
-
// eslint-disable-next-line react/prop-types
|
|
27
|
-
const ReactWrapper = ({ children }) => (
|
|
28
|
-
<ViewportTracker viewportEventsManager={viewportEventsManager}>
|
|
29
|
-
<ScrollView>{children}</ScrollView>
|
|
30
|
-
</ViewportTracker>
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
const wrapper = TestRenderer.create(
|
|
34
|
-
<ReactWrapper>
|
|
35
|
-
<TestComponent />
|
|
36
|
-
</ReactWrapper>
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
const scrollView = wrapper.root.findByType(ScrollView);
|
|
40
|
-
|
|
41
31
|
beforeEach(() => {
|
|
42
32
|
viewportEventSpy.mockClear();
|
|
43
33
|
});
|
|
44
34
|
|
|
45
35
|
it("renders correctly", () => {
|
|
36
|
+
// eslint-disable-next-line react/prop-types
|
|
37
|
+
const ReactWrapper = ({ children }) => (
|
|
38
|
+
<ViewportTracker viewportEventsManager={viewportEventsManager}>
|
|
39
|
+
<ScrollView>{children}</ScrollView>
|
|
40
|
+
</ViewportTracker>
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const wrapper = render(
|
|
44
|
+
<ReactWrapper>
|
|
45
|
+
<TestComponent />
|
|
46
|
+
</ReactWrapper>
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const scrollView = wrapper.UNSAFE_getByType(ScrollView);
|
|
50
|
+
|
|
46
51
|
expect(wrapper.toJSON()).toMatchSnapshot();
|
|
47
52
|
expect(scrollView.props).toMatchSnapshot();
|
|
48
53
|
});
|
|
49
54
|
|
|
50
55
|
it("notifies viewport listeners when layout changes", () => {
|
|
51
|
-
|
|
56
|
+
// eslint-disable-next-line react/prop-types
|
|
57
|
+
const ReactWrapper = ({ children }) => (
|
|
58
|
+
<ViewportTracker viewportEventsManager={viewportEventsManager}>
|
|
59
|
+
<ScrollView>{children}</ScrollView>
|
|
60
|
+
</ViewportTracker>
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const wrapper = render(
|
|
64
|
+
<ReactWrapper>
|
|
65
|
+
<TestComponent />
|
|
66
|
+
</ReactWrapper>
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const scrollView = wrapper.UNSAFE_getByType(ScrollView);
|
|
70
|
+
|
|
71
|
+
act(() => {
|
|
72
|
+
scrollView.props.onLayout(event);
|
|
73
|
+
});
|
|
52
74
|
|
|
53
75
|
expect(viewportEventSpy).toHaveBeenCalledWith(
|
|
54
76
|
expect.objectContaining({
|
|
@@ -63,12 +85,50 @@ describe("<ViewportTracker />", () => {
|
|
|
63
85
|
});
|
|
64
86
|
|
|
65
87
|
it("notifies viewport listeners when content scrolls", () => {
|
|
66
|
-
|
|
88
|
+
// eslint-disable-next-line react/prop-types
|
|
89
|
+
const ReactWrapper = ({ children }) => (
|
|
90
|
+
<ViewportTracker viewportEventsManager={viewportEventsManager}>
|
|
91
|
+
<ScrollView>{children}</ScrollView>
|
|
92
|
+
</ViewportTracker>
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const wrapper = render(
|
|
96
|
+
<ReactWrapper>
|
|
97
|
+
<TestComponent />
|
|
98
|
+
</ReactWrapper>
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const scrollView = wrapper.UNSAFE_getByType(ScrollView);
|
|
102
|
+
|
|
103
|
+
act(() => {
|
|
104
|
+
scrollView.props.onLayout(event);
|
|
105
|
+
scrollView.props.onScroll(event);
|
|
106
|
+
});
|
|
107
|
+
|
|
67
108
|
expect(viewportEventSpy).toHaveBeenCalled();
|
|
68
109
|
});
|
|
69
110
|
|
|
70
111
|
it("notifies viewport listeners when content size changes", () => {
|
|
71
|
-
|
|
112
|
+
// eslint-disable-next-line react/prop-types
|
|
113
|
+
const ReactWrapper = ({ children }) => (
|
|
114
|
+
<ViewportTracker viewportEventsManager={viewportEventsManager}>
|
|
115
|
+
<ScrollView>{children}</ScrollView>
|
|
116
|
+
</ViewportTracker>
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
const wrapper = render(
|
|
120
|
+
<ReactWrapper>
|
|
121
|
+
<TestComponent />
|
|
122
|
+
</ReactWrapper>
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const scrollView = wrapper.UNSAFE_getByType(ScrollView);
|
|
126
|
+
|
|
127
|
+
act(() => {
|
|
128
|
+
scrollView.props.onLayout(event);
|
|
129
|
+
scrollView.props.onContentSizeChange(100, 100);
|
|
130
|
+
});
|
|
131
|
+
|
|
72
132
|
expect(viewportEventSpy).toHaveBeenCalled();
|
|
73
133
|
});
|
|
74
134
|
});
|
|
@@ -4,8 +4,8 @@ which helps in detecting whether a given component is visible within the viewpor
|
|
|
4
4
|
It is useful for implementing lazy loading or triggering specific actions when a component comes into view.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import React, {
|
|
8
|
-
import {
|
|
7
|
+
import React, { FC, ReactNode, useEffect, useRef, useState } from "react";
|
|
8
|
+
import { Dimensions, View } from "react-native";
|
|
9
9
|
import { useIsRTL } from "@applicaster/zapp-react-native-utils/localizationUtils";
|
|
10
10
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
11
11
|
|
|
@@ -78,7 +78,7 @@ const VisibilitySensorComponent: FC<Props> = ({
|
|
|
78
78
|
};
|
|
79
79
|
|
|
80
80
|
const stopWatching = () => {
|
|
81
|
-
|
|
81
|
+
clearInterval(interval);
|
|
82
82
|
};
|
|
83
83
|
|
|
84
84
|
const isInViewPort = () => {
|
|
@@ -21,13 +21,13 @@ const prepareConfiguration = (
|
|
|
21
21
|
keys: [string]
|
|
22
22
|
) => R.compose(R.evolve(keysMap), R.pickAll(keys))(configuration);
|
|
23
23
|
|
|
24
|
+
const configurationKeys = R.keys(keysMap);
|
|
25
|
+
|
|
24
26
|
export function withConfigurationProvider(Component: React.ComponentType<any>) {
|
|
25
27
|
return function WithConfigurationProvider(props: Props) {
|
|
26
28
|
const styles = props?.screenData?.styles;
|
|
27
29
|
const general = props?.screenData?.general;
|
|
28
30
|
|
|
29
|
-
const configurationKeys = React.useMemo(() => R.keys(keysMap), []);
|
|
30
|
-
|
|
31
31
|
const configuration = React.useMemo(
|
|
32
32
|
() => prepareConfiguration({ ...general, ...styles }, configurationKeys),
|
|
33
33
|
[]
|
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
loadDatasources,
|
|
14
14
|
usePipesContexts,
|
|
15
15
|
} from "./utils";
|
|
16
|
-
import { useScreenResolvers } from "@applicaster/zapp-react-native-utils/actionsExecutor/screenResolver";
|
|
17
16
|
|
|
18
17
|
type RiverProps = {
|
|
19
18
|
dispatch: DispatchProp;
|
|
@@ -26,7 +25,7 @@ export function WithRiverFeedLoader(Component: ZappComponent) {
|
|
|
26
25
|
return function WrappedWithRiverFeedLoader(props: RiverProps) {
|
|
27
26
|
const { river } = props;
|
|
28
27
|
const { screenData, pathname } = useRoute();
|
|
29
|
-
|
|
28
|
+
|
|
30
29
|
const pipesContexts = usePipesContexts(river.id, pathname);
|
|
31
30
|
|
|
32
31
|
const componentsToLoad = ignoreComponentsWithClearCacheFlag(
|
|
@@ -50,12 +49,7 @@ export function WithRiverFeedLoader(Component: ZappComponent) {
|
|
|
50
49
|
item?.filter((item2) => item2 !== undefined)
|
|
51
50
|
);
|
|
52
51
|
|
|
53
|
-
loadDatasources(
|
|
54
|
-
nonEmptyDataSources,
|
|
55
|
-
river?.id,
|
|
56
|
-
props.dispatch,
|
|
57
|
-
resolvers
|
|
58
|
-
);
|
|
52
|
+
loadDatasources(nonEmptyDataSources, river?.id, props.dispatch);
|
|
59
53
|
}, []);
|
|
60
54
|
|
|
61
55
|
return <Component {...props} />;
|
|
@@ -12,16 +12,11 @@ export { getDatasourceUrl } from "./getDatasourceUrl";
|
|
|
12
12
|
|
|
13
13
|
export const DATASOURCE_CHUNKS = 10;
|
|
14
14
|
|
|
15
|
-
export async function loadDatasources(
|
|
16
|
-
urls: string[][],
|
|
17
|
-
riverId,
|
|
18
|
-
dispatch,
|
|
19
|
-
resolvers
|
|
20
|
-
) {
|
|
15
|
+
export async function loadDatasources(urls: string[][], riverId, dispatch) {
|
|
21
16
|
return reducePromises<string, void>(
|
|
22
17
|
mapPromises<string, void>((url) => {
|
|
23
18
|
if (url) {
|
|
24
|
-
return dispatch(loadPipesData(url, { riverId
|
|
19
|
+
return dispatch(loadPipesData(url, { riverId }));
|
|
25
20
|
}
|
|
26
21
|
}),
|
|
27
22
|
undefined,
|
|
@@ -13,12 +13,9 @@ const rivers = {
|
|
|
13
13
|
},
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
jest.doMock(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
usePickFromState: jest.fn(() => ({ rivers })),
|
|
20
|
-
})
|
|
21
|
-
);
|
|
16
|
+
jest.doMock("@applicaster/zapp-react-native-redux/hooks", () => ({
|
|
17
|
+
usePickFromState: jest.fn(() => ({ rivers })),
|
|
18
|
+
}));
|
|
22
19
|
|
|
23
20
|
jest.doMock(
|
|
24
21
|
"@applicaster/zapp-react-native-utils/reactHooks/navigation/usePathname",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// ResolverSelector.tsx
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { ComponentDataSourceContext, ZappPipesDataProps } from "./types";
|
|
4
|
+
import { StaticFeedResolver } from "./resolvers/StaticFeedResolver";
|
|
5
|
+
import { UrlFeedResolver } from "./resolvers/UrlFeedResolver";
|
|
6
|
+
import { NullFeedResolver } from "./resolvers/NullFeedResolver";
|
|
7
|
+
|
|
8
|
+
type ResolverSelectorProps = ComponentDataSourceContext & {
|
|
9
|
+
children: (dataProps: ZappPipesDataProps) => React.ReactNode;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function ResolverSelector(props: ResolverSelectorProps) {
|
|
13
|
+
const { getStaticComponentFeed, component, feedUrl, children } = props;
|
|
14
|
+
|
|
15
|
+
// Determine which resolver to use
|
|
16
|
+
if (getStaticComponentFeed) {
|
|
17
|
+
return <StaticFeedResolver {...props}>{children}</StaticFeedResolver>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (feedUrl || component?.data?.source) {
|
|
21
|
+
return <UrlFeedResolver {...props}>{children}</UrlFeedResolver>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return <NullFeedResolver>{children}</NullFeedResolver>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
import { render } from "@testing-library/react-native";
|
|
4
|
+
import { NullFeedResolver } from "../resolvers/NullFeedResolver";
|
|
5
|
+
import { ReloadDataFunction } from "@applicaster/zapp-react-native-utils/reactHooks/feed/useFeedLoader";
|
|
6
|
+
|
|
7
|
+
type MockChildrenArgs = {
|
|
8
|
+
zappPipesData?: {
|
|
9
|
+
loading: boolean;
|
|
10
|
+
data?: any;
|
|
11
|
+
error?: Error | null;
|
|
12
|
+
};
|
|
13
|
+
reloadData?: ReloadDataFunction;
|
|
14
|
+
loadNextData?: () => void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
describe("NullFeedResolver", () => {
|
|
18
|
+
it("should render children with correct default props", () => {
|
|
19
|
+
const mockChildren = jest.fn((_args: MockChildrenArgs) => (
|
|
20
|
+
<View testID="mock-children" />
|
|
21
|
+
));
|
|
22
|
+
|
|
23
|
+
render(<NullFeedResolver>{mockChildren}</NullFeedResolver>);
|
|
24
|
+
|
|
25
|
+
expect(mockChildren).toHaveBeenCalledWith(
|
|
26
|
+
expect.objectContaining({
|
|
27
|
+
zappPipesData: {
|
|
28
|
+
url: "",
|
|
29
|
+
loading: false,
|
|
30
|
+
data: null,
|
|
31
|
+
error: null,
|
|
32
|
+
},
|
|
33
|
+
reloadData: expect.any(Function),
|
|
34
|
+
loadNextData: undefined,
|
|
35
|
+
})
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("should render children component", () => {
|
|
40
|
+
const { getByTestId } = render(
|
|
41
|
+
<NullFeedResolver>{() => <View testID="test-child" />}</NullFeedResolver>
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
expect(getByTestId("test-child")).toBeTruthy();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should create a memoized data object that doesn't change on re-renders", () => {
|
|
48
|
+
const mockChildren = jest.fn(() => <View testID="mock-children" />);
|
|
49
|
+
|
|
50
|
+
const { rerender } = render(
|
|
51
|
+
<NullFeedResolver>{mockChildren}</NullFeedResolver>
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
expect(mockChildren).toHaveBeenCalled();
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
const firstCallDataProps = mockChildren.mock.calls[0][0];
|
|
57
|
+
|
|
58
|
+
rerender(<NullFeedResolver>{mockChildren}</NullFeedResolver>);
|
|
59
|
+
|
|
60
|
+
// @ts-ignore
|
|
61
|
+
const secondCallDataProps = mockChildren.mock.calls[1][0];
|
|
62
|
+
|
|
63
|
+
expect(firstCallDataProps).toBe(secondCallDataProps);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should have reloadData function that returns null", () => {
|
|
67
|
+
const mockChildren = jest.fn(() => <View testID="mock-children" />);
|
|
68
|
+
|
|
69
|
+
render(<NullFeedResolver>{mockChildren}</NullFeedResolver>);
|
|
70
|
+
|
|
71
|
+
expect(mockChildren).toHaveBeenCalled();
|
|
72
|
+
|
|
73
|
+
// @ts-ignore
|
|
74
|
+
const { reloadData } = mockChildren.mock.calls[0][0];
|
|
75
|
+
|
|
76
|
+
expect(reloadData()).toBeNull();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
import { render } from "@testing-library/react-native";
|
|
4
|
+
import { ResolverSelector } from "../ResolverSelector";
|
|
5
|
+
import { StaticFeedResolver } from "../resolvers/StaticFeedResolver";
|
|
6
|
+
import { UrlFeedResolver } from "../resolvers/UrlFeedResolver";
|
|
7
|
+
import { NullFeedResolver } from "../resolvers/NullFeedResolver";
|
|
8
|
+
|
|
9
|
+
jest.mock("../resolvers/StaticFeedResolver", () => ({
|
|
10
|
+
StaticFeedResolver: jest.fn(() => null),
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
jest.mock("../resolvers/UrlFeedResolver", () => ({
|
|
14
|
+
UrlFeedResolver: jest.fn(() => null),
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
jest.mock("../resolvers/NullFeedResolver", () => ({
|
|
18
|
+
NullFeedResolver: jest.fn(() => null),
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
const testPlugin = {
|
|
22
|
+
identifier: "test-plugin",
|
|
23
|
+
name: "test",
|
|
24
|
+
type: "general" as PluginType,
|
|
25
|
+
module: jest.fn(),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
describe("ResolverSelector", () => {
|
|
29
|
+
const mockChildren = jest.fn(() => <View testID="mock-children" />);
|
|
30
|
+
|
|
31
|
+
const mockComponent = {
|
|
32
|
+
id: "test-component",
|
|
33
|
+
type: "vertical_list",
|
|
34
|
+
styles: {},
|
|
35
|
+
} as any;
|
|
36
|
+
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
jest.clearAllMocks();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("should render StaticFeedResolver when getStaticComponentFeed is provided", () => {
|
|
42
|
+
const props = {
|
|
43
|
+
getStaticComponentFeed: jest.fn(),
|
|
44
|
+
component: mockComponent,
|
|
45
|
+
children: mockChildren,
|
|
46
|
+
riverId: "test-river",
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
render(<ResolverSelector {...props} />);
|
|
50
|
+
|
|
51
|
+
expect(StaticFeedResolver).toHaveBeenCalledWith(
|
|
52
|
+
expect.objectContaining({
|
|
53
|
+
getStaticComponentFeed: props.getStaticComponentFeed,
|
|
54
|
+
component: mockComponent,
|
|
55
|
+
children: mockChildren,
|
|
56
|
+
}),
|
|
57
|
+
expect.anything()
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
expect(UrlFeedResolver).not.toHaveBeenCalled();
|
|
61
|
+
expect(NullFeedResolver).not.toHaveBeenCalled();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("should render UrlFeedResolver when feedUrl is provided", () => {
|
|
65
|
+
const props = {
|
|
66
|
+
feedUrl: "https://example.com/feed",
|
|
67
|
+
component: mockComponent,
|
|
68
|
+
children: mockChildren,
|
|
69
|
+
riverId: "test-river",
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
render(<ResolverSelector {...props} />);
|
|
73
|
+
|
|
74
|
+
expect(UrlFeedResolver).toHaveBeenCalledWith(
|
|
75
|
+
expect.objectContaining({
|
|
76
|
+
feedUrl: props.feedUrl,
|
|
77
|
+
component: mockComponent,
|
|
78
|
+
children: mockChildren,
|
|
79
|
+
}),
|
|
80
|
+
expect.anything()
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
expect(StaticFeedResolver).not.toHaveBeenCalled();
|
|
84
|
+
expect(NullFeedResolver).not.toHaveBeenCalled();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("should render UrlFeedResolver when component.data.source is provided", () => {
|
|
88
|
+
const componentWithSource = {
|
|
89
|
+
...mockComponent,
|
|
90
|
+
data: {
|
|
91
|
+
source: "data-source",
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const props = {
|
|
96
|
+
component: componentWithSource,
|
|
97
|
+
children: mockChildren,
|
|
98
|
+
riverId: "test-river",
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
render(<ResolverSelector {...props} />);
|
|
102
|
+
|
|
103
|
+
expect(UrlFeedResolver).toHaveBeenCalledWith(
|
|
104
|
+
expect.objectContaining({
|
|
105
|
+
component: componentWithSource,
|
|
106
|
+
children: mockChildren,
|
|
107
|
+
}),
|
|
108
|
+
expect.anything()
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
expect(StaticFeedResolver).not.toHaveBeenCalled();
|
|
112
|
+
expect(NullFeedResolver).not.toHaveBeenCalled();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("should render NullFeedResolver when no data source is provided", () => {
|
|
116
|
+
const props = {
|
|
117
|
+
component: mockComponent,
|
|
118
|
+
children: mockChildren,
|
|
119
|
+
riverId: "test-river",
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
render(<ResolverSelector {...props} />);
|
|
123
|
+
|
|
124
|
+
expect(NullFeedResolver).toHaveBeenCalledWith(
|
|
125
|
+
expect.objectContaining({
|
|
126
|
+
children: mockChildren,
|
|
127
|
+
}),
|
|
128
|
+
expect.anything()
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
expect(StaticFeedResolver).not.toHaveBeenCalled();
|
|
132
|
+
expect(UrlFeedResolver).not.toHaveBeenCalled();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("should pass all props to StaticFeedResolver", () => {
|
|
136
|
+
const props = {
|
|
137
|
+
getStaticComponentFeed: jest.fn(),
|
|
138
|
+
component: mockComponent,
|
|
139
|
+
children: mockChildren,
|
|
140
|
+
riverId: "test-river",
|
|
141
|
+
isLast: true,
|
|
142
|
+
componentIndex: 1,
|
|
143
|
+
isScreenWrappedInContainer: true,
|
|
144
|
+
entryContext: { entry: "test" },
|
|
145
|
+
screenContext: { screen: "test" },
|
|
146
|
+
searchContext: "search",
|
|
147
|
+
screenData: { data: "test" },
|
|
148
|
+
plugins: [testPlugin],
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
render(<ResolverSelector {...props} />);
|
|
152
|
+
|
|
153
|
+
expect(StaticFeedResolver).toHaveBeenCalledWith(
|
|
154
|
+
expect.objectContaining(props),
|
|
155
|
+
expect.anything()
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it("should pass all props to UrlFeedResolver", () => {
|
|
160
|
+
const props = {
|
|
161
|
+
feedUrl: "https://example.com/feed",
|
|
162
|
+
component: mockComponent,
|
|
163
|
+
children: mockChildren,
|
|
164
|
+
riverId: "test-river",
|
|
165
|
+
isLast: true,
|
|
166
|
+
componentIndex: 1,
|
|
167
|
+
isScreenWrappedInContainer: true,
|
|
168
|
+
entryContext: { entry: "test" },
|
|
169
|
+
screenContext: { screen: "test" },
|
|
170
|
+
searchContext: "search",
|
|
171
|
+
screenData: { data: "test" },
|
|
172
|
+
plugins: [testPlugin],
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
render(<ResolverSelector {...props} />);
|
|
176
|
+
|
|
177
|
+
expect(UrlFeedResolver).toHaveBeenCalledWith(
|
|
178
|
+
expect.objectContaining(props),
|
|
179
|
+
expect.anything()
|
|
180
|
+
);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("should prioritize StaticFeedResolver over UrlFeedResolver when both conditions are met", () => {
|
|
184
|
+
const componentWithSource = {
|
|
185
|
+
...mockComponent,
|
|
186
|
+
data: {
|
|
187
|
+
source: "data-source",
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const props = {
|
|
192
|
+
getStaticComponentFeed: jest.fn(),
|
|
193
|
+
feedUrl: "https://example.com/feed",
|
|
194
|
+
component: componentWithSource,
|
|
195
|
+
children: mockChildren,
|
|
196
|
+
riverId: "test-river",
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
render(<ResolverSelector {...props} />);
|
|
200
|
+
|
|
201
|
+
expect(StaticFeedResolver).toHaveBeenCalled();
|
|
202
|
+
expect(UrlFeedResolver).not.toHaveBeenCalled();
|
|
203
|
+
expect(NullFeedResolver).not.toHaveBeenCalled();
|
|
204
|
+
});
|
|
205
|
+
});
|