template-saas-backend-v2/src/modules/sales/__tests__/activities.controller.spec.ts
Adrian Flores Cortes 61d7d29212 test(P2): Add controller tests for sales, commissions, and portfolio
- 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>
2026-02-03 13:25:42 -06:00

180 lines
5.9 KiB
TypeScript

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