@@ -1355,14 +1355,15 @@ describe('startProxyServer', () => {
13551355 nock . enableNetConnect ( ( host ) => host . startsWith ( '127.0.0.1' ) || host . startsWith ( 'localhost' ) ) ;
13561356
13571357 // Ensure the http.createServer mock used by startProxyServer behaves asynchronously for listen and close
1358+ // This mock is specific to the 'startProxyServer' describe block.
13581359 vi . mocked ( http . createServer ) . mockImplementation ( ( ) => {
13591360 const serverInstance = {
1360- _listeners : { } as Record < string , ( ( ...args : any [ ] ) => void ) | undefined > ,
1361- _port : null as number | null , // Add _port to store the listening port
1362- _host : null as string | null , // Add _host to store the listening host
1361+ _listeners : { } as Record < string , ( ( ...args : any [ ] ) => void ) | ( ( ... args : any [ ] ) => void ) [ ] | undefined > ,
1362+ _port : null as number | null ,
1363+ _host : null as string | null ,
13631364 listen : vi . fn ( function ( this : any , portOrPathOrOptions : any , hostOrCb ?: any , backlogOrCb ?: any , cb ?: any ) {
13641365 let portToListen : number | undefined ;
1365- let hostToListen : string | undefined = 'localhost ' ; // Default host
1366+ let hostToListen : string | undefined = '127.0.0.1 ' ; // Default host for listen
13661367 let actualCallback : ( ( ) => void ) | undefined ;
13671368
13681369 if ( typeof portOrPathOrOptions === 'number' ) {
@@ -1374,7 +1375,7 @@ describe('startProxyServer', () => {
13741375 } else if ( typeof hostOrCb === 'function' ) {
13751376 actualCallback = hostOrCb ;
13761377 }
1377- } else if ( typeof portOrPathOrOptions === 'object' && portOrPathOrOptions !== null ) { // Options object
1378+ } else if ( typeof portOrPathOrOptions === 'object' && portOrPathOrOptions !== null ) {
13781379 portToListen = ( portOrPathOrOptions as import ( 'net' ) . ListenOptions ) . port ;
13791380 hostToListen = ( portOrPathOrOptions as import ( 'net' ) . ListenOptions ) . host || hostToListen ;
13801381 if ( typeof hostOrCb === 'function' ) actualCallback = hostOrCb ;
@@ -1383,59 +1384,67 @@ describe('startProxyServer', () => {
13831384 this . _port = portToListen ?? null ;
13841385 this . _host = hostToListen ?? null ;
13851386
1386- process . nextTick ( ( ) => { // Simulate async listen
1387+ process . nextTick ( ( ) => {
13871388 if ( this . _listeners && typeof this . _listeners . listening === 'function' ) {
1388- this . _listeners . listening ( ) ;
1389- }
1390- if ( actualCallback ) {
1391- actualCallback ( ) ;
1389+ ( this . _listeners . listening as ( ) => void ) ( ) ;
1390+ } else if ( Array . isArray ( this . _listeners ?. listening ) ) {
1391+ ( this . _listeners . listening as ( ( ...args : any [ ] ) => void ) [ ] ) . forEach ( fn => fn ( ) ) ;
13921392 }
1393+ if ( actualCallback ) actualCallback ( ) ;
13931394 } ) ;
13941395 return this ;
13951396 } ) ,
13961397 on : vi . fn ( function ( this : any , event : string , callback : ( ...args : any [ ] ) => void ) {
1397- if ( ! this . _listeners [ event ] ) this . _listeners [ event ] = [ ] ;
1398- this . _listeners [ event ] . push ( callback ) ; // Support multiple listeners if needed, though emit below is simple
1399- // For simplicity, if 'error' or 'listening' is set, we'll just use the last one for emit.
1400- // A full EventEmitter mock would handle arrays of listeners.
1401- // For this test's purpose, storing the last one for 'error' and 'listening' is likely sufficient.
1402- if ( event === 'error' || event === 'listening' || event === 'close' ) {
1403- this . _listeners [ event ] = callback ; // Overwrite for simplicity for these key events
1398+ if ( ! this . _listeners [ event ] ) {
1399+ this . _listeners [ event ] = [ ] ;
1400+ }
1401+ if ( Array . isArray ( this . _listeners [ event ] ) ) {
1402+ ( this . _listeners [ event ] as ( ( ... args : any [ ] ) => void ) [ ] ) . push ( callback ) ;
1403+ } else { // If it was a single function (e.g. from 'once'), make it an array
1404+ this . _listeners [ event ] = [ this . _listeners [ event ] as ( ... args : any [ ] ) => void , callback ] ;
14041405 }
14051406 return this ;
14061407 } ) ,
14071408 once : vi . fn ( function ( this : any , event : string , callback : ( ...args : any [ ] ) => void ) {
1408- // A simple once: store it, and if emit is called, it will be invoked then cleared.
1409- // For findFreePort, it uses 'once' for 'error' and 'listening'.
1410- this . _listeners [ event ] = ( ...args : any [ ] ) => {
1411- delete this . _listeners [ event ] ; // Remove after one call
1409+ const onceWrapper = ( ...args : any [ ] ) => {
1410+ if ( Array . isArray ( this . _listeners [ event ] ) ) {
1411+ this . _listeners [ event ] = ( this . _listeners [ event ] as ( ( ...args : any [ ] ) => void ) [ ] ) . filter ( fn => fn !== onceWrapper ) ;
1412+ } else if ( this . _listeners [ event ] === onceWrapper ) {
1413+ delete this . _listeners [ event ] ;
1414+ }
14121415 callback ( ...args ) ;
14131416 } ;
1417+ this . on ( event , onceWrapper ) ; // Use the 'on' method to add it
14141418 return this ;
14151419 } ) ,
1416- address : vi . fn ( function ( this : any ) { // Use function for 'this'
1420+ address : vi . fn ( function ( this : any ) {
14171421 if ( this . _port !== null ) {
14181422 return { port : this . _port , address : this . _host || '127.0.0.1' , family : 'IPv4' } ;
14191423 }
14201424 return null ;
14211425 } ) ,
14221426 close : vi . fn ( function ( this : any , cb ?: ( err ?: Error ) => void ) {
1423- process . nextTick ( ( ) => { // Simulate async close
1427+ process . nextTick ( ( ) => {
14241428 if ( this . _listeners && typeof this . _listeners . close === 'function' ) {
1425- this . _listeners . close ( ) ;
1429+ ( this . _listeners . close as ( ) => void ) ( ) ;
1430+ } else if ( Array . isArray ( this . _listeners ?. close ) ) {
1431+ ( this . _listeners . close as ( ( ...args : any [ ] ) => void ) [ ] ) . forEach ( fn => fn ( ) ) ;
14261432 }
14271433 if ( cb ) cb ( ) ;
14281434 } ) ;
14291435 return this ;
14301436 } ) ,
14311437 removeAllListeners : vi . fn ( ) . mockReturnThis ( ) ,
1432- emit : vi . fn ( function ( this : any , event : string , ...args : any [ ] ) { // Basic emit for testing
1433- if ( this . _listeners && typeof this . _listeners [ event ] === 'function' ) {
1434- this . _listeners [ event ] ( ...args ) ;
1438+ emit : vi . fn ( function ( this : any , event : string , ...args : any [ ] ) {
1439+ const listeners = this . _listeners ?. [ event ] ;
1440+ if ( typeof listeners === 'function' ) {
1441+ listeners ( ...args ) ;
1442+ } else if ( Array . isArray ( listeners ) ) {
1443+ listeners . forEach ( fn => fn ( ...args ) ) ;
14351444 }
14361445 } ) ,
14371446 } ;
1438- return serverInstance as unknown as http . Server ; // Cast to http.Server
1447+ return serverInstance as unknown as http . Server ;
14391448 } ) ;
14401449 } ) ;
14411450
@@ -1501,7 +1510,7 @@ describe('startProxyServer', () => {
15011510 expect ( actualProxyListenPort ) . toBe ( proxyListenPort ) ;
15021511
15031512 // Check for key log messages with more flexibility
1504- const infoCalls = ml . info . mock . calls . map ( call => call [ 0 ] ) ;
1513+ const infoCalls = ml . info . mock . calls . map ( call => String ( call [ 0 ] ) ) ; // Ensure string for matching
15051514 expect ( infoCalls ) . toEqual ( expect . arrayContaining ( [
15061515 expect . stringContaining ( `Original CodeCompass server (v1.0.0-existing) is running on port ${ targetExistingServerPort } ` ) ,
15071516 expect . stringContaining ( `This instance (CodeCompass Proxy) is listening on port ${ actualProxyListenPort } ` ) ,
0 commit comments