import React from 'react'; import { screen, act, fireEvent, waitFor } from '@testing-library/react'; import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { renderWithProvider } from '../../../../test/lib/render-helpers'; import mockState from '../../../../test/data/mock-state.json'; import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/swaps'; import { CHAIN_IDS } from '../../../../shared/constants/network'; import { shortenAddress } from '../../../helpers/utils/util'; import InteractiveReplacementTokenPage from '.'; const custodianAccounts = [ { address: '0x9d0ba4ddac06032527b140912ec808ab9451b788', balance: '0x', name: 'Jupiter', labels: [ { key: 'service', value: 'Label test 1', }, ], }, { address: '0xeb9e64b93097bc15f01f13eae97015c57ab64823', balance: '0x', name: 'Jupiter', labels: [ { key: 'service', value: 'Label test 2', }, ], }, ]; const mockedShowInteractiveReplacementTokenBanner = jest.fn(); const mockedRemoveAddTokenConnectRequest = jest .fn() .mockReturnValue({ type: 'TYPE' }); const mockedSetCustodianNewRefreshToken = jest .fn() .mockReturnValue({ type: 'TYPE' }); let mockedGetCustodianConnectRequest = jest .fn() .mockReturnValue(async () => await custodianAccounts); jest.mock('../../../store/institutional/institution-background', () => ({ mmiActionsFactory: () => ({ removeAddTokenConnectRequest: mockedRemoveAddTokenConnectRequest, setCustodianNewRefreshToken: mockedSetCustodianNewRefreshToken, getCustodianAccounts: mockedGetCustodianConnectRequest, }), showInteractiveReplacementTokenBanner: () => mockedShowInteractiveReplacementTokenBanner, })); const address = '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F'; const custodianAddress = '0xeb9e64b93097bc15f01f13eae97015c57ab64823'; const accountName = 'Jupiter'; const labels = [ { key: 'service', value: 'label test', }, ]; const connectRequests = [ { labels, origin: 'origin', apiUrl: 'apiUrl', token: { projectName: 'projectName', projectId: 'projectId', clientId: 'clientId', }, }, ]; const props = { history: { push: jest.fn(), }, }; const render = ({ newState } = {}) => { const state = { ...mockState, metamask: { ...mockState.metamask, modal: { props: address }, selectedAddress: address, interactiveReplacementToken: { url: 'https://saturn-custody-ui.codefi.network/', }, custodyAccountDetails: { [address]: { balance: '0x', custodianName: 'Jupiter' }, }, mmiConfiguration: { custodians: [ { production: true, name: 'Jupiter', type: 'Jupiter', iconUrl: 'iconUrl', displayName: 'displayName', }, ], }, institutionalFeatures: { complianceProjectId: '', connectRequests, }, ...newState, }, }; const middlewares = [thunk]; const mockStore = configureMockStore(middlewares); const store = mockStore(state); return renderWithProvider( , store, ); }; describe('Interactive Replacement Token Page', function () { afterEach(() => { jest.clearAllMocks(); }); it('should render all the accounts correctly', async () => { const expectedHref = `${ SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[CHAIN_IDS.MAINNET] }address/${custodianAddress}`; await act(async () => await render()); expect(screen.getByText(accountName)).toBeInTheDocument(); const link = screen.getByRole('link', { name: shortenAddress(custodianAddress), }); expect(link).toHaveAttribute('href', expectedHref); expect( screen.getByText(shortenAddress(custodianAddress)), ).toBeInTheDocument(); expect( screen.getByText(custodianAccounts[1].labels[0].value), ).toBeInTheDocument(); }); it('should not render if connectRequests is empty', async () => { const newState = { institutionalFeatures: { connectRequests: [], }, }; const { queryByTestId } = render({ newState }); expect( queryByTestId('interactive-replacement-token'), ).not.toBeInTheDocument(); }); it('should call onRemoveAddTokenConnectRequest and navigate to mostRecentOverviewPage when handleReject is called', () => { const mostRecentOverviewPage = '/mostRecentOverviewPage'; const { getByText } = render(); fireEvent.click(getByText('Reject')); expect(mockedRemoveAddTokenConnectRequest).toHaveBeenCalled(); expect(mockedRemoveAddTokenConnectRequest).toHaveBeenCalledWith({ origin: connectRequests[0].origin, apiUrl: connectRequests[0].apiUrl, token: connectRequests[0].token, }); expect(props.history.push).toHaveBeenCalled(); expect(props.history.push).toHaveBeenCalledWith(mostRecentOverviewPage); }); it('should call onRemoveAddTokenConnectRequest, setCustodianNewRefreshToken, and dispatch showInteractiveReplacementTokenBanner when handleApprove is called', async () => { const mostRecentOverviewPage = { pathname: '/institutional-features/done', state: { description: 'You can now use your custodian accounts in MetaMask Institutional.', imgSrc: 'iconUrl', title: 'Your custodian token has been refreshed', }, }; await act(async () => { const { getByText } = await render(); fireEvent.click(getByText('Approve')); }); expect(mockedShowInteractiveReplacementTokenBanner).toHaveBeenCalled(); expect(mockedRemoveAddTokenConnectRequest).toHaveBeenCalled(); expect(mockedRemoveAddTokenConnectRequest).toHaveBeenCalledWith({ origin: connectRequests[0].origin, apiUrl: connectRequests[0].apiUrl, token: connectRequests[0].token, }); expect(props.history.push).toHaveBeenCalled(); expect(props.history.push).toHaveBeenCalledWith(mostRecentOverviewPage); }); it('should reject if there are errors', async () => { mockedGetCustodianConnectRequest = jest.fn().mockReturnValue(async () => { throw new Error(); }); await act(async () => { const { getByText, container } = await render(); fireEvent.click(getByText('Approve')); await waitFor(() => { expect(container).toMatchSnapshot(); }); }); }); });