From b33740047db5eca8346d88830d9880e4be7fa599 Mon Sep 17 00:00:00 2001 From: schmanu Date: Thu, 5 Oct 2023 15:51:52 +0200 Subject: [PATCH] tests: MPCLogin test --- .../common/ConnectWallet/MPCLogin.tsx | 6 +- .../common/ConnectWallet/WalletDetails.tsx | 2 +- .../ConnectWallet/__tests__/MPCLogin.test.tsx | 107 ++++++++++++++++++ src/components/welcome/WelcomeLogin/index.tsx | 2 +- 4 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 src/components/common/ConnectWallet/__tests__/MPCLogin.test.tsx diff --git a/src/components/common/ConnectWallet/MPCLogin.tsx b/src/components/common/ConnectWallet/MPCLogin.tsx index 68da758eee..e980b556e5 100644 --- a/src/components/common/ConnectWallet/MPCLogin.tsx +++ b/src/components/common/ConnectWallet/MPCLogin.tsx @@ -8,7 +8,7 @@ import GoogleLogo from '@/public/images/welcome/logo-google.svg' import css from './styles.module.css' import useWallet from '@/hooks/wallets/useWallet' -export const MPCLogin = ({ onLogin }: { onLogin?: () => void }) => { +const MPCLogin = ({ onLogin }: { onLogin?: () => void }) => { const { loginPending, triggerLogin, userInfo, walletState, recoverFactorWithPassword } = useContext(MpcWalletContext) const wallet = useWallet() @@ -25,7 +25,7 @@ export const MPCLogin = ({ onLogin }: { onLogin?: () => void }) => { if (loginTriggered && wallet && onLogin) { onLogin() } - }, [loginTriggered, onLogin, walletState, wallet]) + }, [loginTriggered, onLogin, wallet]) return ( <> @@ -77,3 +77,5 @@ export const MPCLogin = ({ onLogin }: { onLogin?: () => void }) => { ) } + +export default MPCLogin diff --git a/src/components/common/ConnectWallet/WalletDetails.tsx b/src/components/common/ConnectWallet/WalletDetails.tsx index a07a2ca830..1104d9dd23 100644 --- a/src/components/common/ConnectWallet/WalletDetails.tsx +++ b/src/components/common/ConnectWallet/WalletDetails.tsx @@ -3,7 +3,7 @@ import type { ReactElement } from 'react' import KeyholeIcon from '@/components/common/icons/KeyholeIcon' import useConnectWallet from '@/components/common/ConnectWallet/useConnectWallet' -import { MPCLogin } from './MPCLogin' +import MPCLogin from './MPCLogin' const WalletDetails = ({ onConnect }: { onConnect?: () => void }): ReactElement => { const connectWallet = useConnectWallet() diff --git a/src/components/common/ConnectWallet/__tests__/MPCLogin.test.tsx b/src/components/common/ConnectWallet/__tests__/MPCLogin.test.tsx new file mode 100644 index 0000000000..bbafa6ea6a --- /dev/null +++ b/src/components/common/ConnectWallet/__tests__/MPCLogin.test.tsx @@ -0,0 +1,107 @@ +import { act, render, waitFor } from '@/tests/test-utils' +import * as useWallet from '@/hooks/wallets/useWallet' +import * as useMPCWallet from '@/hooks/wallets/mpc/useMPCWallet' +import MPCLogin from '../MPCLogin' +import { hexZeroPad } from '@ethersproject/bytes' +import { type EIP1193Provider } from '@web3-onboard/common' +import { ONBOARD_MPC_MODULE_LABEL } from '@/services/mpc/module' +import { MpcWalletProvider } from '../MPCWalletProvider' + +describe('WalletLogin', () => { + beforeEach(() => { + jest.resetAllMocks() + }) + + it('should render continue with connected account', async () => { + const mockOnLogin = jest.fn() + const walletAddress = hexZeroPad('0x1', 20) + jest.spyOn(useWallet, 'default').mockReturnValue({ + address: walletAddress, + chainId: '5', + label: ONBOARD_MPC_MODULE_LABEL, + provider: {} as unknown as EIP1193Provider, + }) + jest.spyOn(useMPCWallet, 'useMPCWallet').mockReturnValue({ + userInfo: { + email: 'test@safe.test', + name: 'Test Testermann', + profileImage: 'test.png', + }, + triggerLogin: jest.fn(), + walletState: useMPCWallet.MPCWalletState.READY, + } as unknown as useMPCWallet.MPCWalletHook) + + const result = render( + + + , + ) + + await waitFor(() => { + expect(result.findByText('Continue as Test Testermann')).resolves.toBeDefined() + }) + + // We do not automatically invoke the callback as the user did not actively connect + expect(mockOnLogin).not.toHaveBeenCalled() + + const button = await result.findByRole('button') + button.click() + + expect(mockOnLogin).toHaveBeenCalled() + }) + + it('should render connect wallet and invoke the callback on connection if no wallet is connected', async () => { + const mockOnLogin = jest.fn() + const walletAddress = hexZeroPad('0x1', 20) + const mockUseWallet = jest.spyOn(useWallet, 'default').mockReturnValue(null) + const mockTriggerLogin = jest.fn() + const mockUseMPCWallet = jest.spyOn(useMPCWallet, 'useMPCWallet').mockReturnValue({ + userInfo: { + email: undefined, + name: undefined, + profileImage: undefined, + }, + triggerLogin: mockTriggerLogin, + walletState: useMPCWallet.MPCWalletState.NOT_INITIALIZED, + } as unknown as useMPCWallet.MPCWalletHook) + + const result = render( + + + , + ) + + await waitFor(() => { + expect(result.findByText('Continue with Google')).resolves.toBeDefined() + }) + + // We do not automatically invoke the callback as the user did not actively connect + expect(mockOnLogin).not.toHaveBeenCalled() + + await act(async () => { + // Click the button and mock a successful login + const button = await result.findByRole('button') + button.click() + mockUseMPCWallet.mockReset().mockReturnValue({ + userInfo: { + email: 'test@safe.test', + name: 'Test Testermann', + profileImage: 'test.png', + }, + triggerLogin: jest.fn(), + walletState: useMPCWallet.MPCWalletState.READY, + } as unknown as useMPCWallet.MPCWalletHook) + + mockUseWallet.mockReset().mockReturnValue({ + address: walletAddress, + chainId: '5', + label: ONBOARD_MPC_MODULE_LABEL, + provider: {} as unknown as EIP1193Provider, + }) + }) + + await waitFor(() => { + expect(mockOnLogin).toHaveBeenCalled() + }) + }) +}) diff --git a/src/components/welcome/WelcomeLogin/index.tsx b/src/components/welcome/WelcomeLogin/index.tsx index 619331c5b3..079787e222 100644 --- a/src/components/welcome/WelcomeLogin/index.tsx +++ b/src/components/welcome/WelcomeLogin/index.tsx @@ -1,4 +1,4 @@ -import { MPCLogin } from '@/components/common/ConnectWallet/MPCLogin' +import MPCLogin from '@/components/common/ConnectWallet/MPCLogin' import { AppRoutes } from '@/config/routes' import { Paper, SvgIcon, Typography, Divider, Link, Box } from '@mui/material' import SafeLogo from '@/public/images/logo-text.svg'