@@ -65,6 +65,7 @@ describe("startSshPortForward", () => {
6565 const openServers : net . Server [ ] = [ ] ;
6666
6767 afterEach ( async ( ) => {
68+ vi . useRealTimers ( ) ;
6869 while ( openServers . length > 0 ) {
6970 const server = openServers . pop ( ) ;
7071 await new Promise < void > ( ( resolve ) => {
@@ -165,37 +166,43 @@ describe("startSshPortForward", () => {
165166 } ) ;
166167
167168 it ( "rejects with the spawn error when ssh binary is missing" , async ( ) => {
169+ vi . useFakeTimers ( ) ;
168170 const spawnError = new Error ( "ENOENT: no such file or directory, spawn /usr/bin/ssh" ) ;
169171 ( spawnError as NodeJS . ErrnoException ) . code = "ENOENT" ;
172+ const kill = vi . fn ( ( ) => false ) ;
170173 mocks . spawn . mockImplementation ( ( ) => {
171174 const child = new EventEmitter ( ) as EventEmitter & {
172175 killed : boolean ;
173- pid : number ;
176+ pid ? : number ;
174177 stderr : EventEmitter & { setEncoding : ( enc : string ) => void } ;
175178 kill : ( signal ?: string ) => boolean ;
176179 } ;
177180 child . killed = false ;
178- child . pid = 0 ;
179181 const stderr = new EventEmitter ( ) as EventEmitter & { setEncoding : ( enc : string ) => void } ;
180182 stderr . setEncoding = ( ) => { } ;
181183 child . stderr = stderr ;
182- child . kill = ( ) => {
183- child . killed = true ;
184- queueMicrotask ( ( ) => child . emit ( "exit" , null , "SIGTERM" ) ) ;
185- return true ;
186- } ;
187- // Emit the error asynchronously, matching real spawn behavior
188- queueMicrotask ( ( ) => child . emit ( "error" , spawnError ) ) ;
184+ child . kill = kill ;
185+ queueMicrotask ( ( ) => {
186+ child . emit ( "error" , spawnError ) ;
187+ child . emit ( "close" , - 2 , null ) ;
188+ } ) ;
189189 return child ;
190190 } ) ;
191191
192- await expect (
193- startSshPortForward ( {
194- 195- localPortPreferred : 43210 ,
196- remotePort : 18789 ,
197- timeoutMs : 500 ,
198- } ) ,
199- ) . rejects . toThrow ( "ENOENT" ) ;
192+ const forwarding = startSshPortForward ( {
193+ 194+ localPortPreferred : 43210 ,
195+ remotePort : 18789 ,
196+ timeoutMs : 500 ,
197+ } ) ;
198+ const rejection = expect ( forwarding ) . rejects . toMatchObject ( {
199+ message : expect . stringContaining ( "ENOENT" ) ,
200+ cause : spawnError ,
201+ } ) ;
202+
203+ await vi . advanceTimersByTimeAsync ( 0 ) ;
204+ expect ( vi . getTimerCount ( ) ) . toBe ( 0 ) ;
205+ await rejection ;
206+ expect ( kill ) . toHaveBeenCalledWith ( "SIGTERM" ) ;
200207 } ) ;
201208} ) ;
0 commit comments