@applicaster/zapp-react-native-ui-components 15.0.0-rc.11 → 15.0.0-rc.110
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 +69 -26
- package/Components/BaseFocusable/index.ios.ts +12 -2
- package/Components/Cell/Cell.tsx +14 -3
- package/Components/Cell/CellWithFocusable.tsx +9 -0
- package/Components/Cell/FocusableWrapper.tsx +47 -0
- package/Components/Cell/TvOSCellComponent.tsx +106 -19
- package/Components/Focusable/Focusable.tsx +4 -2
- package/Components/Focusable/FocusableTvOS.tsx +18 -1
- package/Components/Focusable/__tests__/__snapshots__/FocusableTvOS.test.tsx.snap +1 -0
- package/Components/FocusableGroup/FocusableTvOS.tsx +32 -1
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +1 -1
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +22 -6
- package/Components/HandlePlayable/HandlePlayable.tsx +33 -94
- package/Components/HandlePlayable/const.ts +3 -0
- package/Components/HandlePlayable/utils.ts +105 -0
- package/Components/Layout/TV/LayoutBackground.tsx +5 -2
- package/Components/Layout/TV/ScreenContainer.tsx +2 -6
- package/Components/Layout/TV/index.tsx +3 -4
- package/Components/Layout/TV/index.web.tsx +3 -4
- package/Components/LinkHandler/LinkHandler.tsx +2 -2
- package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +16 -1
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +30 -2
- package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +11 -3
- package/Components/MasterCell/DefaultComponents/Image/Image.web.tsx +9 -1
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +15 -14
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +10 -6
- package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +40 -39
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/Image.test.tsx +95 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +86 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/index.test.ts +141 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/hooks/__tests__/useGetImageDimensions.test.ts +7 -6
- package/Components/MasterCell/DefaultComponents/SecondaryImage/index.ts +1 -1
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +8 -8
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -2
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/getPluginIdentifier.test.ts +233 -11
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +19 -15
- package/Components/MasterCell/hoc/__tests__/withAsyncRender.test.tsx +219 -0
- package/Components/MasterCell/hoc/withAsyncRender.tsx +9 -7
- package/Components/MasterCell/index.tsx +2 -0
- package/Components/MasterCell/utils/__tests__/resolveColor.test.js +82 -3
- package/Components/MasterCell/utils/index.ts +61 -31
- package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +102 -87
- package/Components/MeasurmentsPortal/__tests__/MeasurementsPortal.test.tsx +355 -0
- package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +17 -9
- package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +16 -8
- package/Components/OfflineHandler/NotificationView/NotificationView.tsx +2 -2
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +17 -18
- package/Components/OfflineHandler/NotificationView/utils.ts +34 -0
- package/Components/OfflineHandler/__tests__/index.test.tsx +27 -18
- package/Components/PlayerContainer/PlayerContainer.tsx +43 -55
- package/Components/PlayerImageBackground/index.tsx +3 -22
- package/Components/River/ComponentsMap/ComponentsMap.tsx +16 -0
- package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +1 -1
- package/Components/River/TV/River.tsx +31 -14
- package/Components/River/TV/index.tsx +8 -4
- package/Components/River/TV/utils/__tests__/toStringOrEmpty.test.ts +30 -0
- package/Components/River/TV/utils/index.ts +4 -0
- package/Components/River/TV/withFocusableGroupForContent.tsx +71 -0
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -0
- package/Components/River/__tests__/componentsMap.test.js +38 -0
- package/Components/Screen/TV/index.web.tsx +4 -2
- package/Components/Screen/__tests__/Screen.test.tsx +66 -42
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +68 -44
- package/Components/Screen/hooks.ts +75 -6
- package/Components/Screen/index.tsx +9 -4
- package/Components/Screen/navigationHandler.ts +49 -24
- package/Components/Screen/orientationHandler.ts +10 -13
- package/Components/ScreenResolver/index.tsx +26 -16
- package/Components/ScreenRevealManager/ScreenRevealManager.ts +40 -8
- package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +86 -69
- package/Components/ScreenRevealManager/withScreenRevealManager.tsx +44 -26
- package/Components/Tabs/TV/Tabs.tsx +20 -3
- package/Components/Tabs/TabContent.tsx +7 -4
- package/Components/Transitioner/Scene.tsx +10 -3
- package/Components/Transitioner/index.js +3 -3
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +118 -171
- package/Components/VideoModal/ModalAnimation/index.ts +2 -13
- package/Components/VideoModal/ModalAnimation/utils.ts +1 -327
- package/Components/VideoModal/PlayerWrapper.tsx +14 -88
- package/Components/VideoModal/VideoModal.tsx +1 -5
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -0
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +15 -7
- package/Components/VideoModal/hooks/useModalSize.ts +10 -5
- package/Components/VideoModal/playerWrapperStyle.ts +70 -0
- package/Components/VideoModal/playerWrapperUtils.ts +91 -0
- package/Components/VideoModal/utils.ts +19 -9
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +0 -2
- package/Components/Viewport/ViewportAware/index.tsx +16 -7
- package/Components/Viewport/ViewportEvents/__tests__/viewportEvents.test.js +1 -1
- package/Contexts/ScreenContext/index.tsx +54 -19
- package/Contexts/ScreenTrackedViewPositionsContext/__tests__/index.test.tsx +1 -1
- package/Contexts/ZappHookModalContext/index.tsx +37 -61
- package/Contexts/ZappPipesContext/ZappPipesContextFactory.tsx +18 -7
- package/Contexts/index.ts +0 -2
- package/Decorators/Analytics/index.tsx +6 -5
- package/Decorators/ConfigurationWrapper/__tests__/__snapshots__/withConfigurationProvider.test.tsx.snap +1 -0
- package/Decorators/ConfigurationWrapper/const.ts +1 -0
- package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -7
- package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +212 -5
- package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +39 -21
- package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +1 -1
- package/Decorators/ZappPipesDataConnector/index.tsx +2 -2
- package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +1 -1
- package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +18 -7
- package/Helpers/DataSourceHelper/__tests__/itemLimitForData.test.ts +80 -0
- package/Helpers/DataSourceHelper/index.ts +19 -0
- package/events/index.ts +3 -0
- package/events/scrollEndReached.ts +15 -0
- package/index.d.ts +7 -0
- package/package.json +6 -5
- package/Components/River/TV/withTVEventHandler.tsx +0 -27
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +0 -60
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +0 -417
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.web.tsx +0 -294
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +0 -176
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.web.tsx +0 -93
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +0 -500
- package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +0 -108
- package/Helpers/DataSourceHelper/index.js +0 -19
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { create } from "zustand";
|
|
2
2
|
|
|
3
3
|
type HookModalState = {
|
|
4
4
|
path: string;
|
|
@@ -10,11 +10,12 @@ export type HookModalContextT = {
|
|
|
10
10
|
setIsHooksExecutionInProgress: (hookExecutionState?: boolean) => void;
|
|
11
11
|
isRunningInBackground: boolean;
|
|
12
12
|
isPresentationFullScreen: boolean;
|
|
13
|
-
setIsRunningInBackground: (
|
|
14
|
-
setIsPresentingFullScreen: (
|
|
13
|
+
setIsRunningInBackground: () => void;
|
|
14
|
+
setIsPresentingFullScreen: () => void;
|
|
15
15
|
state: HookModalState;
|
|
16
16
|
setState: (state: HookModalState) => void;
|
|
17
17
|
resetState: () => void;
|
|
18
|
+
hookPresentationMode: HookPresentationMode;
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
const initialState = {
|
|
@@ -24,68 +25,43 @@ const initialState = {
|
|
|
24
25
|
|
|
25
26
|
type HookPresentationMode = "background" | "fullScreen";
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
isRunningInBackground: null,
|
|
31
|
-
setIsRunningInBackground: () => {},
|
|
32
|
-
setIsPresentingFullScreen: () => {},
|
|
33
|
-
isPresentationFullScreen: null,
|
|
28
|
+
// Use useZappHookModalStore() in React components (hooks)
|
|
29
|
+
// Use zappHookModalStore.getState() in non-React functions (utility functions, etc.)
|
|
30
|
+
export const useZappHookModalStore = create<HookModalContextT>()((set) => ({
|
|
34
31
|
state: initialState,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const Provider = ({ children }: { children: React.ReactNode }) => {
|
|
40
|
-
const [state, setState] = React.useState<HookModalState>(initialState);
|
|
41
|
-
|
|
42
|
-
const [hookPresentationMode, setHookPresentationMode] =
|
|
43
|
-
React.useState<HookPresentationMode>(null);
|
|
44
|
-
|
|
45
|
-
const resetState = useCallback(() => {
|
|
46
|
-
setState(initialState);
|
|
47
|
-
}, [setState]);
|
|
48
|
-
|
|
49
|
-
const [isHooksExecutionInProgress, setIsHooksExecutionInProgress] =
|
|
50
|
-
React.useState(false);
|
|
32
|
+
isHooksExecutionInProgress: false,
|
|
33
|
+
hookPresentationMode: null as HookPresentationMode,
|
|
34
|
+
isRunningInBackground: false,
|
|
35
|
+
isPresentationFullScreen: false,
|
|
51
36
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
37
|
+
setState: (newState: HookModalState) => {
|
|
38
|
+
set({ state: newState });
|
|
39
|
+
},
|
|
55
40
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
41
|
+
setIsHooksExecutionInProgress: (hookExecutionState?: boolean) => {
|
|
42
|
+
set({ isHooksExecutionInProgress: hookExecutionState ?? false });
|
|
43
|
+
},
|
|
59
44
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
isHooksExecutionInProgress,
|
|
68
|
-
setIsHooksExecutionInProgress,
|
|
69
|
-
state,
|
|
70
|
-
setState,
|
|
71
|
-
resetState,
|
|
72
|
-
}}
|
|
73
|
-
>
|
|
74
|
-
{children}
|
|
75
|
-
</ReactContext.Provider>
|
|
76
|
-
);
|
|
77
|
-
};
|
|
45
|
+
setIsRunningInBackground: () => {
|
|
46
|
+
set({
|
|
47
|
+
hookPresentationMode: "background",
|
|
48
|
+
isRunningInBackground: true,
|
|
49
|
+
isPresentationFullScreen: false,
|
|
50
|
+
});
|
|
51
|
+
},
|
|
78
52
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
};
|
|
53
|
+
setIsPresentingFullScreen: () => {
|
|
54
|
+
set({
|
|
55
|
+
hookPresentationMode: "fullScreen",
|
|
56
|
+
isRunningInBackground: false,
|
|
57
|
+
isPresentationFullScreen: true,
|
|
58
|
+
});
|
|
59
|
+
},
|
|
87
60
|
|
|
88
|
-
|
|
89
|
-
};
|
|
61
|
+
resetState: () => {
|
|
62
|
+
set({ state: initialState });
|
|
63
|
+
},
|
|
64
|
+
}));
|
|
90
65
|
|
|
91
|
-
|
|
66
|
+
// Export an alias for clearer non-React usage (utility functions, etc.)
|
|
67
|
+
export const zappHookModalStore = useZappHookModalStore;
|
|
@@ -5,10 +5,10 @@ import React, {
|
|
|
5
5
|
useMemo,
|
|
6
6
|
useState,
|
|
7
7
|
} from "react";
|
|
8
|
-
import * as R from "ramda";
|
|
9
8
|
|
|
10
|
-
type ProviderProps = {
|
|
9
|
+
type ProviderProps<S> = {
|
|
11
10
|
children: React.ReactChild;
|
|
11
|
+
initialContextValue?: S;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
type ContextType<T> = {
|
|
@@ -27,21 +27,29 @@ export function createZappPipesContext<T, S = T>(
|
|
|
27
27
|
) {
|
|
28
28
|
const Context = createContext<ContextType<S>>(initialContext);
|
|
29
29
|
|
|
30
|
-
const
|
|
30
|
+
const defaultSelector = (c: any) => c;
|
|
31
|
+
const defaultPrepareContext = (n: any) => n;
|
|
32
|
+
const joinArgs = (args: any[]) => args.join("-");
|
|
33
|
+
|
|
34
|
+
const { selector = defaultSelector, prepareContext = defaultPrepareContext } =
|
|
35
|
+
options || {};
|
|
31
36
|
|
|
32
37
|
function useZappPipesContext(...hookArgs: any[]): [T, (T) => void] {
|
|
33
38
|
const { context, setContext } = useContext(Context);
|
|
39
|
+
const joinedArgs = joinArgs(hookArgs);
|
|
34
40
|
|
|
35
41
|
const contextValue = useMemo(
|
|
36
42
|
() => selector(context, ...hookArgs),
|
|
37
|
-
|
|
43
|
+
// eslint-disable-next-line @wogns3623/better-exhaustive-deps/exhaustive-deps
|
|
44
|
+
[context, joinedArgs]
|
|
38
45
|
);
|
|
39
46
|
|
|
40
47
|
const contextSetter = useCallback(
|
|
41
48
|
(newContext: T) => {
|
|
42
49
|
setContext(prepareContext(newContext, context, ...hookArgs));
|
|
43
50
|
},
|
|
44
|
-
|
|
51
|
+
// eslint-disable-next-line @wogns3623/better-exhaustive-deps/exhaustive-deps
|
|
52
|
+
[context, joinedArgs]
|
|
45
53
|
);
|
|
46
54
|
|
|
47
55
|
return useMemo(
|
|
@@ -50,8 +58,11 @@ export function createZappPipesContext<T, S = T>(
|
|
|
50
58
|
);
|
|
51
59
|
}
|
|
52
60
|
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
/** Provider accepts `initialContextValue` prop to set the initial context value */
|
|
62
|
+
function Provider({ children, initialContextValue }: ProviderProps<S>) {
|
|
63
|
+
const [context, setContext] = useState<S>(
|
|
64
|
+
initialContextValue ?? initialContext.context
|
|
65
|
+
);
|
|
55
66
|
|
|
56
67
|
return (
|
|
57
68
|
<Context.Provider value={{ context, setContext }}>
|
package/Contexts/index.ts
CHANGED
|
@@ -12,8 +12,6 @@ export { HorizontalScrollContext } from "./HorizontalScrollContext";
|
|
|
12
12
|
|
|
13
13
|
export { RiverOffsetContext } from "./RiverOffsetContext";
|
|
14
14
|
|
|
15
|
-
export { ZappHookModalContext } from "./ZappHookModalContext";
|
|
16
|
-
|
|
17
15
|
export { MeasurementContext } from "./MeasurementContext";
|
|
18
16
|
|
|
19
17
|
export * from "./ZappPipesContext";
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
3
|
import { getAnalyticsFunctions } from "@applicaster/zapp-react-native-utils/analyticsUtils";
|
|
4
|
-
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
5
4
|
|
|
6
5
|
type ComponentProps = {
|
|
7
6
|
component: {
|
|
@@ -21,11 +20,13 @@ type ComponentProps = {
|
|
|
21
20
|
|
|
22
21
|
function withAnalytics(Component) {
|
|
23
22
|
return function WithAnalytics(props: ComponentProps) {
|
|
24
|
-
const { appData } = usePickFromState(["appData"]);
|
|
25
|
-
|
|
26
23
|
const analyticsFunctions = React.useMemo(
|
|
27
|
-
() =>
|
|
28
|
-
|
|
24
|
+
() =>
|
|
25
|
+
getAnalyticsFunctions({
|
|
26
|
+
component: props.component,
|
|
27
|
+
zappPipesData: props.zappPipesData,
|
|
28
|
+
} as any),
|
|
29
|
+
[props.component, props.zappPipesData]
|
|
29
30
|
);
|
|
30
31
|
|
|
31
32
|
return (
|
|
@@ -88,6 +88,7 @@ exports[`withConfigurationProvider correctly passes all the configuration keys c
|
|
|
88
88
|
tab_cell_padding_right={10}
|
|
89
89
|
tab_cell_padding_top={14}
|
|
90
90
|
tablet_theme={false}
|
|
91
|
+
tabs_screen_background_color="transparent"
|
|
91
92
|
target={false}
|
|
92
93
|
target_screen_switch={false}
|
|
93
94
|
text_label_active_font_color="rgba(239, 239, 239, 0.5)"
|
|
@@ -208,4 +208,5 @@ export const keysMap: Record<string, Function> = {
|
|
|
208
208
|
tab_bar_item_margin_right: castOrDefaultValue(Number, 0),
|
|
209
209
|
tab_bar_item_margin_bottom: castOrDefaultValue(Number, 0),
|
|
210
210
|
tab_bar_item_margin_left: castOrDefaultValue(Number, 0),
|
|
211
|
+
tabs_screen_background_color: castOrDefaultValue(R.identity, "transparent"),
|
|
211
212
|
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// ResolverSelector.tsx
|
|
2
1
|
import React from "react";
|
|
3
2
|
import { ComponentDataSourceContext, ZappPipesDataProps } from "./types";
|
|
4
3
|
import { StaticFeedResolver } from "./resolvers/StaticFeedResolver";
|
|
@@ -12,14 +11,33 @@ type ResolverSelectorProps = ComponentDataSourceContext & {
|
|
|
12
11
|
export function ResolverSelector(props: ResolverSelectorProps) {
|
|
13
12
|
const { getStaticComponentFeed, component, feedUrl, children } = props;
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
const renderDefaultResolver = (
|
|
15
|
+
fallbackChildren: (dataProps: ZappPipesDataProps) => React.ReactNode
|
|
16
|
+
) => {
|
|
17
|
+
if (feedUrl || component?.data?.source) {
|
|
18
|
+
return <UrlFeedResolver {...props}>{fallbackChildren}</UrlFeedResolver>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return <NullFeedResolver>{fallbackChildren}</NullFeedResolver>;
|
|
22
|
+
};
|
|
23
|
+
|
|
16
24
|
if (getStaticComponentFeed) {
|
|
17
|
-
return
|
|
18
|
-
|
|
25
|
+
return (
|
|
26
|
+
<StaticFeedResolver {...props}>
|
|
27
|
+
{(zappPipesDataProps) => {
|
|
28
|
+
const { data, loading, error } = zappPipesDataProps.zappPipesData;
|
|
29
|
+
|
|
30
|
+
const shouldFallback = !loading && data === null && !error;
|
|
31
|
+
|
|
32
|
+
if (shouldFallback) {
|
|
33
|
+
return renderDefaultResolver(children);
|
|
34
|
+
}
|
|
19
35
|
|
|
20
|
-
|
|
21
|
-
|
|
36
|
+
return children(zappPipesDataProps);
|
|
37
|
+
}}
|
|
38
|
+
</StaticFeedResolver>
|
|
39
|
+
);
|
|
22
40
|
}
|
|
23
41
|
|
|
24
|
-
return
|
|
42
|
+
return renderDefaultResolver(children);
|
|
25
43
|
}
|
|
@@ -7,15 +7,30 @@ import { UrlFeedResolver } from "../resolvers/UrlFeedResolver";
|
|
|
7
7
|
import { NullFeedResolver } from "../resolvers/NullFeedResolver";
|
|
8
8
|
|
|
9
9
|
jest.mock("../resolvers/StaticFeedResolver", () => ({
|
|
10
|
-
StaticFeedResolver: jest.fn(() =>
|
|
10
|
+
StaticFeedResolver: jest.fn(({ children }) =>
|
|
11
|
+
children({
|
|
12
|
+
zappPipesData: { loading: true, data: null, error: null },
|
|
13
|
+
reloadData: jest.fn(),
|
|
14
|
+
})
|
|
15
|
+
),
|
|
11
16
|
}));
|
|
12
17
|
|
|
13
18
|
jest.mock("../resolvers/UrlFeedResolver", () => ({
|
|
14
|
-
UrlFeedResolver: jest.fn(() =>
|
|
19
|
+
UrlFeedResolver: jest.fn(({ children }) =>
|
|
20
|
+
children({
|
|
21
|
+
zappPipesData: { loading: true, data: null, error: null },
|
|
22
|
+
reloadData: jest.fn(),
|
|
23
|
+
})
|
|
24
|
+
),
|
|
15
25
|
}));
|
|
16
26
|
|
|
17
27
|
jest.mock("../resolvers/NullFeedResolver", () => ({
|
|
18
|
-
NullFeedResolver: jest.fn(() =>
|
|
28
|
+
NullFeedResolver: jest.fn(({ children }) =>
|
|
29
|
+
children({
|
|
30
|
+
zappPipesData: { loading: false, data: null, error: null },
|
|
31
|
+
reloadData: jest.fn(),
|
|
32
|
+
})
|
|
33
|
+
),
|
|
19
34
|
}));
|
|
20
35
|
|
|
21
36
|
const testPlugin = {
|
|
@@ -52,7 +67,7 @@ describe("ResolverSelector", () => {
|
|
|
52
67
|
expect.objectContaining({
|
|
53
68
|
getStaticComponentFeed: props.getStaticComponentFeed,
|
|
54
69
|
component: mockComponent,
|
|
55
|
-
children:
|
|
70
|
+
children: expect.any(Function),
|
|
56
71
|
}),
|
|
57
72
|
expect.anything()
|
|
58
73
|
);
|
|
@@ -151,7 +166,10 @@ describe("ResolverSelector", () => {
|
|
|
151
166
|
render(<ResolverSelector {...props} />);
|
|
152
167
|
|
|
153
168
|
expect(StaticFeedResolver).toHaveBeenCalledWith(
|
|
154
|
-
expect.objectContaining(
|
|
169
|
+
expect.objectContaining({
|
|
170
|
+
...props,
|
|
171
|
+
children: expect.any(Function),
|
|
172
|
+
}),
|
|
155
173
|
expect.anything()
|
|
156
174
|
);
|
|
157
175
|
});
|
|
@@ -202,4 +220,193 @@ describe("ResolverSelector", () => {
|
|
|
202
220
|
expect(UrlFeedResolver).not.toHaveBeenCalled();
|
|
203
221
|
expect(NullFeedResolver).not.toHaveBeenCalled();
|
|
204
222
|
});
|
|
223
|
+
|
|
224
|
+
describe("Fallback Logic", () => {
|
|
225
|
+
it("should fallback to UrlFeedResolver when StaticFeedResolver returns null and feedUrl is present", () => {
|
|
226
|
+
const props = {
|
|
227
|
+
getStaticComponentFeed: jest.fn(),
|
|
228
|
+
feedUrl: "https://example.com/feed",
|
|
229
|
+
component: mockComponent,
|
|
230
|
+
children: mockChildren,
|
|
231
|
+
riverId: "test-river",
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
(StaticFeedResolver as jest.Mock).mockImplementation(({ children }) =>
|
|
235
|
+
children({
|
|
236
|
+
zappPipesData: { loading: false, data: null, error: null },
|
|
237
|
+
reloadData: jest.fn(),
|
|
238
|
+
})
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
render(<ResolverSelector {...props} />);
|
|
242
|
+
|
|
243
|
+
expect(StaticFeedResolver).toHaveBeenCalled();
|
|
244
|
+
|
|
245
|
+
expect(UrlFeedResolver).toHaveBeenCalledWith(
|
|
246
|
+
expect.objectContaining({
|
|
247
|
+
feedUrl: props.feedUrl,
|
|
248
|
+
component: mockComponent,
|
|
249
|
+
children: mockChildren,
|
|
250
|
+
}),
|
|
251
|
+
expect.anything()
|
|
252
|
+
);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it("should fallback to UrlFeedResolver when StaticFeedResolver returns null and component.data.source is present", () => {
|
|
256
|
+
const componentWithSource = {
|
|
257
|
+
...mockComponent,
|
|
258
|
+
data: {
|
|
259
|
+
source: "data-source",
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const props = {
|
|
264
|
+
getStaticComponentFeed: jest.fn(),
|
|
265
|
+
component: componentWithSource,
|
|
266
|
+
children: mockChildren,
|
|
267
|
+
riverId: "test-river",
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
(StaticFeedResolver as jest.Mock).mockImplementation(({ children }) =>
|
|
271
|
+
children({
|
|
272
|
+
zappPipesData: { loading: false, data: null, error: null },
|
|
273
|
+
reloadData: jest.fn(),
|
|
274
|
+
})
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
render(<ResolverSelector {...props} />);
|
|
278
|
+
|
|
279
|
+
expect(StaticFeedResolver).toHaveBeenCalled();
|
|
280
|
+
|
|
281
|
+
expect(UrlFeedResolver).toHaveBeenCalledWith(
|
|
282
|
+
expect.objectContaining({
|
|
283
|
+
component: componentWithSource,
|
|
284
|
+
children: mockChildren,
|
|
285
|
+
}),
|
|
286
|
+
expect.anything()
|
|
287
|
+
);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("should fallback to NullFeedResolver when StaticFeedResolver returns null and no feedUrl/source is present", () => {
|
|
291
|
+
const props = {
|
|
292
|
+
getStaticComponentFeed: jest.fn(),
|
|
293
|
+
component: mockComponent,
|
|
294
|
+
children: mockChildren,
|
|
295
|
+
riverId: "test-river",
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
(StaticFeedResolver as jest.Mock).mockImplementation(({ children }) =>
|
|
299
|
+
children({
|
|
300
|
+
zappPipesData: { loading: false, data: null, error: null },
|
|
301
|
+
reloadData: jest.fn(),
|
|
302
|
+
})
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
render(<ResolverSelector {...props} />);
|
|
306
|
+
|
|
307
|
+
expect(StaticFeedResolver).toHaveBeenCalled();
|
|
308
|
+
expect(UrlFeedResolver).not.toHaveBeenCalled();
|
|
309
|
+
|
|
310
|
+
expect(NullFeedResolver).toHaveBeenCalledWith(
|
|
311
|
+
expect.objectContaining({
|
|
312
|
+
children: mockChildren,
|
|
313
|
+
}),
|
|
314
|
+
expect.anything()
|
|
315
|
+
);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it("should NOT fallback and call children with static data when StaticFeedResolver returns data", () => {
|
|
319
|
+
const staticData = { entry: [{ id: "1" }] };
|
|
320
|
+
|
|
321
|
+
const props = {
|
|
322
|
+
getStaticComponentFeed: jest.fn(),
|
|
323
|
+
feedUrl: "https://example.com/feed",
|
|
324
|
+
component: mockComponent,
|
|
325
|
+
children: mockChildren,
|
|
326
|
+
riverId: "test-river",
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
(StaticFeedResolver as jest.Mock).mockImplementation(({ children }) =>
|
|
330
|
+
children({
|
|
331
|
+
zappPipesData: { loading: false, data: staticData, error: null },
|
|
332
|
+
reloadData: jest.fn(),
|
|
333
|
+
})
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
render(<ResolverSelector {...props} />);
|
|
337
|
+
|
|
338
|
+
expect(StaticFeedResolver).toHaveBeenCalled();
|
|
339
|
+
expect(UrlFeedResolver).not.toHaveBeenCalled();
|
|
340
|
+
|
|
341
|
+
expect(mockChildren).toHaveBeenCalledWith(
|
|
342
|
+
expect.objectContaining({
|
|
343
|
+
zappPipesData: expect.objectContaining({
|
|
344
|
+
data: staticData,
|
|
345
|
+
}),
|
|
346
|
+
})
|
|
347
|
+
);
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
it("should NOT fallback and call children with loading state when StaticFeedResolver is loading", () => {
|
|
351
|
+
const props = {
|
|
352
|
+
getStaticComponentFeed: jest.fn(),
|
|
353
|
+
feedUrl: "https://example.com/feed",
|
|
354
|
+
component: mockComponent,
|
|
355
|
+
children: mockChildren,
|
|
356
|
+
riverId: "test-river",
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
(StaticFeedResolver as jest.Mock).mockImplementation(({ children }) =>
|
|
360
|
+
children({
|
|
361
|
+
zappPipesData: { loading: true, data: null, error: null },
|
|
362
|
+
reloadData: jest.fn(),
|
|
363
|
+
})
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
render(<ResolverSelector {...props} />);
|
|
367
|
+
|
|
368
|
+
expect(StaticFeedResolver).toHaveBeenCalled();
|
|
369
|
+
expect(UrlFeedResolver).not.toHaveBeenCalled();
|
|
370
|
+
|
|
371
|
+
expect(mockChildren).toHaveBeenCalledWith(
|
|
372
|
+
expect.objectContaining({
|
|
373
|
+
zappPipesData: expect.objectContaining({
|
|
374
|
+
loading: true,
|
|
375
|
+
}),
|
|
376
|
+
})
|
|
377
|
+
);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
it("should NOT fallback and call children with error when StaticFeedResolver returns error", () => {
|
|
381
|
+
const error = new Error("Static error");
|
|
382
|
+
|
|
383
|
+
const props = {
|
|
384
|
+
getStaticComponentFeed: jest.fn(),
|
|
385
|
+
feedUrl: "https://example.com/feed",
|
|
386
|
+
component: mockComponent,
|
|
387
|
+
children: mockChildren,
|
|
388
|
+
riverId: "test-river",
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
(StaticFeedResolver as jest.Mock).mockImplementation(({ children }) =>
|
|
392
|
+
children({
|
|
393
|
+
zappPipesData: { loading: false, data: null, error },
|
|
394
|
+
reloadData: jest.fn(),
|
|
395
|
+
})
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
render(<ResolverSelector {...props} />);
|
|
399
|
+
|
|
400
|
+
expect(StaticFeedResolver).toHaveBeenCalled();
|
|
401
|
+
expect(UrlFeedResolver).not.toHaveBeenCalled();
|
|
402
|
+
|
|
403
|
+
expect(mockChildren).toHaveBeenCalledWith(
|
|
404
|
+
expect.objectContaining({
|
|
405
|
+
zappPipesData: expect.objectContaining({
|
|
406
|
+
error,
|
|
407
|
+
}),
|
|
408
|
+
})
|
|
409
|
+
);
|
|
410
|
+
});
|
|
411
|
+
});
|
|
205
412
|
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import * as useFeedLoaderModule from "@applicaster/zapp-react-native-utils/reactHooks/feed/useFeedLoader";
|
|
3
|
-
import * as useFeedRefreshModule from "@applicaster/zapp-react-native-utils/reactHooks/feed/useFeedRefresh";
|
|
4
3
|
import { favoritesListener } from "@applicaster/zapp-react-native-bridge/Favorites";
|
|
5
4
|
import { UrlFeedResolver } from "../resolvers/UrlFeedResolver";
|
|
6
5
|
import { renderWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
|
|
@@ -14,10 +13,6 @@ jest
|
|
|
14
13
|
|
|
15
14
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/feed/useFeedLoader");
|
|
16
15
|
|
|
17
|
-
jest.mock(
|
|
18
|
-
"@applicaster/zapp-react-native-utils/reactHooks/feed/useFeedRefresh"
|
|
19
|
-
);
|
|
20
|
-
|
|
21
16
|
jest.mock("@applicaster/zapp-pipes-v2-client");
|
|
22
17
|
|
|
23
18
|
jest.mock("@applicaster/zapp-react-native-bridge/Favorites", () => ({
|
|
@@ -62,6 +57,9 @@ describe("UrlFeedResolver", () => {
|
|
|
62
57
|
component: { ...componentRequiredKeys } as any,
|
|
63
58
|
children: mockChildren,
|
|
64
59
|
riverId: "test-river",
|
|
60
|
+
screenContext: {
|
|
61
|
+
id: "screenId",
|
|
62
|
+
},
|
|
65
63
|
};
|
|
66
64
|
|
|
67
65
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -82,6 +80,9 @@ describe("UrlFeedResolver", () => {
|
|
|
82
80
|
} as any,
|
|
83
81
|
children: mockChildren,
|
|
84
82
|
riverId: "test-river",
|
|
83
|
+
screenContext: {
|
|
84
|
+
id: "screenId",
|
|
85
|
+
},
|
|
85
86
|
};
|
|
86
87
|
|
|
87
88
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -103,6 +104,9 @@ describe("UrlFeedResolver", () => {
|
|
|
103
104
|
} as any,
|
|
104
105
|
children: mockChildren,
|
|
105
106
|
riverId: "test-river",
|
|
107
|
+
screenContext: {
|
|
108
|
+
id: "screenId",
|
|
109
|
+
},
|
|
106
110
|
};
|
|
107
111
|
|
|
108
112
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -132,6 +136,9 @@ describe("UrlFeedResolver", () => {
|
|
|
132
136
|
} as any,
|
|
133
137
|
children: mockChildren,
|
|
134
138
|
riverId: "test-river",
|
|
139
|
+
screenContext: {
|
|
140
|
+
id: "screenId",
|
|
141
|
+
},
|
|
135
142
|
};
|
|
136
143
|
|
|
137
144
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -155,6 +162,9 @@ describe("UrlFeedResolver", () => {
|
|
|
155
162
|
children: mockChildren,
|
|
156
163
|
riverId: "test-river",
|
|
157
164
|
plugins: [],
|
|
165
|
+
screenContext: {
|
|
166
|
+
id: "screenId",
|
|
167
|
+
},
|
|
158
168
|
};
|
|
159
169
|
|
|
160
170
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -173,6 +183,9 @@ describe("UrlFeedResolver", () => {
|
|
|
173
183
|
component: { ...componentRequiredKeys } as any,
|
|
174
184
|
children: mockChildren,
|
|
175
185
|
riverId: "test-river",
|
|
186
|
+
screenContext: {
|
|
187
|
+
id: "screenId",
|
|
188
|
+
},
|
|
176
189
|
};
|
|
177
190
|
|
|
178
191
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -197,6 +210,9 @@ describe("UrlFeedResolver", () => {
|
|
|
197
210
|
},
|
|
198
211
|
},
|
|
199
212
|
] as any,
|
|
213
|
+
screenContext: {
|
|
214
|
+
id: "screenId",
|
|
215
|
+
},
|
|
200
216
|
};
|
|
201
217
|
|
|
202
218
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -215,6 +231,9 @@ describe("UrlFeedResolver", () => {
|
|
|
215
231
|
} as any,
|
|
216
232
|
children: mockChildren,
|
|
217
233
|
riverId: "test-river",
|
|
234
|
+
screenContext: {
|
|
235
|
+
id: "screenId",
|
|
236
|
+
},
|
|
218
237
|
};
|
|
219
238
|
|
|
220
239
|
(useFeedLoaderModule.useFeedLoader as jest.Mock).mockReturnValue({
|
|
@@ -250,6 +269,9 @@ describe("UrlFeedResolver", () => {
|
|
|
250
269
|
children: mockChildren,
|
|
251
270
|
riverId: "test-river",
|
|
252
271
|
isLast: true,
|
|
272
|
+
screenContext: {
|
|
273
|
+
id: "screenId",
|
|
274
|
+
},
|
|
253
275
|
};
|
|
254
276
|
|
|
255
277
|
renderWithProviders(<UrlFeedResolver {...props1} />);
|
|
@@ -272,6 +294,9 @@ describe("UrlFeedResolver", () => {
|
|
|
272
294
|
children: mockChildren,
|
|
273
295
|
riverId: "test-river",
|
|
274
296
|
isLast: false,
|
|
297
|
+
screenContext: {
|
|
298
|
+
id: "screenId",
|
|
299
|
+
},
|
|
275
300
|
};
|
|
276
301
|
|
|
277
302
|
renderWithProviders(<UrlFeedResolver {...props2} />);
|
|
@@ -294,6 +319,9 @@ describe("UrlFeedResolver", () => {
|
|
|
294
319
|
children: mockChildren,
|
|
295
320
|
riverId: "test-river",
|
|
296
321
|
isLast: false,
|
|
322
|
+
screenContext: {
|
|
323
|
+
id: "screenId",
|
|
324
|
+
},
|
|
297
325
|
};
|
|
298
326
|
|
|
299
327
|
renderWithProviders(<UrlFeedResolver {...props3} />);
|
|
@@ -311,6 +339,9 @@ describe("UrlFeedResolver", () => {
|
|
|
311
339
|
component: { ...componentRequiredKeys } as any,
|
|
312
340
|
children: mockChildren,
|
|
313
341
|
riverId: "test-river",
|
|
342
|
+
screenContext: {
|
|
343
|
+
id: "screenId",
|
|
344
|
+
},
|
|
314
345
|
};
|
|
315
346
|
|
|
316
347
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -327,22 +358,6 @@ describe("UrlFeedResolver", () => {
|
|
|
327
358
|
});
|
|
328
359
|
});
|
|
329
360
|
|
|
330
|
-
it("should apply feed refresh hook", () => {
|
|
331
|
-
const props = {
|
|
332
|
-
feedUrl: "https://example.com/feed",
|
|
333
|
-
component: { ...componentRequiredKeys } as any,
|
|
334
|
-
children: mockChildren,
|
|
335
|
-
riverId: "test-river",
|
|
336
|
-
};
|
|
337
|
-
|
|
338
|
-
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
339
|
-
|
|
340
|
-
expect(useFeedRefreshModule.useFeedRefresh).toHaveBeenCalledWith({
|
|
341
|
-
reloadData: mockReloadData,
|
|
342
|
-
component: props.component,
|
|
343
|
-
});
|
|
344
|
-
});
|
|
345
|
-
|
|
346
361
|
it("should clean up listeners on unmount", () => {
|
|
347
362
|
const props = {
|
|
348
363
|
component: {
|
|
@@ -354,6 +369,9 @@ describe("UrlFeedResolver", () => {
|
|
|
354
369
|
} as any,
|
|
355
370
|
children: mockChildren,
|
|
356
371
|
riverId: "test-river",
|
|
372
|
+
screenContext: {
|
|
373
|
+
id: "screenId",
|
|
374
|
+
},
|
|
357
375
|
};
|
|
358
376
|
|
|
359
377
|
const { unmount } = renderWithProviders(<UrlFeedResolver {...props} />);
|