import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { render, screen } from '@testing-library/react'; import { type ReactNode } from 'react'; import { MemoryRouter } from 'react-router-dom'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { BrokerEventsOverview } from './BrokerEventsOverview'; vi.mock('@/entities/broker-event', () => ({ useBrokerEvents: vi.fn(), })); import { useBrokerEvents } from '@/entities/broker-event'; vi.mock('@moex-vibe/design-system', () => ({ Heading: ({ children }: { children: ReactNode }) =>

{children}

, Text: ({ children }: { children: ReactNode }) => {children}, })); function createWrapper() { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }); return function Wrapper({ children }: { children: ReactNode }) { return ( {children} ); }; } const mockItems = [ { id: 'ev-1', type: 'dividend', ticker: 'SBER', name: 'Сбер Банк', eventDate: '2026-06-25', estimatedAmount: 150, currency: 'RUB' as const, }, { id: 'ev-2', type: 'coupon', ticker: 'SU26238RMFS5', name: 'ОФЗ 26238', eventDate: '2026-06-27', estimatedAmount: 36.9, currency: 'RUB' as const, }, ]; describe('BrokerEventsOverview', () => { beforeEach(() => { vi.clearAllMocks(); }); it('renders loading state', () => { vi.mocked(useBrokerEvents).mockReturnValue({ data: undefined, isLoading: true, isError: false, error: null, isSuccess: false, isPending: true, dataUpdatedAt: 0, errorUpdatedAt: 0, failureCount: 0, failureReason: null, errorUpdateCount: 0, isFetched: false, isFetchedAfterMount: false, isFetching: true, isInitialLoading: true, isPaused: false, isLoadingError: false, isRefetchError: false, isPlaceholderData: false, isStale: false, refetch: vi.fn(), promise: new Promise(() => {}), status: 'pending', fetchStatus: 'fetching', } as unknown as ReturnType); render(, { wrapper: createWrapper() }); expect(screen.getByText('Загрузка событий…')).toBeInTheDocument(); }); it('returns null on error', () => { vi.mocked(useBrokerEvents).mockReturnValue({ data: undefined, isLoading: false, isError: true, error: new Error('fail'), isSuccess: false, isPending: false, dataUpdatedAt: 0, errorUpdatedAt: 0, failureCount: 1, failureReason: null, errorUpdateCount: 1, isFetched: true, isFetchedAfterMount: true, isFetching: false, isInitialLoading: false, isPaused: false, isLoadingError: true, isRefetchError: false, isPlaceholderData: false, isStale: false, refetch: vi.fn(), promise: Promise.reject(new Error('fail')), status: 'error', fetchStatus: 'idle', } as unknown as ReturnType); const { container } = render(, { wrapper: createWrapper(), }); expect(container).toBeEmptyDOMElement(); }); it('returns null when items array is empty', () => { vi.mocked(useBrokerEvents).mockReturnValue({ data: { summary: { eventCount: 0, totalEstimatedCashflow: 0, nearestEventDate: null, currency: 'RUB', }, items: [], }, isLoading: false, isError: false, error: null, isSuccess: true, isPending: false, dataUpdatedAt: Date.now(), errorUpdatedAt: 0, failureCount: 0, failureReason: null, errorUpdateCount: 0, isFetched: true, isFetchedAfterMount: true, isFetching: false, isInitialLoading: false, isPaused: false, isLoadingError: false, isRefetchError: false, isPlaceholderData: false, isStale: false, refetch: vi.fn(), promise: Promise.resolve({ summary: { eventCount: 0, totalEstimatedCashflow: 0, nearestEventDate: null, currency: 'RUB', }, items: [], }), status: 'success', fetchStatus: 'idle', } as unknown as ReturnType); const { container } = render(, { wrapper: createWrapper(), }); expect(container).toBeEmptyDOMElement(); }); it('renders event items and link to full page', () => { vi.mocked(useBrokerEvents).mockReturnValue({ data: { summary: { eventCount: 2, totalEstimatedCashflow: 186.9, nearestEventDate: '2026-06-25', currency: 'RUB', }, items: mockItems, }, isLoading: false, isError: false, error: null, isSuccess: true, isPending: false, dataUpdatedAt: Date.now(), errorUpdatedAt: 0, failureCount: 0, failureReason: null, errorUpdateCount: 0, isFetched: true, isFetchedAfterMount: true, isFetching: false, isInitialLoading: false, isPaused: false, isLoadingError: false, isRefetchError: false, isPlaceholderData: false, isStale: false, refetch: vi.fn(), promise: Promise.resolve({ summary: { eventCount: 2, totalEstimatedCashflow: 186.9, nearestEventDate: '2026-06-25', currency: 'RUB', }, items: mockItems, }), status: 'success', fetchStatus: 'idle', } as unknown as ReturnType); render(, { wrapper: createWrapper() }); expect(screen.getByText('Ближайшие события')).toBeInTheDocument(); expect(screen.getByText('SBER')).toBeInTheDocument(); expect(screen.getByText('SU26238RMFS5')).toBeInTheDocument(); expect(screen.getByText('Все события')).toBeInTheDocument(); expect(screen.getByRole('link', { name: 'Все события' })).toHaveAttribute( 'href', '/broker/acc-1/events', ); }); it('renders at most 5 items', () => { const manyItems = Array.from({ length: 7 }, (_, i) => ({ id: `ev-${i}`, type: 'dividend' as const, ticker: `TICKER${i}`, name: null as string | null, eventDate: '2026-06-25', estimatedAmount: 100, currency: 'RUB' as const, })); vi.mocked(useBrokerEvents).mockReturnValue({ data: { summary: { eventCount: 7, totalEstimatedCashflow: 700, nearestEventDate: '2026-06-25', currency: 'RUB', }, items: manyItems, }, isLoading: false, isError: false, error: null, isSuccess: true, isPending: false, dataUpdatedAt: Date.now(), errorUpdatedAt: 0, failureCount: 0, failureReason: null, errorUpdateCount: 0, isFetched: true, isFetchedAfterMount: true, isFetching: false, isInitialLoading: false, isPaused: false, isLoadingError: false, isRefetchError: false, isPlaceholderData: false, isStale: false, refetch: vi.fn(), promise: Promise.resolve({ summary: { eventCount: 7, totalEstimatedCashflow: 700, nearestEventDate: '2026-06-25', currency: 'RUB', }, items: manyItems, }), status: 'success', fetchStatus: 'idle', } as unknown as ReturnType); render(, { wrapper: createWrapper() }); expect(screen.getAllByText(/TICKER/)).toHaveLength(5); }); });