1- import { describe , it , expect , beforeEach , afterEach , vi } from 'vitest' ;
1+ import { describe , it , expect , beforeEach , afterEach , vi , type Mock } from 'vitest' ;
22import { useDiagnosticsLogger } from '../../src/runtime/composables/useDiagnosticsLogger' ;
3- import { LogLevel , type ILogHandler } from '@powersync/web' ;
43import { withSetup } from '../utils' ;
4+ import { LogLevels , type LogRecord , type PowerSyncLogger } from '@powersync/common' ;
55
66describe ( 'useDiagnosticsLogger' , ( ) => {
77 beforeEach ( ( ) => {
@@ -17,8 +17,7 @@ describe('useDiagnosticsLogger', () => {
1717 const [ { logger, logsStorage } ] = withSetup ( ( ) => useDiagnosticsLogger ( ) ) ;
1818
1919 const testMessage = 'Test log message for storage' ;
20- const extraPayload = { name : 'TestContext' , level : { name : 'INFO' } } ;
21- await logger . log ( testMessage , extraPayload as any ) ;
20+ await logger . log ( { level : LogLevels . info , message : testMessage , tag : 'TestContext' } ) ;
2221
2322 // Wait for async storage operations
2423 await new Promise ( ( resolve ) => setTimeout ( resolve , 150 ) ) ;
@@ -30,87 +29,64 @@ describe('useDiagnosticsLogger', () => {
3029 expect ( logKeys . length ) . toBeGreaterThan ( 0 ) ;
3130
3231 // Find the log that contains our message (key order may vary)
33- let storedLog : { args ?: unknown [ ] } | null = null ;
32+ let storedLog : { message : string } | null = null ;
3433 for ( const key of logKeys ) {
35- const log = ( await logsStorage . getItem ( key ) ) as { args ?: unknown [ ] } | null ;
36- const args = log ?. args ;
37- if ( args ?. some ( ( arg ) => typeof arg === 'string' && arg . includes ( testMessage ) ) ) {
34+ const log = ( await logsStorage . getItem ( key ) ) as { message : string } ;
35+ if ( log . message . indexOf ( testMessage ) >= 0 ) {
3836 storedLog = log ;
3937 break ;
4038 }
4139 }
4240
43- expect ( storedLog ) . toBeDefined ( ) ;
44- expect ( storedLog ) . toHaveProperty ( 'args' ) ;
45- expect ( Array . isArray ( storedLog ?. args ) ) . toBe ( true ) ;
46- const logArgs = storedLog ?. args as any [ ] ;
47- expect ( logArgs [ 0 ] ) . toBe ( testMessage ) ;
48- // args[1] is stored as-is (object, not "[object Object]")
49- expect ( logArgs [ 1 ] ) . toBeDefined ( ) ;
50- expect ( logArgs [ 1 ] ) . toHaveProperty ( 'name' , 'TestContext' ) ;
51- expect ( logArgs [ 2 ] ) . toBeDefined ( ) ;
52- expect ( logArgs [ 2 ] ) . toHaveProperty ( 'level' ) ;
41+ expect ( storedLog ) . toMatchObject ( {
42+ tag : 'TestContext' ,
43+ level : 'INFO' ,
44+ message : testMessage
45+ } ) ;
5346 } ) ;
5447
5548 it ( 'should emit log events with correct payload structure' , async ( ) => {
5649 const logEvents : any [ ] = [ ] ;
5750 const [ { logger, emitter } ] = withSetup ( ( ) => useDiagnosticsLogger ( ) ) ;
58-
51+
5952 // Listen for log events
6053 emitter . on ( 'log' , ( event ) => {
6154 logEvents . push ( event ) ;
6255 } ) ;
63-
56+
6457 const testMessage = 'Test event message' ;
65- await logger . log ( testMessage , {
66- name : 'TestContext' ,
67- level : { name : 'WARN' }
58+ await logger . log ( {
59+ message : testMessage ,
60+ tag : 'TestContext' ,
61+ level : LogLevels . warn
6862 } as any ) ;
69-
63+
7064 // Wait for async operations
71- await new Promise ( resolve => setTimeout ( resolve , 150 ) ) ;
72-
65+ await new Promise ( ( resolve ) => setTimeout ( resolve , 150 ) ) ;
66+
7367 // Verify event was emitted with correct structure
7468 expect ( logEvents . length ) . toBeGreaterThan ( 0 ) ;
7569 const event = logEvents [ 0 ] ;
76- expect ( event ) . toHaveProperty ( 'key' ) ;
77- expect ( event ) . toHaveProperty ( 'value' ) ;
78- expect ( typeof event . key ) . toBe ( 'string' ) ;
79- expect ( event . key ) . toMatch ( / ^ l o g : / ) ;
80- expect ( event . value ) . toBeDefined ( ) ;
81- expect ( event . value ) . toHaveProperty ( 'args' ) ;
70+ expect ( event . value ) . toMatchObject ( {
71+ tag : 'TestContext' ,
72+ message : testMessage ,
73+ level : 'WARNING'
74+ } ) ;
8275 } ) ;
8376
8477 it ( 'should call custom handler with correct messages and context' , async ( ) => {
85- const customHandler = vi . fn < ILogHandler > ( ) ;
86- const [ { logger } ] = withSetup ( ( ) => useDiagnosticsLogger ( customHandler ) ) ;
78+ const log = vi . fn ( ( _record : LogRecord ) => { } ) ;
79+ const [ { logger } ] = withSetup ( ( ) => useDiagnosticsLogger ( { log } ) ) ;
8780
88- const testMessages = [ 'Message 1' , 'Message 2' ] ;
89- const testContext = { name : 'TestContext' , level : { name : 'ERROR' } } as any ;
90-
91- await logger . log ( testMessages , testContext ) ;
81+ await logger . log ( { level : LogLevels . warn , message : 'Message 1' , tag : 'TestContext' } ) ;
9282
9383 // Wait for async handler
9484 await new Promise ( ( resolve ) => setTimeout ( resolve , 150 ) ) ;
9585
96- expect ( customHandler ) . toHaveBeenCalledTimes ( 1 ) ;
97- const [ messages , context ] = customHandler . mock . calls [ 0 ] ;
98-
99- const messagesArray = Array . from ( messages ) ;
100- expect ( messagesArray . length ) . toBeGreaterThan ( 0 ) ;
101- // First argument to log() is what we passed (array or string)
102- const firstArg = messagesArray [ 0 ] ;
103- const hasMessage1 =
104- ( Array . isArray ( firstArg ) && firstArg . includes ( 'Message 1' ) ) ||
105- ( typeof firstArg === 'string' && firstArg . includes ( 'Message 1' ) ) ;
106- expect ( hasMessage1 ) . toBe ( true ) ;
107- // When two args passed to log(), second is in messages (js-logger passes all log args)
108- if ( messagesArray . length > 1 && typeof messagesArray [ 1 ] === 'object' && messagesArray [ 1 ] ?. name ) {
109- expect ( messagesArray [ 1 ] . name ) . toBe ( 'TestContext' ) ;
110- expect ( messagesArray [ 1 ] . level ?. name ) . toBe ( 'ERROR' ) ;
111- }
112- expect ( context ) . toBeDefined ( ) ;
113- expect ( context . level ?. name ) . toBeDefined ( ) ;
86+ expect ( log ) . toHaveBeenCalledTimes ( 1 ) ;
87+ const [ record ] = log . mock . calls [ 0 ] ;
88+
89+ expect ( record ) . toStrictEqual ( { level : LogLevels . warn , message : 'Message 1' , tag : 'TestContext' } ) ;
11490 } ) ;
11591
11692 it ( 'should format messages with PowerSync prefix to console' , async ( ) => {
@@ -120,46 +96,15 @@ describe('useDiagnosticsLogger', () => {
12096 const [ { logger } ] = withSetup ( ( ) => useDiagnosticsLogger ( ) ) ;
12197
12298 const testMessage = 'Test formatted message' ;
123- await logger . log ( [ testMessage , 'Extra data' ] , {
124- name : 'PowerSyncTest' ,
125- level : { name : 'INFO' }
126- } as any ) ;
99+ await logger . log ( { message : testMessage , level : LogLevels . info , tag : 'tag' } ) ;
127100
128101 await new Promise ( ( resolve ) => setTimeout ( resolve , 150 ) ) ;
129102
130103 expect ( consoleSpy ) . toHaveBeenCalled ( ) ;
131- const hasPowerSyncPrefix = consoleSpy . mock . calls . some ( ( call ) => {
132- const firstArg = call [ 0 ] ;
133- return typeof firstArg === 'string' && firstArg . includes ( '[PowerSync]' ) ;
134- } ) ;
135- expect ( hasPowerSyncPrefix ) . toBe ( true ) ;
104+ expect ( consoleSpy . mock . calls . map ( ( call ) => call [ 0 ] ) ) . toEqual (
105+ expect . arrayContaining ( [ expect . stringContaining ( '[PowerSync.tag]' ) ] )
106+ ) ;
136107
137108 consoleSpy . mockRestore ( ) ;
138109 } ) ;
139-
140- it ( 'should store object as extra arg (not "[object Object]")' , async ( ) => {
141- const [ { logger, logsStorage } ] = withSetup ( ( ) => useDiagnosticsLogger ( ) ) ;
142-
143- const payload = { userId : 'u1' , synced : true } ;
144- await logger . log ( 'User is logged in' , payload ) ;
145-
146- await new Promise ( ( resolve ) => setTimeout ( resolve , 150 ) ) ;
147-
148- const allKeys = await logsStorage . getKeys ( ) ;
149- const logKeys = allKeys . filter ( ( key : string ) => key . startsWith ( 'log:' ) ) ;
150- expect ( logKeys . length ) . toBeGreaterThan ( 0 ) ;
151-
152- const storedLog = ( await logsStorage . getItem ( logKeys [ 0 ] ) ) as { args ?: unknown [ ] } | null ;
153- const args = storedLog ?. args ;
154- expect ( args ) . toBeDefined ( ) ;
155- expect ( args ?. length ) . toBeGreaterThanOrEqual ( 2 ) ;
156- expect ( args ?. [ 1 ] ) . toEqual ( payload ) ;
157- expect ( args ?. [ 1 ] ) . not . toBe ( '[object Object]' ) ;
158- } ) ;
159-
160- it ( 'should configure logger with DEBUG level' , ( ) => {
161- const [ { logger } ] = withSetup ( ( ) => useDiagnosticsLogger ( ) ) ;
162-
163- expect ( logger . getLevel ( ) ) . toBe ( LogLevel . DEBUG ) ;
164- } ) ;
165110} ) ;
0 commit comments