updating unit and integration tests
This commit is contained in:
@@ -45,10 +45,15 @@ jest.mock('../../../middleware/rateLimiter', () => ({
|
||||
loginLimiter: (req, res, next) => next(),
|
||||
registerLimiter: (req, res, next) => next(),
|
||||
passwordResetLimiter: (req, res, next) => next(),
|
||||
emailVerificationLimiter: (req, res, next) => next(),
|
||||
}));
|
||||
|
||||
jest.mock('../../../middleware/auth', () => ({
|
||||
optionalAuth: (req, res, next) => next(),
|
||||
authenticateToken: (req, res, next) => {
|
||||
req.user = { id: 'user-123' };
|
||||
next();
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../../services/email', () => ({
|
||||
@@ -290,7 +295,7 @@ describe('Auth Routes', () => {
|
||||
});
|
||||
|
||||
expect(response.status).toBe(401);
|
||||
expect(response.body.error).toBe('Invalid credentials');
|
||||
expect(response.body.error).toBe('Unable to log in. Please check your email and password, or create an account.');
|
||||
});
|
||||
|
||||
it('should reject login with invalid password', async () => {
|
||||
@@ -311,7 +316,7 @@ describe('Auth Routes', () => {
|
||||
});
|
||||
|
||||
expect(response.status).toBe(401);
|
||||
expect(response.body.error).toBe('Invalid credentials');
|
||||
expect(response.body.error).toBe('Unable to log in. Please check your email and password, or create an account.');
|
||||
expect(mockUser.incLoginAttempts).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -536,95 +541,147 @@ describe('Auth Routes', () => {
|
||||
});
|
||||
|
||||
describe('POST /auth/verify-email', () => {
|
||||
it('should verify email with valid token', async () => {
|
||||
it('should verify email with valid 6-digit code', async () => {
|
||||
const mockUser = {
|
||||
id: 1,
|
||||
id: 'user-123',
|
||||
email: 'test@example.com',
|
||||
isVerified: false,
|
||||
verificationToken: 'valid-token',
|
||||
verificationToken: '123456',
|
||||
verificationTokenExpiry: new Date(Date.now() + 3600000), // 1 hour from now
|
||||
verificationAttempts: 0,
|
||||
isVerificationLocked: jest.fn().mockReturnValue(false),
|
||||
isVerificationTokenValid: jest.fn().mockReturnValue(true),
|
||||
verifyEmail: jest.fn().mockResolvedValue()
|
||||
};
|
||||
|
||||
User.findOne.mockResolvedValue(mockUser);
|
||||
User.findByPk.mockResolvedValue(mockUser);
|
||||
|
||||
const response = await request(app)
|
||||
.post('/auth/verify-email')
|
||||
.send({ token: 'valid-token' });
|
||||
.send({ code: '123456' });
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.message).toBe('Email verified successfully');
|
||||
expect(response.body.user).toMatchObject({
|
||||
id: 1,
|
||||
id: 'user-123',
|
||||
email: 'test@example.com',
|
||||
isVerified: true
|
||||
});
|
||||
expect(mockUser.verifyEmail).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should reject missing token', async () => {
|
||||
it('should reject missing code', async () => {
|
||||
const response = await request(app)
|
||||
.post('/auth/verify-email')
|
||||
.send({});
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.error).toBe('Verification token required');
|
||||
expect(response.body.code).toBe('TOKEN_REQUIRED');
|
||||
expect(response.body.error).toBe('Verification code required');
|
||||
expect(response.body.code).toBe('CODE_REQUIRED');
|
||||
});
|
||||
|
||||
it('should reject invalid token', async () => {
|
||||
User.findOne.mockResolvedValue(null);
|
||||
it('should reject invalid code format (not 6 digits)', async () => {
|
||||
const response = await request(app)
|
||||
.post('/auth/verify-email')
|
||||
.send({ code: '12345' }); // Only 5 digits
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.error).toBe('Verification code must be 6 digits');
|
||||
expect(response.body.code).toBe('INVALID_CODE_FORMAT');
|
||||
});
|
||||
|
||||
it('should reject when user not found', async () => {
|
||||
User.findByPk.mockResolvedValue(null);
|
||||
|
||||
const response = await request(app)
|
||||
.post('/auth/verify-email')
|
||||
.send({ token: 'invalid-token' });
|
||||
.send({ code: '123456' });
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.error).toBe('Invalid verification token');
|
||||
expect(response.body.code).toBe('VERIFICATION_TOKEN_INVALID');
|
||||
expect(response.status).toBe(404);
|
||||
expect(response.body.error).toBe('User not found');
|
||||
expect(response.body.code).toBe('USER_NOT_FOUND');
|
||||
});
|
||||
|
||||
it('should reject already verified user', async () => {
|
||||
const mockUser = {
|
||||
id: 1,
|
||||
id: 'user-123',
|
||||
isVerified: true
|
||||
};
|
||||
|
||||
User.findOne.mockResolvedValue(mockUser);
|
||||
User.findByPk.mockResolvedValue(mockUser);
|
||||
|
||||
const response = await request(app)
|
||||
.post('/auth/verify-email')
|
||||
.send({ token: 'some-token' });
|
||||
.send({ code: '123456' });
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.error).toBe('Email already verified');
|
||||
expect(response.body.code).toBe('ALREADY_VERIFIED');
|
||||
});
|
||||
|
||||
it('should reject expired token', async () => {
|
||||
it('should reject when too many verification attempts', async () => {
|
||||
const mockUser = {
|
||||
id: 1,
|
||||
id: 'user-123',
|
||||
isVerified: false,
|
||||
isVerificationTokenValid: jest.fn().mockReturnValue(false)
|
||||
isVerificationLocked: jest.fn().mockReturnValue(true)
|
||||
};
|
||||
|
||||
User.findOne.mockResolvedValue(mockUser);
|
||||
User.findByPk.mockResolvedValue(mockUser);
|
||||
|
||||
const response = await request(app)
|
||||
.post('/auth/verify-email')
|
||||
.send({ token: 'expired-token' });
|
||||
.send({ code: '123456' });
|
||||
|
||||
expect(response.status).toBe(429);
|
||||
expect(response.body.error).toContain('Too many verification attempts');
|
||||
expect(response.body.code).toBe('TOO_MANY_ATTEMPTS');
|
||||
});
|
||||
|
||||
it('should reject when no verification code exists', async () => {
|
||||
const mockUser = {
|
||||
id: 'user-123',
|
||||
isVerified: false,
|
||||
verificationToken: null,
|
||||
isVerificationLocked: jest.fn().mockReturnValue(false)
|
||||
};
|
||||
|
||||
User.findByPk.mockResolvedValue(mockUser);
|
||||
|
||||
const response = await request(app)
|
||||
.post('/auth/verify-email')
|
||||
.send({ code: '123456' });
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.error).toContain('No verification code found');
|
||||
expect(response.body.code).toBe('NO_CODE');
|
||||
});
|
||||
|
||||
it('should reject expired verification code', async () => {
|
||||
const mockUser = {
|
||||
id: 'user-123',
|
||||
isVerified: false,
|
||||
verificationToken: '123456',
|
||||
verificationTokenExpiry: new Date(Date.now() - 3600000), // 1 hour ago (expired)
|
||||
isVerificationLocked: jest.fn().mockReturnValue(false)
|
||||
};
|
||||
|
||||
User.findByPk.mockResolvedValue(mockUser);
|
||||
|
||||
const response = await request(app)
|
||||
.post('/auth/verify-email')
|
||||
.send({ code: '123456' });
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.error).toContain('expired');
|
||||
expect(response.body.code).toBe('VERIFICATION_TOKEN_EXPIRED');
|
||||
expect(response.body.code).toBe('VERIFICATION_EXPIRED');
|
||||
});
|
||||
|
||||
it('should handle verification errors', async () => {
|
||||
User.findOne.mockRejectedValue(new Error('Database error'));
|
||||
User.findByPk.mockRejectedValue(new Error('Database error'));
|
||||
|
||||
const response = await request(app)
|
||||
.post('/auth/verify-email')
|
||||
.send({ token: 'some-token' });
|
||||
.send({ code: '123456' });
|
||||
|
||||
expect(response.status).toBe(500);
|
||||
expect(response.body.error).toBe('Email verification failed. Please try again.');
|
||||
@@ -835,6 +892,48 @@ describe('Auth Routes', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /auth/status', () => {
|
||||
it('should return authenticated true when user is logged in', async () => {
|
||||
// The optionalAuth middleware sets req.user if authenticated
|
||||
// We need to modify the mock for this specific test
|
||||
const mockUser = {
|
||||
id: 1,
|
||||
email: 'test@example.com',
|
||||
firstName: 'Test',
|
||||
lastName: 'User',
|
||||
isVerified: true
|
||||
};
|
||||
|
||||
// Create a custom app for this test with user set
|
||||
const statusApp = express();
|
||||
statusApp.use(express.json());
|
||||
statusApp.use((req, res, next) => {
|
||||
req.user = mockUser;
|
||||
next();
|
||||
});
|
||||
statusApp.use('/auth', authRoutes);
|
||||
|
||||
const response = await request(statusApp)
|
||||
.get('/auth/status');
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.authenticated).toBe(true);
|
||||
expect(response.body.user).toMatchObject({
|
||||
id: 1,
|
||||
email: 'test@example.com'
|
||||
});
|
||||
});
|
||||
|
||||
it('should return authenticated false when user is not logged in', async () => {
|
||||
const response = await request(app)
|
||||
.get('/auth/status');
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.authenticated).toBe(false);
|
||||
expect(response.body.user).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /auth/forgot-password', () => {
|
||||
it('should send password reset email for existing user', async () => {
|
||||
const mockUser = {
|
||||
|
||||
Reference in New Issue
Block a user