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(); }); }); });