init
This commit is contained in:
168
tests/unit/middlewares/error.test.js
Normal file
168
tests/unit/middlewares/error.test.js
Normal file
@@ -0,0 +1,168 @@
|
||||
const mongoose = require('mongoose');
|
||||
const httpStatus = require('http-status');
|
||||
const httpMocks = require('node-mocks-http');
|
||||
const { errorConverter, errorHandler } = require('../../../src/middlewares/error');
|
||||
const ApiError = require('../../../src/utils/ApiError');
|
||||
const config = require('../../../src/config/config');
|
||||
const logger = require('../../../src/config/logger');
|
||||
|
||||
describe('Error middlewares', () => {
|
||||
describe('Error converter', () => {
|
||||
test('should return the same ApiError object it was called with', () => {
|
||||
const error = new ApiError(httpStatus.BAD_REQUEST, 'Any error');
|
||||
const next = jest.fn();
|
||||
|
||||
errorConverter(error, httpMocks.createRequest(), httpMocks.createResponse(), next);
|
||||
|
||||
expect(next).toHaveBeenCalledWith(error);
|
||||
});
|
||||
|
||||
test('should convert an Error to ApiError and preserve its status and message', () => {
|
||||
const error = new Error('Any error');
|
||||
error.statusCode = httpStatus.BAD_REQUEST;
|
||||
const next = jest.fn();
|
||||
|
||||
errorConverter(error, httpMocks.createRequest(), httpMocks.createResponse(), next);
|
||||
|
||||
expect(next).toHaveBeenCalledWith(expect.any(ApiError));
|
||||
expect(next).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
statusCode: error.statusCode,
|
||||
message: error.message,
|
||||
isOperational: false,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test('should convert an Error without status to ApiError with status 500', () => {
|
||||
const error = new Error('Any error');
|
||||
const next = jest.fn();
|
||||
|
||||
errorConverter(error, httpMocks.createRequest(), httpMocks.createResponse(), next);
|
||||
|
||||
expect(next).toHaveBeenCalledWith(expect.any(ApiError));
|
||||
expect(next).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
statusCode: httpStatus.INTERNAL_SERVER_ERROR,
|
||||
message: error.message,
|
||||
isOperational: false,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test('should convert an Error without message to ApiError with default message of that http status', () => {
|
||||
const error = new Error();
|
||||
error.statusCode = httpStatus.BAD_REQUEST;
|
||||
const next = jest.fn();
|
||||
|
||||
errorConverter(error, httpMocks.createRequest(), httpMocks.createResponse(), next);
|
||||
|
||||
expect(next).toHaveBeenCalledWith(expect.any(ApiError));
|
||||
expect(next).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
statusCode: error.statusCode,
|
||||
message: httpStatus[error.statusCode],
|
||||
isOperational: false,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test('should convert a Mongoose error to ApiError with status 400 and preserve its message', () => {
|
||||
const error = new mongoose.Error('Any mongoose error');
|
||||
const next = jest.fn();
|
||||
|
||||
errorConverter(error, httpMocks.createRequest(), httpMocks.createResponse(), next);
|
||||
|
||||
expect(next).toHaveBeenCalledWith(expect.any(ApiError));
|
||||
expect(next).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
statusCode: httpStatus.BAD_REQUEST,
|
||||
message: error.message,
|
||||
isOperational: false,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test('should convert any other object to ApiError with status 500 and its message', () => {
|
||||
const error = {};
|
||||
const next = jest.fn();
|
||||
|
||||
errorConverter(error, httpMocks.createRequest(), httpMocks.createResponse(), next);
|
||||
|
||||
expect(next).toHaveBeenCalledWith(expect.any(ApiError));
|
||||
expect(next).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
statusCode: httpStatus.INTERNAL_SERVER_ERROR,
|
||||
message: httpStatus[httpStatus.INTERNAL_SERVER_ERROR],
|
||||
isOperational: false,
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Error handler', () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(logger, 'error').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
test('should send proper error response and put the error message in res.locals', () => {
|
||||
const error = new ApiError(httpStatus.BAD_REQUEST, 'Any error');
|
||||
const res = httpMocks.createResponse();
|
||||
const sendSpy = jest.spyOn(res, 'send');
|
||||
|
||||
errorHandler(error, httpMocks.createRequest(), res);
|
||||
|
||||
expect(sendSpy).toHaveBeenCalledWith(expect.objectContaining({ code: error.statusCode, message: error.message }));
|
||||
expect(res.locals.errorMessage).toBe(error.message);
|
||||
});
|
||||
|
||||
test('should put the error stack in the response if in development mode', () => {
|
||||
config.env = 'development';
|
||||
const error = new ApiError(httpStatus.BAD_REQUEST, 'Any error');
|
||||
const res = httpMocks.createResponse();
|
||||
const sendSpy = jest.spyOn(res, 'send');
|
||||
|
||||
errorHandler(error, httpMocks.createRequest(), res);
|
||||
|
||||
expect(sendSpy).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ code: error.statusCode, message: error.message, stack: error.stack })
|
||||
);
|
||||
config.env = process.env.NODE_ENV;
|
||||
});
|
||||
|
||||
test('should send internal server error status and message if in production mode and error is not operational', () => {
|
||||
config.env = 'production';
|
||||
const error = new ApiError(httpStatus.BAD_REQUEST, 'Any error', false);
|
||||
const res = httpMocks.createResponse();
|
||||
const sendSpy = jest.spyOn(res, 'send');
|
||||
|
||||
errorHandler(error, httpMocks.createRequest(), res);
|
||||
|
||||
expect(sendSpy).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
code: httpStatus.INTERNAL_SERVER_ERROR,
|
||||
message: httpStatus[httpStatus.INTERNAL_SERVER_ERROR],
|
||||
})
|
||||
);
|
||||
expect(res.locals.errorMessage).toBe(error.message);
|
||||
config.env = process.env.NODE_ENV;
|
||||
});
|
||||
|
||||
test('should preserve original error status and message if in production mode and error is operational', () => {
|
||||
config.env = 'production';
|
||||
const error = new ApiError(httpStatus.BAD_REQUEST, 'Any error');
|
||||
const res = httpMocks.createResponse();
|
||||
const sendSpy = jest.spyOn(res, 'send');
|
||||
|
||||
errorHandler(error, httpMocks.createRequest(), res);
|
||||
|
||||
expect(sendSpy).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
code: error.statusCode,
|
||||
message: error.message,
|
||||
})
|
||||
);
|
||||
config.env = process.env.NODE_ENV;
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user