/** * @jest-environment jsdom */ import Mpc from '../../../mpc' import Noah from '.' import portalMock from '../../../__mocks/portal/portal' import { mockHost } from '../../../__mocks/constants' const TRUSTED_KYC_HOST = 'kyc.example' const openTrustedUrl = (url: string) => { let parsed: URL try { parsed = new URL(url) } catch { throw new Error('Invalid hostedUrl') } if (parsed.protocol !== 'https:' || parsed.hostname !== TRUSTED_KYC_HOST) { throw new Error('Untrusted hostedUrl origin') } return window.open(parsed.toString(), '_blank', 'noopener,noreferrer') } describe('Noah', () => { let mpc: Mpc let noah: Noah beforeEach(() => { jest.clearAllMocks() portalMock.host = mockHost mpc = new Mpc({ portal: portalMock, }) noah = new Noah({ mpc }) }) it('should call mpc.initiateKyc with the request', async () => { const spy = jest.spyOn(mpc, 'initiateKyc').mockResolvedValue({ data: { hostedUrl: 'https://kyc.example', }, }) const openSpy = jest.spyOn(window, 'open').mockImplementation(() => null) const body = { returnUrl: 'https://app.example/cb' } const result = await noah.initiateKyc(body) expect(spy).toHaveBeenCalledWith(body) expect(result.data.hostedUrl).toBe('https://kyc.example') openTrustedUrl(result.data.hostedUrl) expect(openSpy).toHaveBeenCalledWith( 'https://kyc.example/', '_blank', 'noopener,noreferrer', ) openSpy.mockRestore() }) it('should call mpc.initiatePayin', async () => { const req = { fiatCurrency: 'USD', cryptoCurrency: 'USDC_TEST', network: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1', destinationAddress: 'SoLAddr1111111111111111111111111111111111111', } const spy = jest.spyOn(mpc, 'initiatePayin').mockResolvedValue({ data: { payinId: 'p1', bankDetails: { paymentMethodId: 'pm-123', paymentMethodType: 'bank_account', accountNumber: '1234567890', network: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1', }, }, }) await noah.initiatePayin(req) expect(spy).toHaveBeenCalledWith(req) }) it('should call mpc.simulatePayin with sandbox body', async () => { const sim = { paymentMethodId: 'pm-1', fiatAmount: '10', fiatCurrency: 'USD', } const spy = jest.spyOn(mpc, 'simulatePayin').mockResolvedValue({ data: { fiatDepositId: 'deposit-123' }, }) await noah.simulatePayin(sim) expect(spy).toHaveBeenCalledWith(sim) }) it('should call mpc.getPayoutCountries', async () => { const spy = jest.spyOn(mpc, 'getPayoutCountries').mockResolvedValue({ data: { countries: { US: ['USD'], MX: ['MXN', 'USD'] } }, }) await noah.getPayoutCountries() expect(spy).toHaveBeenCalled() }) it('should call mpc.getPayoutChannels', async () => { const req = { country: 'US', cryptoCurrency: 'USDC_TEST', fiatCurrency: 'USD', fiatAmount: '10', } const spy = jest.spyOn(mpc, 'getPayoutChannels').mockResolvedValue({ data: { items: [] }, } as never) await noah.getPayoutChannels(req) expect(spy).toHaveBeenCalledWith(req) }) it('should call mpc.getPayoutChannelForm', async () => { const spy = jest .spyOn(mpc, 'getPayoutChannelForm') .mockResolvedValue({ data: { formSchema: { type: 'object', properties: {} }, formMetadata: { contentHash: 'abc123' }, }, } as never) await noah.getPayoutChannelForm('ch-1') expect(spy).toHaveBeenCalledWith('ch-1') }) it('should call mpc.getPayoutQuote', async () => { const req = { channelId: 'ch-1', cryptoCurrency: 'USDC_TEST', fiatAmount: '10', } const spy = jest.spyOn(mpc, 'getPayoutQuote').mockResolvedValue({ data: { payoutId: 'out-1', formSessionId: 'fs-1', cryptoAmountEstimate: '10', totalFee: '0.01', }, }) await noah.getPayoutQuote(req) expect(spy).toHaveBeenCalledWith(req) }) it('should call mpc.initiatePayout', async () => { const expiry = new Date(Date.now() + 24 * 60 * 60 * 1000) .toISOString() .replace(/\.\d{3}Z$/, 'Z') const nonce = `nonce-${Date.now()}-${Math.floor(Math.random() * 1e9)}` const req = { payoutId: 'p1', sourceAddress: 'SoLAddr1111111111111111111111111111111111111', expiry, nonce, network: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1', } const spy = jest.spyOn(mpc, 'initiatePayout').mockResolvedValue({ data: { destinationAddress: 'dest', conditions: [] }, }) await noah.initiatePayout(req) expect(spy).toHaveBeenCalledWith(req) }) it('should call mpc.getPaymentMethods', async () => { const spy = jest.spyOn(mpc, 'getPaymentMethods').mockResolvedValue({ data: { paymentMethods: [] }, }) await noah.getPaymentMethods() expect(spy).toHaveBeenCalled() }) })