test: add unit tests for users module
Added comprehensive unit tests for `UsersController` and `UsersService`, covering CRUD operations, GDPR consent updates, data export, and exception handling. Mocked `JwtAuthGuard` and database operations for all tests.
This commit is contained in:
parent
269ba622f8
commit
576d063e52
127
backend/src/modules/users/controllers/users.controller.spec.ts
Normal file
127
backend/src/modules/users/controllers/users.controller.spec.ts
Normal file
@ -0,0 +1,127 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { UsersController } from './users.controller';
|
||||
import { UsersService } from '../services/users.service';
|
||||
import { CreateUserDto } from '../dto/create-user.dto';
|
||||
import { UpdateUserDto } from '../dto/update-user.dto';
|
||||
import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard';
|
||||
|
||||
describe('UsersController', () => {
|
||||
let controller: UsersController;
|
||||
let service: UsersService;
|
||||
|
||||
// Mock data
|
||||
const mockUser = {
|
||||
id: 'user1',
|
||||
name: 'Test User',
|
||||
avatar: 'https://example.com/avatar.jpg',
|
||||
githubId: '12345',
|
||||
metadata: {},
|
||||
gdprTimestamp: new Date(),
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
const mockUserData = {
|
||||
user: mockUser,
|
||||
projects: [
|
||||
{
|
||||
id: 'project1',
|
||||
name: 'Test Project',
|
||||
ownerId: 'user1',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [UsersController],
|
||||
providers: [
|
||||
{
|
||||
provide: UsersService,
|
||||
useValue: {
|
||||
create: jest.fn().mockResolvedValue(mockUser),
|
||||
findAll: jest.fn().mockResolvedValue([mockUser]),
|
||||
findById: jest.fn().mockResolvedValue(mockUser),
|
||||
update: jest.fn().mockResolvedValue(mockUser),
|
||||
remove: jest.fn().mockResolvedValue(mockUser),
|
||||
updateGdprConsent: jest.fn().mockResolvedValue(mockUser),
|
||||
exportUserData: jest.fn().mockResolvedValue(mockUserData),
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.overrideGuard(JwtAuthGuard)
|
||||
.useValue({ canActivate: () => true })
|
||||
.compile();
|
||||
|
||||
controller = module.get<UsersController>(UsersController);
|
||||
service = module.get<UsersService>(UsersService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
|
||||
describe('create', () => {
|
||||
it('should create a new user', async () => {
|
||||
const createUserDto: CreateUserDto = {
|
||||
name: 'Test User',
|
||||
githubId: '12345',
|
||||
};
|
||||
|
||||
expect(await controller.create(createUserDto)).toBe(mockUser);
|
||||
expect(service.create).toHaveBeenCalledWith(createUserDto);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findAll', () => {
|
||||
it('should return all users', async () => {
|
||||
expect(await controller.findAll()).toEqual([mockUser]);
|
||||
expect(service.findAll).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('findOne', () => {
|
||||
it('should return a user by ID', async () => {
|
||||
const id = 'user1';
|
||||
expect(await controller.findOne(id)).toBe(mockUser);
|
||||
expect(service.findById).toHaveBeenCalledWith(id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', () => {
|
||||
it('should update a user', async () => {
|
||||
const id = 'user1';
|
||||
const updateUserDto: UpdateUserDto = {
|
||||
name: 'Updated User',
|
||||
};
|
||||
|
||||
expect(await controller.update(id, updateUserDto)).toBe(mockUser);
|
||||
expect(service.update).toHaveBeenCalledWith(id, updateUserDto);
|
||||
});
|
||||
});
|
||||
|
||||
describe('remove', () => {
|
||||
it('should delete a user', async () => {
|
||||
const id = 'user1';
|
||||
expect(await controller.remove(id)).toBe(mockUser);
|
||||
expect(service.remove).toHaveBeenCalledWith(id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateGdprConsent', () => {
|
||||
it('should update GDPR consent timestamp', async () => {
|
||||
const id = 'user1';
|
||||
expect(await controller.updateGdprConsent(id)).toBe(mockUser);
|
||||
expect(service.updateGdprConsent).toHaveBeenCalledWith(id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('exportUserData', () => {
|
||||
it('should export user data', async () => {
|
||||
const id = 'user1';
|
||||
expect(await controller.exportUserData(id)).toBe(mockUserData);
|
||||
expect(service.exportUserData).toHaveBeenCalledWith(id);
|
||||
});
|
||||
});
|
||||
});
|
250
backend/src/modules/users/services/users.service.spec.ts
Normal file
250
backend/src/modules/users/services/users.service.spec.ts
Normal file
@ -0,0 +1,250 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { UsersService } from './users.service';
|
||||
import { NotFoundException } from '@nestjs/common';
|
||||
import { DRIZZLE } from '../../../database/database.module';
|
||||
|
||||
describe('UsersService', () => {
|
||||
let service: UsersService;
|
||||
let mockDb: any;
|
||||
|
||||
// Mock data
|
||||
const mockUser = {
|
||||
id: 'user1',
|
||||
name: 'Test User',
|
||||
avatar: 'https://example.com/avatar.jpg',
|
||||
githubId: '12345',
|
||||
metadata: {},
|
||||
gdprTimestamp: new Date(),
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
const mockProject = {
|
||||
id: 'project1',
|
||||
name: 'Test Project',
|
||||
ownerId: 'user1',
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
// Mock database operations
|
||||
const mockDbOperations = {
|
||||
select: jest.fn().mockReturnThis(),
|
||||
from: jest.fn().mockReturnThis(),
|
||||
where: jest.fn().mockReturnThis(),
|
||||
insert: jest.fn().mockReturnThis(),
|
||||
values: jest.fn().mockReturnThis(),
|
||||
update: jest.fn().mockReturnThis(),
|
||||
set: jest.fn().mockReturnThis(),
|
||||
delete: jest.fn().mockReturnThis(),
|
||||
returning: jest.fn().mockImplementation(() => {
|
||||
return [mockUser];
|
||||
}),
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
mockDb = {
|
||||
...mockDbOperations,
|
||||
};
|
||||
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
UsersService,
|
||||
{
|
||||
provide: DRIZZLE,
|
||||
useValue: mockDb,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get<UsersService>(UsersService);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
|
||||
describe('create', () => {
|
||||
it('should create a new user', async () => {
|
||||
const createUserDto = {
|
||||
name: 'Test User',
|
||||
githubId: '12345',
|
||||
};
|
||||
|
||||
const result = await service.create(createUserDto);
|
||||
|
||||
expect(mockDb.insert).toHaveBeenCalled();
|
||||
expect(mockDb.values).toHaveBeenCalledWith({
|
||||
...createUserDto,
|
||||
gdprTimestamp: expect.any(Date),
|
||||
});
|
||||
expect(result).toEqual(mockUser);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findAll', () => {
|
||||
it('should return all users', async () => {
|
||||
mockDb.select.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.from.mockImplementationOnce(() => [mockUser]);
|
||||
|
||||
const result = await service.findAll();
|
||||
|
||||
expect(mockDb.select).toHaveBeenCalled();
|
||||
expect(mockDb.from).toHaveBeenCalled();
|
||||
expect(result).toEqual([mockUser]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findById', () => {
|
||||
it('should return a user by ID', async () => {
|
||||
const id = 'user1';
|
||||
mockDb.select.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.from.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.where.mockImplementationOnce(() => [mockUser]);
|
||||
|
||||
const result = await service.findById(id);
|
||||
|
||||
expect(mockDb.select).toHaveBeenCalled();
|
||||
expect(mockDb.from).toHaveBeenCalled();
|
||||
expect(mockDb.where).toHaveBeenCalled();
|
||||
expect(result).toEqual(mockUser);
|
||||
});
|
||||
|
||||
it('should throw NotFoundException if user not found', async () => {
|
||||
const id = 'nonexistent';
|
||||
mockDb.select.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.from.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.where.mockImplementationOnce(() => []);
|
||||
|
||||
await expect(service.findById(id)).rejects.toThrow(NotFoundException);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findByGithubId', () => {
|
||||
it('should return a user by GitHub ID', async () => {
|
||||
const githubId = '12345';
|
||||
mockDb.select.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.from.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.where.mockImplementationOnce(() => [mockUser]);
|
||||
|
||||
const result = await service.findByGithubId(githubId);
|
||||
|
||||
expect(mockDb.select).toHaveBeenCalled();
|
||||
expect(mockDb.from).toHaveBeenCalled();
|
||||
expect(mockDb.where).toHaveBeenCalled();
|
||||
expect(result).toEqual(mockUser);
|
||||
});
|
||||
|
||||
it('should return undefined if user not found', async () => {
|
||||
const githubId = 'nonexistent';
|
||||
mockDb.select.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.from.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.where.mockImplementationOnce(() => []);
|
||||
|
||||
const result = await service.findByGithubId(githubId);
|
||||
|
||||
expect(mockDb.select).toHaveBeenCalled();
|
||||
expect(mockDb.from).toHaveBeenCalled();
|
||||
expect(mockDb.where).toHaveBeenCalled();
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', () => {
|
||||
it('should update a user', async () => {
|
||||
const id = 'user1';
|
||||
const updateUserDto = {
|
||||
name: 'Updated User',
|
||||
};
|
||||
|
||||
const result = await service.update(id, updateUserDto);
|
||||
|
||||
expect(mockDb.update).toHaveBeenCalled();
|
||||
expect(mockDb.set).toHaveBeenCalledWith({
|
||||
...updateUserDto,
|
||||
updatedAt: expect.any(Date),
|
||||
});
|
||||
expect(mockDb.where).toHaveBeenCalled();
|
||||
expect(result).toEqual(mockUser);
|
||||
});
|
||||
|
||||
it('should throw NotFoundException if user not found', async () => {
|
||||
const id = 'nonexistent';
|
||||
const updateUserDto = {
|
||||
name: 'Updated User',
|
||||
};
|
||||
|
||||
mockDb.update.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.set.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.where.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.returning.mockImplementationOnce(() => []);
|
||||
|
||||
await expect(service.update(id, updateUserDto)).rejects.toThrow(NotFoundException);
|
||||
});
|
||||
});
|
||||
|
||||
describe('remove', () => {
|
||||
it('should delete a user', async () => {
|
||||
const id = 'user1';
|
||||
|
||||
const result = await service.remove(id);
|
||||
|
||||
expect(mockDb.delete).toHaveBeenCalled();
|
||||
expect(mockDb.where).toHaveBeenCalled();
|
||||
expect(result).toEqual(mockUser);
|
||||
});
|
||||
|
||||
it('should throw NotFoundException if user not found', async () => {
|
||||
const id = 'nonexistent';
|
||||
|
||||
mockDb.delete.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.where.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.returning.mockImplementationOnce(() => []);
|
||||
|
||||
await expect(service.remove(id)).rejects.toThrow(NotFoundException);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateGdprConsent', () => {
|
||||
it('should update GDPR consent timestamp', async () => {
|
||||
const id = 'user1';
|
||||
|
||||
// Mock the update method
|
||||
jest.spyOn(service, 'update').mockResolvedValueOnce(mockUser);
|
||||
|
||||
const result = await service.updateGdprConsent(id);
|
||||
|
||||
expect(service.update).toHaveBeenCalledWith(id, { gdprTimestamp: expect.any(Date) });
|
||||
expect(result).toEqual(mockUser);
|
||||
});
|
||||
});
|
||||
|
||||
describe('exportUserData', () => {
|
||||
it('should export user data', async () => {
|
||||
const id = 'user1';
|
||||
|
||||
// Mock the findById method
|
||||
jest.spyOn(service, 'findById').mockResolvedValueOnce(mockUser);
|
||||
|
||||
// Mock the database query for projects
|
||||
mockDb.select.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.from.mockImplementationOnce(() => mockDbOperations);
|
||||
mockDbOperations.where.mockImplementationOnce(() => [mockProject]);
|
||||
|
||||
const result = await service.exportUserData(id);
|
||||
|
||||
expect(service.findById).toHaveBeenCalledWith(id);
|
||||
expect(mockDb.select).toHaveBeenCalled();
|
||||
expect(mockDb.from).toHaveBeenCalled();
|
||||
expect(mockDb.where).toHaveBeenCalled();
|
||||
expect(result).toEqual({
|
||||
user: mockUser,
|
||||
projects: [mockProject],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user