Skip to content

Commit

Permalink
BC-5489 - For loggables it should possible to pass unknown cause error (
Browse files Browse the repository at this point in the history
  • Loading branch information
SevenWaysDP authored and bergatco committed Nov 2, 2023
1 parent af8ddeb commit ada0744
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 5 deletions.
104 changes: 100 additions & 4 deletions apps/server/src/core/error/filter/global-error.filter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
/* eslint-disable promise/valid-params */
import { NotFound } from '@feathersjs/errors';
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { ArgumentsHost, BadRequestException, HttpStatus } from '@nestjs/common';
import { ArgumentsHost, BadRequestException, HttpStatus, InternalServerErrorException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { BusinessError } from '@shared/common';
import { ErrorLogger, ErrorLogMessage, Loggable, LogMessage, ValidationErrorLogMessage } from '@src/core/logger';
import { Response } from 'express';
import util from 'util';
import { ErrorResponse } from '../dto';
import { ErrorLoggable } from '../loggable/error.loggable';
import { ErrorUtils } from '../utils';
import { GlobalErrorFilter } from './global-error.filter';

class SampleBusinessError extends BusinessError {
Expand Down Expand Up @@ -42,6 +43,24 @@ class SampleLoggableException extends BadRequestException implements Loggable {
}
}

class SampleLoggableExceptionWithCause extends InternalServerErrorException implements Loggable {
constructor(private readonly testValue: string, error?: unknown) {
super(ErrorUtils.createHttpExceptionOptions(error));
}

getLogMessage(): ErrorLogMessage {
const message: ErrorLogMessage = {
type: 'WITH_CAUSE',
stack: this.stack,
data: {
testValue: this.testValue,
},
};

return message;
}
}

describe('GlobalErrorFilter', () => {
let module: TestingModule;
let service: GlobalErrorFilter<any>;
Expand Down Expand Up @@ -304,24 +323,101 @@ describe('GlobalErrorFilter', () => {
).toBeCalledWith(expectedResponse);
});
});

describe('when error has a cause error', () => {
const setup = () => {
const causeError = new Error('Cause error');
const error = new SampleLoggableExceptionWithCause('test', causeError);
const expectedResponse = new ErrorResponse(
'SAMPLE_WITH_CAUSE',
'Sample With Cause',
'Sample Loggable Exception With Cause',
HttpStatus.INTERNAL_SERVER_ERROR
);

const argumentsHost = setupHttpArgumentsHost();

return { error, argumentsHost, expectedResponse };
};

it('should set response status appropriately', () => {
const { error, argumentsHost } = setup();

service.catch(error, argumentsHost);

expect(argumentsHost.switchToHttp().getResponse<Response>().status).toBeCalledWith(
HttpStatus.INTERNAL_SERVER_ERROR
);
});

it('should send appropriate error response', () => {
const { error, argumentsHost, expectedResponse } = setup();

service.catch(error, argumentsHost);

expect(
argumentsHost.switchToHttp().getResponse<Response>().status(HttpStatus.INTERNAL_SERVER_ERROR).json
).toBeCalledWith(expectedResponse);
});
});
});

describe('when context is rmq', () => {
describe('when error is unknown error', () => {
const setup = () => {
const argumentsHost = createMock<ArgumentsHost>();
argumentsHost.getType.mockReturnValueOnce('rmq');

const error = new Error();

return { error, argumentsHost };
};

it('should return an RpcMessage with the error', () => {
const { error, argumentsHost } = setup();

const result = service.catch(error, argumentsHost);

expect(result).toEqual({ message: undefined, error });
});
});

describe('when error is a LoggableError', () => {
const setup = () => {
const causeError = new Error('Cause error');
const error = new SampleLoggableExceptionWithCause('test', causeError);
const argumentsHost = createMock<ArgumentsHost>();
argumentsHost.getType.mockReturnValueOnce('rmq');

return { error, argumentsHost };
};

it('should return appropriate error', () => {
const { error, argumentsHost } = setup();

const result = service.catch(error, argumentsHost);

expect(result).toEqual({ message: undefined, error });
});
});
});

describe('when context is other than rmq and http', () => {
const setup = () => {
const argumentsHost = createMock<ArgumentsHost>();
argumentsHost.getType.mockReturnValueOnce('rmq');
argumentsHost.getType.mockReturnValueOnce('other');

const error = new Error();

return { error, argumentsHost };
};

it('should return an RpcMessage with the error', () => {
it('should return undefined', () => {
const { error, argumentsHost } = setup();

const result = service.catch(error, argumentsHost);

expect(result).toEqual({ message: undefined, error });
expect(result).toBeUndefined();
});
});
});
Expand Down
4 changes: 3 additions & 1 deletion apps/server/src/core/error/filter/global-error.filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ export class GlobalErrorFilter<T extends IError | undefined> implements Exceptio

if (contextType === 'http') {
this.sendHttpResponse(error, host);
} else if (contextType === 'rmq') {
}

if (contextType === 'rmq') {
return { message: undefined, error };
}
}
Expand Down

0 comments on commit ada0744

Please sign in to comment.