11import { afterEach , beforeEach , describe , expect , it } from 'vitest' ;
22
33import { DebugLogger } from '../logger' ;
4- import type { DebugLogEntry , DebugLogFilter } from '../types' ;
4+ import type { DebugLogEntry } from '../types' ;
55
6- // Mock transport for testing
76class MockTransport {
87 public sentEntries : DebugLogEntry [ ] = [ ] ;
98
@@ -22,7 +21,7 @@ describe('DebugLogger', () => {
2221
2322 beforeEach ( ( ) => {
2423 mockTransport = new MockTransport ( ) ;
25- logger = new DebugLogger ( mockTransport , 'trace ' ) ;
24+ logger = new DebugLogger ( mockTransport , 'debug ' ) ;
2625 } ) ;
2726
2827 afterEach ( ( ) => {
@@ -35,14 +34,12 @@ describe('DebugLogger', () => {
3534 logger . warn ( 'warn message' ) ;
3635 logger . info ( 'info message' ) ;
3736 logger . debug ( 'debug message' ) ;
38- logger . trace ( 'trace message' ) ;
3937
40- expect ( mockTransport . sentEntries ) . toHaveLength ( 5 ) ;
38+ expect ( mockTransport . sentEntries ) . toHaveLength ( 4 ) ;
4139 expect ( mockTransport . sentEntries [ 0 ] . level ) . toBe ( 'error' ) ;
4240 expect ( mockTransport . sentEntries [ 1 ] . level ) . toBe ( 'warn' ) ;
4341 expect ( mockTransport . sentEntries [ 2 ] . level ) . toBe ( 'info' ) ;
4442 expect ( mockTransport . sentEntries [ 3 ] . level ) . toBe ( 'debug' ) ;
45- expect ( mockTransport . sentEntries [ 4 ] . level ) . toBe ( 'trace' ) ;
4643 } ) ;
4744
4845 it ( 'should include context and source in log entries' , ( ) => {
@@ -59,7 +56,6 @@ describe('DebugLogger', () => {
5956 it ( 'should respect log level filtering' , ( ) => {
6057 const infoLogger = new DebugLogger ( mockTransport , 'info' ) ;
6158
62- infoLogger . trace ( 'trace message' ) ;
6359 infoLogger . debug ( 'debug message' ) ;
6460 infoLogger . info ( 'info message' ) ;
6561 infoLogger . warn ( 'warn message' ) ;
@@ -70,267 +66,64 @@ describe('DebugLogger', () => {
7066 } ) ;
7167 } ) ;
7268
73- describe ( 'filter functionality' , ( ) => {
74- describe ( 'level filtering' , ( ) => {
75- it ( 'should filter by specific log level' , ( ) => {
76- const filters : DebugLogFilter [ ] = [ { level : 'error' } ] ;
77- const filteredLogger = new DebugLogger ( mockTransport , 'debug' , filters ) ;
69+ describe ( 'edge cases' , ( ) => {
70+ it ( 'should handle undefined context' , ( ) => {
71+ logger . info ( 'message with undefined context' , undefined ) ;
7872
79- filteredLogger . info ( 'info message' ) ;
80- filteredLogger . warn ( 'warn message' ) ;
81- filteredLogger . error ( 'error message' ) ;
82-
83- expect ( mockTransport . sentEntries ) . toHaveLength ( 1 ) ;
84- expect ( mockTransport . sentEntries [ 0 ] . level ) . toBe ( 'error' ) ;
85- } ) ;
86-
87- it ( 'should allow all levels when no level filter is specified' , ( ) => {
88- const filters : DebugLogFilter [ ] = [ { } ] ;
89- const filteredLogger = new DebugLogger ( mockTransport , 'debug' , filters ) ;
90-
91- filteredLogger . info ( 'info message' ) ;
92- filteredLogger . warn ( 'warn message' ) ;
93- filteredLogger . error ( 'error message' ) ;
94-
95- expect ( mockTransport . sentEntries ) . toHaveLength ( 3 ) ;
96- } ) ;
97- } ) ;
98-
99- describe ( 'source filtering' , ( ) => {
100- it ( 'should filter by exact string source' , ( ) => {
101- const filters : DebugLogFilter [ ] = [ { source : 'auth-module' } ] ;
102- const filteredLogger = new DebugLogger ( mockTransport , 'debug' , filters ) ;
103-
104- filteredLogger . info ( 'message 1' , undefined , 'auth-module' ) ;
105- filteredLogger . info ( 'message 2' , undefined , 'other-module' ) ;
106- filteredLogger . info ( 'message 3' , undefined , 'auth-module' ) ;
107-
108- expect ( mockTransport . sentEntries ) . toHaveLength ( 2 ) ;
109- expect ( mockTransport . sentEntries [ 0 ] . source ) . toBe ( 'auth-module' ) ;
110- expect ( mockTransport . sentEntries [ 1 ] . source ) . toBe ( 'auth-module' ) ;
111- } ) ;
112-
113- it ( 'should filter by RegExp source pattern' , ( ) => {
114- const filters : DebugLogFilter [ ] = [ { source : / a u t h - .* / } ] ;
115- const filteredLogger = new DebugLogger ( mockTransport , 'debug' , filters ) ;
116-
117- filteredLogger . info ( 'message 1' , undefined , 'auth-module' ) ;
118- filteredLogger . info ( 'message 2' , undefined , 'auth-service' ) ;
119- filteredLogger . info ( 'message 3' , undefined , 'other-module' ) ;
120-
121- expect ( mockTransport . sentEntries ) . toHaveLength ( 2 ) ;
122- expect ( mockTransport . sentEntries [ 0 ] . source ) . toBe ( 'auth-module' ) ;
123- expect ( mockTransport . sentEntries [ 1 ] . source ) . toBe ( 'auth-service' ) ;
124- } ) ;
125-
126- it ( 'should not log when source is undefined and filter expects a source' , ( ) => {
127- const filters : DebugLogFilter [ ] = [ { source : 'auth-module' } ] ;
128- const filteredLogger = new DebugLogger ( mockTransport , 'debug' , filters ) ;
129-
130- filteredLogger . info ( 'message without source' ) ;
131-
132- expect ( mockTransport . sentEntries ) . toHaveLength ( 0 ) ;
133- } ) ;
134- } ) ;
135-
136- describe ( 'include pattern filtering' , ( ) => {
137- it ( 'should include messages matching string patterns' , ( ) => {
138- const filters : DebugLogFilter [ ] = [ { includePatterns : [ 'user' , 'auth' ] } ] ;
139- const filteredLogger = new DebugLogger ( mockTransport , 'debug' , filters ) ;
140-
141- filteredLogger . info ( 'user login successful' ) ;
142- filteredLogger . info ( 'auth token refreshed' ) ;
143- filteredLogger . info ( 'database connection established' ) ;
144-
145- expect ( mockTransport . sentEntries ) . toHaveLength ( 2 ) ;
146- expect ( mockTransport . sentEntries [ 0 ] . message ) . toBe ( 'user login successful' ) ;
147- expect ( mockTransport . sentEntries [ 1 ] . message ) . toBe ( 'auth token refreshed' ) ;
148- } ) ;
149-
150- it ( 'should include messages matching RegExp patterns' , ( ) => {
151- const filters : DebugLogFilter [ ] = [ { includePatterns : [ / u s e r - .* / ] } ] ;
152- const filteredLogger = new DebugLogger ( mockTransport , 'debug' , filters ) ;
153-
154- filteredLogger . info ( 'user-123 logged in' ) ;
155- filteredLogger . info ( 'user-456 logged out' ) ;
156- filteredLogger . info ( 'admin panel accessed' ) ;
157-
158- expect ( mockTransport . sentEntries ) . toHaveLength ( 2 ) ;
159- expect ( mockTransport . sentEntries [ 0 ] . message ) . toBe ( 'user-123 logged in' ) ;
160- expect ( mockTransport . sentEntries [ 1 ] . message ) . toBe ( 'user-456 logged out' ) ;
161- } ) ;
162- } ) ;
163-
164- describe ( 'exclude pattern filtering' , ( ) => {
165- it ( 'should exclude messages matching string patterns' , ( ) => {
166- const filters : DebugLogFilter [ ] = [ { excludePatterns : [ 'debug' , 'test' ] } ] ;
167- const filteredLogger = new DebugLogger ( mockTransport , 'debug' , filters ) ;
168-
169- filteredLogger . info ( 'user login successful' ) ;
170- filteredLogger . info ( 'debug information logged' ) ;
171- filteredLogger . info ( 'test data generated' ) ;
172-
173- expect ( mockTransport . sentEntries ) . toHaveLength ( 1 ) ;
174- expect ( mockTransport . sentEntries [ 0 ] . message ) . toBe ( 'user login successful' ) ;
175- } ) ;
176-
177- it ( 'should exclude messages matching RegExp patterns' , ( ) => {
178- const filters : DebugLogFilter [ ] = [ { excludePatterns : [ / t e s t - .* / ] } ] ;
179- const filteredLogger = new DebugLogger ( mockTransport , 'debug' , filters ) ;
180-
181- filteredLogger . info ( 'user login successful' ) ;
182- filteredLogger . info ( 'test-123 created' ) ;
183- filteredLogger . info ( 'test-456 deleted' ) ;
184-
185- expect ( mockTransport . sentEntries ) . toHaveLength ( 1 ) ;
186- expect ( mockTransport . sentEntries [ 0 ] . message ) . toBe ( 'user login successful' ) ;
187- } ) ;
73+ expect ( mockTransport . sentEntries ) . toHaveLength ( 1 ) ;
74+ expect ( mockTransport . sentEntries [ 0 ] . context ) . toBeUndefined ( ) ;
18875 } ) ;
18976
190- // Note: userId and sessionId filtering are defined in types but not yet implemented
191- // These tests are commented out until the feature is implemented
192- /*
193- describe('userId filtering', () => {
194- it('should filter by specific userId', () => {
195- const filters: DebugLogFilter[] = [{ userId: 'user-123' }];
196- const filteredLogger = new DebugLogger(mockTransport, 'debug', filters);
197-
198- filteredLogger.info('message 1', { userId: 'user-123' });
199- filteredLogger.info('message 2', { userId: 'user-456' });
200- filteredLogger.info('message 3', { userId: 'user-123' });
201-
202- expect(mockTransport.sentEntries).toHaveLength(2);
203- expect(mockTransport.sentEntries[0].context?.userId).toBe('user-123');
204- expect(mockTransport.sentEntries[1].context?.userId).toBe('user-123');
205- });
77+ it ( 'should handle undefined source' , ( ) => {
78+ logger . info ( 'message with undefined source' , { } , undefined ) ;
20679
207- it('should not log when userId is undefined and filter expects a userId', () => {
208- const filters: DebugLogFilter[] = [{ userId: 'user-123' }];
209- const filteredLogger = new DebugLogger(mockTransport, 'debug', filters);
210-
211- filteredLogger.info('message without userId');
212-
213- expect(mockTransport.sentEntries).toHaveLength(0);
214- });
80+ expect ( mockTransport . sentEntries ) . toHaveLength ( 1 ) ;
81+ expect ( mockTransport . sentEntries [ 0 ] . source ) . toBeUndefined ( ) ;
21582 } ) ;
21683
217- describe('sessionId filtering', () => {
218- it('should filter by specific sessionId', () => {
219- const filters: DebugLogFilter[] = [{ sessionId: 'session-abc' }];
220- const filteredLogger = new DebugLogger(mockTransport, 'debug', filters);
84+ it ( 'should handle empty context object' , ( ) => {
85+ logger . info ( 'message with empty context' , { } ) ;
22186
222- filteredLogger.info('message 1', { sessionId: 'session-abc' });
223- filteredLogger.info('message 2', { sessionId: 'session-xyz' });
224- filteredLogger.info('message 3', { sessionId: 'session-abc' });
225-
226- expect(mockTransport.sentEntries).toHaveLength(2);
227- expect(mockTransport.sentEntries[0].context?.sessionId).toBe('session-abc');
228- expect(mockTransport.sentEntries[1].context?.sessionId).toBe('session-abc');
229- });
230-
231- it('should not log when sessionId is undefined and filter expects a sessionId', () => {
232- const filters: DebugLogFilter[] = [{ sessionId: 'session-abc' }];
233- const filteredLogger = new DebugLogger(mockTransport, 'debug', filters);
234-
235- filteredLogger.info('message without sessionId');
236-
237- expect(mockTransport.sentEntries).toHaveLength(0);
238- });
87+ expect ( mockTransport . sentEntries ) . toHaveLength ( 1 ) ;
88+ expect ( mockTransport . sentEntries [ 0 ] . context ) . toEqual ( { } ) ;
23989 } ) ;
240- */
241-
242- describe ( 'combined filtering' , ( ) => {
243- it ( 'should apply multiple filters with AND logic' , ( ) => {
244- const filters : DebugLogFilter [ ] = [
245- { level : 'error' } ,
246- { source : 'auth-module' } ,
247- { includePatterns : [ 'failed' ] } ,
248- ] ;
249- const filteredLogger = new DebugLogger ( mockTransport , 'debug' , filters ) ;
250-
251- filteredLogger . error ( 'login failed' , undefined , 'auth-module' ) ;
252- filteredLogger . error ( 'login successful' , undefined , 'auth-module' ) ;
253- filteredLogger . warn ( 'login failed' , undefined , 'auth-module' ) ;
254- filteredLogger . error ( 'login failed' , undefined , 'other-module' ) ;
25590
256- expect ( mockTransport . sentEntries ) . toHaveLength ( 1 ) ;
257- expect ( mockTransport . sentEntries [ 0 ] . message ) . toBe ( 'login failed' ) ;
258- expect ( mockTransport . sentEntries [ 0 ] . level ) . toBe ( 'error' ) ;
259- expect ( mockTransport . sentEntries [ 0 ] . source ) . toBe ( 'auth-module' ) ;
260- } ) ;
91+ it ( 'should handle empty source string' , ( ) => {
92+ logger . info ( 'message with empty source' , { } , '' ) ;
26193
262- it ( 'should handle empty filters array' , ( ) => {
263- const filters : DebugLogFilter [ ] = [ ] ;
264- const filteredLogger = new DebugLogger ( mockTransport , 'debug' , filters ) ;
265-
266- filteredLogger . info ( 'message 1' ) ;
267- filteredLogger . warn ( 'message 2' ) ;
268- filteredLogger . error ( 'message 3' ) ;
269-
270- expect ( mockTransport . sentEntries ) . toHaveLength ( 3 ) ;
271- } ) ;
94+ expect ( mockTransport . sentEntries ) . toHaveLength ( 1 ) ;
95+ expect ( mockTransport . sentEntries [ 0 ] . source ) . toBe ( '' ) ;
27296 } ) ;
97+ } ) ;
27398
274- describe ( 'edge cases' , ( ) => {
275- it ( 'should handle undefined context' , ( ) => {
276- logger . info ( 'message with undefined context' , undefined ) ;
277-
278- expect ( mockTransport . sentEntries ) . toHaveLength ( 1 ) ;
279- expect ( mockTransport . sentEntries [ 0 ] . context ) . toBeUndefined ( ) ;
280- } ) ;
281-
282- it ( 'should handle undefined source' , ( ) => {
283- logger . info ( 'message with undefined source' , { } , undefined ) ;
284-
285- expect ( mockTransport . sentEntries ) . toHaveLength ( 1 ) ;
286- expect ( mockTransport . sentEntries [ 0 ] . source ) . toBeUndefined ( ) ;
287- } ) ;
99+ describe ( 'transport integration' , ( ) => {
100+ it ( 'should call transport.send for each log entry' , async ( ) => {
101+ let sendCallCount = 0 ;
102+ const countingTransport = {
103+ async send ( _entry : DebugLogEntry ) : Promise < void > {
104+ sendCallCount ++ ;
105+ } ,
106+ } ;
288107
289- it ( 'should handle empty context object' , ( ) => {
290- logger . info ( 'message with empty context' , { } ) ;
108+ const testLogger = new DebugLogger ( countingTransport , 'info' ) ;
291109
292- expect ( mockTransport . sentEntries ) . toHaveLength ( 1 ) ;
293- expect ( mockTransport . sentEntries [ 0 ] . context ) . toEqual ( { } ) ;
294- } ) ;
110+ testLogger . info ( 'message 1' ) ;
111+ testLogger . warn ( 'message 2' ) ;
112+ testLogger . error ( 'message 3' ) ;
295113
296- it ( 'should handle empty source string' , ( ) => {
297- logger . info ( 'message with empty source' , { } , '' ) ;
114+ await new Promise ( resolve => setTimeout ( resolve , 0 ) ) ;
298115
299- expect ( mockTransport . sentEntries ) . toHaveLength ( 1 ) ;
300- expect ( mockTransport . sentEntries [ 0 ] . source ) . toBe ( '' ) ;
301- } ) ;
116+ expect ( sendCallCount ) . toBe ( 3 ) ;
302117 } ) ;
303118
304- describe ( 'transport integration' , ( ) => {
305- it ( 'should call transport.send for each log entry' , async ( ) => {
306- let sendCallCount = 0 ;
307- const countingTransport = {
308- async send ( _entry : DebugLogEntry ) : Promise < void > {
309- sendCallCount ++ ;
310- } ,
311- } ;
119+ it ( 'should include timestamp in log entries' , ( ) => {
120+ const beforeTime = Date . now ( ) ;
121+ logger . info ( 'test message' ) ;
122+ const afterTime = Date . now ( ) ;
312123
313- const testLogger = new DebugLogger ( countingTransport , 'info' ) ;
314-
315- testLogger . info ( 'message 1' ) ;
316- testLogger . warn ( 'message 2' ) ;
317- testLogger . error ( 'message 3' ) ;
318-
319- // Allow async operations to complete
320- await new Promise ( resolve => setTimeout ( resolve , 0 ) ) ;
321-
322- expect ( sendCallCount ) . toBe ( 3 ) ;
323- } ) ;
324-
325- it ( 'should include timestamp in log entries' , ( ) => {
326- const beforeTime = Date . now ( ) ;
327- logger . info ( 'test message' ) ;
328- const afterTime = Date . now ( ) ;
329-
330- expect ( mockTransport . sentEntries ) . toHaveLength ( 1 ) ;
331- expect ( mockTransport . sentEntries [ 0 ] . timestamp ) . toBeGreaterThanOrEqual ( beforeTime ) ;
332- expect ( mockTransport . sentEntries [ 0 ] . timestamp ) . toBeLessThanOrEqual ( afterTime ) ;
333- } ) ;
124+ expect ( mockTransport . sentEntries ) . toHaveLength ( 1 ) ;
125+ expect ( mockTransport . sentEntries [ 0 ] . timestamp ) . toBeGreaterThanOrEqual ( beforeTime ) ;
126+ expect ( mockTransport . sentEntries [ 0 ] . timestamp ) . toBeLessThanOrEqual ( afterTime ) ;
334127 } ) ;
335128 } ) ;
336129} ) ;
0 commit comments