yatra-x-user / __tests__ /auth.controller.test.js
imkrish's picture
Upload folder using huggingface_hub
5b9f147 verified
Raw History Blame Contribute Delete
9.5 kB
'use strict';
/**
* Auth Controller Unit Tests
* Tests for user authentication endpoints
*/
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
process.env.JWT_SECRET = 'test-secret-for-unit-tests';
// Mock dependencies before requiring the controller
const mockPool = {
query: jest.fn(),
connect: jest.fn(() => ({
query: jest.fn(),
release: jest.fn()
}))
};
jest.mock('../db', () => ({
getPool: jest.fn(() => mockPool)
}));
jest.mock('../services/google.service', () => ({
verifyToken: jest.fn()
}));
// Now require the controller
const authController = require('../controllers/auth.controller');
const { getPool } = require('../db');
describe('Auth Controller', () => {
let mockReq;
let mockRes;
let mockPool;
beforeEach(() => {
mockReq = {
body: {},
user: {},
headers: {}
};
mockRes = {
status: jest.fn().mockReturnThis(),
json: jest.fn().mockReturnThis()
};
mockPool = getPool();
jest.clearAllMocks();
});
describe('register', () => {
it('should return 400 if email already exists', async () => {
mockReq.body = {
email: 'existing@example.com',
password: 'Password123!',
name: 'Test User'
};
mockPool.query.mockResolvedValueOnce({ rows: [{ id: 'existing-id' }] });
await authController.register(mockReq, mockRes);
expect(mockRes.status).toHaveBeenCalledWith(400);
expect(mockRes.json).toHaveBeenCalledWith({ error: 'Email already registered' });
});
it('should successfully register a new user', async () => {
mockReq.body = {
email: 'newuser@example.com',
password: 'SecurePass123!',
name: 'New User'
};
// User doesn't exist
mockPool.query.mockResolvedValueOnce({ rows: [] });
// Insert user returns new user
const newUser = {
id: 'new-user-id',
email: 'newuser@example.com',
name: 'New User',
role: 'tourist'
};
mockPool.query.mockResolvedValueOnce({ rows: [newUser] });
await authController.register(mockReq, mockRes);
expect(mockRes.status).toHaveBeenCalledWith(201);
expect(mockRes.json).toHaveBeenCalledWith(
expect.objectContaining({
user: expect.objectContaining({
email: 'newuser@example.com'
}),
tokens: expect.objectContaining({
accessToken: expect.any(String),
refreshToken: expect.any(String)
})
})
);
});
it('should return 500 on database error', async () => {
mockReq.body = { email: 'test@test.com', password: 'pass', name: 'Test' };
mockPool.query.mockRejectedValueOnce(new Error('Database error'));
await authController.register(mockReq, mockRes);
expect(mockRes.status).toHaveBeenCalledWith(500);
});
});
describe('login', () => {
it('should return 401 for non-existent user', async () => {
mockReq.body = {
email: 'nonexistent@example.com',
password: 'password123'
};
mockPool.query.mockResolvedValueOnce({ rows: [] });
await authController.login(mockReq, mockRes);
expect(mockRes.status).toHaveBeenCalledWith(401);
expect(mockRes.json).toHaveBeenCalledWith({ error: 'Invalid credentials' });
});
it('should return 401 for invalid password', async () => {
mockReq.body = {
email: 'user@example.com',
password: 'wrongpassword'
};
// User exists with different password
const user = {
id: 'user-id',
email: 'user@example.com',
password_hash: await bcrypt.hash('correctpassword', 10),
is_active: true
};
mockPool.query.mockResolvedValueOnce({ rows: [user] });
await authController.login(mockReq, mockRes);
expect(mockRes.status).toHaveBeenCalledWith(401);
});
it('should successfully login with valid credentials', async () => {
const password = 'ValidPassword123!';
const hashedPassword = await bcrypt.hash(password, 10);
mockReq.body = {
email: 'user@example.com',
password: password
};
const user = {
id: 'user-id',
email: 'user@example.com',
password_hash: hashedPassword,
name: 'Test User',
role: 'tourist',
is_active: true
};
mockPool.query.mockResolvedValueOnce({ rows: [user] });
await authController.login(mockReq, mockRes);
expect(mockRes.json).toHaveBeenCalledWith(
expect.objectContaining({
user: expect.objectContaining({
email: 'user@example.com'
}),
tokens: expect.objectContaining({
accessToken: expect.any(String),
refreshToken: expect.any(String)
})
})
);
});
});
describe('currentUser', () => {
it('should return current user info', async () => {
mockReq.user = {
id: 'user-id',
email: 'user@example.com',
role: 'tourist'
};
const fullUser = {
id: 'user-id',
email: 'user@example.com',
name: 'Test User',
role: 'tourist'
};
mockPool.query.mockResolvedValueOnce({ rows: [fullUser] });
await authController.currentUser(mockReq, mockRes);
expect(mockRes.json).toHaveBeenCalledWith(
expect.objectContaining({
user: expect.objectContaining({
email: 'user@example.com'
})
})
);
});
it('should return 404 if user not found', async () => {
mockReq.user = { id: 'nonexistent-id' };
mockPool.query.mockResolvedValueOnce({ rows: [] });
await authController.currentUser(mockReq, mockRes);
expect(mockRes.status).toHaveBeenCalledWith(404);
});
});
describe('logout', () => {
it('should return success message', async () => {
await authController.logout(mockReq, mockRes);
expect(mockRes.json).toHaveBeenCalledWith({
success: true,
message: 'Logged out successfully'
});
});
});
describe('refresh', () => {
it('should return 401 for invalid refresh token', async () => {
mockReq.body = { refreshToken: 'invalid-token' };
await authController.refresh(mockReq, mockRes);
expect(mockRes.status).toHaveBeenCalledWith(401);
});
it('should return 401 for token without refresh type', async () => {
// Create a token without type: 'refresh'
const invalidToken = jwt.sign({ id: 'user-id' }, process.env.JWT_SECRET, { expiresIn: '1h' });
mockReq.body = { refreshToken: invalidToken };
await authController.refresh(mockReq, mockRes);
expect(mockRes.status).toHaveBeenCalledWith(401);
});
it('should refresh tokens successfully with valid refresh token', async () => {
// Create a valid refresh token
const validRefreshToken = jwt.sign(
{ id: 'user-id', type: 'refresh' },
process.env.JWT_SECRET,
{ expiresIn: '30d' }
);
mockReq.body = { refreshToken: validRefreshToken };
const user = { id: 'user-id', email: 'user@test.com', name: 'Test', role: 'tourist' };
mockPool.query.mockResolvedValueOnce({ rows: [user] });
await authController.refresh(mockReq, mockRes);
expect(mockRes.json).toHaveBeenCalledWith(
expect.objectContaining({
user: expect.objectContaining({ email: 'user@test.com' }),
tokens: expect.objectContaining({
accessToken: expect.any(String),
refreshToken: expect.any(String)
})
})
);
});
});
describe('changePassword', () => {
it('should return 400 if passwords missing', async () => {
mockReq.user = { id: 'user-id' };
mockReq.body = {};
await authController.changePassword(mockReq, mockRes);
expect(mockRes.status).toHaveBeenCalledWith(400);
});
it('should return 401 if current password is incorrect', async () => {
mockReq.user = { id: 'user-id' };
mockReq.body = {
currentPassword: 'wrongpassword',
newPassword: 'NewSecurePass123!'
};
const user = {
id: 'user-id',
password_hash: await bcrypt.hash('correctpassword', 10)
};
mockPool.query.mockResolvedValueOnce({ rows: [user] });
await authController.changePassword(mockReq, mockRes);
expect(mockRes.status).toHaveBeenCalledWith(401);
});
it('should successfully change password with correct current password', async () => {
const currentPassword = 'CurrentPass123!';
mockReq.user = { id: 'user-id' };
mockReq.body = {
currentPassword: currentPassword,
newPassword: 'NewSecurePass123!'
};
const user = {
id: 'user-id',
password_hash: await bcrypt.hash(currentPassword, 10)
};
mockPool.query.mockResolvedValueOnce({ rows: [user] });
mockPool.query.mockResolvedValueOnce({}); // UPDATE query
await authController.changePassword(mockReq, mockRes);
expect(mockRes.json).toHaveBeenCalledWith({
success: true,
message: 'Password changed successfully'
});
});
});
});