import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest' import userEvent from '@testing-library/user-event' import { within } from '@testing-library/react' import { api } from '@/api/endpoints' import type { Account, BudgetCategory, Page, Operation } from '@/api/types' import { ImportsPage } from '@/pages/ImportsPage' import { OperationsPage } from '@/pages/OperationsPage' import { renderWithProviders } from './helpers' vi.mock('@/api/endpoints', () => ({ api: { accounts: { list: vi.fn(), create: vi.fn(), archive: vi.fn(), adjustBalance: vi.fn(), }, operations: { list: vi.fn(), create: vi.fn(), void: vi.fn(), categorize: vi.fn(), savingsTransfer: vi.fn(), savingsTransferRevert: vi.fn(), }, budget: { summary: vi.fn(), categories: vi.fn(), updatePlan: vi.fn(), fund: vi.fn(), close: vi.fn(), reopen: vi.fn(), copyPrevious: vi.fn(), categoryDefinitions: vi.fn(), createCategory: vi.fn(), updateCategoryDefinition: vi.fn(), }, imports: { list: vi.fn(), get: vi.fn(), upload: vi.fn(), saveRowDecision: vi.fn(), resolveHold: vi.fn(), confirm: vi.fn(), reparse: vi.fn(), revert: vi.fn(), }, }, })) const listAccountsMock = vi.mocked(api.accounts.list) const operationsListMock = vi.mocked(api.operations.list) const budgetCategoriesMock = vi.mocked(api.budget.categories) const importsListMock = vi.mocked(api.imports.list) function account(overrides: Partial = {}): Account { return { id: 'a1', name: 'Alfa Card', type: 'debit', status: 'active', bankCode: null, maskedNumber: null, openedOn: '2026-01-15', currency: 'RUB', systemKey: null, nameKey: null, balanceKopecks: 123456, ...overrides, } } describe('system savings account picker exclusion', () => { beforeEach(() => { listAccountsMock.mockResolvedValue([ account(), account({ id: 'a2', name: 'Cash wallet', type: 'cash' }), account({ id: 'a-sys', name: 'Накопления', nameKey: 'account.savings', type: 'savings', systemKey: 'savings', balanceKopecks: 0, }), ]) operationsListMock.mockResolvedValue({ items: [], nextCursor: null } as Page) budgetCategoriesMock.mockResolvedValue([] as BudgetCategory[]) importsListMock.mockResolvedValue([]) }) afterEach(() => { vi.clearAllMocks() }) it('hides the savings account in the expense form but keeps it in the transfer form and filters', async () => { const screen = renderWithProviders() await userEvent.click( await screen.findByRole('button', { name: '+ New operation' }), ) const dialog = await screen.findByRole('dialog', { name: 'New operation' }) const expenseSelect = within(dialog).getByLabelText('Account') as HTMLSelectElement const expenseOptions = Array.from(expenseSelect.options).map((option) => option.textContent) expect(expenseOptions).toContain('Alfa Card') expect(expenseOptions).not.toContain('Savings') await userEvent.click(within(dialog).getByRole('button', { name: 'Transfer' })) const transferSelects = within(dialog) .getAllByRole('combobox') .filter((select) => (select as HTMLSelectElement).options.length > 2) as HTMLSelectElement[] const transferOptions = transferSelects.flatMap((select) => Array.from(select.options).map((option) => option.textContent), ) expect(transferOptions).toContain('Savings') const filterSelect = screen.getByLabelText('Account') as HTMLSelectElement const filterOptions = Array.from(filterSelect.options).map((option) => option.textContent) expect(filterOptions).toContain('Savings') }) it('hides the savings account in the statement upload target selector', async () => { const screen = renderWithProviders() await userEvent.click(await screen.findByRole('button', { name: '+ Upload statement' })) const dialog = await screen.findByRole('dialog', { name: 'New import' }) const select = within(dialog).getByLabelText('Target account') as HTMLSelectElement const options = Array.from(select.options).map((option) => option.textContent) expect(options).toContain('Alfa Card') expect(options).toContain('Cash wallet') expect(options).not.toContain('Savings') }) })