const mockAppStoreGet = jest.fn(); const mockFindPluginByIdentifier = jest.fn(); jest.mock("@applicaster/zapp-react-native-redux/AppStore", () => ({ appStore: { get: (key: string) => mockAppStoreGet(key) }, })); jest.mock("@applicaster/zapp-react-native-utils/pluginUtils", () => ({ findPluginByIdentifier: (id: string, plugins: any) => mockFindPluginByIdentifier(id, plugins), })); import { PlayerRole } from "../conts"; import { playerFactory } from "../playerFactory"; const fakeComponent = () => null; class FakeController { receivedConfig: any; constructor(config: any) { this.receivedConfig = config; } } const baseConfig = { player: {}, playerId: "p1", autoplay: false, entry: { id: "entry-1" } as any, muted: false, playerPluginId: "test-plugin", screenConfig: { foo: "bar" }, playerRole: PlayerRole.Cell, }; const installPluginWithProtocol = ( protocolReturn: any | ((screenConfig: any, entry: any) => any) ) => { const playerProtocol = typeof protocolReturn === "function" ? protocolReturn : () => protocolReturn; mockAppStoreGet.mockImplementation((key: string) => key === "plugins" ? { "test-plugin": {} } : null ); mockFindPluginByIdentifier.mockReturnValue({ module: { playerProtocol }, }); }; describe("playerFactory", () => { beforeEach(() => { mockAppStoreGet.mockReset(); mockFindPluginByIdentifier.mockReset(); }); it("resolves with controller and Component when playerProtocol returns synchronously", async () => { installPluginWithProtocol({ Component: fakeComponent, controllerClass: FakeController, }); const item = await playerFactory(baseConfig); expect(item).not.toBeNull(); expect(item?.Component).toBe(fakeComponent); expect(item?.controller).toBeInstanceOf(FakeController); expect((item?.controller as FakeController).receivedConfig).toBe( baseConfig ); }); it("resolves with controller and Component when playerProtocol returns a Promise (delayed import)", async () => { installPluginWithProtocol(async () => ({ Component: fakeComponent, controllerClass: FakeController, })); const item = await playerFactory(baseConfig); expect(item).not.toBeNull(); expect(item?.Component).toBe(fakeComponent); expect(item?.controller).toBeInstanceOf(FakeController); }); it("passes screenConfig and entry through to playerProtocol", async () => { const playerProtocol = jest.fn(() => ({ Component: fakeComponent, controllerClass: FakeController, })); mockAppStoreGet.mockImplementation((key: string) => key === "plugins" ? { "test-plugin": {} } : null ); mockFindPluginByIdentifier.mockReturnValue({ module: { playerProtocol } }); await playerFactory(baseConfig); expect(playerProtocol).toHaveBeenCalledWith( baseConfig.screenConfig, baseConfig.entry ); }); it("resolves to null when playerPluginId is missing", async () => { expect( await playerFactory({ ...baseConfig, playerPluginId: "" } as any) ).toBeNull(); }); it("resolves to null when appStore has no plugins", async () => { mockAppStoreGet.mockReturnValue(null); expect(await playerFactory(baseConfig)).toBeNull(); }); it("resolves to null when the plugin has no playerProtocol", async () => { mockAppStoreGet.mockImplementation((key: string) => key === "plugins" ? { "test-plugin": {} } : null ); mockFindPluginByIdentifier.mockReturnValue({ module: {} }); expect(await playerFactory(baseConfig)).toBeNull(); }); it("resolves to null when playerProtocol returns without a Component", async () => { installPluginWithProtocol({ controllerClass: FakeController }); expect(await playerFactory(baseConfig)).toBeNull(); }); it("resolves to null when playerProtocol returns without a controllerClass", async () => { installPluginWithProtocol({ Component: fakeComponent }); expect(await playerFactory(baseConfig)).toBeNull(); }); it("rejects when playerProtocol throws synchronously", async () => { installPluginWithProtocol(() => { throw new Error("boom"); }); await expect(playerFactory(baseConfig)).rejects.toThrow("boom"); }); });