This commit is contained in:
116
src/__tests__/finance-api.test.js
Normal file
116
src/__tests__/finance-api.test.js
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||||
|
|
||||||
|
// Mock client module
|
||||||
|
vi.mock('../api/client', () => {
|
||||||
|
return {
|
||||||
|
default: {
|
||||||
|
get: vi.fn(),
|
||||||
|
post: vi.fn(),
|
||||||
|
put: vi.fn(),
|
||||||
|
delete: vi.fn(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
import client from '../api/client'
|
||||||
|
import { financeApi } from '../api/finance'
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('financeApi', () => {
|
||||||
|
// Categories
|
||||||
|
describe('categories', () => {
|
||||||
|
it('listCategories calls GET finance/categories', async () => {
|
||||||
|
const mockData = [{ id: 1, name: 'Еда', emoji: '🍔' }]
|
||||||
|
client.get.mockResolvedValue({ data: mockData })
|
||||||
|
const result = await financeApi.listCategories()
|
||||||
|
expect(client.get).toHaveBeenCalledWith('finance/categories')
|
||||||
|
expect(result).toEqual(mockData)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('createCategory calls POST finance/categories', async () => {
|
||||||
|
const input = { name: 'Test', type: 'expense', emoji: '🧪' }
|
||||||
|
const mockData = { id: 1, ...input }
|
||||||
|
client.post.mockResolvedValue({ data: mockData })
|
||||||
|
const result = await financeApi.createCategory(input)
|
||||||
|
expect(client.post).toHaveBeenCalledWith('finance/categories', input)
|
||||||
|
expect(result).toEqual(mockData)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('updateCategory calls PUT finance/categories/:id', async () => {
|
||||||
|
const data = { name: 'Updated' }
|
||||||
|
client.put.mockResolvedValue({ data: { id: 5, ...data } })
|
||||||
|
const result = await financeApi.updateCategory(5, data)
|
||||||
|
expect(client.put).toHaveBeenCalledWith('finance/categories/5', data)
|
||||||
|
expect(result.name).toBe('Updated')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('deleteCategory calls DELETE finance/categories/:id', async () => {
|
||||||
|
client.delete.mockResolvedValue({})
|
||||||
|
await financeApi.deleteCategory(3)
|
||||||
|
expect(client.delete).toHaveBeenCalledWith('finance/categories/3')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Transactions
|
||||||
|
describe('transactions', () => {
|
||||||
|
it('listTransactions calls GET with params', async () => {
|
||||||
|
const mockData = [{ id: 1, amount: 500 }]
|
||||||
|
client.get.mockResolvedValue({ data: mockData })
|
||||||
|
const params = { month: 3, year: 2026 }
|
||||||
|
const result = await financeApi.listTransactions(params)
|
||||||
|
expect(client.get).toHaveBeenCalledWith('finance/transactions', { params })
|
||||||
|
expect(result).toEqual(mockData)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('listTransactions works without params', async () => {
|
||||||
|
client.get.mockResolvedValue({ data: [] })
|
||||||
|
const result = await financeApi.listTransactions()
|
||||||
|
expect(client.get).toHaveBeenCalledWith('finance/transactions', { params: {} })
|
||||||
|
expect(result).toEqual([])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('createTransaction calls POST', async () => {
|
||||||
|
const input = { amount: 100, type: 'expense', category_id: 1, date: '2026-03-01' }
|
||||||
|
client.post.mockResolvedValue({ data: { id: 1, ...input } })
|
||||||
|
const result = await financeApi.createTransaction(input)
|
||||||
|
expect(client.post).toHaveBeenCalledWith('finance/transactions', input)
|
||||||
|
expect(result.amount).toBe(100)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('updateTransaction calls PUT', async () => {
|
||||||
|
const data = { amount: 200 }
|
||||||
|
client.put.mockResolvedValue({ data: { id: 7, ...data } })
|
||||||
|
const result = await financeApi.updateTransaction(7, data)
|
||||||
|
expect(client.put).toHaveBeenCalledWith('finance/transactions/7', data)
|
||||||
|
expect(result.amount).toBe(200)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('deleteTransaction calls DELETE', async () => {
|
||||||
|
client.delete.mockResolvedValue({})
|
||||||
|
await financeApi.deleteTransaction(10)
|
||||||
|
expect(client.delete).toHaveBeenCalledWith('finance/transactions/10')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Summary & Analytics
|
||||||
|
describe('summary & analytics', () => {
|
||||||
|
it('getSummary calls GET with params', async () => {
|
||||||
|
const mockData = { balance: 5000, total_income: 10000, total_expense: 5000 }
|
||||||
|
client.get.mockResolvedValue({ data: mockData })
|
||||||
|
const result = await financeApi.getSummary({ month: 3, year: 2026 })
|
||||||
|
expect(client.get).toHaveBeenCalledWith('finance/summary', { params: { month: 3, year: 2026 } })
|
||||||
|
expect(result.balance).toBe(5000)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getAnalytics calls GET with params', async () => {
|
||||||
|
const mockData = { monthly_trend: [], avg_daily_expense: 500 }
|
||||||
|
client.get.mockResolvedValue({ data: mockData })
|
||||||
|
const result = await financeApi.getAnalytics({ months: 6 })
|
||||||
|
expect(client.get).toHaveBeenCalledWith('finance/analytics', { params: { months: 6 } })
|
||||||
|
expect(result.avg_daily_expense).toBe(500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
64
src/__tests__/tracker.test.jsx
Normal file
64
src/__tests__/tracker.test.jsx
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import { describe, it, expect, vi } from 'vitest'
|
||||||
|
import { render, screen, fireEvent } from '@testing-library/react'
|
||||||
|
import Tracker from '../pages/Tracker'
|
||||||
|
|
||||||
|
// Mock child pages
|
||||||
|
vi.mock('../pages/Habits', () => ({
|
||||||
|
default: ({ embedded }) => <div data-testid="habits">Habits {embedded ? 'embedded' : ''}</div>
|
||||||
|
}))
|
||||||
|
vi.mock('../pages/Tasks', () => ({
|
||||||
|
default: ({ embedded }) => <div data-testid="tasks">Tasks {embedded ? 'embedded' : ''}</div>
|
||||||
|
}))
|
||||||
|
vi.mock('../pages/Stats', () => ({
|
||||||
|
default: ({ embedded }) => <div data-testid="stats">Stats {embedded ? 'embedded' : ''}</div>
|
||||||
|
}))
|
||||||
|
vi.mock('../components/Navigation', () => ({
|
||||||
|
default: () => <nav data-testid="navigation">Nav</nav>
|
||||||
|
}))
|
||||||
|
|
||||||
|
describe('Tracker', () => {
|
||||||
|
it('renders header with title', () => {
|
||||||
|
render(<Tracker />)
|
||||||
|
expect(screen.getByText(/Трекер/)).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders all three tab buttons', () => {
|
||||||
|
render(<Tracker />)
|
||||||
|
expect(screen.getByText(/Привычки/)).toBeInTheDocument()
|
||||||
|
expect(screen.getByText(/Задачи/)).toBeInTheDocument()
|
||||||
|
expect(screen.getByText(/Статистика/)).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows Habits tab by default', () => {
|
||||||
|
render(<Tracker />)
|
||||||
|
expect(screen.getByTestId('habits')).toBeInTheDocument()
|
||||||
|
expect(screen.queryByTestId('tasks')).not.toBeInTheDocument()
|
||||||
|
expect(screen.queryByTestId('stats')).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('switches to Tasks tab on click', () => {
|
||||||
|
render(<Tracker />)
|
||||||
|
fireEvent.click(screen.getByText(/Задачи/))
|
||||||
|
expect(screen.getByTestId('tasks')).toBeInTheDocument()
|
||||||
|
expect(screen.queryByTestId('habits')).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('switches to Stats tab on click', () => {
|
||||||
|
render(<Tracker />)
|
||||||
|
fireEvent.click(screen.getByText(/Статистика/))
|
||||||
|
expect(screen.getByTestId('stats')).toBeInTheDocument()
|
||||||
|
expect(screen.queryByTestId('habits')).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('switches back to Habits', () => {
|
||||||
|
render(<Tracker />)
|
||||||
|
fireEvent.click(screen.getByText(/Задачи/))
|
||||||
|
fireEvent.click(screen.getByText(/Привычки/))
|
||||||
|
expect(screen.getByTestId('habits')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders navigation', () => {
|
||||||
|
render(<Tracker />)
|
||||||
|
expect(screen.getByTestId('navigation')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user