import request from 'supertest'; import app from '../../../services/api-gateway/src/app.js'; import { connectDatabase, closeDatabase, clearDatabase } from '../../helpers/database.js'; import { createUser } from '../../helpers/factories.js'; import bcrypt from 'bcryptjs'; describe('Auth API Integration Tests', () => { beforeAll(async () => { await connectDatabase(); }); afterEach(async () => { await clearDatabase(); }); afterAll(async () => { await closeDatabase(); }); describe('POST /api/v1/auth/login', () => { it('should login with valid credentials', async () => { // Create a user in the database const password = 'Test123!@#'; const hashedPassword = await bcrypt.hash(password, 10); const userData = createUser({ password: hashedPassword }); // Save user to database (you'll need to import and use your User model) // const user = await User.create(userData); const response = await request(app) .post('/api/v1/auth/login') .send({ username: userData.username, password: password }); expect(response.status).toBe(200); expect(response.body.success).toBe(true); expect(response.body.data).toHaveProperty('accessToken'); expect(response.body.data).toHaveProperty('refreshToken'); expect(response.body.data.user).toHaveProperty('id'); expect(response.body.data.user.username).toBe(userData.username); }); it('should fail with invalid credentials', async () => { const response = await request(app) .post('/api/v1/auth/login') .send({ username: 'nonexistent', password: 'wrongpassword' }); expect(response.status).toBe(401); expect(response.body.success).toBe(false); expect(response.body.error).toBe('Invalid credentials'); }); it('should fail with missing credentials', async () => { const response = await request(app) .post('/api/v1/auth/login') .send({ username: 'testuser' // missing password }); expect(response.status).toBe(400); expect(response.body.success).toBe(false); expect(response.body.error).toContain('required'); }); it('should handle rate limiting', async () => { // Make multiple requests to trigger rate limit const requests = Array(11).fill(null).map(() => request(app) .post('/api/v1/auth/login') .send({ username: 'testuser', password: 'password' }) ); const responses = await Promise.all(requests); const rateLimited = responses.some(res => res.status === 429); expect(rateLimited).toBe(true); }); }); describe('POST /api/v1/auth/register', () => { it('should register new user', async () => { const userData = { username: 'newuser', email: 'newuser@example.com', password: 'SecurePass123!', fullName: 'New User' }; const response = await request(app) .post('/api/v1/auth/register') .send(userData); expect(response.status).toBe(201); expect(response.body.success).toBe(true); expect(response.body.message).toBe('Registration successful'); }); it('should fail with duplicate username', async () => { const userData = { username: 'existinguser', email: 'test@example.com', password: 'SecurePass123!' }; // First registration await request(app) .post('/api/v1/auth/register') .send(userData); // Duplicate registration const response = await request(app) .post('/api/v1/auth/register') .send(userData); expect(response.status).toBe(409); expect(response.body.success).toBe(false); expect(response.body.error).toContain('already exists'); }); it('should validate email format', async () => { const response = await request(app) .post('/api/v1/auth/register') .send({ username: 'testuser', email: 'invalid-email', password: 'SecurePass123!' }); expect(response.status).toBe(400); expect(response.body.success).toBe(false); expect(response.body.error).toContain('email'); }); }); describe('POST /api/v1/auth/refresh', () => { let accessToken, refreshToken; beforeEach(async () => { // Login to get tokens const loginResponse = await request(app) .post('/api/v1/auth/login') .send({ username: 'admin', password: 'password123' }); accessToken = loginResponse.body.data.accessToken; refreshToken = loginResponse.body.data.refreshToken; }); it('should refresh access token', async () => { const response = await request(app) .post('/api/v1/auth/refresh') .send({ refreshToken: refreshToken }); expect(response.status).toBe(200); expect(response.body.success).toBe(true); expect(response.body.data).toHaveProperty('accessToken'); expect(response.body.data.accessToken).not.toBe(accessToken); }); it('should fail with invalid refresh token', async () => { const response = await request(app) .post('/api/v1/auth/refresh') .send({ refreshToken: 'invalid-refresh-token' }); expect(response.status).toBe(401); expect(response.body.success).toBe(false); expect(response.body.error).toBe('Invalid refresh token'); }); }); describe('GET /api/v1/auth/me', () => { let accessToken; beforeEach(async () => { // Login to get token const loginResponse = await request(app) .post('/api/v1/auth/login') .send({ username: 'admin', password: 'password123' }); accessToken = loginResponse.body.data.accessToken; }); it('should get current user info', async () => { const response = await request(app) .get('/api/v1/auth/me') .set('Authorization', `Bearer ${accessToken}`); expect(response.status).toBe(200); expect(response.body.success).toBe(true); expect(response.body.data).toHaveProperty('id'); expect(response.body.data).toHaveProperty('role'); }); it('should fail without token', async () => { const response = await request(app) .get('/api/v1/auth/me'); expect(response.status).toBe(401); expect(response.body.success).toBe(false); expect(response.body.error).toBe('No token provided'); }); }); describe('POST /api/v1/auth/logout', () => { let accessToken; beforeEach(async () => { // Login to get token const loginResponse = await request(app) .post('/api/v1/auth/login') .send({ username: 'admin', password: 'password123' }); accessToken = loginResponse.body.data.accessToken; }); it('should logout successfully', async () => { const response = await request(app) .post('/api/v1/auth/logout') .set('Authorization', `Bearer ${accessToken}`); expect(response.status).toBe(200); expect(response.body.success).toBe(true); expect(response.body.message).toBe('Logged out successfully'); // Verify token is blacklisted const meResponse = await request(app) .get('/api/v1/auth/me') .set('Authorization', `Bearer ${accessToken}`); expect(meResponse.status).toBe(401); }); }); });