@@ -106,13 +106,12 @@ describe("PortManager", () => {
106106 }
107107 } ) ;
108108
109- // Try to allocate again - should get next port
110- const port2 = await portManager . allocatePort ( 3141 ) ;
111- expect ( port2 ) . not . toBe ( 3141 ) ;
112- expect ( port2 ) . toBe ( 4310 ) ; // Next preferred port
109+ await expect ( portManager . allocatePort ( 3141 ) ) . rejects . toThrow (
110+ "Port 3141 is already in use. To use another port, pass it to your server config, for example: honoServer({ port: 4310 })" ,
111+ ) ;
113112 } ) ;
114113
115- it ( "should handle port in use (EADDRINUSE)" , async ( ) => {
114+ it ( "should throw with guidance when preferred port is in use (EADDRINUSE)" , async ( ) => {
116115 let portBeingTested : number | undefined ;
117116
118117 ( createNetServer as any ) . mockImplementation ( ( ) => {
@@ -145,9 +144,44 @@ describe("PortManager", () => {
145144 return mockServer ;
146145 } ) ;
147146
148- const port = await portManager . allocatePort ( 3141 ) ;
149- expect ( port ) . not . toBe ( 3141 ) ;
150- expect ( port ) . toBe ( 4310 ) ; // Should try next port after skipping duplicate 3141
147+ await expect ( portManager . allocatePort ( 3141 ) ) . rejects . toThrow (
148+ "Port 3141 is already in use. To use another port, pass it to your server config, for example: honoServer({ port: 4310 })" ,
149+ ) ;
150+ } ) ;
151+
152+ it ( "should throw with guidance when default port is in use" , async ( ) => {
153+ let portBeingTested : number | undefined ;
154+
155+ ( createNetServer as any ) . mockImplementation ( ( ) => {
156+ const mockServer = {
157+ once : vi . fn ( ) ,
158+ listen : vi . fn ( ( port : number ) => {
159+ portBeingTested = port ;
160+ } ) ,
161+ close : vi . fn ( ( callback ?: ( ) => void ) => callback ?.( ) ) ,
162+ } ;
163+
164+ const handlers : Record < string , ( ...args : any [ ] ) => void > = { } ;
165+ mockServer . once . mockImplementation ( ( event : string , handler : ( ...args : any [ ] ) => void ) => {
166+ handlers [ event ] = handler ;
167+ if ( Object . keys ( handlers ) . length === 2 ) {
168+ setTimeout ( ( ) => {
169+ if ( portBeingTested === 3141 ) {
170+ handlers . error ( { code : "EADDRINUSE" } ) ;
171+ } else {
172+ handlers . listening ( ) ;
173+ }
174+ } , 0 ) ;
175+ }
176+ return mockServer ;
177+ } ) ;
178+
179+ return mockServer ;
180+ } ) ;
181+
182+ await expect ( portManager . allocatePort ( ) ) . rejects . toThrow (
183+ "Port 3141 is already in use. To use another port, pass it to your server config, for example: honoServer({ port: 4310 })" ,
184+ ) ;
151185 } ) ;
152186
153187 it ( "should handle permission denied (EACCES)" , async ( ) => {
@@ -183,9 +217,9 @@ describe("PortManager", () => {
183217 return mockServer ;
184218 } ) ;
185219
186- const port = await portManager . allocatePort ( 80 ) ; // Low port, likely EACCES
187- expect ( port ) . not . toBe ( 80 ) ;
188- expect ( port ) . toBe ( 3141 ) ; // Should try next port
220+ await expect ( portManager . allocatePort ( 80 ) ) . rejects . toThrow (
221+ "Port 80 is already in use. To use another port, pass it to your server config, for example: honoServer({ port: 3141 })" ,
222+ ) ;
189223 } ) ;
190224
191225 it ( "should throw error when no ports are available" , async ( ) => {
@@ -202,10 +236,12 @@ describe("PortManager", () => {
202236 getPortsToTry : originalGetPortsToTry ,
203237 } ) ) ;
204238
205- await expect ( portManager . allocatePort ( ) ) . rejects . toThrow ( "Could not find an available port" ) ;
239+ await expect ( portManager . allocatePort ( ) ) . rejects . toThrow (
240+ "Port 3141 is already in use and no alternative port is available" ,
241+ ) ;
206242 } ) ;
207243
208- it ( "should handle concurrent allocation requests" , async ( ) => {
244+ it ( "should reject concurrent default allocation requests after the first allocation " , async ( ) => {
209245 // Create multiple mock servers for concurrent allocation
210246 ( createNetServer as any ) . mockImplementation ( ( ) => {
211247 const newMockServer = {
@@ -226,21 +262,28 @@ describe("PortManager", () => {
226262 } ) ;
227263
228264 // Start multiple allocations concurrently
229- const promises = [
265+ const results = await Promise . allSettled ( [
230266 portManager . allocatePort ( ) ,
231267 portManager . allocatePort ( ) ,
232268 portManager . allocatePort ( ) ,
233- ] ;
269+ ] ) ;
234270
235- const results = await Promise . all ( promises ) ;
271+ const fulfilled = results . filter ( ( result ) => result . status === "fulfilled" ) ;
272+ const rejected = results . filter ( ( result ) => result . status === "rejected" ) ;
236273
237- // All ports should be different
238- expect ( new Set ( results ) . size ) . toBe ( 3 ) ;
274+ expect ( fulfilled ) . toHaveLength ( 1 ) ;
275+ expect ( rejected ) . toHaveLength ( 2 ) ;
276+ expect ( fulfilled [ 0 ] ) . toMatchObject ( { value : 3141 } ) ;
239277
240- // All ports should be allocated
241- results . forEach ( ( port ) => {
242- expect ( portManager . isPortAllocated ( port ) ) . toBe ( true ) ;
278+ rejected . forEach ( ( result ) => {
279+ expect ( result . reason ) . toBeInstanceOf ( Error ) ;
280+ expect ( ( result . reason as Error ) . message ) . toMatch (
281+ / ^ P o r t 3 1 4 1 i s a l r e a d y i n u s e \. T o u s e a n o t h e r p o r t , p a s s i t t o y o u r s e r v e r c o n f i g , f o r e x a m p l e : h o n o S e r v e r \( \{ p o r t : \d + \} \) $ / ,
282+ ) ;
243283 } ) ;
284+
285+ expect ( portManager . isPortAllocated ( 3141 ) ) . toBe ( true ) ;
286+ expect ( portManager . isPortAllocated ( 4310 ) ) . toBe ( false ) ;
244287 } ) ;
245288
246289 it ( "should wait for existing port check to complete" , async ( ) => {
@@ -269,12 +312,13 @@ describe("PortManager", () => {
269312 await delay ( 10 ) ; // Small delay to ensure first check is in progress
270313 const promise2 = portManager . allocatePort ( 5000 ) ;
271314
272- const [ port1 , port2 ] = await Promise . all ( [ promise1 , promise2 ] ) ;
315+ const port1 = await promise1 ;
316+ await expect ( promise2 ) . rejects . toThrow (
317+ "Port 5000 is already in use. To use another port, pass it to your server config, for example: honoServer({ port: 3141 })" ,
318+ ) ;
273319
274320 // First should get the requested port
275321 expect ( port1 ) . toBe ( 5000 ) ;
276- // Second should get a different port (since first is checking/allocated)
277- expect ( port2 ) . not . toBe ( 5000 ) ;
278322 expect ( checkCompleted ) . toBe ( true ) ;
279323 } ) ;
280324 } ) ;
@@ -443,9 +487,9 @@ describe("PortManager", () => {
443487 return mockServer ;
444488 } ) ;
445489
446- const port = await portManager . allocatePort ( 3000 ) ;
447- expect ( port ) . not . toBe ( 3000 ) ;
448- expect ( port ) . toBe ( 3141 ) ; // Should try the first preferred port
490+ await expect ( portManager . allocatePort ( 3000 ) ) . rejects . toThrow (
491+ "Port 3000 is already in use. To use another port, pass it to your server config, for example: honoServer({ port: 3141 })" ,
492+ ) ;
449493 } ) ;
450494
451495 it ( "should cleanup promises map even on error" , async ( ) => {
0 commit comments