@applicaster/zapp-react-native-utils
Version:
Applicaster Zapp React Native utilities package
387 lines (316 loc) • 11.3 kB
JavaScript
import * as R from "ramda";
import * as navigationUtils from "..";
import {
river,
riverPlugin,
riverFeed,
article,
menuItem,
content,
riverPluginPlayable,
} from "./fixtures";
import { SCREEN_TYPES } from "../itemTypes";
describe("getNavigationType", () => {
const { getNavigationType } = navigationUtils;
const navigations = [
{
category: "nav_bar",
navigation_type: "navigation_bar",
},
{
category: "menu",
navigation_type: "side_menu",
},
];
it("returns the type of navigation for a category", () => {
expect(getNavigationType("menu", navigations)).toBe("side_menu");
});
it("returns null if the category can't be found", () => {
expect(getNavigationType("some_nav", navigations)).toBeUndefined();
});
});
describe("resolveNavigationPlugin", () => {
const { resolveNavigationPlugin } = navigationUtils;
const defaultNav = {
module: jest.fn(),
name: "default nav",
identifier: "default_nav",
type: "menu",
default: true,
};
const otherDefaultPlugin = {
module: jest.fn(),
name: "some default plugin",
identifier: "Default_Plugin",
type: "player",
default: true,
};
const optionalNav = {
module: jest.fn(),
name: "Optional nav",
identifier: "optional_nav",
type: "menu",
};
const plugins = [defaultNav, otherDefaultPlugin, optionalNav];
const category = "menu";
it("returns null if navigation type cannot be found", () => {
const navigations = [];
expect(resolveNavigationPlugin({ category, navigations, plugins })).toBe(
null
);
});
it("returns the plugin matching the navigation type if it exists", () => {
const navigations = [
{
category: "menu",
navigation_type: "optional_nav",
},
];
expect(resolveNavigationPlugin({ category, navigations, plugins })).toEqual(
optionalNav
);
});
it("returns the default plugin otherwise", () => {
const navigations = [
{
category: "menu",
navigation_type: "unknown_nav",
},
];
expect(resolveNavigationPlugin({ category, navigations, plugins })).toEqual(
defaultNav
);
});
it("returns the default plugin if there's no other", () => {
const navigations = [
{
category: "menu",
navigation_type: "any_plugin",
},
];
expect(
resolveNavigationPlugin({ category, navigations, plugins: [defaultNav] })
).toEqual(defaultNav);
});
});
describe("getNavigationProps", () => {
const { getNavigationProps } = navigationUtils;
const baseScreen = {
id: "A1234",
name: "base screen",
home: false,
};
const category = "menu";
it("returns null if the screen has no navigation props", () => {
const navigations = [];
const navigator = {
activeRiver: R.merge(baseScreen, { navigations }),
};
expect(getNavigationProps({ navigator, category })).toBe(null);
});
it("returns the props otherwise", () => {
const navigations = [
{
category: "menu",
styles: { style: "foo" },
assets: { appLogo: "appLogo.png" },
nav_items: [{ type: "label" }],
rules: {},
},
];
const navigator = {
screenTitle: "base screen",
activeRiver: R.merge(baseScreen, { navigations }),
};
expect(
getNavigationProps({ navigator, title: "testTitle", category })
).toMatchSnapshot();
});
});
describe("getPathAttributes", () => {
const getLocation = (pathname) => ({ pathname });
const { getPathAttributes } = navigationUtils;
it("returns an empty array if path is empty", () => {
const location = getLocation("");
expect(getPathAttributes(location)).toEqual([]);
});
it("returns an empty array if path is /", () => {
const location = getLocation("/");
expect(getPathAttributes(location)).toEqual([]);
});
it("forms the path attributes", () => {
const location = getLocation("/river/A1234/someScreen/B456");
expect(getPathAttributes(location)).toEqual([
{ screenType: "river", screenId: "A1234" },
{ screenType: "someScreen", screenId: "B456" },
]);
});
});
describe("getItemType", () => {
const { getItemType } = navigationUtils;
describe("layouts v1", () => {
it("returns the type of an item", () => {
expect(getItemType(river, "v1")).toBe("river");
expect(getItemType(riverFeed, "v1")).toBe("river");
expect(getItemType(menuItem, "v1")).toBe("menu_item");
expect(getItemType(article, "v1")).toBe("article");
expect(getItemType(content, "v1")).toBe("content_screen");
});
});
describe("layouts v2", () => {
it("returns the type of an item", () => {
expect(getItemType(river, "v2")).toBe("river");
expect(getItemType(riverFeed, "v2")).toBe("river");
expect(getItemType(menuItem, "v2")).toBe("river");
expect(getItemType(article, "v2")).toBe("river");
expect(getItemType(content, "v2")).toBe("river");
});
});
});
describe("getItemTargetId", () => {
const { getItemTargetId } = navigationUtils;
it("returns the target id of an item", () => {
expect(getItemTargetId(river, "river")).toBe(river.id);
expect(getItemTargetId(riverFeed, "river")).toBe(riverFeed.riverId);
expect(getItemTargetId(menuItem, "menu_item")).toBe(menuItem.data.target);
expect(getItemTargetId(article, "article")).toBe(article.id);
expect(getItemTargetId(content, "content_screen")).toBe(content.id);
});
});
describe("getTargetRoute", () => {
const { getItemType, getItemTargetId, getTargetRoute } = navigationUtils;
describe("layout v1", () => {
const layoutVersion = "v1";
it("returns the target route for a given item", () => {
const pathname = "/foo";
const riverType = getItemType(river, layoutVersion);
const riverId = getItemTargetId(river, riverType);
expect(getTargetRoute(river, pathname, { layoutVersion })).toBe(
`${pathname}/${riverType}/${riverId}`
);
});
it("returns the target route for an item that is not a menu item", () => {
const pathname = "/foo";
const articleType = getItemType(article, layoutVersion);
const articleId = getItemTargetId(article, articleType);
expect(getTargetRoute(article, pathname, { layoutVersion })).toBe(
`${pathname}/${articleType}/${articleId}`
);
});
it("returns a valid path when initial pathname is /", () => {
const targetRoute = getTargetRoute(river, "/", { layoutVersion });
expect(targetRoute).toEqual(`/river/${river.id}`);
expect(targetRoute).not.toInclude("//");
});
});
describe("layout v2", () => {
const layoutVersion = "v2";
it("returns the target route for a given item", () => {
const pathname = "/foo";
const riverType = getItemType(river, layoutVersion);
const riverId = getItemTargetId(river, riverType);
expect(getTargetRoute(river, pathname, { layoutVersion })).toBe(
`${pathname}/${riverType}/${riverId}`
);
});
it("returns the target route for an item that is not a menu item", () => {
const pathname = "/foo";
const articleType = getItemType(article, layoutVersion);
const articleId = getItemTargetId(article, articleType);
expect(getTargetRoute(article, pathname, { layoutVersion })).toBe(
`${pathname}/${articleType}/${articleId}`
);
});
it("returns a valid path when initial pathname is /", () => {
const targetRoute = getTargetRoute(river, "/", { layoutVersion });
expect(targetRoute).toEqual(`/river/${river.id}`);
expect(targetRoute).not.toInclude("//");
});
});
});
describe("getRiverFromRoute", () => {
const { getRiverFromRoute } = navigationUtils;
const rivers = {
[river.id]: river,
[riverFeed.id]: riverFeed,
[riverPlugin.id]: riverPlugin,
[riverPluginPlayable.id]: riverPluginPlayable,
};
it("returns null if the route is not valid", () => {
const route = "foo-bar";
expect(getRiverFromRoute({ route, rivers })).toBe(null);
});
it("returns the screen type & screen id if it cannot find a river", () => {
const route = "/article/A123";
expect(getRiverFromRoute({ route: route, rivers })).toEqual({
screenType: "article",
screenId: "A123",
});
});
it("returns the plugin screen if the river points to a plugin screen ", () => {
const route = `/river/${river.id}/${riverPlugin.type}/SOME_ID`;
expect(getRiverFromRoute({ route, rivers })).toEqual(riverPlugin);
});
it("returns the plugin screen if the river points to a player screen ", () => {
const route = `/river/${river.id}/${SCREEN_TYPES.PLAYABLE}/SOME_ID`;
expect(getRiverFromRoute({ route, rivers })).toEqual(riverPluginPlayable);
});
it("returns the river if the route path is a a river path", () => {
const route = `/river/${river.id}`;
expect(getRiverFromRoute({ route, rivers })).toEqual(river);
});
});
describe("isPreviousRouteHook", () => {
const { isPreviousRouteHook } = navigationUtils;
const history = {
entries: [],
};
it("returns false if it's a root route", () => {
history.entries.push({ pathname: "/river/root" });
const currentResult = isPreviousRouteHook(history.entries);
expect(currentResult).toBe(false);
});
it("returns false if previous root is not a hook", () => {
history.entries.push({ pathname: "/almostHooks/secondLevel" });
const currentResult = isPreviousRouteHook(history.entries);
expect(currentResult).toBe(false);
});
it("returns true if previous root is a hook", () => {
history.entries.push({ pathname: "/hooks/ThirdLevel" });
history.entries.push({ pathname: "/almostHooks/forthLevel" });
const currentResult = isPreviousRouteHook(history.entries);
expect(currentResult).toBe(true);
});
});
describe("getPreviousHooksCount", () => {
const { getPreviousHooksCount } = navigationUtils;
const history = {
entries: [],
};
it("returns 0 if it's a root route", () => {
history.entries.push({ pathname: "/river/root" });
const currentResult = getPreviousHooksCount(history);
expect(currentResult).toBe(0);
});
it("returns 0 if previous root is not a hook", () => {
history.entries.push({ pathname: "/almostHooks/secondLevel" });
const currentResult = getPreviousHooksCount(history);
expect(currentResult).toBe(0);
});
it("returns 1 if previous root is a hook", () => {
history.entries = [];
history.entries.push({ pathname: "/hooks/ThirdLevel" });
history.entries.push({ pathname: "/almostHooks/forthLevel" });
const currentResult = getPreviousHooksCount(history);
expect(currentResult).toBe(1);
});
it("returns 2 if 2 previous routes are a hooks", () => {
history.entries = [];
history.entries.push({ pathname: "/almostHooks/forthLevel" });
history.entries.push({ pathname: "/hooks/myHook" });
history.entries.push({ pathname: "/hooks/myHook" });
history.entries.push({ pathname: "/almostHooks/forthLevel" });
const currentResult = getPreviousHooksCount(history);
expect(currentResult).toBe(2);
});
});