55 createReadinessParser ,
66 type HostChild ,
77} from '../src/host-supervisor'
8+ import * as hostSupervisor from '../src/host-supervisor'
89
910vi . mock ( 'node:child_process' , { spy : true } )
1011
@@ -112,6 +113,34 @@ describe('desktop Host readiness', () => {
112113 } )
113114} )
114115
116+ describe ( 'desktop Host port' , ( ) => {
117+ it ( 'uses fixed ports for packaged and development builds without an override' , ( ) => {
118+ expect ( hostSupervisor . DESKTOP_PACKAGED_PORT ) . toBe ( 24_827 )
119+ expect ( hostSupervisor . DESKTOP_DEV_PORT ) . toBe ( 24_828 )
120+ expect ( hostSupervisor . resolveDesktopPort ( { } , true ) ) . toBe ( 24_827 )
121+ expect ( hostSupervisor . resolveDesktopPort ( { } , false ) ) . toBe ( 24_828 )
122+ } )
123+
124+ it ( 'uses a valid port override for packaged and development builds' , ( ) => {
125+ const env = { PYTHINKER_DESKTOP_PORT : '45231' }
126+
127+ expect ( hostSupervisor . resolveDesktopPort ( env , true ) ) . toBe ( 45_231 )
128+ expect ( hostSupervisor . resolveDesktopPort ( env , false ) ) . toBe ( 45_231 )
129+ } )
130+
131+ it . each ( [ 'not-a-port' , '70000' ] ) ( 'rejects an invalid port override: %s' , ( value ) => {
132+ expect ( ( ) => hostSupervisor . resolveDesktopPort ( { PYTHINKER_DESKTOP_PORT : value } , true ) )
133+ . toThrow ( new RegExp ( `PYTHINKER_DESKTOP_PORT.*${ value } ` , 'u' ) )
134+ } )
135+
136+ it ( 'detects output that reports a port collision' , ( ) => {
137+ expect ( hostSupervisor . isPortInUseError (
138+ 'listen EADDRINUSE: address already in use 127.0.0.1:24827' ,
139+ ) ) . toBe ( true )
140+ expect ( hostSupervisor . isPortInUseError ( 'desktop Host exited before readiness (code 1, signal null)' ) ) . toBe ( false )
141+ } )
142+ } )
143+
115144describe ( 'desktop Host supervisor' , ( ) => {
116145 it ( 'starts one child for concurrent callers and returns its stdout readiness URL' , async ( ) => {
117146 const child = new FakeHostChild ( )
@@ -296,6 +325,7 @@ describe('desktop Host process', () => {
296325 cliEntry : '/Applications/Pythinker.app/Contents/Resources/host/node_modules/@pymodel/pythinker-code/dist/launcher.mjs' ,
297326 cwd : '/Users/tester' ,
298327 env : { PYTHINKER_DESKTOP : '1' } ,
328+ port : 24_827 ,
299329 electronRunAsNode : true ,
300330 } )
301331
@@ -307,7 +337,7 @@ describe('desktop Host process', () => {
307337 'run' ,
308338 '--foreground' ,
309339 '--port' ,
310- '0 ' ,
340+ '24827 ' ,
311341 '--log-level' ,
312342 'error' ,
313343 ] ,
@@ -341,6 +371,7 @@ describe('desktop Host process', () => {
341371 cliEntry : '/tmp/launcher.mjs' ,
342372 cwd : '/tmp' ,
343373 env : { } ,
374+ port : 24_827 ,
344375 } )
345376 host . kill ( 'SIGTERM' )
346377
@@ -379,6 +410,7 @@ describe('desktop Host process', () => {
379410 cliEntry : '/tmp/launcher.mjs' ,
380411 cwd : '/tmp' ,
381412 env : { } ,
413+ port : 24_827 ,
382414 } )
383415 host . kill ( 'SIGTERM' )
384416
@@ -404,6 +436,7 @@ describe('desktop Host process', () => {
404436 cliEntry : '/tmp/launcher.mjs' ,
405437 cwd : '/tmp' ,
406438 env : { } ,
439+ port : 24_827 ,
407440 } )
408441 host . kill ( 'SIGTERM' )
409442
0 commit comments