import { Request, Response, NextFunction } from 'express'; // Mock JWTService before importing anything else const mockJWTService = { verify: jest.fn(), refreshIfNeeded: jest.fn(), create: jest.fn(), shouldRefreshToken: jest.fn(), test: jest.fn(), }; jest.mock('../../../src/Application/Services/JWTService', () => { return { JWTService: jest.fn().mockImplementation(() => mockJWTService) }; }); // Now import the middleware which will use the mocked JWTService import { authRequired, adminRequired } from '../../../src/Application/Services/AuthMiddleware'; describe('AuthMiddleware', () => { let mockRequest: Partial; let mockResponse: Partial; let mockNext: NextFunction; beforeEach(() => { jest.clearAllMocks(); mockRequest = { cookies: {} }; mockResponse = { status: jest.fn().mockReturnThis(), json: jest.fn().mockReturnThis(), cookie: jest.fn() }; mockNext = jest.fn(); }); describe('authRequired', () => { it('should call next() when token is valid', () => { // Arrange const validPayload = { userId: 'user-123', authLevel: 0 as 0 | 1, orgId: 'org-123' }; mockJWTService.verify.mockReturnValue(validPayload); mockJWTService.refreshIfNeeded.mockReturnValue(false); // Token doesn't need refresh // Act authRequired(mockRequest as Request, mockResponse as Response, mockNext); // Assert expect(mockJWTService.verify).toHaveBeenCalledWith(mockRequest); expect(mockJWTService.refreshIfNeeded).toHaveBeenCalledWith(validPayload, mockResponse); expect((mockRequest as any).user).toBe(validPayload); expect(mockNext).toHaveBeenCalled(); expect(mockResponse.status).not.toHaveBeenCalled(); expect(mockResponse.json).not.toHaveBeenCalled(); }); it('should return 401 when token is invalid', () => { // Arrange mockJWTService.verify.mockReturnValue(null); // Act authRequired(mockRequest as Request, mockResponse as Response, mockNext); // Assert expect(mockJWTService.verify).toHaveBeenCalledWith(mockRequest); expect(mockJWTService.refreshIfNeeded).not.toHaveBeenCalled(); expect(mockNext).not.toHaveBeenCalled(); expect(mockResponse.status).toHaveBeenCalledWith(401); expect(mockResponse.json).toHaveBeenCalledWith({ error: 'Unauthorized' }); }); it('should refresh token when needed', () => { // Arrange const validPayload = { userId: 'user-123', authLevel: 0 as 0 | 1, orgId: 'org-123' }; mockJWTService.verify.mockReturnValue(validPayload); mockJWTService.refreshIfNeeded.mockReturnValue(true); // Token needs refresh // Act authRequired(mockRequest as Request, mockResponse as Response, mockNext); // Assert expect(mockJWTService.verify).toHaveBeenCalledWith(mockRequest); expect(mockJWTService.refreshIfNeeded).toHaveBeenCalledWith(validPayload, mockResponse); expect((mockRequest as any).user).toBe(validPayload); expect(mockNext).toHaveBeenCalled(); expect(mockResponse.status).not.toHaveBeenCalled(); expect(mockResponse.json).not.toHaveBeenCalled(); }); }); describe('adminRequired', () => { it('should call next() when token is valid and user is admin', () => { // Arrange const adminPayload = { userId: 'admin-123', authLevel: 1 as 0 | 1, orgId: 'org-123' }; mockJWTService.verify.mockReturnValue(adminPayload); mockJWTService.refreshIfNeeded.mockReturnValue(false); // Act adminRequired(mockRequest as Request, mockResponse as Response, mockNext); // Assert expect(mockJWTService.verify).toHaveBeenCalledWith(mockRequest); expect(mockJWTService.refreshIfNeeded).toHaveBeenCalledWith(adminPayload, mockResponse); expect((mockRequest as any).user).toBe(adminPayload); expect(mockNext).toHaveBeenCalled(); expect(mockResponse.status).not.toHaveBeenCalled(); expect(mockResponse.json).not.toHaveBeenCalled(); }); it('should return 403 when token is invalid', () => { // Arrange mockJWTService.verify.mockReturnValue(null); // Act adminRequired(mockRequest as Request, mockResponse as Response, mockNext); // Assert expect(mockJWTService.verify).toHaveBeenCalledWith(mockRequest); expect(mockJWTService.refreshIfNeeded).not.toHaveBeenCalled(); expect(mockNext).not.toHaveBeenCalled(); expect(mockResponse.status).toHaveBeenCalledWith(403); expect(mockResponse.json).toHaveBeenCalledWith({ error: 'Forbidden' }); }); it('should return 403 when user is not admin', () => { // Arrange const regularUserPayload = { userId: 'user-123', authLevel: 0 as 0 | 1, orgId: 'org-123' }; mockJWTService.verify.mockReturnValue(regularUserPayload); // Act adminRequired(mockRequest as Request, mockResponse as Response, mockNext); // Assert expect(mockJWTService.verify).toHaveBeenCalledWith(mockRequest); expect(mockJWTService.refreshIfNeeded).not.toHaveBeenCalled(); expect(mockNext).not.toHaveBeenCalled(); expect(mockResponse.status).toHaveBeenCalledWith(403); expect(mockResponse.json).toHaveBeenCalledWith({ error: 'Forbidden' }); }); it('should refresh token for valid admin user', () => { // Arrange const adminPayload = { userId: 'admin-123', authLevel: 1 as 0 | 1, orgId: 'org-123' }; mockJWTService.verify.mockReturnValue(adminPayload); mockJWTService.refreshIfNeeded.mockReturnValue(true); // Act adminRequired(mockRequest as Request, mockResponse as Response, mockNext); // Assert expect(mockJWTService.verify).toHaveBeenCalledWith(mockRequest); expect(mockJWTService.refreshIfNeeded).toHaveBeenCalledWith(adminPayload, mockResponse); expect((mockRequest as any).user).toBe(adminPayload); expect(mockNext).toHaveBeenCalled(); expect(mockResponse.status).not.toHaveBeenCalled(); expect(mockResponse.json).not.toHaveBeenCalled(); }); }); });