import { Test, TestingModule } from '@nestjs/testing'; import { SalesDashboardController } from '../controllers/dashboard.controller'; import { SalesDashboardService } from '../services/sales-dashboard.service'; import { LeadStatus, LeadSource } from '../entities/lead.entity'; import { OpportunityStage } from '../entities/opportunity.entity'; describe('SalesDashboardController', () => { let controller: SalesDashboardController; let dashboardService: jest.Mocked; const mockTenantId = '550e8400-e29b-41d4-a716-446655440001'; const mockUserId = '550e8400-e29b-41d4-a716-446655440002'; const mockRequestUser = { id: mockUserId, email: 'test@example.com', tenant_id: mockTenantId, role: 'admin', }; const mockDashboardSummary = { totalLeads: 150, newLeadsThisMonth: 25, qualifiedLeads: 45, convertedLeads: 30, totalOpportunities: 80, openOpportunities: 50, wonOpportunities: 25, lostOpportunities: 5, totalPipelineValue: 500000, wonValue: 150000, averageDealSize: 6000, winRate: 83.33, }; const mockLeadsByStatus = [ { status: LeadStatus.NEW, count: 50 }, { status: LeadStatus.CONTACTED, count: 35 }, { status: LeadStatus.QUALIFIED, count: 45 }, { status: LeadStatus.CONVERTED, count: 20 }, ]; const mockLeadsBySource = [ { source: LeadSource.WEBSITE, count: 60 }, { source: LeadSource.REFERRAL, count: 40 }, { source: LeadSource.SOCIAL_MEDIA, count: 25 }, { source: LeadSource.EVENT, count: 25 }, ]; const mockOpportunitiesByStage = [ { stage: OpportunityStage.PROSPECTING, count: 15, value: 75000 }, { stage: OpportunityStage.QUALIFICATION, count: 12, value: 60000 }, { stage: OpportunityStage.PROPOSAL, count: 10, value: 100000 }, { stage: OpportunityStage.NEGOTIATION, count: 8, value: 120000 }, { stage: OpportunityStage.CLOSED_WON, count: 25, value: 150000 }, ]; const mockConversionFunnel = [ { stage: 'Lead Created', count: 150, percentage: 100 }, { stage: 'Qualified', count: 45, percentage: 30 }, { stage: 'Opportunity Created', count: 35, percentage: 23 }, { stage: 'Proposal Sent', count: 25, percentage: 17 }, { stage: 'Won', count: 20, percentage: 13 }, ]; const mockSalesPerformance = [ { userId: mockUserId, name: 'John Doe', leadsConverted: 10, opportunitiesWon: 5, totalValue: 50000 }, { userId: 'user-2', name: 'Jane Smith', leadsConverted: 8, opportunitiesWon: 4, totalValue: 40000 }, ]; beforeEach(async () => { const mockDashboardService = { getDashboardSummary: jest.fn(), getLeadsByStatus: jest.fn(), getLeadsBySource: jest.fn(), getOpportunitiesByStage: jest.fn(), getConversionFunnel: jest.fn(), getSalesPerformance: jest.fn(), }; const module: TestingModule = await Test.createTestingModule({ controllers: [SalesDashboardController], providers: [ { provide: SalesDashboardService, useValue: mockDashboardService, }, ], }).compile(); controller = module.get(SalesDashboardController); dashboardService = module.get(SalesDashboardService); }); afterEach(() => { jest.clearAllMocks(); }); describe('getSummary', () => { it('should return dashboard summary', async () => { dashboardService.getDashboardSummary.mockResolvedValue(mockDashboardSummary); const result = await controller.getSummary(mockRequestUser); expect(dashboardService.getDashboardSummary).toHaveBeenCalledWith(mockTenantId); expect(result).toEqual(mockDashboardSummary); expect(result.totalLeads).toBe(150); expect(result.winRate).toBe(83.33); }); }); describe('getLeadsByStatus', () => { it('should return leads grouped by status', async () => { dashboardService.getLeadsByStatus.mockResolvedValue(mockLeadsByStatus); const result = await controller.getLeadsByStatus(mockRequestUser); expect(dashboardService.getLeadsByStatus).toHaveBeenCalledWith(mockTenantId); expect(result).toEqual(mockLeadsByStatus); expect(result.length).toBe(4); }); }); describe('getLeadsBySource', () => { it('should return leads grouped by source', async () => { dashboardService.getLeadsBySource.mockResolvedValue(mockLeadsBySource); const result = await controller.getLeadsBySource(mockRequestUser); expect(dashboardService.getLeadsBySource).toHaveBeenCalledWith(mockTenantId); expect(result).toEqual(mockLeadsBySource); expect(result.length).toBe(4); }); }); describe('getOpportunitiesByStage', () => { it('should return opportunities grouped by stage', async () => { dashboardService.getOpportunitiesByStage.mockResolvedValue(mockOpportunitiesByStage); const result = await controller.getOpportunitiesByStage(mockRequestUser); expect(dashboardService.getOpportunitiesByStage).toHaveBeenCalledWith(mockTenantId); expect(result).toEqual(mockOpportunitiesByStage); expect(result.length).toBe(5); }); }); describe('getConversionFunnel', () => { it('should return conversion funnel data', async () => { dashboardService.getConversionFunnel.mockResolvedValue(mockConversionFunnel); const result = await controller.getConversionFunnel(mockRequestUser); expect(dashboardService.getConversionFunnel).toHaveBeenCalledWith(mockTenantId); expect(result).toEqual(mockConversionFunnel); expect(result[0].percentage).toBe(100); }); }); describe('getSalesPerformance', () => { it('should return sales performance by user', async () => { dashboardService.getSalesPerformance.mockResolvedValue(mockSalesPerformance); const result = await controller.getSalesPerformance(mockRequestUser); expect(dashboardService.getSalesPerformance).toHaveBeenCalledWith(mockTenantId); expect(result).toEqual(mockSalesPerformance); expect(result.length).toBe(2); }); }); });