Skip to content

Commit

Permalink
fix: resolved an issue that caused errors to not be output properly
Browse files Browse the repository at this point in the history
  • Loading branch information
cecilia-sanare committed Feb 23, 2024
1 parent e6695bf commit 7c14f94
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 49 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"chalk": "^3"
},
"devDependencies": {
"@jest/types": "^29.6.1",
"@types/jest": "^29.5.3",
"@types/node": "^18",
"@typescript-eslint/eslint-plugin": "^6.1.0",
Expand Down
73 changes: 33 additions & 40 deletions src/__tests__/logger.spec.ts
Original file line number Diff line number Diff line change
@@ -1,85 +1,78 @@
import { Chance } from 'chance';
import { LEVEL_CHALK, LogLevel, Logger } from '../index';
import { stringify } from '../utils/stringify';
import { LEVEL_CHALK, LogLevel, Logger, MAX_LENGTH } from '../index';
import { sanitizeMessages } from '../utils/messages';

const chance = new Chance();

describe('util(Logger)', () => {
let log: jest.SpyInstance<void, [message?: unknown, ...optionalParams: unknown[]], unknown>;

beforeEach(() => {
log = jest.spyOn(console, 'log');
log = jest.spyOn(console, 'log').mockReturnValue(null);

Logger.setLevel(LogLevel.SILLY);
});

afterEach(() => {
jest.resetAllMocks();
jest.restoreAllMocks();
});

function validate(level: LogLevel, ...messages: any[]): void {
const chalk = LEVEL_CHALK[level];

expect(log).toHaveBeenCalledWith(
chalk(`[${LogLevel[level].toLowerCase()}]:`).padEnd(MAX_LENGTH, ' '),
...sanitizeMessages(messages).map((message) => (message instanceof Error ? message : chalk(message)))
);
}

describe('func(log)', () => {
it('should output a console log given the log level', () => {
const expectedMessage = chance.word();

Logger.log(LogLevel.INFO, expectedMessage);

expect(log).toHaveBeenCalledWith(LEVEL_CHALK[LogLevel.INFO](`[info]: ${expectedMessage}`));
validate(LogLevel.INFO, expectedMessage);
});

it('should support objects', () => {
const expectedObject = { hello: 'world' };

Logger.log(LogLevel.INFO, expectedObject);

expect(log).toHaveBeenCalledWith(LEVEL_CHALK[LogLevel.INFO](`[info]: ${stringify(expectedObject)}`));
});

it('should not output a console log if the current log level is below the required level', () => {
Logger.setLevel(LogLevel.ERROR);

Logger.log(LogLevel.INFO, chance.word());

expect(log).not.toHaveBeenCalled();
validate(LogLevel.INFO, expectedObject);
});
});

describe('func(error)', () => {
it('should output a console log with the expected level', () => {
const expectedMessage = chance.word();
it('should support errors', () => {
const expectedError = new Error('Oops!');

Logger.error(expectedMessage);
Logger.log(LogLevel.INFO, expectedError);

expect(log).toHaveBeenCalledWith(LEVEL_CHALK[LogLevel.ERROR](`[error]: ${expectedMessage}`));
validate(LogLevel.INFO, expectedError);
});
});

describe('func(warn)', () => {
it('should output a console log with the expected level', () => {
const expectedMessage = chance.word();
it('should not output a console log if the current log level is below the required level', () => {
Logger.setLevel(LogLevel.ERROR);

Logger.warn(expectedMessage);
Logger.log(LogLevel.INFO, chance.word());

expect(log).toHaveBeenCalledWith(LEVEL_CHALK[LogLevel.WARN](`[warn]: ${expectedMessage}`));
expect(log).not.toHaveBeenCalled();
});
});

describe('func(info)', () => {
it('should output a console log with the expected level', () => {
const expectedMessage = chance.word();

Logger.info(expectedMessage);
const levels = Object.values(LogLevel).filter((value) => !isNaN(Number(value))) as LogLevel[];

expect(log).toHaveBeenCalledWith(LEVEL_CHALK[LogLevel.INFO](`[info]: ${expectedMessage}`));
});
});
for (const level of levels) {
const name = LogLevel[level].toLowerCase();

describe('func(silly)', () => {
it('should output a console log with the expected level', () => {
const expectedMessage = chance.word();
describe(`func(${name})`, () => {
it('should output a console log with the expected level', () => {
const expectedMessage = chance.word();

Logger.silly(expectedMessage);
Logger[name](expectedMessage);

expect(log).toHaveBeenCalledWith(LEVEL_CHALK[LogLevel.SILLY](`[silly]: ${expectedMessage}`));
validate(level, expectedMessage);
});
});
});
}
});
14 changes: 5 additions & 9 deletions src/logger.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Chalk, red, yellow, cyan, magenta } from 'chalk';
import { stringify } from './utils/stringify';
import { sanitizeMessages } from './utils/messages';

export enum LogLevel {
ERROR,
Expand Down Expand Up @@ -42,15 +42,11 @@ export class Logger {

const chalk = LEVEL_CHALK[level];

const messages = rawMessages.map((rawMessage) => {
return typeof rawMessage === 'object' ? stringify(rawMessage) : rawMessage;
});

console.log(
chalk(
`${`[${LogLevel[level].toLowerCase()}]:`.padEnd(MAX_LENGTH, ' ')} ${messages.join(' ')}`
)
const messages = sanitizeMessages(rawMessages).map((message) =>
message instanceof Error ? message : chalk(message)
);

console.log(chalk(`[${LogLevel[level].toLowerCase()}]:`).padEnd(MAX_LENGTH, ' '), ...messages);
}

public static error(...message: any[]) {
Expand Down
22 changes: 22 additions & 0 deletions src/utils/__tests__/messages.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { sanitizeMessages } from '../messages';
import { stringify } from '../stringify';

describe('util(Messages)', () => {
describe('func(sanitizeMessages)', () => {
it('should leave strings alone', () => {
expect(sanitizeMessages(['hello world'])).toEqual(['hello world']);
});

it('should errors alone', () => {
const error = new Error('hello world');

expect(sanitizeMessages([error])).toEqual([error]);
});

it('should stringify objects', () => {
const expectedObject = { hello: 'world' };

expect(sanitizeMessages([expectedObject])).toEqual([stringify(expectedObject)]);
});
});
});
11 changes: 11 additions & 0 deletions src/utils/messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { stringify } from './stringify';

export function sanitizeMessages(messages: any[]): any[] {
return messages.map((message) => {
if (message instanceof Error || typeof message !== 'object') {
return message;
}

return stringify(message);
});
}
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1945,6 +1945,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@rain-cafe/logger@workspace:."
dependencies:
"@jest/types": ^29.6.1
"@types/jest": ^29.5.3
"@types/node": ^18
"@typescript-eslint/eslint-plugin": ^6.1.0
Expand Down

0 comments on commit 7c14f94

Please sign in to comment.