const { describe, it, beforeEach, afterEach, before, after } = require('mocha'); const { expect } = require('chai'); const sinon = require('sinon'); const jwt = require('jsonwebtoken'); const { setupTestEnvironment, teardownTestEnvironment, cleanDatabase, mockRequest, mockResponse, mockNext, createTestUser, createTestTenant } = require('../setup'); describe('Authentication Middleware', () => { let models, sequelize, authenticateToken; before(async () => { ({ models, sequelize } = await setupTestEnvironment()); // Import middleware after setup to ensure it uses test models const authMiddleware = require('../../middleware/auth'); authenticateToken = authMiddleware.authenticateToken; }); 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: '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 format' }); }); 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('Token expired'); }); it('should accept valid JWT token and set user data', async () => { const user = await createTestUser({ username: 'testuser', role: 'admin' }); const token = jwt.sign( { userId: user.id, 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.userId).to.equal(user.id); 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 }); const token = jwt.sign( { userId: user.id, 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.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('User not found'); }); it('should reject inactive user', async () => { const user = await createTestUser({ username: 'inactive', is_active: false }); const token = jwt.sign( { userId: user.id, 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('User account is inactive'); }); }); });