@@ -199,15 +199,21 @@ describe("_runCommand error handling", () => {
199199
200200describe . skipIf ( process . env . RUN_INTEGRATION_TESTS !== "1" ) ( "Sandbox" , ( ) => {
201201 const PORTS = [ 3000 , 4000 ] ;
202+ const SNAPSHOT_EXPIRATION = ms ( "1d" ) ;
203+
202204 let sandbox : Sandbox ;
203205
204206 beforeEach ( async ( ) => {
205- sandbox = await Sandbox . create ( { ports : PORTS } ) ;
207+ sandbox = await Sandbox . create ( {
208+ ports : PORTS ,
209+ persistent : false ,
210+ snapshotExpiration : SNAPSHOT_EXPIRATION ,
211+ } ) ;
206212 } ) ;
207213
208214 afterEach ( async ( ) => {
209- await sandbox . stop ( ) ;
210- } ) ;
215+ await sandbox . delete ( ) ;
216+ } , 30_000 ) ;
211217
212218 it ( "allows to write files and then read them as a stream" , async ( ) => {
213219 await sandbox . writeFiles ( [
@@ -346,20 +352,37 @@ for (const port of ports) {
346352 } ) ;
347353
348354 it ( "auto-resumes a stopped session when running a command" , async ( ) => {
349- await sandbox . stop ( ) ;
350- const result = await sandbox . runCommand ( "echo" , [ "resumed!" ] ) ;
351- expect ( result . exitCode ) . toBe ( 0 ) ;
352- expect ( await result . stdout ( ) ) . toContain ( "resumed!" ) ;
355+ const sbx = await Sandbox . create ( {
356+ persistent : true ,
357+ snapshotExpiration : SNAPSHOT_EXPIRATION ,
358+ } ) ;
359+ try {
360+ await sbx . stop ( ) ;
361+ const result = await sbx . runCommand ( "echo" , [ "resumed!" ] ) ;
362+ expect ( result . exitCode ) . toBe ( 0 ) ;
363+ expect ( await result . stdout ( ) ) . toContain ( "resumed!" ) ;
364+ } finally {
365+ await sbx . delete ( ) ;
366+ }
353367 } ) ;
354368
355369 it ( "auto-resumes a stopped session when reading a file" , async ( ) => {
356- await sandbox . writeFiles ( [
357- { path : "persist.txt" , content : Buffer . from ( "persisted content" ) } ,
358- ] ) ;
359- await sandbox . stop ( ) ;
370+ const sbx = await Sandbox . create ( {
371+ persistent : true ,
372+ snapshotExpiration : SNAPSHOT_EXPIRATION ,
373+ } ) ;
360374
361- const content = await sandbox . readFileToBuffer ( { path : "persist.txt" } ) ;
362- expect ( content ?. toString ( ) ) . toBe ( "persisted content" ) ;
375+ try {
376+ await sbx . writeFiles ( [
377+ { path : "persist.txt" , content : Buffer . from ( "persisted content" ) } ,
378+ ] ) ;
379+ await sbx . stop ( ) ;
380+
381+ const content = await sbx . readFileToBuffer ( { path : "persist.txt" } ) ;
382+ expect ( content ?. toString ( ) ) . toBe ( "persisted content" ) ;
383+ } finally {
384+ await sbx . delete ( ) ;
385+ }
363386 } ) ;
364387
365388 it ( "raises an error when the timeout cannot be updated" , async ( ) => {
@@ -378,9 +401,12 @@ for (const port of ports) {
378401 } ) ;
379402
380403 it ( "returns not found when getting a deleted sandbox" , async ( ) => {
381- const sandbox = await Sandbox . create ( ) ;
382- const name = sandbox . name ;
383- await sandbox . delete ( ) ;
404+ const sbx = await Sandbox . create ( {
405+ persistent : false ,
406+ snapshotExpiration : SNAPSHOT_EXPIRATION ,
407+ } ) ;
408+ const name = sbx . name ;
409+ await sbx . delete ( ) ;
384410
385411 try {
386412 await Sandbox . get ( { name } ) ;
@@ -394,105 +420,140 @@ for (const port of ports) {
394420 } ) ;
395421
396422 it ( "lists two sessions after stop and resume" , async ( ) => {
397- const sandbox = await Sandbox . create ( ) ;
398- await sandbox . stop ( ) ;
423+ const sbx = await Sandbox . create ( {
424+ persistent : true ,
425+ snapshotExpiration : SNAPSHOT_EXPIRATION ,
426+ } ) ;
399427
400- const resumed = await Sandbox . get ( { name : sandbox . name , resume : true } ) ;
401- const { sessions } = await resumed . listSessions ( ) ;
428+ try {
429+ await sbx . stop ( ) ;
430+
431+ const resumed = await Sandbox . get ( { name : sbx . name , resume : true } ) ;
432+ const { sessions } = await resumed . listSessions ( ) ;
402433
403- expect ( sessions ) . toHaveLength ( 2 ) ;
434+ expect ( sessions ) . toHaveLength ( 2 ) ;
404435
405- const currentSessionId = resumed . currentSession ( ) . sessionId ;
406- const match = sessions . find ( ( s ) => s . id === currentSessionId ) ;
407- expect ( match ) . toBeDefined ( ) ;
436+ const currentSessionId = resumed . currentSession ( ) . sessionId ;
437+ const match = sessions . find ( ( s ) => s . id === currentSessionId ) ;
438+ expect ( match ) . toBeDefined ( ) ;
439+ } finally {
440+ await sbx . delete ( ) ;
441+ }
408442 } ) ;
409443
410444 it ( "lists one snapshot after creating one" , async ( ) => {
411- const sandbox = await Sandbox . create ( ) ;
412445 await sandbox . snapshot ( ) ;
413446
414447 const { snapshots } = await sandbox . listSnapshots ( ) ;
415448 expect ( snapshots ) . toHaveLength ( 1 ) ;
416449 } ) ;
417450
418451 it ( "reflects updated resources after update" , async ( ) => {
419- const sandbox = await Sandbox . create ( { timeout : 60_000 , persistent : true , snapshotExpiration : 7 * 86400000 } ) ;
420- expect ( sandbox . snapshotExpiration ) . toBe ( 7 * 86400000 ) ;
421- await sandbox . stop ( ) ;
452+ const sbx = await Sandbox . create ( {
453+ timeout : 60_000 ,
454+ persistent : true ,
455+ snapshotExpiration : 7 * 86400000 ,
456+ } ) ;
457+
458+ try {
459+ expect ( sbx . snapshotExpiration ) . toBe ( 7 * 86400000 ) ;
460+ await sbx . stop ( ) ;
422461
423- const { snapshotId } = await sandbox . snapshot ( ) ;
462+ const { snapshotId } = await sbx . snapshot ( ) ;
424463
425- await sandbox . update ( {
426- resources : { vcpus : 4 } ,
427- timeout : 30_000 ,
428- persistent : false ,
429- snapshotExpiration : 2 * 86400000 ,
430- currentSnapshotId : snapshotId ,
431- } ) ;
464+ await sbx . update ( {
465+ resources : { vcpus : 4 } ,
466+ timeout : 30_000 ,
467+ persistent : false ,
468+ snapshotExpiration : 2 * 86400000 ,
469+ currentSnapshotId : snapshotId ,
470+ } ) ;
432471
433- const updated = await Sandbox . get ( {
434- name : sandbox . name ,
435- resume : false ,
436- } ) ;
437- expect ( updated . vcpus ) . toBe ( 4 ) ;
438- expect ( updated . memory ) . toBe ( 8192 ) ;
439- expect ( updated . timeout ) . toBe ( 30_000 ) ;
440- expect ( updated . persistent ) . toBe ( false ) ;
441- expect ( updated . snapshotExpiration ) . toBe ( 2 * 86400000 ) ;
442- expect ( updated . currentSnapshotId ) . toBe ( snapshotId ) ;
472+ const updated = await Sandbox . get ( {
473+ name : sbx . name ,
474+ resume : false ,
475+ } ) ;
476+ expect ( updated . vcpus ) . toBe ( 4 ) ;
477+ expect ( updated . memory ) . toBe ( 8192 ) ;
478+ expect ( updated . timeout ) . toBe ( 30_000 ) ;
479+ expect ( updated . persistent ) . toBe ( false ) ;
480+ expect ( updated . snapshotExpiration ) . toBe ( 2 * 86400000 ) ;
481+ expect ( updated . currentSnapshotId ) . toBe ( snapshotId ) ;
482+ } finally {
483+ await sbx . delete ( ) ;
484+ }
443485 } ) ;
444486
445487 it ( "appears in the sandbox list after creation" , async ( ) => {
446- const sandbox = await Sandbox . create ( ) ;
447488 await sandbox . stop ( ) ;
448489 const { sandboxes } = await Sandbox . list ( { limit : 1 } ) ;
449490 expect ( sandboxes ) . toHaveLength ( 1 ) ;
450491 expect ( sandboxes [ 0 ] . name ) . toBe ( sandbox . name ) ;
451492 } ) ;
452493
453494 it ( "calls onResume when Sandbox.get resumes a stopped sandbox" , async ( ) => {
454- const sandbox = await Sandbox . create ( ) ;
455- await sandbox . stop ( ) ;
456-
457- let resumedSandbox : Sandbox | null = null ;
458- const retrieved = await Sandbox . get ( {
459- name : sandbox . name ,
460- resume : true ,
461- onResume : async ( sbx ) => {
462- resumedSandbox = sbx ;
463- } ,
495+ const sbx = await Sandbox . create ( {
496+ persistent : true ,
497+ snapshotExpiration : SNAPSHOT_EXPIRATION ,
464498 } ) ;
465499
466- expect ( resumedSandbox ) . toBe ( retrieved ) ;
500+ try {
501+ await sbx . stop ( ) ;
502+
503+ let resumedSandbox : Sandbox | null = null ;
504+ const retrieved = await Sandbox . get ( {
505+ name : sbx . name ,
506+ resume : true ,
507+ onResume : async ( s ) => {
508+ resumedSandbox = s ;
509+ } ,
510+ } ) ;
511+
512+ expect ( resumedSandbox ) . toBe ( retrieved ) ;
513+ } finally {
514+ await sbx . delete ( ) ;
515+ }
467516 } ) ;
468517
469518 it ( "calls onResume on auto-resume after a stopped session" , async ( ) => {
470519 let resumeCount = 0 ;
471- const sandbox = await Sandbox . create ( {
520+ const sbx = await Sandbox . create ( {
521+ persistent : true ,
522+ snapshotExpiration : SNAPSHOT_EXPIRATION ,
472523 onResume : async ( ) => {
473524 resumeCount ++ ;
474525 } ,
475526 } ) ;
476527
477- await sandbox . stop ( ) ;
478- await sandbox . runCommand ( "echo" , [ "hello" ] ) ;
528+ try {
529+ await sbx . stop ( ) ;
530+ await sbx . runCommand ( "echo" , [ "hello" ] ) ;
479531
480- expect ( resumeCount ) . toBe ( 1 ) ;
532+ expect ( resumeCount ) . toBe ( 1 ) ;
533+ } finally {
534+ await sbx . delete ( ) ;
535+ }
481536 } ) ;
482537
483538 it ( "updates status and currentSnapshotId after stopping a persistent sandbox" , async ( ) => {
484- const sandbox = await Sandbox . create ( { persistent : true } ) ;
485- expect ( sandbox . status ) . toBe ( "running" ) ;
539+ const sbx = await Sandbox . create ( {
540+ persistent : true ,
541+ snapshotExpiration : SNAPSHOT_EXPIRATION ,
542+ } ) ;
486543
487- await sandbox . stop ( ) ;
544+ try {
545+ expect ( sbx . status ) . toBe ( "running" ) ;
546+
547+ await sbx . stop ( ) ;
488548
489- expect ( sandbox . status ) . toBe ( "stopped" ) ;
490- expect ( sandbox . currentSnapshotId ) . not . toBeNull ( ) ;
549+ expect ( sbx . status ) . toBe ( "stopped" ) ;
550+ expect ( sbx . currentSnapshotId ) . not . toBeNull ( ) ;
551+ } finally {
552+ await sbx . delete ( ) ;
553+ }
491554 } ) ;
492555
493556 it ( "does not call onResume when Sandbox.get does not resume" , async ( ) => {
494- const sandbox = await Sandbox . create ( ) ;
495-
496557 let called = false ;
497558 await Sandbox . get ( {
498559 name : sandbox . name ,
0 commit comments