import { Spinner } from '@/internal/components/Spinner';
import { pressable } from '@/styles/theme';
import { fireEvent, render, screen } from '@testing-library/react';
import { type Mock, beforeEach, describe, expect, it, vi } from 'vitest';
import { useWithdrawButton } from '../hooks/useWithdrawButton';
import { useAppchainBridgeContext } from './AppchainBridgeProvider';
import { AppchainBridgeWithdraw } from './AppchainBridgeWithdraw';
vi.mock('./AppchainBridgeProvider', () => ({
useAppchainBridgeContext: vi.fn(),
}));
vi.mock('../hooks/useWithdrawButton', () => ({
useWithdrawButton: vi.fn(),
}));
describe('AppchainBridgeWithdraw', () => {
const mockSetIsWithdrawModalOpen = vi.fn();
const mockSetIsSuccessModalOpen = vi.fn();
const mockWaitForWithdrawal = vi.fn();
const mockProveAndFinalizeWithdrawal = vi.fn();
beforeEach(() => {
vi.resetAllMocks();
(useAppchainBridgeContext as Mock).mockReturnValue({
withdrawStatus: 'init',
waitForWithdrawal: mockWaitForWithdrawal,
proveAndFinalizeWithdrawal: mockProveAndFinalizeWithdrawal,
setIsWithdrawModalOpen: mockSetIsWithdrawModalOpen,
setIsSuccessModalOpen: mockSetIsSuccessModalOpen,
});
(useWithdrawButton as Mock).mockReturnValue({
isSuccess: false,
buttonDisabled: false,
buttonContent: 'Claim',
shouldShowClaim: false,
label: 'Withdraw',
});
});
it('renders the loading state correctly', () => {
(useWithdrawButton as Mock).mockReturnValue({
isPending: true,
isSuccess: false,
buttonDisabled: false,
buttonContent: 'Claim',
shouldShowClaim: false,
label: 'Withdraw',
});
render();
expect(screen.getByText('Withdraw')).toBeInTheDocument();
expect(
screen.getByText((content) =>
content.includes('Waiting for claim to be ready...'),
),
).toBeInTheDocument();
expect(
screen.getByText((content) =>
content.includes('Please do not close this window.'),
),
).toBeInTheDocument();
});
it('renders the claim state correctly', () => {
(useWithdrawButton as Mock).mockReturnValue({
isSuccess: false,
buttonDisabled: false,
buttonContent: 'Claim Funds',
shouldShowClaim: true,
label: 'Claim',
});
render();
const claimButton = screen.getByText('Claim Funds');
expect(claimButton).toBeInTheDocument();
fireEvent.click(claimButton);
expect(mockProveAndFinalizeWithdrawal).toHaveBeenCalledTimes(1);
});
it('renders the error state correctly', () => {
(useWithdrawButton as Mock).mockReturnValue({
isError: true,
});
render();
expect(
screen.getByText((content) =>
content.includes('There was an error processing your withdrawal.'),
),
).toBeInTheDocument();
});
it('shows error message when claim is rejected', () => {
(useAppchainBridgeContext as Mock).mockReturnValue({
withdrawStatus: 'claimRejected',
waitForWithdrawal: mockWaitForWithdrawal,
proveAndFinalizeWithdrawal: mockProveAndFinalizeWithdrawal,
setIsWithdrawModalOpen: mockSetIsWithdrawModalOpen,
});
render();
expect(screen.getByText('Transaction denied')).toBeInTheDocument();
});
it('calls waitForWithdrawal when withdrawStatus changes to withdrawSuccess', () => {
(useAppchainBridgeContext as Mock).mockReturnValue({
withdrawStatus: 'withdrawSuccess',
waitForWithdrawal: mockWaitForWithdrawal,
proveAndFinalizeWithdrawal: mockProveAndFinalizeWithdrawal,
setIsWithdrawModalOpen: mockSetIsWithdrawModalOpen,
});
render();
expect(mockWaitForWithdrawal).toHaveBeenCalled();
});
it('calls waitForWithdrawal with resumeWithdrawalTxHash when resumeWithdrawalTxHash is set', () => {
(useAppchainBridgeContext as Mock).mockReturnValue({
resumeWithdrawalTxHash: '0x123',
waitForWithdrawal: mockWaitForWithdrawal,
});
render();
expect(mockWaitForWithdrawal).toHaveBeenCalledWith('0x123');
});
it('disables claim button when buttonDisabled is true', () => {
(useWithdrawButton as Mock).mockReturnValue({
isSuccess: false,
buttonDisabled: true,
buttonContent: ,
shouldShowClaim: true,
label: 'Claim',
});
render();
const claimButton = screen.getByRole('button');
expect(claimButton).toHaveClass(pressable.disabled);
});
});