import { Test, TestingModule } from '@nestjs/testing'; import { ActivitiesController } from '../controllers/activities.controller'; import { ActivitiesService } from '../services/activities.service'; import { CreateActivityDto, UpdateActivityDto, CompleteActivityDto, ActivityListQueryDto } from '../dto'; import { ActivityType, ActivityStatus } from '../entities/activity.entity'; describe('ActivitiesController', () => { let controller: ActivitiesController; let activitiesService: jest.Mocked; const mockTenantId = '550e8400-e29b-41d4-a716-446655440001'; const mockUserId = '550e8400-e29b-41d4-a716-446655440002'; const mockActivityId = '550e8400-e29b-41d4-a716-446655440003'; const mockRequestUser = { id: mockUserId, email: 'test@example.com', tenant_id: mockTenantId, role: 'admin', }; const mockActivity = { id: mockActivityId, tenantId: mockTenantId, type: ActivityType.CALL, status: ActivityStatus.PENDING, subject: 'Follow up call', description: 'Discuss proposal', dueDate: new Date('2026-02-10'), assignedTo: mockUserId, createdAt: new Date('2026-01-01'), updatedAt: new Date('2026-01-01'), createdBy: mockUserId, }; const mockPaginatedActivities = { data: [mockActivity], total: 1, page: 1, limit: 20, totalPages: 1, }; beforeEach(async () => { const mockActivitiesService = { findAll: jest.fn(), findOne: jest.fn(), create: jest.fn(), update: jest.fn(), complete: jest.fn(), remove: jest.fn(), getUpcoming: jest.fn(), }; const module: TestingModule = await Test.createTestingModule({ controllers: [ActivitiesController], providers: [ { provide: ActivitiesService, useValue: mockActivitiesService, }, ], }).compile(); controller = module.get(ActivitiesController); activitiesService = module.get(ActivitiesService); }); afterEach(() => { jest.clearAllMocks(); }); describe('findAll', () => { it('should return paginated activities', async () => { const query: ActivityListQueryDto = { page: 1, limit: 20 }; activitiesService.findAll.mockResolvedValue(mockPaginatedActivities); const result = await controller.findAll(mockRequestUser, query); expect(activitiesService.findAll).toHaveBeenCalledWith(mockTenantId, query); expect(result).toEqual(mockPaginatedActivities); }); it('should filter by type', async () => { const query: ActivityListQueryDto = { page: 1, limit: 20, type: ActivityType.MEETING }; activitiesService.findAll.mockResolvedValue({ ...mockPaginatedActivities, data: [] }); await controller.findAll(mockRequestUser, query); expect(activitiesService.findAll).toHaveBeenCalledWith(mockTenantId, query); }); }); describe('getUpcoming', () => { it('should return upcoming activities', async () => { activitiesService.getUpcoming.mockResolvedValue([mockActivity]); const result = await controller.getUpcoming(mockRequestUser); expect(activitiesService.getUpcoming).toHaveBeenCalledWith(mockTenantId, mockUserId); expect(result).toEqual([mockActivity]); }); }); describe('findOne', () => { it('should return an activity by id', async () => { activitiesService.findOne.mockResolvedValue(mockActivity); const result = await controller.findOne(mockRequestUser, mockActivityId); expect(activitiesService.findOne).toHaveBeenCalledWith(mockTenantId, mockActivityId); expect(result).toEqual(mockActivity); }); }); describe('create', () => { it('should create a new activity', async () => { const createDto: CreateActivityDto = { type: ActivityType.CALL, subject: 'Initial call', dueDate: '2026-02-15', }; const createdActivity = { ...mockActivity, ...createDto, id: 'new-activity-id' }; activitiesService.create.mockResolvedValue(createdActivity); const result = await controller.create(mockRequestUser, createDto); expect(activitiesService.create).toHaveBeenCalledWith(mockTenantId, mockUserId, createDto); expect(result).toEqual(createdActivity); }); }); describe('update', () => { it('should update an activity', async () => { const updateDto: UpdateActivityDto = { subject: 'Updated call subject', status: ActivityStatus.COMPLETED, }; const updatedActivity = { ...mockActivity, ...updateDto }; activitiesService.update.mockResolvedValue(updatedActivity); const result = await controller.update(mockRequestUser, mockActivityId, updateDto); expect(activitiesService.update).toHaveBeenCalledWith(mockTenantId, mockActivityId, updateDto); expect(result.subject).toBe('Updated call subject'); }); }); describe('complete', () => { it('should complete an activity', async () => { const completeDto: CompleteActivityDto = { outcome: 'Discussed proposal details', }; const completedActivity = { ...mockActivity, status: ActivityStatus.COMPLETED, completedAt: new Date(), outcome: completeDto.outcome, }; activitiesService.complete.mockResolvedValue(completedActivity); const result = await controller.complete(mockRequestUser, mockActivityId, completeDto); expect(activitiesService.complete).toHaveBeenCalledWith(mockTenantId, mockActivityId, completeDto); expect(result.status).toBe(ActivityStatus.COMPLETED); }); }); describe('remove', () => { it('should delete an activity', async () => { activitiesService.remove.mockResolvedValue(undefined); const result = await controller.remove(mockRequestUser, mockActivityId); expect(activitiesService.remove).toHaveBeenCalledWith(mockTenantId, mockActivityId); expect(result).toEqual({ message: 'Activity deleted successfully' }); }); }); });