const { describe, it, beforeEach, afterEach, before, after } = require('mocha'); const { expect } = require('chai'); const sinon = require('sinon'); const jwt = require('jsonwebtoken'); const { authenticateToken } = require('../../middleware/auth'); const { setupTestEnvironment, teardownTestEnvironment, cleanDatabase, mockRequest, mockResponse, mockNext, createTestUser, createTestTenant } = require('../setup'); describe('Authentication Middleware', () => { let models, sequelize; before(async () => { ({ models, sequelize } = await setupTestEnvironment()); // Set models for auth middleware const auth = require('../../middleware/auth'); auth.setModels(models); }); after(async () => { await teardownTestEnvironment(); }); beforeEach(async () => { await cleanDatabase(); }); describe('authenticateToken', () => { it('should reject request without Authorization header', async () => { const req = mockRequest(); const res = mockResponse(); const next = mockNext(); await authenticateToken(req, res, next); expect(res.statusCode).to.equal(401); expect(res.data).to.deep.equal({ success: false, message: 'Access token required' }); expect(next.errors).to.have.length(0); }); it('should reject request with invalid token format', async () => { const req = mockRequest({ headers: { authorization: 'Bearer invalidtoken' } }); const res = mockResponse(); const next = mockNext(); await authenticateToken(req, res, next); expect(res.statusCode).to.equal(401); expect(res.data).to.deep.equal({ success: false, message: 'Invalid token' }); }); it('should reject request with invalid JWT token', async () => { const req = mockRequest({ headers: { authorization: 'Bearer invalid.jwt.token' } }); const res = mockResponse(); const next = mockNext(); await authenticateToken(req, res, next); expect(res.statusCode).to.equal(401); expect(res.data.success).to.be.false; expect(res.data.message).to.equal('Invalid token'); }); it('should reject request with expired JWT token', async () => { const expiredToken = jwt.sign( { userId: 1, username: 'test' }, process.env.JWT_SECRET || 'test-secret', { expiresIn: '-1h' } ); const req = mockRequest({ headers: { authorization: `Bearer ${expiredToken}` } }); const res = mockResponse(); const next = mockNext(); await authenticateToken(req, res, next); expect(res.statusCode).to.equal(401); expect(res.data.success).to.be.false; expect(res.data.message).to.equal('Invalid token'); }); it('should accept valid JWT token and set user data', async () => { const user = await createTestUser({ username: 'testuser', role: 'admin' }); console.log('Created user:', user.toJSON()); // Debug log // Get the actual string value of the UUID const userId = user.getDataValue('id') || user.id; console.log('User ID for JWT:', userId, typeof userId); const token = jwt.sign( { userId: userId, username: user.username, role: user.role, email: user.email }, process.env.JWT_SECRET || 'test-secret', { expiresIn: '1h' } ); const req = mockRequest({ headers: { authorization: `Bearer ${token}` } }); const res = mockResponse(); const next = mockNext(); await authenticateToken(req, res, next); expect(req.user).to.exist; expect(req.user.id).to.equal(userId); expect(req.user.username).to.equal(user.username); expect(req.user.role).to.equal(user.role); expect(next.errors).to.have.length(0); }); it('should handle token with tenantId', async () => { const tenant = await createTestTenant({ slug: 'test-tenant' }); const user = await createTestUser({ username: 'testuser', tenant_id: tenant.id }); // Get the actual string value of the UUID const userId = user.getDataValue('id') || user.id; const token = jwt.sign( { userId: userId, username: user.username, role: user.role, tenantId: tenant.slug }, process.env.JWT_SECRET || 'test-secret', { expiresIn: '1h' } ); const req = mockRequest({ headers: { authorization: `Bearer ${token}` } }); const res = mockResponse(); const next = mockNext(); await authenticateToken(req, res, next); expect(req.user).to.exist; expect(req.user.username).to.equal(user.username); expect(req.tenantId).to.equal(tenant.slug); expect(next.errors).to.have.length(0); }); it('should reject user not found in database', async () => { const token = jwt.sign( { userId: 99999, username: 'nonexistent' }, process.env.JWT_SECRET || 'test-secret', { expiresIn: '1h' } ); const req = mockRequest({ headers: { authorization: `Bearer ${token}` } }); const res = mockResponse(); const next = mockNext(); await authenticateToken(req, res, next); expect(res.statusCode).to.equal(401); expect(res.data.success).to.be.false; expect(res.data.message).to.equal('Invalid or inactive user'); }); it('should reject inactive user', async () => { const user = await createTestUser({ username: 'inactive', is_active: false }); // Get the actual string value of the UUID const userId = user.getDataValue('id') || user.id; const token = jwt.sign( { userId: userId, username: user.username }, process.env.JWT_SECRET || 'test-secret', { expiresIn: '1h' } ); const req = mockRequest({ headers: { authorization: `Bearer ${token}` } }); const res = mockResponse(); const next = mockNext(); await authenticateToken(req, res, next); expect(res.statusCode).to.equal(401); expect(res.data.success).to.be.false; expect(res.data.message).to.equal('Invalid or inactive user'); }); }); });