diff --git a/jest.config.js b/jest.config.js index ab9b4739..f50f4163 100644 --- a/jest.config.js +++ b/jest.config.js @@ -2,6 +2,9 @@ export default { // Use Node's experimental ESM support testEnvironment: 'node', + // Setup files to run before tests + setupFiles: ['./jest.setup.js'], + // Transform ES modules transform: {}, @@ -31,4 +34,7 @@ export default { // Verbose output verbose: true, + + // Test timeout (increase for database operations) + testTimeout: 10000, }; diff --git a/jest.setup.js b/jest.setup.js new file mode 100644 index 00000000..7ca954e4 --- /dev/null +++ b/jest.setup.js @@ -0,0 +1,13 @@ +/** + * Jest setup file - configure test environment + */ + +// Set test environment variables +process.env.NODE_ENV = 'test'; +process.env.JWT_SECRET = 'test-jwt-secret-key-for-testing-purposes-only'; +process.env.JWT_EXPIRES_IN = '1h'; +process.env.PORT = '3001'; + +// Disable console logs during tests (optional) +// console.log = jest.fn(); +// console.error = jest.fn(); diff --git a/src/middleware/auth.js b/src/middleware/auth.js index c0911a6c..25fc3c17 100644 --- a/src/middleware/auth.js +++ b/src/middleware/auth.js @@ -51,10 +51,10 @@ export const authenticateToken = async (req, res, next) => { next(); } catch (error) { if (error.name === 'JsonWebTokenError') { - return next(new AppError('Token invalide', 403)); + return next(new AppError('Token invalide', 401)); } if (error.name === 'TokenExpiredError') { - return next(new AppError('Token expiré', 403)); + return next(new AppError('Token expiré', 401)); } return next(error); } diff --git a/src/middleware/errorHandler.js b/src/middleware/errorHandler.js index a38de2e2..29411d0f 100644 --- a/src/middleware/errorHandler.js +++ b/src/middleware/errorHandler.js @@ -52,7 +52,7 @@ export const errorHandler = (err, req, res, _next) => { res.status(error.statusCode || 500).json({ success: false, - error: error.message || 'Erreur serveur', + message: error.message || 'Erreur serveur', ...(process.env.NODE_ENV === 'development' && { stack: err.stack }), }); }; diff --git a/src/middleware/validate.js b/src/middleware/validate.js index 2fc57b81..7a84e269 100644 --- a/src/middleware/validate.js +++ b/src/middleware/validate.js @@ -11,16 +11,17 @@ export const validate = (schema) => async (req, res, next) => { }); next(); } catch (error) { - if (error.errors) { + // Check for Zod validation errors (works with ESM) + if (error.issues && Array.isArray(error.issues)) { // Erreurs de validation Zod - const errorMessages = error.errors.map((err) => ({ + const errorMessages = error.issues.map((err) => ({ field: err.path.join('.'), message: err.message, })); return res.status(400).json({ success: false, - error: 'Erreur de validation', + message: 'Erreur de validation', details: errorMessages, }); } diff --git a/test/unit/middleware.test.js b/test/unit/middleware.test.js index c42e70e7..64a7fe4a 100644 --- a/test/unit/middleware.test.js +++ b/test/unit/middleware.test.js @@ -10,7 +10,6 @@ jest.unstable_mockModule('../../db.js', () => ({ }, })); -const { pool } = await import('../../db.js'); const { authenticateToken, authorizeRoles, optionalAuth } = await import('../../src/middleware/auth.js'); const { AppError, errorHandler, asyncHandler } = await import('../../src/middleware/errorHandler.js'); const { validate } = await import('../../src/middleware/validate.js'); @@ -37,13 +36,12 @@ describe('Auth Middleware', () => { it('should return 401 if no token provided', async () => { await authenticateToken(mockReq, mockRes, mockNext); - expect(mockRes.status).toHaveBeenCalledWith(401); - expect(mockRes.json).toHaveBeenCalledWith( + expect(mockNext).toHaveBeenCalledWith( expect.objectContaining({ - success: false, + statusCode: 401, + isOperational: true, }) ); - expect(mockNext).not.toHaveBeenCalled(); }); it('should return 401 for invalid token', async () => { @@ -51,8 +49,12 @@ describe('Auth Middleware', () => { await authenticateToken(mockReq, mockRes, mockNext); - expect(mockRes.status).toHaveBeenCalledWith(401); - expect(mockNext).not.toHaveBeenCalled(); + expect(mockNext).toHaveBeenCalledWith( + expect.objectContaining({ + statusCode: 401, + isOperational: true, + }) + ); }); }); @@ -72,8 +74,12 @@ describe('Auth Middleware', () => { middleware(mockReq, mockRes, mockNext); - expect(mockRes.status).toHaveBeenCalledWith(403); - expect(mockNext).not.toHaveBeenCalled(); + expect(mockNext).toHaveBeenCalledWith( + expect.objectContaining({ + statusCode: 403, + isOperational: true, + }) + ); }); }); @@ -132,6 +138,11 @@ describe('Error Handler Middleware', () => { errorHandler(error, mockReq, mockRes, mockNext); expect(mockRes.status).toHaveBeenCalledWith(500); + expect(mockRes.json).toHaveBeenCalledWith( + expect.objectContaining({ + success: false, + }) + ); }); });