import { fireEvent, render, waitFor } from '@testing-library/react-native' import * as React from 'react' import 'react-native' import { Inquiry } from 'react-native-persona' import { Provider } from 'react-redux' import Persona, { Props } from 'src/account/Persona' import { KycStatus } from 'src/account/reducer' import { createPersonaAccount } from 'src/in-house-liquidity' import { createMockStore } from 'test/utils' const FAKE_TEMPLATE_ID = 'fake template id' jest.mock('react-native-persona') jest.mock('src/firebase/firebase', () => ({ getPersonaTemplateId: jest.fn(() => FAKE_TEMPLATE_ID), })) jest.mock('src/in-house-liquidity', () => ({ ...(jest.requireActual('src/in-house-liquidity') as any), createPersonaAccount: jest.fn(() => Promise.resolve()), })) const mockInquiryBuilder = { referenceId: jest.fn().mockReturnThis(), accountId: jest.fn().mockReturnThis(), environment: jest.fn().mockReturnThis(), sessionToken: jest.fn().mockReturnThis(), fields: jest.fn().mockReturnThis(), iosTheme: jest.fn().mockReturnThis(), onComplete: jest.fn().mockReturnThis(), onCanceled: jest.fn().mockReturnThis(), onError: jest.fn().mockReturnThis(), build: jest.fn().mockReturnValue({ start: jest.fn() }), } jest.mock('react-native-persona', () => ({ ...(jest.requireActual('react-native-persona') as any), Inquiry: { fromTemplate: jest.fn(() => mockInquiryBuilder), }, })) describe('Persona', () => { const store = createMockStore() beforeEach(() => { jest.useRealTimers() jest.clearAllMocks() }) it('renders correctly', () => { const personaProps: Props = { kycStatus: KycStatus.Created, disabled: false, } const { toJSON } = render( ) expect(toJSON()).toMatchSnapshot() }) it('calls IHL to create a persona account if launching the first time', async () => { const personaProps: Props = { kycStatus: undefined, disabled: false, } const { getByTestId } = render( ) // Should be disabled to start because we don't know if they have an account until the IHL call happens expect(getByTestId('PersonaButton')).toBeDisabled() await waitFor(() => expect(getByTestId('PersonaButton')).not.toBeDisabled()) expect(createPersonaAccount).toHaveBeenCalledTimes(1) }) it('calls IHL to create a persona account if persona account not created', async () => { const personaProps: Props = { kycStatus: KycStatus.NotCreated, disabled: false, } const { getByTestId } = render( ) // Should be disabled to start because we don't know if they have an account until the IHL call happens expect(getByTestId('PersonaButton')).toBeDisabled() await waitFor(() => expect(getByTestId('PersonaButton')).not.toBeDisabled()) expect(createPersonaAccount).toHaveBeenCalledTimes(1) }) it('disables the button when the disabled prop is true', async () => { const personaProps: Props = { kycStatus: KycStatus.Created, disabled: true, } const { getByTestId } = render( ) await waitFor(() => expect(getByTestId('PersonaButton')).toBeDisabled()) }) it('launches persona on button press', async () => { const personaProps: Props = { kycStatus: KycStatus.Created, disabled: false, } const { getByTestId } = render( ) await waitFor(() => expect(getByTestId('PersonaButton')).not.toBeDisabled()) fireEvent.press(getByTestId('PersonaButton')) expect(Inquiry.fromTemplate).toHaveBeenCalledWith(FAKE_TEMPLATE_ID) }) it('calls onSuccess callback on inquiry success', async () => { const personaProps: Props = { kycStatus: KycStatus.Created, onSuccess: jest.fn(), disabled: false, } const { getByTestId } = render( ) await waitFor(() => expect(getByTestId('PersonaButton')).not.toBeDisabled()) fireEvent.press(getByTestId('PersonaButton')) expect(Inquiry.fromTemplate).toHaveBeenCalledWith(FAKE_TEMPLATE_ID) expect(mockInquiryBuilder.onComplete).toHaveBeenCalled() expect(personaProps.onSuccess).not.toHaveBeenCalled() mockInquiryBuilder.onComplete.mock.calls?.[0]?.[0]?.('', 'completed') // simulate Persona invoking the onSuccess callback with success expect(personaProps.onSuccess).toHaveBeenCalled() }) it('calls onCanceled callback on inquiry cancel', async () => { const personaProps: Props = { kycStatus: KycStatus.Created, onCanceled: jest.fn(), disabled: false, } const { getByTestId } = render( ) await waitFor(() => expect(getByTestId('PersonaButton')).not.toBeDisabled()) fireEvent.press(getByTestId('PersonaButton')) expect(Inquiry.fromTemplate).toHaveBeenCalledWith(FAKE_TEMPLATE_ID) expect(mockInquiryBuilder.onCanceled).toHaveBeenCalled() expect(personaProps.onCanceled).not.toHaveBeenCalled() mockInquiryBuilder.onCanceled.mock.calls?.[0]?.[0]?.() // simulate Persona invoking the onCanceled callback expect(personaProps.onCanceled).toHaveBeenCalled() }) it('calls onError callback on inquiry failed', async () => { const personaProps: Props = { kycStatus: KycStatus.Created, onError: jest.fn(), disabled: false, } const { getByTestId } = render( ) await waitFor(() => expect(getByTestId('PersonaButton')).not.toBeDisabled()) fireEvent.press(getByTestId('PersonaButton')) expect(Inquiry.fromTemplate).toHaveBeenCalledWith(FAKE_TEMPLATE_ID) expect(mockInquiryBuilder.onComplete).toHaveBeenCalled() expect(personaProps.onError).not.toHaveBeenCalled() mockInquiryBuilder.onComplete.mock.calls?.[0]?.[0]?.('', 'failed') // simulate Persona invoking the onComplete callback with failed expect(personaProps.onError).toHaveBeenCalled() }) it('calls onError callback on inquiry error', async () => { const personaProps: Props = { kycStatus: KycStatus.Created, onError: jest.fn(), disabled: false, } const { getByTestId } = render( ) await waitFor(() => expect(getByTestId('PersonaButton')).not.toBeDisabled()) fireEvent.press(getByTestId('PersonaButton')) expect(Inquiry.fromTemplate).toHaveBeenCalledWith(FAKE_TEMPLATE_ID) expect(mockInquiryBuilder.onError).toHaveBeenCalled() expect(personaProps.onError).not.toHaveBeenCalled() mockInquiryBuilder.onError.mock.calls?.[0]?.[0]?.({ message: 'error' }) // simulate Persona invoking the onError callback expect(personaProps.onError).toHaveBeenCalled() }) })