import request from 'supertest'; import app from '../../../src/app'; import { setupTestDb, teardownTestDb, resetDatabase } from '../../utils/testDb'; import { createUser } from '../../utils/factories'; import { generateTokens } from '../../utils/auth'; describe('Auth Routes Integration Tests', () => { beforeAll(async () => { await setupTestDb(); }); afterAll(async () => { await teardownTestDb(); }); beforeEach(async () => { await resetDatabase(); }); describe('POST /api/v1/auth/register', () => { const validRegisterData = { email: 'test@example.com', password: 'Password123!', firstName: 'Test', lastName: 'User', phone: '+1234567890', playerLevel: 'BEGINNER', handPreference: 'RIGHT', positionPreference: 'BOTH', }; it('should register a new user successfully', async () => { // Act const response = await request(app) .post('/api/v1/auth/register') .send(validRegisterData); // Assert expect(response.status).toBe(201); expect(response.body).toHaveProperty('success', true); expect(response.body.data).toHaveProperty('user'); expect(response.body.data).toHaveProperty('accessToken'); expect(response.body.data).toHaveProperty('refreshToken'); expect(response.body.data.user).toHaveProperty('email', validRegisterData.email); expect(response.body.data.user).toHaveProperty('firstName', validRegisterData.firstName); expect(response.body.data.user).not.toHaveProperty('password'); }); it('should return 409 when email already exists', async () => { // Arrange await createUser({ email: validRegisterData.email }); // Act const response = await request(app) .post('/api/v1/auth/register') .send(validRegisterData); // Assert expect(response.status).toBe(409); expect(response.body).toHaveProperty('success', false); expect(response.body).toHaveProperty('message', 'El email ya está registrado'); }); it('should return 400 when email is invalid', async () => { // Act const response = await request(app) .post('/api/v1/auth/register') .send({ ...validRegisterData, email: 'invalid-email' }); // Assert expect(response.status).toBe(400); expect(response.body).toHaveProperty('success', false); }); it('should return 400 when password is too short', async () => { // Act const response = await request(app) .post('/api/v1/auth/register') .send({ ...validRegisterData, password: '123' }); // Assert expect(response.status).toBe(400); expect(response.body).toHaveProperty('success', false); }); it('should return 400 when required fields are missing', async () => { // Act const response = await request(app) .post('/api/v1/auth/register') .send({ email: 'test@example.com', password: 'Password123!' }); // Assert expect(response.status).toBe(400); expect(response.body).toHaveProperty('success', false); }); }); describe('POST /api/v1/auth/login', () => { const validLoginData = { email: 'login@example.com', password: 'Password123!', }; it('should login with valid credentials', async () => { // Arrange await createUser({ email: validLoginData.email, password: validLoginData.password, firstName: 'Login', lastName: 'Test', }); // Act const response = await request(app) .post('/api/v1/auth/login') .send(validLoginData); // Assert expect(response.status).toBe(200); expect(response.body).toHaveProperty('success', true); expect(response.body.data).toHaveProperty('user'); expect(response.body.data).toHaveProperty('accessToken'); expect(response.body.data).toHaveProperty('refreshToken'); expect(response.body.data.user).toHaveProperty('email', validLoginData.email); expect(response.body.data.user).not.toHaveProperty('password'); }); it('should return 401 with invalid password', async () => { // Arrange await createUser({ email: validLoginData.email, password: validLoginData.password, }); // Act const response = await request(app) .post('/api/v1/auth/login') .send({ ...validLoginData, password: 'WrongPassword123!' }); // Assert expect(response.status).toBe(401); expect(response.body).toHaveProperty('success', false); expect(response.body).toHaveProperty('message', 'Email o contraseña incorrectos'); }); it('should return 401 when user not found', async () => { // Act const response = await request(app) .post('/api/v1/auth/login') .send({ email: 'nonexistent@example.com', password: 'Password123!' }); // Assert expect(response.status).toBe(401); expect(response.body).toHaveProperty('success', false); expect(response.body).toHaveProperty('message', 'Email o contraseña incorrectos'); }); it('should return 401 when user is inactive', async () => { // Arrange await createUser({ email: validLoginData.email, password: validLoginData.password, isActive: false, }); // Act const response = await request(app) .post('/api/v1/auth/login') .send(validLoginData); // Assert expect(response.status).toBe(401); expect(response.body).toHaveProperty('success', false); expect(response.body).toHaveProperty('message', 'Usuario desactivado'); }); it('should return 400 with invalid email format', async () => { // Act const response = await request(app) .post('/api/v1/auth/login') .send({ email: 'invalid-email', password: 'Password123!' }); // Assert expect(response.status).toBe(400); expect(response.body).toHaveProperty('success', false); }); }); describe('GET /api/v1/auth/me', () => { it('should return user profile when authenticated', async () => { // Arrange const user = await createUser({ email: 'profile@example.com', firstName: 'Profile', lastName: 'User', }); const { accessToken } = generateTokens({ userId: user.id, email: user.email, role: user.role, }); // Act const response = await request(app) .get('/api/v1/auth/me') .set('Authorization', `Bearer ${accessToken}`); // Assert expect(response.status).toBe(200); expect(response.body).toHaveProperty('success', true); expect(response.body.data).toHaveProperty('id', user.id); expect(response.body.data).toHaveProperty('email', user.email); expect(response.body.data).toHaveProperty('firstName', 'Profile'); expect(response.body.data).not.toHaveProperty('password'); }); it('should return 401 when no token provided', async () => { // Act const response = await request(app) .get('/api/v1/auth/me'); // Assert expect(response.status).toBe(401); expect(response.body).toHaveProperty('success', false); expect(response.body).toHaveProperty('message', 'Token de autenticación no proporcionado'); }); it('should return 401 with invalid token', async () => { // Act const response = await request(app) .get('/api/v1/auth/me') .set('Authorization', 'Bearer invalid-token'); // Assert expect(response.status).toBe(401); expect(response.body).toHaveProperty('success', false); }); }); describe('POST /api/v1/auth/refresh', () => { it('should refresh access token with valid refresh token', async () => { // Arrange const user = await createUser({ email: 'refresh@example.com' }); const { refreshToken } = generateTokens({ userId: user.id, email: user.email, role: user.role, }); // Act const response = await request(app) .post('/api/v1/auth/refresh') .send({ refreshToken }); // Assert expect(response.status).toBe(200); expect(response.body).toHaveProperty('success', true); expect(response.body.data).toHaveProperty('accessToken'); }); it('should return 400 when refresh token is missing', async () => { // Act const response = await request(app) .post('/api/v1/auth/refresh') .send({}); // Assert expect(response.status).toBe(400); expect(response.body).toHaveProperty('success', false); }); }); describe('POST /api/v1/auth/logout', () => { it('should logout successfully', async () => { // Arrange const user = await createUser({ email: 'logout@example.com' }); const { accessToken } = generateTokens({ userId: user.id, email: user.email, role: user.role, }); // Act const response = await request(app) .post('/api/v1/auth/logout') .set('Authorization', `Bearer ${accessToken}`); // Assert expect(response.status).toBe(200); expect(response.body).toHaveProperty('success', true); expect(response.body).toHaveProperty('message', 'Logout exitoso'); }); it('should allow logout without authentication', async () => { // Act - logout endpoint doesn't require authentication const response = await request(app) .post('/api/v1/auth/logout'); // Assert - logout is allowed without auth (just returns success) expect(response.status).toBe(200); expect(response.body).toHaveProperty('success', true); }); }); });