UNPKG

@applicaster/zapp-react-native-utils

Version:

Applicaster Zapp React Native utilities package

299 lines (237 loc) • 8.08 kB
import * as R from "ramda"; import { Hook } from "../Hook"; import { HOOKS_EVENTS, HOOKS_TRANSITION_TYPE } from "../constants"; const hook = R.merge({ screen_id: "A1234", identifier: "hook_screen", weight: 1, id: "A1234", name: "Hook Screen", type: "hook_screen", styles: {}, advertising: {}, general: { is_flow_blocker: true, allow_screen_plugin_presentation: true, }, navigations: [], hooks: [], }); const hooks = (options, otherHook = null) => R.reject(R.isNil, [ R.pick(["screen_id", "identifier", "type", "weight"], hook(options)), otherHook, ]); const manager = { presentScreenHook: jest.fn(), executeHook: jest.fn(), invokeHandler: jest.fn(), }; const getHook = (options, otherHook) => new Hook({ hook: hook(options), hooks: hooks(options, otherHook), manager, }); function clearMocks() { manager.presentScreenHook.mockClear(); manager.executeHook.mockClear(); manager.invokeHandler.mockClear(); } describe("Hook Properties", () => { const hookPlugin = getHook({}); beforeEach(clearMocks); it("has all the hook properties", () => { expect(hookPlugin).toMatchSnapshot(); }); }); describe("getModalContainer", () => { it("returns ModalContainer", () => { const ModalContainer = jest.fn(); const hookPlugin = getHook({ general: {}, module: { ModalContainer }, }); expect(hookPlugin.getModalContainer()).toBe(ModalContainer); }); }); describe("isFlowBlocker", () => { it("returns true if the hook is flow blocker", () => { const hookPlugin = getHook({ general: { is_flow_blocker: true } }); const hookWithoutScreen = getHook({ general: {}, module: { isFlowBlocker: () => true }, }); expect(hookPlugin.isFlowBlocker()).toBe(true); expect(hookWithoutScreen.isFlowBlocker()).toBe(true); }); it("returns false otherwise", () => { const hookPlugin = getHook({ general: { is_flow_blocker: false } }); const hookWithoutScreen = getHook({ general: {}, module: { isFlowBlocker: () => false }, }); expect(hookPlugin.isFlowBlocker()).toBeFalsy(); expect(hookWithoutScreen.isFlowBlocker()).toBeFalsy(); }); }); describe("skipHook", () => { it("returns true if the hooks module skipHook method returns true", () => { const hookPlugin = getHook({ module: { skipHook: () => true } }); expect(hookPlugin.skipHook()).toBe(true); }); it("returns false otherwise", () => { const hookPlugin = getHook({ module: { skipHook: false } }); const hookPluginWithUndefinedSkipHook = getHook({ module: {} }); expect(hookPlugin.skipHook()).toBeFalsy(); expect(hookPluginWithUndefinedSkipHook.skipHook()).toBeFalsy(); }); }); describe("lastHook", () => { it("returns true if the current hook is the last one", () => { const hookPlugin = getHook({}); expect(hookPlugin.lastHook).toBe(true); }); it("returns false otherwise", () => { const hookPlugin = getHook( {}, { screen_id: "B4567", type: "general", identifier: "some_hook", weight: 2, } ); expect(hookPlugin.lastHook).toBe(false); }); }); describe("setStateAndNotify", () => { let hookPlugin; const args = ["foo", { bar: 42 }]; beforeEach(() => { clearMocks(); hookPlugin = getHook({}); }); it("changes the hook's state", () => { hookPlugin.setStateAndNotify(HOOKS_EVENTS.START, ...args); expect(hookPlugin.state).toEqual(1); }); it("calls invokes the handler on the hook manager", () => { hookPlugin.setStateAndNotify(HOOKS_EVENTS.START, ...args); expect(manager.invokeHandler).toHaveBeenCalledWith( HOOKS_EVENTS.START, ...args ); }); }); describe("shouldPresentScreenHook", () => { it("returns true if the hook has a screenId and allows screen presentation", () => { const hookPlugin = getHook({}); const hookWithoutRiver = getHook({ screen_id: undefined, module: { presentFullScreen: true }, }); expect(hookPlugin.shouldPresentScreenHook()).toBe(true); expect(hookWithoutRiver.shouldPresentScreenHook()).toBe(true); }); it("returns true if the hook is modal presentation", () => { const hookPlugin = getHook({ general: { transition_type: HOOKS_TRANSITION_TYPE.MODAL }, }); expect(hookPlugin.shouldPresentScreenHook()).toBe(true); }); it("returns false otherwise", () => { const hookWithoutScreen = getHook({ screen_id: undefined }); const hookWithoutRiver = getHook({ screen_id: undefined, module: { presentFullScreen: false }, }); const hookWithoutAllowScreen = getHook({ general: { allow_screen_plugin_presentation: false }, }); const hookWithoutScreenAndAllow = getHook({ general: { allow_screen_plugin_presentation: false }, screen_id: null, }); expect(hookWithoutScreen.shouldPresentScreenHook()).toBeFalsy(); expect(hookWithoutAllowScreen.shouldPresentScreenHook()).toBeFalsy(); expect(hookWithoutScreenAndAllow.shouldPresentScreenHook()).toBeFalsy(); expect(hookWithoutRiver.shouldPresentScreenHook()).toBeFalsy(); }); }); describe("shouldStartNexHook", () => { const hookPlugin = getHook({}); const hookWithoutScreen = getHook({ screen_id: undefined }); it("returns true if the nextHook has the same weight and is not a screen", () => { expect( hookWithoutScreen.shouldStartNextHook({ weight: hookWithoutScreen.weight, }) ).toBe(true); }); it("returns false otherwise", () => { // even if weight if the same, since hookPlugin should present a screen, // it cannot run in parallel expect(hookPlugin.shouldStartNextHook({ weight: hookPlugin })).toBeFalsy(); expect( hookWithoutScreen.shouldStartNextHook({ weight: hookWithoutScreen.weight + 1, }) ).toBeFalsy(); }); }); describe("execute", () => { const payload = { foo: "bar" }; const next = jest.fn(); beforeEach(clearMocks); describe("when the hook execution should be skipped", () => { it("doesn't execute the hook, and goes to the next", () => { const hookPlugin = getHook({ module: { skipHook: () => true } }); hookPlugin.execute(payload, next); expect(manager.presentScreenHook).not.toHaveBeenCalled(); expect(manager.executeHook).not.toHaveBeenCalled(); expect(next).toHaveBeenCalledWith({ payload, success: true }); }); }); describe("when the hook is not in pending state", () => { it("doesn't execute the hook, and goes to the next", () => { const hookPlugin = getHook({}); hookPlugin.setStateAndNotify(HOOKS_EVENTS.START); hookPlugin.execute(payload, next); const hookStateSpy = jest.spyOn(hookPlugin, "setStateAndNotify"); expect(hookStateSpy).not.toHaveBeenCalled(); expect(manager.presentScreenHook).not.toHaveBeenCalled(); expect(manager.executeHook).not.toHaveBeenCalled(); expect(next).toHaveBeenCalledWith({ payload }); hookStateSpy.mockRestore(); }); }); describe("when the screen should be presented", () => { it("executes the hook", () => { const hookPlugin = getHook({}); const hookStateSpy = jest.spyOn(hookPlugin, "setStateAndNotify"); hookPlugin.execute(payload, next); expect(hookStateSpy).toHaveBeenCalledWith(HOOKS_EVENTS.START, hookPlugin); expect(manager.presentScreenHook).toHaveBeenCalledWith( hookPlugin, payload, next ); }); }); describe("when the hook is headless", () => { it("executes the hook", () => { const hookPlugin = getHook({ general: { allow_screen_plugin_presentation: false }, }); const hookStateSpy = jest.spyOn(hookPlugin, "setStateAndNotify"); hookPlugin.execute(payload, next); expect(hookStateSpy).toHaveBeenCalledWith(HOOKS_EVENTS.START, hookPlugin); expect(manager.executeHook).toHaveBeenCalledWith( hookPlugin, payload, next ); }); }); });