Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
import { ETH_REQUIRED_FOR_SEND } from '../constants';
import type { SendContextType } from '../types';
import { Send } from './Send';
import { SendAddressSelection } from './SendAddressSelection';
import { SendAddressInput } from './SendAddressInput';
import { SendAddressSelector } from './SendAddressSelector';
import { SendAmountInput } from './SendAmountInput';
import { SendButton } from './SendButton';
import { SendFundWallet } from './SendFundWallet';
Expand All @@ -16,7 +17,8 @@ import { SendTokenSelector } from './SendTokenSelector';
// Mock all dependencies
vi.mock('@/internal/components/Skeleton');
vi.mock('@/internal/hooks/useTheme');
vi.mock('./SendAddressSelection');
vi.mock('./SendAddressInput');
vi.mock('./SendAddressSelector');
vi.mock('./SendAmountInput');
vi.mock('./SendButton');
vi.mock('./SendFundWallet');
Expand Down Expand Up @@ -49,8 +51,15 @@ describe('Send', () => {
it('renders with SendProvider and applies correct classes', () => {
vi.mocked(useSendContext).mockReturnValue({
isInitialized: false,
lifecycleStatus: expect.any(Object),
updateLifecycleStatus: expect.any(Function),
ethBalance: 0,
selectedRecipient: { address: null, displayValue: '' },
recipientState: {
phase: 'input',
input: '',
address: null,
displayValue: null,
},
selectedToken: null,
} as SendContextType);

Expand All @@ -65,7 +74,12 @@ describe('Send', () => {
vi.mocked(useSendContext).mockReturnValue({
isInitialized: false,
ethBalance: 0,
selectedRecipient: { address: null, displayValue: '' },
recipientState: {
phase: 'input',
input: '',
address: null,
displayValue: null,
},
selectedToken: null,
} as SendContextType);

Expand Down Expand Up @@ -93,7 +107,12 @@ describe('Send', () => {
vi.mocked(useSendContext).mockReturnValue({
isInitialized: false,
ethBalance: undefined,
selectedRecipient: { address: null, displayValue: '' },
recipientState: {
phase: 'input',
input: '',
address: null,
displayValue: null,
},
selectedToken: null,
} as SendContextType);

Expand All @@ -115,21 +134,48 @@ describe('Send', () => {

expect(SendHeader).toHaveBeenCalled();
expect(SendFundWallet).toHaveBeenCalled();
expect(SendAddressSelection).not.toHaveBeenCalled();
expect(SendAddressInput).not.toHaveBeenCalled();
});

it('renders SendAddressInput when wallet has sufficient ETH', () => {
vi.mocked(useSendContext).mockReturnValue({
isInitialized: true,
ethBalance: ETH_REQUIRED_FOR_SEND + 0.0000000001, // de-minimis amount above ETH_REQUIRED_FOR_SEND
recipientState: {
phase: 'input',
input: '',
address: null,
displayValue: null,
},
selectedToken: null,
} as SendContextType);

render(<Send />);

expect(SendHeader).toHaveBeenCalled();
expect(SendAddressInput).toHaveBeenCalled();
expect(SendFundWallet).not.toHaveBeenCalled();
expect(SendTokenSelector).not.toHaveBeenCalled();
});

it('renders SendAddressSelection when wallet has sufficient ETH', () => {
it('renders SendAddressSelector when recipient input is validated but no address has been selected', () => {
vi.mocked(useSendContext).mockReturnValue({
isInitialized: true,
ethBalance: ETH_REQUIRED_FOR_SEND + 0.0000000001, // de-minimis amount above ETH_REQUIRED_FOR_SEND
selectedRecipient: { address: null, displayValue: '' },
recipientState: {
phase: 'validated',
input: 'test.base.eth',
address: '0x1234567890123456789012345678901234567890' as Address,
displayValue: '0x1234567890123456789012345678901234567890',
},
selectedToken: null,
} as SendContextType);

render(<Send />);

expect(SendHeader).toHaveBeenCalled();
expect(SendAddressSelection).toHaveBeenCalled();
expect(SendAddressInput).toHaveBeenCalled();
expect(SendAddressSelector).toHaveBeenCalled();
expect(SendFundWallet).not.toHaveBeenCalled();
expect(SendTokenSelector).not.toHaveBeenCalled();
});
Expand All @@ -138,7 +184,9 @@ describe('Send', () => {
vi.mocked(useSendContext).mockReturnValue({
isInitialized: true,
ethBalance: ETH_REQUIRED_FOR_SEND + 0.0000000001, // de-minimis amount above ETH_REQUIRED_FOR_SEND
selectedRecipient: {
recipientState: {
phase: 'selected',
input: 'test.base.eth',
address: '0x1234567890123456789012345678901234567890' as Address,
displayValue: '0x1234567890123456789012345678901234567890',
},
Expand All @@ -148,7 +196,7 @@ describe('Send', () => {
render(<Send />);

expect(SendHeader).toHaveBeenCalled();
expect(SendAddressSelection).toHaveBeenCalled();
expect(SendAddressInput).toHaveBeenCalled();
expect(SendTokenSelector).toHaveBeenCalled();
expect(SendAmountInput).not.toHaveBeenCalled();
});
Expand All @@ -157,7 +205,9 @@ describe('Send', () => {
vi.mocked(useSendContext).mockReturnValue({
isInitialized: true,
ethBalance: ETH_REQUIRED_FOR_SEND + 0.0000001,
selectedRecipient: {
recipientState: {
phase: 'selected',
input: 'test.base.eth',
address: '0x1234567890123456789012345678901234567890' as Address,
displayValue: '0x1234567890123456789012345678901234567890',
},
Expand All @@ -167,7 +217,7 @@ describe('Send', () => {
render(<Send />);

expect(SendHeader).toHaveBeenCalled();
expect(SendAddressSelection).toHaveBeenCalled();
expect(SendAddressInput).toHaveBeenCalled();
expect(SendAmountInput).toHaveBeenCalled();
expect(SendTokenSelector).toHaveBeenCalled();
expect(SendButton).toHaveBeenCalled();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import { Skeleton } from '@/internal/components/Skeleton';
import { background, border, cn, color } from '@/styles/theme';
import { ETH_REQUIRED_FOR_SEND } from '../constants';
import type { SendReact } from '../types';
import { SendAddressSelection } from './SendAddressSelection';
import { SendAmountInput } from './SendAmountInput';
import { SendButton } from './SendButton';
import { SendFundWallet } from './SendFundWallet';
import { SendHeader } from './SendHeader';
import { SendProvider, useSendContext } from './SendProvider';
import { SendTokenSelector } from './SendTokenSelector';
import { SendAddressInput } from './SendAddressInput';
import { SendAddressSelector } from './SendAddressSelector';

export function Send({
children = <SendDefaultChildren />,
Expand Down Expand Up @@ -36,7 +37,7 @@ export function Send({
}

function SendDefaultChildren() {
const { ethBalance, isInitialized, selectedRecipient, selectedToken } =
const { ethBalance, isInitialized, recipientState, selectedToken } =
useSendContext();

const walletHasEth = (ethBalance ?? 0) > ETH_REQUIRED_FOR_SEND;
Expand All @@ -51,12 +52,13 @@ function SendDefaultChildren() {
{walletHasEth ? (
<div className="flex h-full flex-col justify-between gap-4">
<div>
<SendAddressSelection />
{selectedRecipient.address && !selectedToken && (
<SendAddressInput />
{recipientState.phase === 'validated' && <SendAddressSelector />}
{recipientState.phase === 'selected' && !selectedToken && (
<SendTokenSelector />
)}
</div>
{selectedRecipient.address && selectedToken && (
{recipientState.phase === 'selected' && selectedToken && (
<>
<SendAmountInput />
<SendTokenSelector />
Expand Down
Loading