11import fs from "node:fs/promises" ;
22import { afterAll , afterEach , beforeEach , describe , expect , it , vi } from "vitest" ;
33
4- const { TEST_STATE_DIR , SANDBOX_REGISTRY_PATH , SANDBOX_BROWSER_REGISTRY_PATH } = vi . hoisted ( ( ) => {
5- const path = require ( "node:path" ) ;
6- const { mkdtempSync } = require ( "node:fs" ) ;
7- const { tmpdir } = require ( "node:os" ) ;
8- const baseDir = mkdtempSync ( path . join ( tmpdir ( ) , "openclaw-sandbox-registry-" ) ) ;
9-
10- return {
11- TEST_STATE_DIR : baseDir ,
12- SANDBOX_REGISTRY_PATH : path . join ( baseDir , "containers.json" ) ,
13- SANDBOX_BROWSER_REGISTRY_PATH : path . join ( baseDir , "browsers.json" ) ,
14- } ;
15- } ) ;
16-
17- vi . mock ( "./constants.js" , ( ) => ( {
18- SANDBOX_STATE_DIR : TEST_STATE_DIR ,
19- SANDBOX_REGISTRY_PATH ,
20- SANDBOX_BROWSER_REGISTRY_PATH ,
21- } ) ) ;
22-
23- type SandboxBrowserRegistryEntry = import ( "./registry.js" ) . SandboxBrowserRegistryEntry ;
24- type SandboxRegistryEntry = import ( "./registry.js" ) . SandboxRegistryEntry ;
25-
264type WriteDelayConfig = {
275 targetFile : "containers.json" | "browsers.json" ;
286 containerName : string ;
@@ -31,58 +9,67 @@ type WriteDelayConfig = {
319 waitForRelease : Promise < void > ;
3210} ;
3311
34- let activeWriteGate : WriteDelayConfig | null = null ;
35- let readBrowserRegistry : typeof import ( "./registry.js" ) . readBrowserRegistry ;
36- let readRegistry : typeof import ( "./registry.js" ) . readRegistry ;
37- let removeBrowserRegistryEntry : typeof import ( "./registry.js" ) . removeBrowserRegistryEntry ;
38- let removeRegistryEntry : typeof import ( "./registry.js" ) . removeRegistryEntry ;
39- let updateBrowserRegistry : typeof import ( "./registry.js" ) . updateBrowserRegistry ;
40- let updateRegistry : typeof import ( "./registry.js" ) . updateRegistry ;
41-
42- async function loadFreshRegistryModuleForTest ( ) {
43- vi . resetModules ( ) ;
44- vi . doMock ( "./constants.js" , ( ) => ( {
45- SANDBOX_STATE_DIR : TEST_STATE_DIR ,
46- SANDBOX_REGISTRY_PATH ,
47- SANDBOX_BROWSER_REGISTRY_PATH ,
48- } ) ) ;
49- vi . doMock ( "../../infra/json-files.js" , async ( ) => {
50- const actual = await vi . importActual < typeof import ( "../../infra/json-files.js" ) > (
51- "../../infra/json-files.js" ,
52- ) ;
12+ const { TEST_STATE_DIR , SANDBOX_REGISTRY_PATH , SANDBOX_BROWSER_REGISTRY_PATH , writeGateState } =
13+ vi . hoisted ( ( ) => {
14+ const path = require ( "node:path" ) ;
15+ const { mkdtempSync } = require ( "node:fs" ) ;
16+ const { tmpdir } = require ( "node:os" ) ;
17+ const baseDir = mkdtempSync ( path . join ( tmpdir ( ) , "openclaw-sandbox-registry-" ) ) ;
18+
5319 return {
54- ...actual ,
55- writeJsonAtomic : async (
56- filePath : string ,
57- value : unknown ,
58- options ?: Parameters < typeof actual . writeJsonAtomic > [ 2 ] ,
59- ) => {
60- const payload = JSON . stringify ( value ) ;
61- const gate = activeWriteGate ;
62- if (
63- gate &&
64- filePath . includes ( gate . targetFile ) &&
65- payloadMentionsContainer ( payload , gate . containerName )
66- ) {
67- if ( ! gate . started ) {
68- gate . started = true ;
69- gate . markStarted ( ) ;
70- }
71- await gate . waitForRelease ;
72- }
73- await actual . writeJsonAtomic ( filePath , value , options ) ;
74- } ,
20+ TEST_STATE_DIR : baseDir ,
21+ SANDBOX_REGISTRY_PATH : path . join ( baseDir , "containers.json" ) ,
22+ SANDBOX_BROWSER_REGISTRY_PATH : path . join ( baseDir , "browsers.json" ) ,
23+ writeGateState : { active : null as WriteDelayConfig | null } ,
7524 } ;
7625 } ) ;
77- ( {
78- readBrowserRegistry,
79- readRegistry,
80- removeBrowserRegistryEntry,
81- removeRegistryEntry,
82- updateBrowserRegistry,
83- updateRegistry,
84- } = await import ( "./registry.js" ) ) ;
85- }
26+
27+ vi . mock ( "./constants.js" , ( ) => ( {
28+ SANDBOX_STATE_DIR : TEST_STATE_DIR ,
29+ SANDBOX_REGISTRY_PATH ,
30+ SANDBOX_BROWSER_REGISTRY_PATH ,
31+ } ) ) ;
32+
33+ vi . mock ( "../../infra/json-files.js" , async ( ) => {
34+ const actual = await vi . importActual < typeof import ( "../../infra/json-files.js" ) > (
35+ "../../infra/json-files.js" ,
36+ ) ;
37+ return {
38+ ...actual ,
39+ writeJsonAtomic : async (
40+ filePath : string ,
41+ value : unknown ,
42+ options ?: Parameters < typeof actual . writeJsonAtomic > [ 2 ] ,
43+ ) => {
44+ const payload = JSON . stringify ( value ) ;
45+ const gate = writeGateState . active ;
46+ if (
47+ gate &&
48+ filePath . includes ( gate . targetFile ) &&
49+ payloadMentionsContainer ( payload , gate . containerName )
50+ ) {
51+ if ( ! gate . started ) {
52+ gate . started = true ;
53+ gate . markStarted ( ) ;
54+ }
55+ await gate . waitForRelease ;
56+ }
57+ await actual . writeJsonAtomic ( filePath , value , options ) ;
58+ } ,
59+ } ;
60+ } ) ;
61+
62+ import {
63+ readBrowserRegistry ,
64+ readRegistry ,
65+ removeBrowserRegistryEntry ,
66+ removeRegistryEntry ,
67+ updateBrowserRegistry ,
68+ updateRegistry ,
69+ } from "./registry.js" ;
70+
71+ type SandboxBrowserRegistryEntry = import ( "./registry.js" ) . SandboxBrowserRegistryEntry ;
72+ type SandboxRegistryEntry = import ( "./registry.js" ) . SandboxRegistryEntry ;
8673
8774function payloadMentionsContainer ( payload : string , containerName : string ) : boolean {
8875 return (
@@ -111,7 +98,7 @@ function installWriteGate(
11198 const waitForRelease = new Promise < void > ( ( resolve ) => {
11299 resolveRelease = resolve ;
113100 } ) ;
114- activeWriteGate = {
101+ writeGateState . active = {
115102 targetFile,
116103 containerName,
117104 started : false ,
@@ -122,18 +109,16 @@ function installWriteGate(
122109 waitForStart,
123110 release : ( ) => {
124111 resolveRelease ( ) ;
125- activeWriteGate = null ;
112+ writeGateState . active = null ;
126113 } ,
127114 } ;
128115}
129116
130- beforeEach ( async ( ) => {
131- activeWriteGate = null ;
132- await loadFreshRegistryModuleForTest ( ) ;
117+ beforeEach ( ( ) => {
118+ writeGateState . active = null ;
133119} ) ;
134120
135121afterEach ( async ( ) => {
136- vi . restoreAllMocks ( ) ;
137122 await fs . rm ( SANDBOX_REGISTRY_PATH , { force : true } ) ;
138123 await fs . rm ( SANDBOX_BROWSER_REGISTRY_PATH , { force : true } ) ;
139124 await fs . rm ( `${ SANDBOX_REGISTRY_PATH } .lock` , { force : true } ) ;
0 commit comments