@@ -4,6 +4,7 @@ import { ProxyAgent } from "proxy-agent";
4
4
import { describe , it , expect , vi , beforeAll } from "vitest" ;
5
5
import { Inbox } from "./inbox" ;
6
6
import { Storage } from "./storage" ;
7
+ import { createMockOutputChannelWithLogger } from "./test-helpers" ;
7
8
8
9
// Mock dependencies
9
10
vi . mock ( "ws" ) ;
@@ -161,4 +162,178 @@ describe("inbox", () => {
161
162
) ;
162
163
expect ( mockWebSocket . close ) . toHaveBeenCalled ( ) ;
163
164
} ) ;
165
+
166
+ describe ( "Logger integration" , ( ) => {
167
+ it ( "should log messages through Logger when Storage has Logger set" , async ( ) => {
168
+ const { logger} = createMockOutputChannelWithLogger ( ) ;
169
+
170
+ // Mock WebSocket
171
+ let openHandler :( ( ) => void ) | undefined ;
172
+ const mockWebSocket = {
173
+ on :vi . fn ( ( event , handler ) => {
174
+ if ( event === "open" ) {
175
+ openHandler = handler ;
176
+ }
177
+ } ) ,
178
+ close :vi . fn ( ) ,
179
+ } ;
180
+ const { WebSocket :MockWebSocket } = await import ( "ws" ) ;
181
+ vi . mocked ( MockWebSocket ) . mockImplementation ( ( ) => mockWebSocket as never ) ;
182
+
183
+ const mockWorkspace = { id :"workspace-123" } as Workspace ;
184
+ const mockHttpAgent = { } as ProxyAgent ;
185
+ const mockRestClient = {
186
+ getAxiosInstance :vi . fn ( ( ) => ( {
187
+ defaults :{
188
+ baseURL :"https://test.com" ,
189
+ headers :{
190
+ common :{ } ,
191
+ } ,
192
+ } ,
193
+ } ) ) ,
194
+ } as unknown as Api ;
195
+
196
+ // Create mock Storage that uses Logger
197
+ const mockStorage = {
198
+ writeToCoderOutputChannel :vi . fn ( ( msg :string ) => {
199
+ logger . info ( msg ) ;
200
+ } ) ,
201
+ } as unknown as Storage ;
202
+
203
+ new Inbox ( mockWorkspace , mockHttpAgent , mockRestClient , mockStorage ) ;
204
+
205
+ // Trigger open event
206
+ openHandler ?.( ) ;
207
+
208
+ // Verify "Listening to Coder Inbox" was logged
209
+ expect ( mockStorage . writeToCoderOutputChannel ) . toHaveBeenCalledWith (
210
+ "Listening to Coder Inbox" ,
211
+ ) ;
212
+
213
+ const logs = logger . getLogs ( ) ;
214
+ expect ( logs . length ) . toBe ( 1 ) ;
215
+ expect ( logs [ 0 ] . message ) . toBe ( "Listening to Coder Inbox" ) ;
216
+ expect ( logs [ 0 ] . level ) . toBe ( "INFO" ) ;
217
+ } ) ;
218
+
219
+ it ( "should log dispose message through Logger" , async ( ) => {
220
+ const { logger} = createMockOutputChannelWithLogger ( ) ;
221
+
222
+ // Mock WebSocket
223
+ const mockWebSocket = {
224
+ on :vi . fn ( ) ,
225
+ close :vi . fn ( ) ,
226
+ } ;
227
+ const { WebSocket :MockWebSocket } = await import ( "ws" ) ;
228
+ vi . mocked ( MockWebSocket ) . mockImplementation ( ( ) => mockWebSocket as never ) ;
229
+
230
+ const mockWorkspace = { id :"workspace-123" } as Workspace ;
231
+ const mockHttpAgent = { } as ProxyAgent ;
232
+ const mockRestClient = {
233
+ getAxiosInstance :vi . fn ( ( ) => ( {
234
+ defaults :{
235
+ baseURL :"https://test.com" ,
236
+ headers :{
237
+ common :{ } ,
238
+ } ,
239
+ } ,
240
+ } ) ) ,
241
+ } as unknown as Api ;
242
+
243
+ // Create mock Storage that uses Logger
244
+ const mockStorage = {
245
+ writeToCoderOutputChannel :vi . fn ( ( msg :string ) => {
246
+ logger . info ( msg ) ;
247
+ } ) ,
248
+ } as unknown as Storage ;
249
+
250
+ const inbox = new Inbox (
251
+ mockWorkspace ,
252
+ mockHttpAgent ,
253
+ mockRestClient ,
254
+ mockStorage ,
255
+ ) ;
256
+
257
+ // Clear any logs from initialization
258
+ logger . clear ( ) ;
259
+ vi . mocked ( mockStorage . writeToCoderOutputChannel ) . mockClear ( ) ;
260
+
261
+ // Dispose
262
+ inbox . dispose ( ) ;
263
+
264
+ // Verify dispose message was logged
265
+ expect ( mockStorage . writeToCoderOutputChannel ) . toHaveBeenCalledWith (
266
+ "No longer listening to Coder Inbox" ,
267
+ ) ;
268
+
269
+ const logs = logger . getLogs ( ) ;
270
+ expect ( logs . length ) . toBe ( 1 ) ;
271
+ expect ( logs [ 0 ] . message ) . toBe ( "No longer listening to Coder Inbox" ) ;
272
+ } ) ;
273
+
274
+ it ( "should log error messages through Logger" , async ( ) => {
275
+ const { logger} = createMockOutputChannelWithLogger ( ) ;
276
+
277
+ // Mock WebSocket
278
+ let errorHandler :( ( error :Error ) => void ) | undefined ;
279
+ const mockWebSocket = {
280
+ on :vi . fn ( ( event , handler ) => {
281
+ if ( event === "error" ) {
282
+ errorHandler = handler ;
283
+ }
284
+ } ) ,
285
+ close :vi . fn ( ) ,
286
+ } ;
287
+ const { WebSocket :MockWebSocket } = await import ( "ws" ) ;
288
+ vi . mocked ( MockWebSocket ) . mockImplementation ( ( ) => mockWebSocket as never ) ;
289
+
290
+ // Mock errToStr
291
+ const { errToStr} = await import ( "./api-helper" ) ;
292
+ vi . mocked ( errToStr ) . mockReturnValue ( "WebSocket connection error" ) ;
293
+
294
+ const mockWorkspace = { id :"workspace-123" } as Workspace ;
295
+ const mockHttpAgent = { } as ProxyAgent ;
296
+ const mockRestClient = {
297
+ getAxiosInstance :vi . fn ( ( ) => ( {
298
+ defaults :{
299
+ baseURL :"https://test.com" ,
300
+ headers :{
301
+ common :{ } ,
302
+ } ,
303
+ } ,
304
+ } ) ) ,
305
+ } as unknown as Api ;
306
+
307
+ // Create mock Storage that uses Logger
308
+ const mockStorage = {
309
+ writeToCoderOutputChannel :vi . fn ( ( msg :string ) => {
310
+ logger . info ( msg ) ;
311
+ } ) ,
312
+ } as unknown as Storage ;
313
+
314
+ new Inbox ( mockWorkspace , mockHttpAgent , mockRestClient , mockStorage ) ;
315
+
316
+ // Clear any logs from initialization
317
+ logger . clear ( ) ;
318
+ vi . mocked ( mockStorage . writeToCoderOutputChannel ) . mockClear ( ) ;
319
+
320
+ // Trigger error event
321
+ const testError = new Error ( "Test WebSocket error" ) ;
322
+ errorHandler ?.( testError ) ;
323
+
324
+ // Verify error was logged
325
+ expect ( mockStorage . writeToCoderOutputChannel ) . toHaveBeenCalledWith (
326
+ "WebSocket connection error" ,
327
+ ) ;
328
+
329
+ // The second call should be for "No longer listening to Coder Inbox"
330
+ // because the error handler calls dispose()
331
+ expect ( mockStorage . writeToCoderOutputChannel ) . toHaveBeenCalledTimes ( 2 ) ;
332
+
333
+ const logs = logger . getLogs ( ) ;
334
+ expect ( logs . length ) . toBe ( 2 ) ;
335
+ expect ( logs [ 0 ] . message ) . toBe ( "WebSocket connection error" ) ;
336
+ expect ( logs [ 1 ] . message ) . toBe ( "No longer listening to Coder Inbox" ) ;
337
+ } ) ;
338
+ } ) ;
164
339
} ) ;