Skip to content

Commit d3aaa34

Browse files
committed
feat: create logger module
1 parent 93e0cbe commit d3aaa34

File tree

12 files changed

+944
-0
lines changed

12 files changed

+944
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { ok, strictEqual } from 'node:assert';
2+
import { describe, it } from 'node:test';
3+
4+
import { Logger } from '../index.mjs';
5+
6+
describe('Logger singleton', () => {
7+
it('should return the same instance on multiple calls', () => {
8+
const logger1 = Logger.getInstance();
9+
const logger2 = Logger.getInstance();
10+
11+
strictEqual(logger1, logger2);
12+
});
13+
14+
it('should create an instance of logger', () => {
15+
const logger = Logger.getInstance();
16+
17+
ok(logger);
18+
});
19+
});
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
import { deepStrictEqual, strictEqual } from 'node:assert';
2+
import { describe, it } from 'node:test';
3+
4+
import { LogLevel } from '../constants.mjs';
5+
import { createLogger } from '../logger.mjs';
6+
7+
/**
8+
* @type {import('../types').Metadata}
9+
*/
10+
const metadata = {
11+
file: {
12+
path: 'test.md',
13+
position: {
14+
start: { line: 1 },
15+
end: { line: 1 },
16+
},
17+
},
18+
};
19+
20+
describe('createLogger', () => {
21+
describe('DEBUG', () => {
22+
it('should log DEBUG messages when logger level is set to DEBUG', t => {
23+
t.mock.timers.enable({ apis: ['Date'] });
24+
25+
const transport = t.mock.fn();
26+
27+
const logger = createLogger(transport, LogLevel.debug);
28+
29+
logger.debug('Hello, World!', metadata);
30+
31+
strictEqual(transport.mock.callCount(), 1);
32+
33+
const call = transport.mock.calls[0];
34+
deepStrictEqual(call.arguments, [
35+
{
36+
level: LogLevel.debug,
37+
message: 'Hello, World!',
38+
metadata,
39+
timestamp: 0,
40+
},
41+
]);
42+
});
43+
44+
it('should filter DEBUG messages when logger level is set to INFO or higher', t => {
45+
[LogLevel.info, LogLevel.warn, LogLevel.error, LogLevel.fatal].forEach(
46+
loggerLevel => {
47+
const transport = t.mock.fn();
48+
49+
const logger = createLogger(transport, loggerLevel);
50+
51+
logger.debug('Hello, World!');
52+
53+
strictEqual(transport.mock.callCount(), 0);
54+
}
55+
);
56+
});
57+
});
58+
59+
describe('INFO', () => {
60+
it('should log INFO messages when logger level is set to INFO or lower', t => {
61+
t.mock.timers.enable({ apis: ['Date'] });
62+
[LogLevel.info, LogLevel.debug].forEach(loggerLevel => {
63+
const transport = t.mock.fn();
64+
65+
const logger = createLogger(transport, loggerLevel);
66+
67+
logger.info('Hello, World!', metadata);
68+
69+
strictEqual(transport.mock.callCount(), 1);
70+
71+
const call = transport.mock.calls[0];
72+
deepStrictEqual(call.arguments, [
73+
{
74+
level: LogLevel.info,
75+
message: 'Hello, World!',
76+
metadata,
77+
timestamp: 0,
78+
},
79+
]);
80+
});
81+
});
82+
83+
it('should filter INFO messages when logger level is set to WARN or higher', t => {
84+
[LogLevel.warn, LogLevel.error, LogLevel.fatal].forEach(loggerLevel => {
85+
const transport = t.mock.fn();
86+
87+
const logger = createLogger(transport, loggerLevel);
88+
89+
logger.info('Hello, World!');
90+
91+
strictEqual(transport.mock.callCount(), 0);
92+
});
93+
});
94+
});
95+
96+
describe('WARN', () => {
97+
it('should log WARN messages when logger level is set to WARN or lower', t => {
98+
t.mock.timers.enable({ apis: ['Date'] });
99+
100+
[LogLevel.warn, LogLevel.info, LogLevel.debug].forEach(loggerLevel => {
101+
const transport = t.mock.fn();
102+
103+
const logger = createLogger(transport, loggerLevel);
104+
105+
logger.warn('Hello, World!', metadata);
106+
107+
strictEqual(transport.mock.callCount(), 1);
108+
109+
const call = transport.mock.calls[0];
110+
deepStrictEqual(call.arguments, [
111+
{
112+
level: LogLevel.warn,
113+
message: 'Hello, World!',
114+
metadata,
115+
timestamp: 0,
116+
},
117+
]);
118+
});
119+
});
120+
121+
it('should filter WARN messages when logger level is set to ERROR or higher', t => {
122+
[LogLevel.error, LogLevel.fatal].forEach(loggerLevel => {
123+
const transport = t.mock.fn();
124+
125+
const logger = createLogger(transport, loggerLevel);
126+
127+
logger.warn('Hello, World!');
128+
129+
strictEqual(transport.mock.callCount(), 0);
130+
});
131+
});
132+
});
133+
134+
describe('ERROR', () => {
135+
it('should log ERROR messages when logger level is set to ERROR or lower', t => {
136+
t.mock.timers.enable({ apis: ['Date'] });
137+
138+
[LogLevel.error, LogLevel.warn, LogLevel.info, LogLevel.debug].forEach(
139+
loggerLevel => {
140+
const transport = t.mock.fn();
141+
142+
const logger = createLogger(transport, loggerLevel);
143+
144+
logger.error('Hello, World!', metadata);
145+
146+
strictEqual(transport.mock.callCount(), 1);
147+
148+
const call = transport.mock.calls[0];
149+
deepStrictEqual(call.arguments, [
150+
{
151+
level: LogLevel.error,
152+
message: 'Hello, World!',
153+
metadata,
154+
timestamp: 0,
155+
},
156+
]);
157+
}
158+
);
159+
});
160+
161+
it('should filter ERROR messages when logger level is set to FATAL', t => {
162+
const transport = t.mock.fn();
163+
164+
const logger = createLogger(transport, LogLevel.fatal);
165+
166+
logger.warn('Hello, World!');
167+
168+
strictEqual(transport.mock.callCount(), 0);
169+
});
170+
});
171+
172+
it('should filter all messages when minimum level is set above FATAL', t => {
173+
const transport = t.mock.fn();
174+
175+
// silent logs
176+
const logger = createLogger(transport, 100);
177+
178+
Object.keys(LogLevel).forEach(level => {
179+
logger[level]('Hello, World!');
180+
});
181+
182+
strictEqual(transport.mock.callCount(), 0);
183+
});
184+
});

0 commit comments

Comments
 (0)