@@ -289,6 +289,42 @@ describe("API (plugin)", () => {
289289 } ) ;
290290 } ) ;
291291
292+ it ( "should log a listen() failure instead of throwing" , async ( ) => {
293+ // The server is started from the `done` hook, which is a `SyncHook`, so
294+ // `listen()` runs detached. A failure there must be logged, not surface as
295+ // an unhandled rejection.
296+ const compiler = webpack ( config ) ;
297+ const server = new Server ( { port } ) ;
298+ server . apply ( compiler ) ;
299+
300+ const listenError = new Error ( "listen failed" ) ;
301+ const listenSpy = spyOn ( server , "listen" ) . mockImplementation ( ( ) =>
302+ Promise . reject ( listenError ) ,
303+ ) ;
304+ const errorSpy = spyOn ( server . logger , "error" ) ;
305+
306+ await new Promise ( ( resolve , reject ) => {
307+ const timer = setTimeout (
308+ ( ) => reject ( new Error ( "listen error was not logged" ) ) ,
309+ 30000 ,
310+ ) ;
311+ errorSpy . mockImplementation ( ( ) => {
312+ clearTimeout ( timer ) ;
313+ resolve ( ) ;
314+ } ) ;
315+ compiler . watch ( { } , ( ) => { } ) ;
316+ } ) ;
317+
318+ expect ( errorSpy ) . toHaveBeenCalledTimes ( 1 ) ;
319+ expect ( errorSpy ) . toHaveBeenCalledWith ( listenError ) ;
320+
321+ listenSpy . mockRestore ( ) ;
322+ errorSpy . mockRestore ( ) ;
323+ await new Promise ( ( resolve ) => {
324+ compiler . close ( resolve ) ;
325+ } ) ;
326+ } ) ;
327+
292328 describe ( "plugin in webpack config" , ( ) => {
293329 it ( "should work when added to webpack config plugins array" , async ( t ) => {
294330 const server = new Server ( { port } ) ;
0 commit comments