import { renderHook } from '@testing-library/react';
import { type Mock, beforeEach, describe, expect, it, vi } from 'vitest';
import { useChainId } from 'wagmi';
import { useShowCallsStatus } from 'wagmi/experimental';
import { getChainExplorer } from '../../core/network/getChainExplorer';
import { useTransactionContext } from '../components/TransactionProvider';
import { useGetTransactionToastAction } from './useGetTransactionToastAction';
import { ReactElement } from 'react';
vi.mock('../components/TransactionProvider', () => ({
useTransactionContext: vi.fn(),
}));
vi.mock('wagmi', () => ({
useChainId: vi.fn(),
}));
vi.mock('wagmi/experimental', () => ({
useShowCallsStatus: vi.fn(),
}));
vi.mock('../../core/network/getChainExplorer', () => ({
getChainExplorer: vi.fn(),
}));
const mockGetChainExplorer = 'https://etherscan.io';
describe('useGetTransactionToastAction', () => {
beforeEach(() => {
(useChainId as Mock).mockReturnValue(123);
(useShowCallsStatus as Mock).mockReturnValue({
showCallsStatus: vi.fn(),
});
(getChainExplorer as Mock).mockReturnValue(mockGetChainExplorer);
});
it('should return actionElement when transaction hash exists', () => {
(useTransactionContext as Mock).mockReturnValue({
transactionHash: '0x123',
});
const { result } = renderHook(() => useGetTransactionToastAction());
expect(result.current.actionElement).toMatchInlineSnapshot(`
View transaction
`);
});
it('should return actionElement when transaction id exists', () => {
(useTransactionContext as Mock).mockReturnValue({
transactionId: 'ab123',
onSubmit: vi.fn(),
});
const showCallsStatus = vi.fn();
(useShowCallsStatus as Mock).mockReturnValue({ showCallsStatus });
const { result } = renderHook(() => useGetTransactionToastAction());
const button = result.current.actionElement as ReactElement<{
onClick: () => void;
}>;
expect(button.props.onClick).toBeDefined();
expect(button).not.toBeNull();
});
it('should return actionElement when receipt exists', () => {
(useTransactionContext as Mock).mockReturnValue({
receipt: 'receipt',
transactionHash: '0x123',
});
const { result } = renderHook(() => useGetTransactionToastAction());
expect(result.current.actionElement).toMatchInlineSnapshot(`
View transaction
`);
});
it('should return actionElement when error occurs', () => {
const onSubmitMock = vi.fn();
(useTransactionContext as Mock).mockReturnValue({
errorMessage: 'error',
onSubmit: onSubmitMock,
});
const { result } = renderHook(() => useGetTransactionToastAction());
const button = result.current.actionElement as ReactElement<{
onClick: () => void;
}>;
expect(button.props.onClick).toBe(onSubmitMock);
});
it('should return actionElement when no status available', () => {
(useTransactionContext as Mock).mockReturnValue({
errorMessage: '',
});
const { result } = renderHook(() => useGetTransactionToastAction());
expect(result.current.actionElement).toBeNull();
});
it('should prioritize transactionId over transactionHash when both are provided', () => {
const showCallsStatus = vi.fn();
(useTransactionContext as Mock).mockReturnValue({
transactionHash: '0x123',
transactionId: 'ab123',
});
(useShowCallsStatus as Mock).mockReturnValue({ showCallsStatus });
const { result } = renderHook(() => useGetTransactionToastAction());
const button = result.current.actionElement as ReactElement<{
onClick: () => void;
}>;
expect(button.props.onClick).toBeDefined();
expect(button).not.toBeNull();
});
it('should use accountChainId from useChainId when chainId is not available in context', () => {
(useTransactionContext as Mock).mockReturnValue({
chainId: undefined,
transactionHash: '0x123',
});
const { result } = renderHook(() => useGetTransactionToastAction());
expect(result.current.actionElement).toMatchInlineSnapshot(`
View transaction
`);
});
it('should call showCallsStatus when button is clicked', () => {
const showCallsStatus = vi.fn();
(useShowCallsStatus as Mock).mockReturnValue({ showCallsStatus });
(useTransactionContext as Mock).mockReturnValue({
transactionId: 'ab123',
});
const { result } = renderHook(() => useGetTransactionToastAction());
const button = result.current.actionElement as ReactElement<{
onClick: () => void;
}>;
button.props.onClick();
expect(showCallsStatus).toHaveBeenCalledWith({ id: 'ab123' });
});
});