import { Test, TestingModule } from '@nestjs/testing'; import { SalesDashboardController } from '../controllers/dashboard.controller'; import { SalesDashboardService } from '../services'; import { LeadStatus, LeadSource, OpportunityStage } from '../entities'; import { SalesDashboardDto, LeadsByStatusDto, LeadsBySourceDto, OpportunitiesByStageDto, ConversionFunnelDto, SalesPerformanceDto, } from '../dto'; 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 mockSummary: SalesDashboardDto = { totalLeads: 150, totalOpportunities: 45, totalPipelineValue: 1250000, wonDeals: 12, conversionRate: 26.7, averageDealSize: 104166.67, activitiesThisWeek: 35, currency: 'USD', }; const mockLeadsByStatus: LeadsByStatusDto[] = [ { status: LeadStatus.NEW, count: 50, percentage: 33.3 }, { status: LeadStatus.CONTACTED, count: 40, percentage: 26.7 }, { status: LeadStatus.QUALIFIED, count: 35, percentage: 23.3 }, { status: LeadStatus.CONVERTED, count: 25, percentage: 16.7 }, ]; const mockLeadsBySource: LeadsBySourceDto[] = [ { source: LeadSource.WEBSITE, count: 60, percentage: 40.0 }, { source: LeadSource.REFERRAL, count: 45, percentage: 30.0 }, { source: LeadSource.EVENT, count: 25, percentage: 16.7 }, { source: LeadSource.COLD_CALL, count: 20, percentage: 13.3 }, ]; const mockOpportunitiesByStage: OpportunitiesByStageDto[] = [ { stage: OpportunityStage.QUALIFICATION, count: 15, totalAmount: 375000, percentage: 33.3 }, { stage: OpportunityStage.PROPOSAL, count: 12, totalAmount: 480000, percentage: 26.7 }, { stage: OpportunityStage.NEGOTIATION, count: 10, totalAmount: 350000, percentage: 22.2 }, { stage: OpportunityStage.CLOSED_WON, count: 8, totalAmount: 320000, percentage: 17.8 }, ]; const mockConversionFunnel: ConversionFunnelDto[] = [ { stage: 'leads', count: 150, percentage: 100, conversionFromPrevious: 100 }, { stage: 'qualified', count: 75, percentage: 50, conversionFromPrevious: 50 }, { stage: 'opportunities', count: 45, percentage: 30, conversionFromPrevious: 60 }, { stage: 'proposals', count: 30, percentage: 20, conversionFromPrevious: 66.7 }, { stage: 'won', count: 12, percentage: 8, conversionFromPrevious: 40 }, ]; const mockSalesPerformance: SalesPerformanceDto[] = [ { userId: 'user-001', userName: 'John Doe', leadsAssigned: 45, opportunitiesWon: 5, totalRevenue: 125000, conversionRate: 11.1, activitiesCompleted: 120, }, { userId: 'user-002', userName: 'Jane Smith', leadsAssigned: 52, opportunitiesWon: 7, totalRevenue: 175000, conversionRate: 13.5, activitiesCompleted: 145, }, ]; 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(mockSummary); const result = await controller.getSummary(mockRequestUser); expect(dashboardService.getDashboardSummary).toHaveBeenCalledWith(mockTenantId); expect(result).toEqual(mockSummary); expect(result.totalLeads).toBe(150); expect(result.conversionRate).toBe(26.7); }); }); 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(4); }); }); 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.length).toBe(5); expect(result[0].stage).toBe('leads'); }); }); describe('getSalesPerformance', () => { it('should return sales performance data', 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); expect(result[0].totalRevenue).toBe(125000); }); }); });