import { safeLoadBtModule } from ".."; import { BT_NAMESPACE, BtModule, btModulesLoadConfig } from "../types"; import assetLoader from "@braintree/asset-loader"; import { isAmdEnv } from "../../amd-utils"; jest.mock("@braintree/asset-loader", () => { return { loadScript: jest.fn(), loadStylesheet: jest.fn(), }; }); jest.mock("../../amd-utils"); const mockIsAmdEnv = isAmdEnv as jest.MockedFn; describe("safeLoadBtModule", () => { const version = "3.97.2"; describe("in a non-AMD environment", () => { beforeAll(() => { mockIsAmdEnv.mockReturnValue(false); }); it("should attempt to load BT module", async () => { const { id, script } = btModulesLoadConfig.client; await safeLoadBtModule(btModulesLoadConfig.client, version); const scriptSrc = `https://js.braintreegateway.com/web/${version}/js/${script.minified}`; const loadScriptOptions = { id: `${id}-${version}`, src: scriptSrc, }; expect(assetLoader.loadScript).toHaveBeenCalledWith(loadScriptOptions); }); it("should not load BT module if same version already exists", async () => { window.braintree = { [BtModule.Client]: { create: jest.fn(), VERSION: version, }, }; const loadResp = await safeLoadBtModule( btModulesLoadConfig.client, version ); expect(assetLoader.loadScript).not.toHaveBeenCalled(); expect(loadResp).toBe(true); }); it("should not load BT module and return error if module on different version already exists", async () => { window.braintree = { [BtModule.Client]: { create: jest.fn(), VERSION: "3.96.0", }, }; try { await safeLoadBtModule(btModulesLoadConfig.client, version); } catch (error) { expect(error).toStrictEqual( new Error( "client already loaded with version 3.96.0 cannot load version 3.97.2" ) ); } expect(assetLoader.loadScript).not.toHaveBeenCalled(); }); it("should not load BT module and return error if no version specified", async () => { window.braintree = { [BtModule.Client]: { create: jest.fn(), VERSION: "3.96.0", }, }; try { await safeLoadBtModule(btModulesLoadConfig.client, ""); } catch (error) { expect(error).toStrictEqual( new Error("Attempted to load client without specifying version") ); } expect(assetLoader.loadScript).not.toHaveBeenCalled(); }); }); describe("in an AMD environment", () => { const originalWindow = window; let mockRequire: jest.Mock; beforeAll(() => { mockIsAmdEnv.mockReturnValue(true); mockRequire = jest.fn().mockImplementation((deps, cb) => { cb(); }); Object.defineProperty(globalThis, "window", { value: { require: mockRequire, }, }); }); afterAll(() => { Object.defineProperty(globalThis, "window", { value: originalWindow, }); }); it("should attempt to load BT module", async () => { await safeLoadBtModule(btModulesLoadConfig.client, version); expect(assetLoader.loadScript).not.toHaveBeenCalled(); expect(mockRequire).toHaveBeenCalledWith( [`${BT_NAMESPACE}/client.min`], expect.any(Function), expect.any(Function) ); }); it("should reject the promise if the require call fails", async () => { const mockError = new Error("Boom!"); mockRequire.mockImplementationOnce((deps, cb, errback) => { errback(mockError); }); try { await safeLoadBtModule(btModulesLoadConfig.client, version); } catch (error) { expect(error).toBe(mockError); } expect(mockRequire).toHaveBeenCalledWith( [`${BT_NAMESPACE}/client.min`], expect.any(Function), expect.any(Function) ); expect(assetLoader.loadScript).not.toHaveBeenCalled(); }); }); });