hospital-log/backend/api/src/modules/auth/auth.controller.spec.ts

207 lines
5.7 KiB
TypeScript
Raw Normal View History

2025-10-21 10:42:59 +00:00
import { Test, TestingModule } from '@nestjs/testing';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import { UserRole } from './dto/auth.dto';
2025-10-21 10:42:59 +00:00
describe('AuthController', () => {
let controller: AuthController;
let authService: jest.Mocked<AuthService>;
let configService: jest.Mocked<ConfigService>;
const mockAuthService = {
registerUser: jest.fn(),
signIn: jest.fn(),
};
const mockConfigService = {
get: jest.fn(),
};
const mockJwtService = {
signAsync: jest.fn(),
verifyAsync: jest.fn(),
};
2025-10-21 10:42:59 +00:00
beforeEach(async () => {
jest.clearAllMocks();
2025-10-21 10:42:59 +00:00
const module: TestingModule = await Test.createTestingModule({
controllers: [AuthController],
providers: [
{ provide: AuthService, useValue: mockAuthService },
{ provide: ConfigService, useValue: mockConfigService },
{ provide: JwtService, useValue: mockJwtService },
],
2025-10-21 10:42:59 +00:00
}).compile();
controller = module.get<AuthController>(AuthController);
authService = module.get(AuthService);
configService = module.get(ConfigService);
2025-10-21 10:42:59 +00:00
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
describe('registerUser', () => {
const createUserDto = {
nama_lengkap: 'Test User',
username: 'testuser',
password: 'password123',
role: UserRole.User,
};
const expectedResponse = {
id: BigInt(1),
nama_lengkap: 'Test User',
username: 'testuser',
role: UserRole.User,
};
it('should register a new user', async () => {
mockAuthService.registerUser.mockResolvedValue(expectedResponse);
const result = await controller.registerUser(createUserDto);
expect(result).toEqual(expectedResponse);
expect(mockAuthService.registerUser).toHaveBeenCalledWith(createUserDto);
expect(mockAuthService.registerUser).toHaveBeenCalledTimes(1);
});
it('should propagate service errors', async () => {
const error = new Error('Service error');
mockAuthService.registerUser.mockRejectedValue(error);
await expect(controller.registerUser(createUserDto)).rejects.toThrow(
'Service error',
);
});
});
describe('login', () => {
const loginDto = {
username: 'testuser',
password: 'password123',
};
const mockSignInResponse = {
accessToken: 'jwt-token',
csrfToken: 'csrf-token',
user: {
id: BigInt(1),
username: 'testuser',
role: 'user',
},
};
it('should login user and set cookie in development mode', async () => {
mockAuthService.signIn.mockResolvedValue(mockSignInResponse);
mockConfigService.get.mockImplementation((key: string) => {
if (key === 'NODE_ENV') return 'development';
if (key === 'COOKIE_MAX_AGE') return '3600000';
return undefined;
});
const mockResponse = {
cookie: jest.fn(),
};
const result = await controller.login(loginDto, mockResponse as any);
expect(result).toEqual({
user: mockSignInResponse.user,
csrfToken: mockSignInResponse.csrfToken,
});
expect(mockResponse.cookie).toHaveBeenCalledWith(
'access_token',
'jwt-token',
{
httpOnly: true,
secure: false, // development mode
sameSite: 'strict',
maxAge: 3600000,
},
);
});
it('should login user and set secure cookie in production mode', async () => {
mockAuthService.signIn.mockResolvedValue(mockSignInResponse);
mockConfigService.get.mockImplementation((key: string) => {
if (key === 'NODE_ENV') return 'production';
if (key === 'COOKIE_MAX_AGE') return '3600000';
return undefined;
});
const mockResponse = {
cookie: jest.fn(),
};
await controller.login(loginDto, mockResponse as any);
expect(mockResponse.cookie).toHaveBeenCalledWith(
'access_token',
'jwt-token',
{
httpOnly: true,
secure: true, // production mode
sameSite: 'strict',
maxAge: 3600000,
},
);
});
it('should propagate authentication errors', async () => {
mockAuthService.signIn.mockRejectedValue(
new Error('Invalid credentials'),
);
const mockResponse = {
cookie: jest.fn(),
};
await expect(
controller.login(loginDto, mockResponse as any),
).rejects.toThrow('Invalid credentials');
expect(mockResponse.cookie).not.toHaveBeenCalled();
});
});
describe('logout', () => {
it('should clear access_token cookie in development mode', () => {
mockConfigService.get.mockReturnValue('development');
const mockResponse = {
clearCookie: jest.fn(),
};
const result = controller.logout(mockResponse as any);
expect(result).toEqual({ message: 'Logout berhasil' });
expect(mockResponse.clearCookie).toHaveBeenCalledWith('access_token', {
httpOnly: true,
secure: false,
sameSite: 'strict',
});
});
it('should clear access_token cookie with secure flag in production mode', () => {
mockConfigService.get.mockReturnValue('production');
const mockResponse = {
clearCookie: jest.fn(),
};
const result = controller.logout(mockResponse as any);
expect(result).toEqual({ message: 'Logout berhasil' });
expect(mockResponse.clearCookie).toHaveBeenCalledWith('access_token', {
httpOnly: true,
secure: true,
sameSite: 'strict',
});
});
});
2025-10-21 10:42:59 +00:00
});