135 lines
4.4 KiB
TypeScript
135 lines
4.4 KiB
TypeScript
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> = {}): 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<Operation>)
|
|
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(<OperationsPage />)
|
|
|
|
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(<ImportsPage />)
|
|
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')
|
|
})
|
|
})
|