import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { render, screen } from '@testing-library/react'; import React, { type ReactNode } from 'react'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { BrokerEventsPage } from './BrokerEventsPage'; vi.mock('@/entities/broker-event', () => ({ useBrokerEvents: vi.fn(), })); vi.mock('@/widgets/broker-account-layout', () => ({ useBrokerAccountContext: () => ({ accountId: 'acc-1', portfolio: null }), })); const mockSetSearchParams = vi.fn(); vi.mock('react-router-dom', () => ({ useSearchParams: () => [new URLSearchParams(), mockSetSearchParams], })); vi.mock('@moex-vibe/design-system', () => ({ Heading: ({ children }: { children: ReactNode }) =>

{children}

, Text: ({ children }: { children: ReactNode }) => {children}, TextField: ({ label, value, onChange, ...props }: any) => ( {})} type={props.type || 'text'} /> ), })); import { useBrokerEvents } from '@/entities/broker-event'; function createWrapper() { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }); return function Wrapper({ children }: { children: ReactNode }) { return {children}; }; } const mockData = { summary: { eventCount: 3, totalEstimatedCashflow: 450, nearestEventDate: '2026-06-25', currency: 'RUB', }, items: [ { 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, }, { id: 'ev-3', type: 'maturity', ticker: 'VTBR', name: 'ВТБ', eventDate: '2026-06-30', estimatedAmount: 1000, currency: 'RUB' as const, }, ], }; describe('BrokerEventsPage', () => { 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('renders error state', () => { 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: new Promise(() => {}), status: 'error', fetchStatus: 'idle', } as unknown as ReturnType); render(, { wrapper: createWrapper() }); expect(screen.getByText('Не удалось загрузить календарь событий')).toBeInTheDocument(); }); it('renders empty state', () => { 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); render(, { wrapper: createWrapper() }); expect(screen.getByText('В выбранном диапазоне событий нет')).toBeInTheDocument(); }); it('renders date range inputs', () => { vi.mocked(useBrokerEvents).mockReturnValue({ data: mockData, 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(mockData), status: 'success', fetchStatus: 'idle', } as unknown as ReturnType); render(, { wrapper: createWrapper() }); expect(screen.getByLabelText('С')).toBeInTheDocument(); expect(screen.getByLabelText('По')).toBeInTheDocument(); }); it('renders events heading, summary and table', () => { vi.mocked(useBrokerEvents).mockReturnValue({ data: mockData, 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(mockData), status: 'success', fetchStatus: 'idle', } as unknown as ReturnType); render(, { wrapper: createWrapper() }); expect(screen.getByText('События')).toBeInTheDocument(); expect(screen.getByText('Событий')).toBeInTheDocument(); expect(screen.getByText('3')).toBeInTheDocument(); expect(screen.getByText('Ближайшее')).toBeInTheDocument(); expect(screen.getByText('Денежный поток')).toBeInTheDocument(); expect(screen.getByText('Дивиденд')).toBeInTheDocument(); expect(screen.getByText('Купон')).toBeInTheDocument(); expect(screen.getByText('Погашение')).toBeInTheDocument(); expect(screen.getByText('SBER')).toBeInTheDocument(); expect(screen.getByText('SU26238RMFS5')).toBeInTheDocument(); expect(screen.getByText('VTBR')).toBeInTheDocument(); }); });