@@ -233,6 +233,41 @@ describe('browser routing', () => {
233233 await expect ( kernel . browsers . fetch ( 'sess-1' , 'https://example.com/again' ) ) . rejects . toThrow ( / r o u t e c a c h e / ) ;
234234 } ) ;
235235
236+ test ( 'warms cache from browser pool acquire responses' , async ( ) => {
237+ await withBrowserRoutingEnv ( 'process' , async ( ) => {
238+ const calls : string [ ] = [ ] ;
239+ const kernel = new Kernel ( {
240+ apiKey : 'k' ,
241+ baseURL : 'https://api.example/' ,
242+ fetch : async ( input ) => {
243+ const url = normalizeURL ( input ) ;
244+ calls . push ( url ) ;
245+ if ( url === 'https://api.example/browser_pools/pool-1/acquire' ) {
246+ return Response . json ( {
247+ session_id : 'sess-1' ,
248+ base_url : 'http://browser-session.test/browser/kernel' ,
249+ cdp_ws_url : 'wss://browser-session.test/browser/cdp?jwt=token-abc' ,
250+ } ) ;
251+ }
252+ return Response . json ( { exit_code : 0 , stdout_b64 : '' , stderr_b64 : '' } ) ;
253+ } ,
254+ } ) ;
255+
256+ await kernel . browserPools . acquire ( 'pool-1' , { } ) ;
257+ await kernel . browsers . process . exec ( 'sess-1' , { command : 'echo' } ) ;
258+
259+ expect ( kernel . browserRouteCache . get ( 'sess-1' ) ) . toMatchObject ( {
260+ sessionId : 'sess-1' ,
261+ baseURL : 'http://browser-session.test/browser/kernel' ,
262+ jwt : 'token-abc' ,
263+ } ) ;
264+ expect ( calls ) . toEqual ( [
265+ 'https://api.example/browser_pools/pool-1/acquire' ,
266+ 'http://browser-session.test/browser/kernel/process/exec?jwt=token-abc' ,
267+ ] ) ;
268+ } ) ;
269+ } ) ;
270+
236271 test ( 'evicts cached route after successful browser delete by id' , async ( ) => {
237272 const calls : string [ ] = [ ] ;
238273 const kernel = new Kernel ( {
@@ -257,6 +292,30 @@ describe('browser routing', () => {
257292 expect ( kernel . browserRouteCache . get ( 'sess-1' ) ) . toBeUndefined ( ) ;
258293 } ) ;
259294
295+ test ( 'evicts cached route after successful browser pool release' , async ( ) => {
296+ const calls : string [ ] = [ ] ;
297+ const kernel = new Kernel ( {
298+ apiKey : 'k' ,
299+ baseURL : 'https://api.example/' ,
300+ fetch : async ( input ) => {
301+ const url = normalizeURL ( input ) ;
302+ calls . push ( url ) ;
303+ return new Response ( null , { status : 204 } ) ;
304+ } ,
305+ } ) ;
306+
307+ kernel . browserRouteCache . set ( {
308+ sessionId : 'sess-1' ,
309+ baseURL : 'http://browser-session.test/browser/kernel' ,
310+ jwt : 'token-abc' ,
311+ } ) ;
312+
313+ await kernel . browserPools . release ( 'pool-1' , { session_id : 'sess-1' } ) ;
314+
315+ expect ( calls ) . toEqual ( [ 'https://api.example/browser_pools/pool-1/release' ] ) ;
316+ expect ( kernel . browserRouteCache . get ( 'sess-1' ) ) . toBeUndefined ( ) ;
317+ } ) ;
318+
260319 test ( 'keeps cached route when browser delete by id fails' , async ( ) => {
261320 const kernel = new Kernel ( {
262321 apiKey : 'k' ,
@@ -279,6 +338,28 @@ describe('browser routing', () => {
279338 } ) ;
280339 } ) ;
281340
341+ test ( 'keeps cached route when browser pool release fails' , async ( ) => {
342+ const kernel = new Kernel ( {
343+ apiKey : 'k' ,
344+ baseURL : 'https://api.example/' ,
345+ maxRetries : 0 ,
346+ fetch : async ( ) => new Response ( 'boom' , { status : 500 , headers : { 'content-type' : 'text/plain' } } ) ,
347+ } ) ;
348+
349+ kernel . browserRouteCache . set ( {
350+ sessionId : 'sess-1' ,
351+ baseURL : 'http://browser-session.test/browser/kernel' ,
352+ jwt : 'token-abc' ,
353+ } ) ;
354+
355+ await expect ( kernel . browserPools . release ( 'pool-1' , { session_id : 'sess-1' } ) ) . rejects . toThrow ( ) ;
356+ expect ( kernel . browserRouteCache . get ( 'sess-1' ) ) . toMatchObject ( {
357+ sessionId : 'sess-1' ,
358+ baseURL : 'http://browser-session.test/browser/kernel' ,
359+ jwt : 'token-abc' ,
360+ } ) ;
361+ } ) ;
362+
282363 test ( 'browser.fetch rejects methods outside the SDK HTTPMethod union' , async ( ) => {
283364 const kernel = new Kernel ( {
284365 apiKey : 'k' ,
0 commit comments