- Add 12 controller test files (117 tests total): - sales: leads, opportunities, activities, pipeline, dashboard - commissions: schemes, assignments, entries, periods, dashboard - portfolio: categories, products - Fix flaky test in assignments.service.spec.ts (timestamp issue) - All 441 tests passing for these modules Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
172 lines
5.9 KiB
TypeScript
172 lines
5.9 KiB
TypeScript
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<SalesDashboardService>;
|
|
|
|
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>(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);
|
|
});
|
|
});
|
|
});
|