278 lines
9.4 KiB
TypeScript
278 lines
9.4 KiB
TypeScript
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
import {
|
|
createExpense,
|
|
getExpenses,
|
|
getExpenseById,
|
|
updateExpense,
|
|
deleteExpense,
|
|
getExpenseCategories,
|
|
getExpensesByCategory,
|
|
getTotalExpenses
|
|
} from '../expense-management.server';
|
|
import { prisma } from '../db.server';
|
|
|
|
describe('Expense Management', () => {
|
|
beforeEach(async () => {
|
|
// Clean up test data
|
|
await prisma.expense.deleteMany();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
// Clean up test data
|
|
await prisma.expense.deleteMany();
|
|
});
|
|
|
|
describe('createExpense', () => {
|
|
it('should create a new expense', async () => {
|
|
const expenseData = {
|
|
description: 'قطع غيار للمحرك',
|
|
category: 'قطع غيار',
|
|
amount: 500.00,
|
|
expenseDate: new Date('2024-01-15'),
|
|
};
|
|
|
|
const expense = await createExpense(expenseData);
|
|
|
|
expect(expense).toBeDefined();
|
|
expect(expense.description).toBe(expenseData.description);
|
|
expect(expense.category).toBe(expenseData.category);
|
|
expect(expense.amount).toBe(expenseData.amount);
|
|
expect(expense.expenseDate).toEqual(expenseData.expenseDate);
|
|
});
|
|
|
|
it('should create expense with current date if no date provided', async () => {
|
|
const expenseData = {
|
|
description: 'مصروف عام',
|
|
category: 'أخرى',
|
|
amount: 100.00,
|
|
};
|
|
|
|
const expense = await createExpense(expenseData);
|
|
|
|
expect(expense).toBeDefined();
|
|
expect(expense.expenseDate).toBeInstanceOf(Date);
|
|
});
|
|
});
|
|
|
|
describe('getExpenses', () => {
|
|
beforeEach(async () => {
|
|
// Create test expenses
|
|
await prisma.expense.createMany({
|
|
data: [
|
|
{
|
|
description: 'قطع غيار',
|
|
category: 'قطع غيار',
|
|
amount: 500.00,
|
|
expenseDate: new Date('2024-01-15'),
|
|
},
|
|
{
|
|
description: 'أدوات صيانة',
|
|
category: 'أدوات',
|
|
amount: 200.00,
|
|
expenseDate: new Date('2024-01-10'),
|
|
},
|
|
{
|
|
description: 'إيجار المحل',
|
|
category: 'إيجار',
|
|
amount: 3000.00,
|
|
expenseDate: new Date('2024-01-01'),
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('should get all expenses with pagination', async () => {
|
|
const result = await getExpenses();
|
|
|
|
expect(result.expenses).toHaveLength(3);
|
|
expect(result.total).toBe(3);
|
|
expect(result.totalPages).toBe(1);
|
|
});
|
|
|
|
it('should filter expenses by search query', async () => {
|
|
const result = await getExpenses('قطع غيار');
|
|
|
|
expect(result.expenses).toHaveLength(1);
|
|
expect(result.expenses[0].description).toBe('قطع غيار');
|
|
});
|
|
|
|
it('should filter expenses by category', async () => {
|
|
const result = await getExpenses(undefined, 1, 10, 'أدوات');
|
|
|
|
expect(result.expenses).toHaveLength(1);
|
|
expect(result.expenses[0].category).toBe('أدوات');
|
|
});
|
|
|
|
it('should filter expenses by date range', async () => {
|
|
const dateFrom = new Date('2024-01-10');
|
|
const dateTo = new Date('2024-01-20');
|
|
|
|
const result = await getExpenses(undefined, 1, 10, undefined, dateFrom, dateTo);
|
|
|
|
expect(result.expenses).toHaveLength(2);
|
|
});
|
|
|
|
it('should handle pagination correctly', async () => {
|
|
const result = await getExpenses(undefined, 1, 2);
|
|
|
|
expect(result.expenses).toHaveLength(2);
|
|
expect(result.totalPages).toBe(2);
|
|
});
|
|
});
|
|
|
|
describe('getExpenseById', () => {
|
|
it('should get expense by ID', async () => {
|
|
const createdExpense = await prisma.expense.create({
|
|
data: {
|
|
description: 'تست مصروف',
|
|
category: 'أخرى',
|
|
amount: 100.00,
|
|
},
|
|
});
|
|
|
|
const expense = await getExpenseById(createdExpense.id);
|
|
|
|
expect(expense).toBeDefined();
|
|
expect(expense?.id).toBe(createdExpense.id);
|
|
expect(expense?.description).toBe('تست مصروف');
|
|
});
|
|
|
|
it('should return null for non-existent expense', async () => {
|
|
const expense = await getExpenseById(999);
|
|
|
|
expect(expense).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('updateExpense', () => {
|
|
it('should update expense successfully', async () => {
|
|
const createdExpense = await prisma.expense.create({
|
|
data: {
|
|
description: 'مصروف قديم',
|
|
category: 'أخرى',
|
|
amount: 100.00,
|
|
},
|
|
});
|
|
|
|
const updateData = {
|
|
description: 'مصروف محدث',
|
|
category: 'قطع غيار',
|
|
amount: 200.00,
|
|
};
|
|
|
|
const updatedExpense = await updateExpense(createdExpense.id, updateData);
|
|
|
|
expect(updatedExpense.description).toBe(updateData.description);
|
|
expect(updatedExpense.category).toBe(updateData.category);
|
|
expect(updatedExpense.amount).toBe(updateData.amount);
|
|
});
|
|
});
|
|
|
|
describe('deleteExpense', () => {
|
|
it('should delete expense successfully', async () => {
|
|
const createdExpense = await prisma.expense.create({
|
|
data: {
|
|
description: 'مصروف للحذف',
|
|
category: 'أخرى',
|
|
amount: 100.00,
|
|
},
|
|
});
|
|
|
|
await deleteExpense(createdExpense.id);
|
|
|
|
const deletedExpense = await prisma.expense.findUnique({
|
|
where: { id: createdExpense.id },
|
|
});
|
|
|
|
expect(deletedExpense).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('getExpenseCategories', () => {
|
|
beforeEach(async () => {
|
|
await prisma.expense.createMany({
|
|
data: [
|
|
{ description: 'مصروف 1', category: 'قطع غيار', amount: 100 },
|
|
{ description: 'مصروف 2', category: 'أدوات', amount: 200 },
|
|
{ description: 'مصروف 3', category: 'قطع غيار', amount: 150 },
|
|
],
|
|
});
|
|
});
|
|
|
|
it('should get unique expense categories', async () => {
|
|
const categories = await getExpenseCategories();
|
|
|
|
expect(categories).toHaveLength(2);
|
|
expect(categories).toContain('قطع غيار');
|
|
expect(categories).toContain('أدوات');
|
|
});
|
|
});
|
|
|
|
describe('getExpensesByCategory', () => {
|
|
beforeEach(async () => {
|
|
await prisma.expense.createMany({
|
|
data: [
|
|
{ description: 'مصروف 1', category: 'قطع غيار', amount: 100 },
|
|
{ description: 'مصروف 2', category: 'أدوات', amount: 200 },
|
|
{ description: 'مصروف 3', category: 'قطع غيار', amount: 150 },
|
|
],
|
|
});
|
|
});
|
|
|
|
it('should group expenses by category', async () => {
|
|
const result = await getExpensesByCategory();
|
|
|
|
expect(result).toHaveLength(2);
|
|
|
|
const spareParts = result.find(r => r.category === 'قطع غيار');
|
|
expect(spareParts?.total).toBe(250);
|
|
expect(spareParts?.count).toBe(2);
|
|
|
|
const tools = result.find(r => r.category === 'أدوات');
|
|
expect(tools?.total).toBe(200);
|
|
expect(tools?.count).toBe(1);
|
|
});
|
|
});
|
|
|
|
describe('getTotalExpenses', () => {
|
|
beforeEach(async () => {
|
|
await prisma.expense.createMany({
|
|
data: [
|
|
{
|
|
description: 'مصروف 1',
|
|
category: 'قطع غيار',
|
|
amount: 100,
|
|
expenseDate: new Date('2024-01-15'),
|
|
},
|
|
{
|
|
description: 'مصروف 2',
|
|
category: 'أدوات',
|
|
amount: 200,
|
|
expenseDate: new Date('2024-01-10'),
|
|
},
|
|
{
|
|
description: 'مصروف 3',
|
|
category: 'إيجار',
|
|
amount: 3000,
|
|
expenseDate: new Date('2023-12-15'),
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('should calculate total expenses', async () => {
|
|
const total = await getTotalExpenses();
|
|
|
|
expect(total).toBe(3300);
|
|
});
|
|
|
|
it('should calculate total expenses for date range', async () => {
|
|
const dateFrom = new Date('2024-01-01');
|
|
const dateTo = new Date('2024-01-31');
|
|
|
|
const total = await getTotalExpenses(dateFrom, dateTo);
|
|
|
|
expect(total).toBe(300); // Only expenses from January 2024
|
|
});
|
|
});
|
|
}); |