test(03-00): add Wave 0 test stub files for 4 components

- BudgetSetup.test.tsx: smoke test + 2 it.skip for IXTN-01 spinner/disable
- CategoriesPage.test.tsx: smoke test + 4 it.skip for IXTN-05 and STATE-02
- DashboardPage.test.tsx: smoke test + 2 it.skip for STATE-01 and STATE-03
- BillsTracker.test.tsx: smoke test + 3 it.skip for STATE-03 and IXTN-03
This commit is contained in:
2026-03-11 22:32:07 +01:00
parent d9e60fa90c
commit c95c7f248e
4 changed files with 193 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
import { render, screen } from '@testing-library/react'
import { describe, it, expect, vi } from 'vitest'
import { BillsTracker } from './BillsTracker'
import type { BudgetDetail } from '@/lib/api'
vi.mock('react-i18next', () => ({
useTranslation: () => ({ t: (key: string) => key, i18n: { language: 'en' } }),
}))
const emptyBudgetFixture: BudgetDetail = {
id: 'b1',
name: 'Test Budget',
start_date: '2025-01-01',
end_date: '2025-01-31',
currency: 'EUR',
carryover_amount: 0,
items: [],
totals: {
income_budget: 0,
income_actual: 0,
bills_budget: 0,
bills_actual: 0,
expenses_budget: 0,
expenses_actual: 0,
debts_budget: 0,
debts_actual: 0,
savings_budget: 0,
savings_actual: 0,
investments_budget: 0,
investments_actual: 0,
available: 0,
},
}
describe('BillsTracker', () => {
it('renders without crashing', () => {
render(<BillsTracker budget={emptyBudgetFixture} onUpdate={vi.fn()} />)
expect(screen.getByText('dashboard.billsTracker')).toBeInTheDocument()
})
it.skip('shows tinted skeleton when no bill items', () => {
// STATE-03: when budget.items contains no bill-type items, BillsTracker renders
// skeleton rows with a bill-category tint (palette bill light shade) instead of an empty table body
})
it.skip('flashes row green on successful inline save', () => {
// IXTN-03: after onUpdate resolves successfully, the updated row briefly gets a green
// flash class before returning to its normal appearance
})
it.skip('flashes row red on failed inline save', () => {
// IXTN-03: after onUpdate rejects, the row briefly gets a red flash class to signal failure
})
})

View File

@@ -0,0 +1,37 @@
import { render, screen } from '@testing-library/react'
import { describe, it, expect, vi } from 'vitest'
import { BudgetSetup } from './BudgetSetup'
vi.mock('react-i18next', () => ({
useTranslation: () => ({ t: (key: string) => key, i18n: { language: 'en' } }),
}))
vi.mock('@/lib/api', () => ({
budgets: {
create: vi.fn().mockResolvedValue({ id: 'b1', name: 'Test Budget' }),
copyFrom: vi.fn().mockResolvedValue({}),
},
}))
describe('BudgetSetup', () => {
const defaultProps = {
existingBudgets: [],
onCreated: vi.fn(),
onCancel: vi.fn(),
}
it('renders without crashing', () => {
render(<BudgetSetup {...defaultProps} />)
expect(screen.getByText('budget.setup')).toBeInTheDocument()
})
it.skip('shows spinner in create button when saving', () => {
// IXTN-01: while saving is true, the create button renders a spinner (Loader2 icon)
// Steps: fill required fields, click create, assert spinner is visible before resolve
})
it.skip('disables create button when saving', () => {
// IXTN-01: while saving is true, the create button is disabled to prevent double-submit
// Steps: fill required fields, click create, assert button is disabled before resolve
})
})