@@ -1356,93 +1356,90 @@ describe('startProxyServer', () => {
13561356
13571357 // Ensure the http.createServer mock used by startProxyServer behaves asynchronously for listen and close
13581358 // This mock is specific to the 'startProxyServer' describe block.
1359- vi . mocked ( http . createServer ) . mockImplementation ( ( ) => {
1360- const serverInstance = {
1361- _listeners : { } as Record < string , ( ( ...args : any [ ] ) => void ) | ( ( ...args : any [ ] ) => void ) [ ] | undefined > ,
1362- _port : null as number | null ,
1363- _host : null as string | null ,
1364- listen : vi . fn ( function ( this : any , portOrPathOrOptions : any , hostOrCb ?: any , backlogOrCb ?: any , cb ?: any ) {
1365- let portToListen : number | undefined ;
1366- let hostToListen : string | undefined = '127.0.0.1' ; // Default host for listen
1367- let actualCallback : ( ( ) => void ) | undefined ;
1368-
1369- if ( typeof portOrPathOrOptions === 'number' ) {
1370- portToListen = portOrPathOrOptions ;
1371- if ( typeof hostOrCb === 'string' ) {
1372- hostToListen = hostOrCb ;
1373- if ( typeof backlogOrCb === 'function' ) actualCallback = backlogOrCb ;
1374- else if ( typeof cb === 'function' ) actualCallback = cb ;
1375- } else if ( typeof hostOrCb === 'function' ) {
1376- actualCallback = hostOrCb ;
1377- }
1378- } else if ( typeof portOrPathOrOptions === 'object' && portOrPathOrOptions !== null ) {
1379- portToListen = ( portOrPathOrOptions as import ( 'net' ) . ListenOptions ) . port ;
1380- hostToListen = ( portOrPathOrOptions as import ( 'net' ) . ListenOptions ) . host || hostToListen ;
1381- if ( typeof hostOrCb === 'function' ) actualCallback = hostOrCb ;
1359+ vi . mocked ( http . createServer ) . mockImplementation ( ( requestListener ?: http . RequestListener ) => {
1360+ const EventEmitter = ( require ( 'events' ) as { EventEmitter : typeof import ( 'events.EventEmitter' ) } ) . EventEmitter ;
1361+ const serverInstance = new EventEmitter ( ) as unknown as MockedHttpServer & {
1362+ _storedPort ?: number ;
1363+ _storedHost ?: string ;
1364+ _listenShouldError ?: NodeJS . ErrnoException | null ;
1365+ _closeShouldError ?: Error | null ;
1366+ requestListener ?: http . RequestListener ;
1367+ } ;
1368+
1369+ serverInstance . requestListener = requestListener ;
1370+
1371+ serverInstance . listen = vi . fn ( ( portOrPathOrOptions : any , arg2 ?: any , arg3 ?: any , arg4 ?: any ) => {
1372+ let portToListen : number | undefined ;
1373+ let hostToListen : string | undefined = '127.0.0.1' ;
1374+ let actualCallback : ( ( ) => void ) | undefined ;
1375+
1376+ if ( typeof portOrPathOrOptions === 'number' ) {
1377+ portToListen = portOrPathOrOptions ;
1378+ if ( typeof arg2 === 'string' ) {
1379+ hostToListen = arg2 ;
1380+ actualCallback = typeof arg3 === 'function' ? arg3 : ( typeof arg4 === 'function' ? arg4 : undefined ) ;
1381+ } else if ( typeof arg2 === 'function' ) {
1382+ actualCallback = arg2 ;
13821383 }
1383-
1384- this . _port = portToListen ?? null ;
1385- this . _host = hostToListen ?? null ;
1384+ } else if ( typeof portOrPathOrOptions === 'object' && portOrPathOrOptions !== null ) {
1385+ portToListen = ( portOrPathOrOptions as import ( 'net' ) . ListenOptions ) . port ;
1386+ hostToListen = ( portOrPathOrOptions as import ( 'net' ) . ListenOptions ) . host || hostToListen ;
1387+ actualCallback = typeof arg2 === 'function' ? arg2 : undefined ;
1388+ } else if ( typeof portOrPathOrOptions === 'function' ) {
1389+ actualCallback = portOrPathOrOptions ;
1390+ }
1391+
13861392
1387- process . nextTick ( ( ) => {
1388- // Emit 'listening' event
1389- if ( typeof this . emit === 'function' ) {
1390- this . emit ( 'listening' ) ;
1393+ serverInstance . _storedPort = portToListen ?? 0 ;
1394+ serverInstance . _storedHost = hostToListen ;
1395+
1396+ process . nextTick ( ( ) => {
1397+ if ( serverInstance . _listenShouldError ) {
1398+ serverInstance . emit ( 'error' , serverInstance . _listenShouldError ) ;
1399+ if ( actualCallback && serverInstance . _listenShouldError . code !== 'EADDRINUSE' ) {
1400+ actualCallback ( ) ;
13911401 }
1392- // Call direct callback if provided
1393- if ( actualCallback ) actualCallback ( ) ;
1394- } ) ;
1395- return this ;
1396- } ) ,
1397- on : vi . fn ( function ( this : any , event : string , callback : ( ...args : any [ ] ) => void ) {
1398- if ( ! this . _listeners [ event ] ) {
1399- this . _listeners [ event ] = [ ] ;
1402+ if ( serverInstance . _listenShouldError . code === 'EADDRINUSE' ) return ;
14001403 }
1401- const listenersArray = this . _listeners [ event ] as ( ( ...args : any [ ] ) => void ) [ ] ;
1402- if ( ! Array . isArray ( listenersArray ) ) { // Should not happen if initialized as array
1403- this . _listeners [ event ] = [ callback ] ;
1404- } else {
1405- listenersArray . push ( callback ) ;
1404+
1405+ if ( actualCallback && ! serverInstance . _listenShouldError ) {
1406+ actualCallback ( ) ;
14061407 }
1407- return this ;
1408- } ) ,
1409- once : vi . fn ( function ( this : any , event : string , callback : ( ...args : any [ ] ) => void ) {
1410- const onceWrapper = ( ...args : any [ ] ) => {
1411- const listenersArray = this . _listeners [ event ] as ( ( ...args : any [ ] ) => void ) [ ] ;
1412- if ( Array . isArray ( listenersArray ) ) {
1413- this . _listeners [ event ] = listenersArray . filter ( fn => fn !== onceWrapper ) ;
1414- }
1415- callback ( ...args ) ;
1416- } ;
1417- this . on ( event , onceWrapper ) ;
1418- return this ;
1419- } ) ,
1420- address : vi . fn ( function ( this : any ) {
1421- if ( this . _port !== null ) {
1422- return { port : this . _port , address : this . _host || '127.0.0.1' , family : 'IPv4' } ;
1408+ if ( ! serverInstance . _listenShouldError ) {
1409+ serverInstance . emit ( 'listening' ) ;
14231410 }
1424- return null ;
1425- } ) ,
1426- close : vi . fn ( function ( this : any , cb ?: ( err ?: Error ) => void ) {
1427- process . nextTick ( ( ) => {
1428- if ( typeof this . emit === 'function' ) {
1429- this . emit ( 'close' ) ;
1430- }
1411+ } ) ;
1412+ return serverInstance ;
1413+ } ) ;
1414+
1415+ serverInstance . close = vi . fn ( ( cb ?: ( err ?: Error ) => void ) => {
1416+ process . nextTick ( ( ) => {
1417+ if ( serverInstance . _closeShouldError ) {
1418+ serverInstance . emit ( 'error' , serverInstance . _closeShouldError ) ;
1419+ if ( cb ) cb ( serverInstance . _closeShouldError ) ;
1420+ } else {
1421+ serverInstance . emit ( 'close' ) ;
14311422 if ( cb ) cb ( ) ;
1432- } ) ;
1433- return this ;
1434- } ) ,
1435- removeAllListeners : vi . fn ( ) . mockReturnThis ( ) ,
1436- emit : vi . fn ( function ( this : any , event : string , ...args : any [ ] ) {
1437- const listeners = this . _listeners ?. [ event ] ;
1438- if ( typeof listeners === 'function' ) { // Should not happen with 'on' pushing to array
1439- listeners ( ...args ) ;
1440- } else if ( Array . isArray ( listeners ) ) {
1441- // Iterate over a copy in case a listener removes itself
1442- [ ...listeners ] . forEach ( fn => fn ( ...args ) ) ;
1443- }
1444- } ) ,
1445- } ;
1423+ }
1424+ } ) ;
1425+ return serverInstance ;
1426+ } ) ;
1427+
1428+ serverInstance . address = vi . fn ( ( ) => {
1429+ if ( serverInstance . _storedPort === undefined ) return null ;
1430+ return { port : serverInstance . _storedPort , address : serverInstance . _storedHost || '127.0.0.1' , family : 'IPv4' } ;
1431+ } ) ;
1432+
1433+ // Standard EventEmitter methods are inherited, but if specific mock behavior is needed:
1434+ serverInstance . on = vi . fn ( serverInstance . on . bind ( serverInstance ) ) ;
1435+ serverInstance . once = vi . fn ( serverInstance . once . bind ( serverInstance ) ) ;
1436+ serverInstance . emit = vi . fn ( serverInstance . emit . bind ( serverInstance ) ) ;
1437+ serverInstance . removeAllListeners = vi . fn ( serverInstance . removeAllListeners . bind ( serverInstance ) ) ;
1438+
1439+ if ( requestListener ) {
1440+ serverInstance . on ( 'request' , requestListener ) ;
1441+ }
1442+
14461443 return serverInstance as unknown as http . Server ;
14471444 } ) ;
14481445 } ) ;
0 commit comments