import React from "react";
import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
import { renderHook } from "@testing-library/react-hooks";
import { isNavBarVisible, useRoute } from "../";
import { Provider } from "react-redux";
import configureMockStore from "redux-mock-store";
import { NavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NavigationContext";
import { ROUTE_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtils/routeTypes";
import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
const plugins = [];
const rivers = {
"river-player": {
id: "river-player",
plugin_type: "player",
},
"river-general": {
id: "river-general",
plugin_type: "general",
},
};
const contentTypes = {
video: { screen_id: "river-player" },
link: { screen_id: "river-general" },
};
const screen = {
id: "123",
};
const entry = { id: "abc" };
const homeStack = {
route: "/home",
state: {
screen,
entry,
},
};
const videoItem = {
id: "video-1",
type: { value: "video" },
};
const mockGetStackForPathname = jest.fn().mockReturnValue(homeStack);
const mainStackNavigator = {
getStackForPathname: mockGetStackForPathname,
getModalState: () => {},
videoModalState: {},
canGoBack: jest.fn(),
};
const _createWrapper = (Wrapper, props) => {
return function CreatedWrapper({ children }: any) {
return {children};
};
};
const videoModalNavigator = {
...mainStackNavigator,
videoModalState: { item: videoItem },
};
const hookModalNavigator = {
...mainStackNavigator,
};
const hookModalContextState = {
isRunningInBackground: false,
setIsRunningInBackground: jest.fn(),
setIsPresentingFullScreen: jest.fn(),
isPresentationFullScreen: true,
isHooksExecutionInProgress: true,
setIsHooksExecutionInProgress: jest.fn(),
state: {
path: "/home",
screenData: { payload: { id: "hookExecutedInModal" } },
},
setState: jest.fn(),
resetState: jest.fn(),
hookPresentationMode: null,
};
const hooksModalPathname = `${ROUTE_TYPES.HOOKS_MODAL}/${hookModalContextState.state.screenData.payload.id}`;
jest.mock(
"@applicaster/zapp-react-native-ui-components/Contexts/ZappHookModalContext",
() => {
// Define state inside mock factory to avoid hoisting issues
const mockState = {
isRunningInBackground: false,
setIsRunningInBackground: jest.fn(),
setIsPresentingFullScreen: jest.fn(),
isPresentationFullScreen: true,
isHooksExecutionInProgress: true,
setIsHooksExecutionInProgress: jest.fn(),
state: {
path: "/home",
screenData: { payload: { id: "hookExecutedInModal" } },
},
setState: jest.fn(),
resetState: jest.fn(),
hookPresentationMode: null,
};
const mockHook = jest.fn((selector) => {
return selector ? selector(mockState) : mockState;
}) as jest.MockedFunction & { getState: () => typeof mockState };
// Add getState method to the mock hook (Zustand stores have this)
mockHook.getState = jest.fn(() => mockState);
return {
useZappHookModalStore: mockHook,
zappHookModalStore: mockHook,
};
}
);
const videoModalPathname = `${ROUTE_TYPES.VIDEO_MODAL}/${videoModalNavigator.videoModalState.item.id}`;
const mockStore = configureMockStore();
const store = mockStore({
plugins,
rivers,
contentTypes,
});
const mainStackWrapper = ({
children,
navigator = {},
pathname = homeStack.route,
}) => (
{children}
);
const videoModalWrapper = ({ children }) => (
{children}
);
const hookModalWrapper = ({ children }) => (
{children}
);
describe("navigation", () => {
describe("useRoute", () => {
describe("Main stack components", () => {
it("should return a correct pathname", () => {
const { result } = renderHook(() => useRoute(), {
wrapper: mainStackWrapper,
});
expect(result.current.pathname).toEqual(homeStack.route);
});
it("should return correct screenData information", () => {
const { result } = renderHook(() => useRoute(), {
wrapper: mainStackWrapper,
});
expect(result.current.screenData.id).toEqual(entry.id);
expect(result.current.screenData.targetScreen.id).toEqual(screen.id);
});
});
describe("Hook modal components", () => {
it("should return a correct pathname", () => {
const { result } = renderHook(() => useRoute(), {
wrapper: hookModalWrapper,
});
expect(result.current.pathname).toEqual(hooksModalPathname);
});
it("should return correct screenData information", () => {
const { result } = renderHook(() => useRoute(), {
wrapper: hookModalWrapper,
});
expect(result.current.screenData.id).toEqual(
hookModalContextState.state.screenData.payload.id
);
});
});
describe("Video modal components", () => {
it("should return a correct pathname", () => {
const { result } = renderHook(() => useRoute(), {
wrapper: videoModalWrapper,
});
expect(result.current.pathname).toEqual(videoModalPathname);
});
it("should return correct screenData information", () => {
const { result } = renderHook(() => useRoute(), {
wrapper: videoModalWrapper,
});
expect(result.current.screenData.id).toEqual(
videoModalNavigator.videoModalState.item.id
);
expect(result.current.screenData.targetScreen.id).toEqual(
rivers["river-player"].id
);
});
});
});
describe("isNavBarVisible", () => {
it("returns false when the route is a player route", () => {
const navBarVisible = isNavBarVisible(
"/playable/some_vod_item",
{} as ZappRiver,
false,
false
);
expect(navBarVisible).toBe(false);
});
it("returns false when the next screen is the QB search screen", () => {
const navBarVisible = isNavBarVisible(
"/river/A1234",
{
type: "qb_search_screen",
} as any,
false,
false
);
expect(navBarVisible).toBe(false);
});
describe("when screen is a hook", () => {
it("returns true if the `showNavBar` flag is set to true", () => {
const navBarVisible = isNavBarVisible(
"",
{
hookPlugin: {
module: {
showNavBar: true,
},
},
} as any,
false,
false
);
expect(navBarVisible).toBe(true);
});
it("returns true if presentFullScreen flag is set to false", () => {
const navBarVisible = isNavBarVisible(
"",
{
hookPlugin: {
module: {
presentFullScreen: false,
},
},
} as any,
false,
false
);
expect(navBarVisible).toBe(true);
});
it("returns false if presentFullScreen flag is set to true", () => {
const navBarVisible = isNavBarVisible(
"",
{
hookPlugin: {
module: {
presentFullScreen: true,
},
},
} as any,
false,
false
);
expect(navBarVisible).toBe(false);
});
});
it("returns false if the screen's general settings allow screen presentation", () => {
const navBarVisible = isNavBarVisible(
"",
{
general: {
allow_screen_plugin_presentation: true,
},
} as any,
false,
false
);
expect(navBarVisible).toBe(false);
});
it("returns false if the screen's general settings hide app nav bar", () => {
const navBarVisible = isNavBarVisible(
"",
{
general: {
hide_app_nav_bar: true,
},
} as any,
false,
false
);
expect(navBarVisible).toBe(false);
});
it("returns false if it's secondary nav bar and show_secondary_level_menu is false", () => {
const navBarVisible = isNavBarVisible(
"",
{
navigations: [
{
styles: {
show_secondary_level_menu: false,
},
},
],
} as any,
false,
true
);
expect(navBarVisible).toBe(false);
});
it("returns true if it's secondary nav bar and show_secondary_level_menu is true", () => {
const navBarVisible = isNavBarVisible(
"",
{
navigations: [
{
styles: {
show_secondary_level_menu: true,
},
},
],
} as any,
true,
false
);
expect(navBarVisible).toBe(true);
});
it("returns true if it's first level menu and show_secondary_level_menu is false", () => {
const navBarVisible = isNavBarVisible(
"",
{
navigations: [
{
styles: {
show_secondary_level_menu: false,
},
},
],
} as any,
true,
false
);
expect(navBarVisible).toBe(true);
});
});
});