import { MOCK_EARN_CONTEXT } from '@/earn/mocks/mocks.test'; import { fireEvent, render, screen } from '@testing-library/react'; import { type Mock, beforeEach, describe, expect, it, vi } from 'vitest'; import { useEarnContext } from './EarnProvider'; import { YieldDetails } from './YieldDetails'; vi.mock('./EarnProvider', () => ({ useEarnContext: vi.fn(), })); describe('YieldDetails', () => { const mockUseEarnContext = useEarnContext as Mock; beforeEach(() => { mockUseEarnContext.mockReturnValue({ ...MOCK_EARN_CONTEXT, apy: '0.05', nativeApy: '0.05', }); }); it('shows loading skeleton when apy is not available', () => { mockUseEarnContext.mockReturnValue({ ...MOCK_EARN_CONTEXT, apy: undefined, }); render(); expect(screen.getByTestId('ockSkeleton')).toBeInTheDocument(); }); it('displays APY with correct formatting', () => { mockUseEarnContext.mockReturnValue({ ...MOCK_EARN_CONTEXT, apy: '0.05', }); render(); expect(screen.getByTestId('ock-yieldDetails')).toHaveTextContent( 'APY 5.00%', ); }); it('opens popover when info button is clicked', () => { render(); fireEvent.click(screen.getByTestId('ock-apyInfoButton')); expect(screen.getByTestId('ock-earnNativeApy')).toBeInTheDocument(); }); it('displays native APY in popover', () => { render(); fireEvent.click(screen.getByTestId('ock-apyInfoButton')); expect(screen.getByTestId('ock-earnNativeApy')).toHaveTextContent('5.00%'); }); it('displays rewards in popover', () => { mockUseEarnContext.mockReturnValue({ ...MOCK_EARN_CONTEXT, apy: '0.05', nativeApy: '0.05', rewards: [ { asset: '0x1', assetName: 'Reward 1', apy: '0.05', }, ], }); render(); fireEvent.click(screen.getByTestId('ock-apyInfoButton')); expect(screen.getByTestId('ock-earnRewards')).toHaveTextContent( 'Reward 15.00%', ); }); it('handles empty rewards array', () => { mockUseEarnContext.mockReturnValue({ ...MOCK_EARN_CONTEXT, apy: '0.05', nativeApy: '0.05', rewards: [], }); render(); fireEvent.click(screen.getByTestId('ock-apyInfoButton')); expect(screen.queryByTestId('ock-earnRewards')).not.toBeInTheDocument(); }); it('handles null rewards', () => { mockUseEarnContext.mockReturnValue({ ...MOCK_EARN_CONTEXT, apy: '0.05', nativeApy: '0.05', rewards: null, }); render(); fireEvent.click(screen.getByTestId('ock-apyInfoButton')); expect(screen.queryByTestId('ock-earnRewards')).not.toBeInTheDocument(); }); it('displays performance fee in popover', () => { mockUseEarnContext.mockReturnValue({ ...MOCK_EARN_CONTEXT, apy: '0.05', nativeApy: '0.05', vaultFee: '0.01', }); render(); fireEvent.click(screen.getByTestId('ock-apyInfoButton')); expect(screen.getByTestId('ock-earnPerformanceFee')).toHaveTextContent( 'Perf. Fee (1%)', ); expect(screen.getByTestId('ock-earnPerformanceFee')).toHaveTextContent( '-0.05%', ); }); it('closes popover when onClose is triggered', () => { render(); // Open the popover first fireEvent.click(screen.getByTestId('ock-apyInfoButton')); expect(screen.getByTestId('ock-earnNativeApy')).toBeInTheDocument(); // Trigger onClose (simulating clicking outside or pressing escape) const popover = screen.getByRole('dialog'); fireEvent.keyDown(popover, { key: 'Escape' }); // Verify popover is closed expect(screen.queryByTestId('ock-earnNativeApy')).not.toBeInTheDocument(); }); it('handles missing native APY gracefully', () => { mockUseEarnContext.mockReturnValue({ ...MOCK_EARN_CONTEXT, apy: '0.05', nativeApy: undefined, }); render(); fireEvent.click(screen.getByTestId('ock-apyInfoButton')); expect(screen.queryByTestId('ock-earnNativeApy')).not.toBeInTheDocument(); }); it('handles cases where vault fees are falsey', () => { mockUseEarnContext.mockReturnValue({ ...MOCK_EARN_CONTEXT, apy: '0.05', nativeApy: '0.05', vaultFee: undefined, }); render(); fireEvent.click(screen.getByTestId('ock-apyInfoButton')); expect( screen.queryByTestId('ock-earnPerformanceFee'), ).not.toBeInTheDocument(); }); });