import { act, renderHook } from '@testing-library/react-hooks'; import { waitFor } from '@testing-library/react'; import type { MockedResponse } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing'; import type { ReactNode } from 'react'; import { useCompleteWithdraw } from './use-complete-withdraw'; import type { Erc20Approval } from './__generated__/Erc20Approval'; import { ERC20_APPROVAL_QUERY_NEW } from './queries'; import * as web3 from '@vegaprotocol/web3'; import * as sentry from '@sentry/react'; import type { Erc20ApprovalNew_erc20WithdrawalApproval } from './__generated__/Erc20ApprovalNew'; jest.mock('@vegaprotocol/web3', () => ({ useBridgeContract: jest.fn(), useEthereumTransaction: jest.fn(), })); function setup(mocks?: MockedResponse[]) { const wrapper = ({ children }: { children: ReactNode }) => ( {children} ); return renderHook(() => useCompleteWithdraw(true), { wrapper }); } it('Should perform the Ethereum transaction with the fetched approval', async () => { const withdrawalId = 'withdrawal-id'; const erc20WithdrawalApproval: Erc20ApprovalNew_erc20WithdrawalApproval = { __typename: 'Erc20WithdrawalApproval', assetSource: 'asset-source', amount: '100', nonce: '1', creation: '1', signatures: 'signatures', targetAddress: 'target-address', expiry: 'expiry', }; const mockERC20Approval: MockedResponse = { request: { query: ERC20_APPROVAL_QUERY_NEW, variables: { withdrawalId }, }, result: { data: { erc20WithdrawalApproval, }, }, }; const mockPerform = jest.fn(); jest.spyOn(web3, 'useEthereumTransaction').mockReturnValue({ // @ts-ignore allow null transaction as its not used in hook logic transaction: { txHash: 'tx-hash' }, perform: mockPerform, }); const { result } = setup([mockERC20Approval]); act(() => { result.current.submit(withdrawalId); }); await waitFor(() => { expect(mockPerform).toHaveBeenCalledWith(erc20WithdrawalApproval); expect(result.current.withdrawalId).toBe(withdrawalId); }); }); it('Captures an error if the erc20Withdrawal is not found', async () => { const withdrawalId = 'withdrawal-id'; const mockERC20Approval: MockedResponse = { request: { query: ERC20_APPROVAL_QUERY_NEW, variables: { withdrawalId }, }, result: { data: { erc20WithdrawalApproval: null, }, }, }; const mockPerform = jest.fn(); const spyOnCaptureException = jest.spyOn(sentry, 'captureException'); jest.spyOn(web3, 'useEthereumTransaction').mockReturnValue({ // @ts-ignore allow null transaction as its not used in hook logic transaction: { txHash: 'tx-hash' }, perform: mockPerform, }); const { result } = setup([mockERC20Approval]); act(() => { result.current.submit(withdrawalId); }); await waitFor(() => { expect(mockPerform).not.toHaveBeenCalled(); expect(spyOnCaptureException).toHaveBeenCalled(); expect(result.current.withdrawalId).toBe(withdrawalId); }); }); it('Captures an error if erc20 approval query fails', async () => { const withdrawalId = 'withdrawal-id'; const mockERC20Approval: MockedResponse = { request: { query: ERC20_APPROVAL_QUERY_NEW, variables: { withdrawalId }, }, error: new Error('query failed'), }; const mockPerform = jest.fn(); const spyOnCaptureException = jest.spyOn(sentry, 'captureException'); jest.spyOn(web3, 'useEthereumTransaction').mockReturnValue({ // @ts-ignore allow null transaction as its not used in hook logic transaction: { txHash: 'tx-hash' }, perform: mockPerform, }); const { result } = setup([mockERC20Approval]); act(() => { result.current.submit(withdrawalId); }); await waitFor(() => { expect(mockPerform).not.toHaveBeenCalled(); expect(spyOnCaptureException).toHaveBeenCalled(); expect(result.current.withdrawalId).toBe(withdrawalId); }); });