car_mms/app/lib/__tests__/customer-management.test.ts
2025-09-11 14:22:27 +03:00

437 lines
12 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
// Mock Prisma first
vi.mock('../db.server', () => ({
prisma: {
customer: {
findMany: vi.fn(),
findUnique: vi.fn(),
findFirst: vi.fn(),
create: vi.fn(),
update: vi.fn(),
delete: vi.fn(),
count: vi.fn(),
},
},
}));
import {
getCustomers,
createCustomer,
updateCustomer,
deleteCustomer,
getCustomerById,
getCustomersForSelect,
searchCustomers,
getCustomerStats
} from '../customer-management.server';
import { prisma } from '../db.server';
const mockPrisma = prisma as any;
describe('Customer Management Server', () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe('getCustomers', () => {
it('should return customers with pagination', async () => {
const mockCustomers = [
{
id: 1,
name: 'أحمد محمد',
phone: '0501234567',
email: 'ahmed@example.com',
address: 'الرياض',
createdDate: new Date(),
updateDate: new Date(),
vehicles: [],
maintenanceVisits: [],
},
];
mockPrisma.customer.findMany.mockResolvedValue(mockCustomers);
mockPrisma.customer.count.mockResolvedValue(1);
const result = await getCustomers('', 1, 10);
expect(result).toEqual({
customers: mockCustomers,
total: 1,
totalPages: 1,
});
expect(mockPrisma.customer.findMany).toHaveBeenCalledWith({
where: {},
include: {
vehicles: {
select: {
id: true,
plateNumber: true,
manufacturer: true,
model: true,
year: true,
lastVisitDate: true,
suggestedNextVisitDate: true,
},
},
maintenanceVisits: {
select: {
id: true,
visitDate: true,
cost: true,
maintenanceType: true,
},
orderBy: { visitDate: 'desc' },
take: 5,
},
},
orderBy: { createdDate: 'desc' },
skip: 0,
take: 10,
});
});
it('should handle search query', async () => {
mockPrisma.customer.findMany.mockResolvedValue([]);
mockPrisma.customer.count.mockResolvedValue(0);
await getCustomers('أحمد', 1, 10);
expect(mockPrisma.customer.findMany).toHaveBeenCalledWith({
where: {
OR: [
{ name: { contains: 'أحمد' } },
{ phone: { contains: 'أحمد' } },
{ email: { contains: 'أحمد' } },
{ address: { contains: 'أحمد' } },
],
},
include: expect.any(Object),
orderBy: { createdDate: 'desc' },
skip: 0,
take: 10,
});
});
});
describe('createCustomer', () => {
it('should create a new customer successfully', async () => {
const customerData = {
name: 'أحمد محمد',
phone: '0501234567',
email: 'ahmed@example.com',
address: 'الرياض',
};
const mockCustomer = {
id: 1,
...customerData,
createdDate: new Date(),
updateDate: new Date(),
};
mockPrisma.customer.findFirst.mockResolvedValue(null);
mockPrisma.customer.create.mockResolvedValue(mockCustomer);
const result = await createCustomer(customerData);
expect(result).toEqual({
success: true,
customer: mockCustomer,
});
expect(mockPrisma.customer.create).toHaveBeenCalledWith({
data: {
name: 'أحمد محمد',
phone: '0501234567',
email: 'ahmed@example.com',
address: 'الرياض',
},
});
});
it('should return error if phone already exists', async () => {
const customerData = {
name: 'أحمد محمد',
phone: '0501234567',
};
const existingCustomer = {
id: 2,
name: 'محمد أحمد',
phone: '0501234567',
email: null,
address: null,
createdDate: new Date(),
updateDate: new Date(),
};
mockPrisma.customer.findFirst.mockResolvedValue(existingCustomer);
const result = await createCustomer(customerData);
expect(result).toEqual({
success: false,
error: 'رقم الهاتف موجود بالفعل',
});
expect(mockPrisma.customer.create).not.toHaveBeenCalled();
});
it('should return error if email already exists', async () => {
const customerData = {
name: 'أحمد محمد',
email: 'ahmed@example.com',
};
const existingCustomer = {
id: 2,
name: 'محمد أحمد',
phone: null,
email: 'ahmed@example.com',
address: null,
createdDate: new Date(),
updateDate: new Date(),
};
mockPrisma.customer.findFirst.mockResolvedValue(existingCustomer);
const result = await createCustomer(customerData);
expect(result).toEqual({
success: false,
error: 'البريد الإلكتروني موجود بالفعل',
});
expect(mockPrisma.customer.create).not.toHaveBeenCalled();
});
});
describe('updateCustomer', () => {
it('should update customer successfully', async () => {
const customerId = 1;
const updateData = {
name: 'أحمد محمد المحدث',
phone: '0509876543',
};
const existingCustomer = {
id: customerId,
name: 'أحمد محمد',
phone: '0501234567',
email: null,
address: null,
createdDate: new Date(),
updateDate: new Date(),
};
const updatedCustomer = {
...existingCustomer,
...updateData,
updateDate: new Date(),
};
mockPrisma.customer.findUnique.mockResolvedValue(existingCustomer);
mockPrisma.customer.findFirst.mockResolvedValue(null);
mockPrisma.customer.update.mockResolvedValue(updatedCustomer);
const result = await updateCustomer(customerId, updateData);
expect(result).toEqual({
success: true,
customer: updatedCustomer,
});
expect(mockPrisma.customer.update).toHaveBeenCalledWith({
where: { id: customerId },
data: {
name: 'أحمد محمد المحدث',
phone: '0509876543',
},
});
});
it('should return error if customer not found', async () => {
const customerId = 999;
const updateData = { name: 'أحمد محمد' };
mockPrisma.customer.findUnique.mockResolvedValue(null);
const result = await updateCustomer(customerId, updateData);
expect(result).toEqual({
success: false,
error: 'العميل غير موجود',
});
expect(mockPrisma.customer.update).not.toHaveBeenCalled();
});
});
describe('deleteCustomer', () => {
it('should delete customer successfully when no relationships exist', async () => {
const customerId = 1;
const existingCustomer = {
id: customerId,
name: 'أحمد محمد',
phone: '0501234567',
email: null,
address: null,
createdDate: new Date(),
updateDate: new Date(),
vehicles: [],
maintenanceVisits: [],
};
mockPrisma.customer.findUnique.mockResolvedValue(existingCustomer);
mockPrisma.customer.delete.mockResolvedValue(existingCustomer);
const result = await deleteCustomer(customerId);
expect(result).toEqual({
success: true,
});
expect(mockPrisma.customer.delete).toHaveBeenCalledWith({
where: { id: customerId },
});
});
it('should return error if customer has vehicles', async () => {
const customerId = 1;
const existingCustomer = {
id: customerId,
name: 'أحمد محمد',
phone: '0501234567',
email: null,
address: null,
createdDate: new Date(),
updateDate: new Date(),
vehicles: [{ id: 1, plateNumber: 'ABC-123' }],
maintenanceVisits: [],
};
mockPrisma.customer.findUnique.mockResolvedValue(existingCustomer);
const result = await deleteCustomer(customerId);
expect(result).toEqual({
success: false,
error: 'لا يمكن حذف العميل لأنه يملك 1 مركبة. يرجى حذف المركبات أولاً',
});
expect(mockPrisma.customer.delete).not.toHaveBeenCalled();
});
it('should return error if customer has maintenance visits', async () => {
const customerId = 1;
const existingCustomer = {
id: customerId,
name: 'أحمد محمد',
phone: '0501234567',
email: null,
address: null,
createdDate: new Date(),
updateDate: new Date(),
vehicles: [],
maintenanceVisits: [{ id: 1, visitDate: new Date() }],
};
mockPrisma.customer.findUnique.mockResolvedValue(existingCustomer);
const result = await deleteCustomer(customerId);
expect(result).toEqual({
success: false,
error: 'لا يمكن حذف العميل لأنه لديه 1 زيارة صيانة. يرجى حذف الزيارات أولاً',
});
expect(mockPrisma.customer.delete).not.toHaveBeenCalled();
});
it('should return error if customer not found', async () => {
const customerId = 999;
mockPrisma.customer.findUnique.mockResolvedValue(null);
const result = await deleteCustomer(customerId);
expect(result).toEqual({
success: false,
error: 'العميل غير موجود',
});
expect(mockPrisma.customer.delete).not.toHaveBeenCalled();
});
});
describe('searchCustomers', () => {
it('should return empty array for short queries', async () => {
const result = await searchCustomers('a');
expect(result).toEqual([]);
expect(mockPrisma.customer.findMany).not.toHaveBeenCalled();
});
it('should search customers by name, phone, and email', async () => {
const mockCustomers = [
{
id: 1,
name: 'أحمد محمد',
phone: '0501234567',
email: 'ahmed@example.com',
},
];
mockPrisma.customer.findMany.mockResolvedValue(mockCustomers);
const result = await searchCustomers('أحمد', 10);
expect(result).toEqual(mockCustomers);
expect(mockPrisma.customer.findMany).toHaveBeenCalledWith({
where: {
OR: [
{ name: { contains: 'أحمد' } },
{ phone: { contains: 'أحمد' } },
{ email: { contains: 'أحمد' } },
],
},
select: {
id: true,
name: true,
phone: true,
email: true,
},
orderBy: { name: 'asc' },
take: 10,
});
});
});
describe('getCustomerStats', () => {
it('should return customer statistics', async () => {
const customerId = 1;
const mockCustomer = {
id: customerId,
name: 'أحمد محمد',
vehicles: [{ id: 1 }, { id: 2 }],
maintenanceVisits: [
{ cost: 100, visitDate: new Date('2024-01-15') },
{ cost: 200, visitDate: new Date('2024-01-10') },
{ cost: 150, visitDate: new Date('2024-01-05') },
],
};
mockPrisma.customer.findUnique.mockResolvedValue(mockCustomer);
const result = await getCustomerStats(customerId);
expect(result).toEqual({
totalVehicles: 2,
totalVisits: 3,
totalSpent: 450,
lastVisitDate: new Date('2024-01-15'),
});
});
it('should return null if customer not found', async () => {
const customerId = 999;
mockPrisma.customer.findUnique.mockResolvedValue(null);
const result = await getCustomerStats(customerId);
expect(result).toBeNull();
});
});
});