diff --git a/src/__tests__/finance-api.test.js b/src/__tests__/finance-api.test.js new file mode 100644 index 0000000..4bc41db --- /dev/null +++ b/src/__tests__/finance-api.test.js @@ -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) + }) + }) +}) diff --git a/src/__tests__/tracker.test.jsx b/src/__tests__/tracker.test.jsx new file mode 100644 index 0000000..85bc0c5 --- /dev/null +++ b/src/__tests__/tracker.test.jsx @@ -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 }) =>