moex-vibe/apps/frontend/src/widgets/broker-events-overview/ui/BrokerEventsOverview.test.tsx
2026-06-22 06:41:37 +03:00

288 lines
7.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 }) => <h3>{children}</h3>,
Text: ({ children }: { children: ReactNode }) => <span>{children}</span>,
}));
function createWrapper() {
const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
return function Wrapper({ children }: { children: ReactNode }) {
return (
<QueryClientProvider client={queryClient}>
<MemoryRouter>{children}</MemoryRouter>
</QueryClientProvider>
);
};
}
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<never>(() => {}),
status: 'pending',
fetchStatus: 'fetching',
} as unknown as ReturnType<typeof useBrokerEvents>);
render(<BrokerEventsOverview accountId="acc-1" />, { 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<typeof useBrokerEvents>);
const { container } = render(<BrokerEventsOverview accountId="acc-1" />, {
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<typeof useBrokerEvents>);
const { container } = render(<BrokerEventsOverview accountId="acc-1" />, {
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<typeof useBrokerEvents>);
render(<BrokerEventsOverview accountId="acc-1" />, { 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<typeof useBrokerEvents>);
render(<BrokerEventsOverview accountId="acc-1" />, { wrapper: createWrapper() });
expect(screen.getAllByText(/TICKER/)).toHaveLength(5);
});
});