/* eslint-disable @typescript-eslint/no-var-requires */ const SCRIPT_SELECTOR = 'script[src^="https://js.stripe.com/crypto-onramp/v1/crypto-onramp.js"]'; const dispatchCryptoOnrampScriptEvent = (eventType: string): void => { const injectedScript = document.querySelector(SCRIPT_SELECTOR); if (!injectedScript) { throw new Error( 'could not find loadCryptoOnrampAndInitialize script element' ); } injectedScript.dispatchEvent(new Event(eventType)); }; describe('loadCryptoOnrampAndInitialize', () => { afterEach(() => { const scripts = Array.from(document.querySelectorAll(SCRIPT_SELECTOR)); for (const script of scripts) { if (script.parentElement) { script.parentElement.removeChild(script); } } delete (window as any).loadCryptoOnrampAndInitialize; jest.resetModules(); }); it('resolves with an OnrampCoordinator when script loads successfully', async () => { const {loadCryptoOnrampAndInitialize} = require('./embedded_components'); const mockCoordinator = {destroy: jest.fn()}; const mockConstructor = jest.fn(() => mockCoordinator); const resultPromise = loadCryptoOnrampAndInitialize('pk_test_foo', { theme: 'stripe', }); await Promise.resolve(); (window as any).loadCryptoOnrampAndInitialize = mockConstructor; dispatchCryptoOnrampScriptEvent('load'); const result = await resultPromise; expect(mockConstructor).toHaveBeenCalledWith('pk_test_foo', { theme: 'stripe', }); expect(result).toBe(mockCoordinator); }); it('resolves with null when window is undefined', async () => { const originalWindow = globalThis.window; // @ts-expect-error - simulating server-side environment delete globalThis.window; try { const {loadCryptoOnrampAndInitialize} = require('./embedded_components'); const result = await loadCryptoOnrampAndInitialize('pk_test_foo'); expect(result).toBeNull(); } finally { globalThis.window = originalWindow; } }); it('resolves immediately when loadCryptoOnrampAndInitialize is already on window', async () => { const mockCoordinator = {destroy: jest.fn()}; const mockConstructor = jest.fn(() => mockCoordinator); (window as any).loadCryptoOnrampAndInitialize = mockConstructor; const {loadCryptoOnrampAndInitialize} = require('./embedded_components'); const result = await loadCryptoOnrampAndInitialize('pk_test_foo'); expect(mockConstructor).toHaveBeenCalledWith('pk_test_foo', undefined); expect(result).toBe(mockCoordinator); }); it('rejects when the script fails to load', async () => { const {loadCryptoOnrampAndInitialize} = require('./embedded_components'); const resultPromise = loadCryptoOnrampAndInitialize('pk_test_foo'); await Promise.resolve(); dispatchCryptoOnrampScriptEvent('error'); await expect(resultPromise).rejects.toEqual( new Error('Failed to load loadCryptoOnrampAndInitialize') ); }); it('rejects when loadCryptoOnrampAndInitialize is not on window after script loads', async () => { const {loadCryptoOnrampAndInitialize} = require('./embedded_components'); const resultPromise = loadCryptoOnrampAndInitialize('pk_test_foo'); await Promise.resolve(); dispatchCryptoOnrampScriptEvent('load'); await expect(resultPromise).rejects.toEqual( new Error('loadCryptoOnrampAndInitialize not available') ); }); it('reuses the same script if one is already present', async () => { const script = document.createElement('script'); script.src = 'https://js.stripe.com/crypto-onramp/v1/crypto-onramp.js'; document.body.appendChild(script); const {loadCryptoOnrampAndInitialize} = require('./embedded_components'); const mockCoordinator = {destroy: jest.fn()}; const resultPromise = loadCryptoOnrampAndInitialize('pk_test_foo'); await Promise.resolve(); (window as any).loadCryptoOnrampAndInitialize = jest.fn( () => mockCoordinator ); dispatchCryptoOnrampScriptEvent('load'); const result = await resultPromise; expect(result).toBe(mockCoordinator); expect(document.querySelectorAll(SCRIPT_SELECTOR)).toHaveLength(1); }); it('caches the script promise across multiple calls', async () => { const {loadCryptoOnrampAndInitialize} = require('./embedded_components'); const mockCoordinator = {destroy: jest.fn()}; const mockConstructor = jest.fn(() => mockCoordinator); const promise1 = loadCryptoOnrampAndInitialize('pk_test_foo'); const promise2 = loadCryptoOnrampAndInitialize('pk_test_bar'); await Promise.resolve(); (window as any).loadCryptoOnrampAndInitialize = mockConstructor; dispatchCryptoOnrampScriptEvent('load'); const [result1, result2] = await Promise.all([promise1, promise2]); expect(result1).toBe(mockCoordinator); expect(result2).toBe(mockCoordinator); expect(document.querySelectorAll(SCRIPT_SELECTOR)).toHaveLength(1); }); });