2026-03-08 23:45:59 +00:00
import { beforeEach , describe , expect , it , vi } from "vitest" ;
const controlServiceMocks = vi . hoisted ( ( ) = > ( {
createBrowserControlContext : vi.fn ( ( ) = > ( { control : true } ) ) ,
startBrowserControlServiceFromConfig : vi.fn ( async ( ) = > true ) ,
} ) ) ;
const dispatcherMocks = vi . hoisted ( ( ) = > ( {
dispatch : vi.fn ( ) ,
createBrowserRouteDispatcher : vi.fn ( ( ) = > ( {
dispatch : dispatcherMocks.dispatch ,
} ) ) ,
} ) ) ;
const configMocks = vi . hoisted ( ( ) = > ( {
loadConfig : vi.fn ( ( ) = > ( {
browser : { } ,
nodeHost : { browserProxy : { enabled : true } } ,
} ) ) ,
} ) ) ;
const browserConfigMocks = vi . hoisted ( ( ) = > ( {
resolveBrowserConfig : vi.fn ( ( ) = > ( {
enabled : true ,
2026-03-14 04:15:25 +00:00
defaultProfile : "openclaw" ,
2026-03-08 23:45:59 +00:00
} ) ) ,
} ) ) ;
vi . mock ( "../browser/control-service.js" , ( ) = > controlServiceMocks ) ;
vi . mock ( "../browser/routes/dispatcher.js" , ( ) = > dispatcherMocks ) ;
vi . mock ( "../config/config.js" , ( ) = > configMocks ) ;
vi . mock ( "../browser/config.js" , ( ) = > browserConfigMocks ) ;
vi . mock ( "../media/mime.js" , ( ) = > ( {
detectMime : vi.fn ( async ( ) = > "image/png" ) ,
} ) ) ;
import { runBrowserProxyCommand } from "./invoke-browser.js" ;
describe ( "runBrowserProxyCommand" , ( ) = > {
beforeEach ( ( ) = > {
vi . clearAllMocks ( ) ;
configMocks . loadConfig . mockReturnValue ( {
browser : { } ,
nodeHost : { browserProxy : { enabled : true } } ,
} ) ;
browserConfigMocks . resolveBrowserConfig . mockReturnValue ( {
enabled : true ,
2026-03-14 04:15:25 +00:00
defaultProfile : "openclaw" ,
2026-03-08 23:45:59 +00:00
} ) ;
controlServiceMocks . startBrowserControlServiceFromConfig . mockResolvedValue ( true ) ;
} ) ;
it ( "adds profile and browser status details on ws-backed timeouts" , async ( ) = > {
dispatcherMocks . dispatch
. mockImplementationOnce ( async ( ) = > {
await new Promise ( ( ) = > { } ) ;
} )
. mockResolvedValueOnce ( {
status : 200 ,
body : {
running : true ,
cdpHttp : true ,
cdpReady : false ,
cdpUrl : "http://127.0.0.1:18792" ,
} ,
} ) ;
await expect (
runBrowserProxyCommand (
JSON . stringify ( {
method : "GET" ,
path : "/snapshot" ,
2026-03-14 04:15:25 +00:00
profile : "chrome-relay" ,
2026-03-08 23:45:59 +00:00
timeoutMs : 5 ,
} ) ,
) ,
) . rejects . toThrow (
2026-03-14 04:15:25 +00:00
/browser proxy timed out for GET \/snapshot after 5ms; ws-backed browser action; profile=chrome-relay; status\(running=true, cdpHttp=true, cdpReady=false, cdpUrl=http:\/\/127\.0\.0\.1:18792\)/ ,
2026-03-08 23:45:59 +00:00
) ;
} ) ;
2026-03-14 03:46:34 +00:00
it ( "includes chrome-mcp transport in timeout diagnostics when no CDP URL exists" , async ( ) = > {
dispatcherMocks . dispatch
. mockImplementationOnce ( async ( ) = > {
await new Promise ( ( ) = > { } ) ;
} )
. mockResolvedValueOnce ( {
status : 200 ,
body : {
running : true ,
transport : "chrome-mcp" ,
cdpHttp : true ,
cdpReady : false ,
cdpUrl : null ,
} ,
} ) ;
await expect (
runBrowserProxyCommand (
JSON . stringify ( {
method : "GET" ,
path : "/snapshot" ,
2026-03-14 04:15:25 +00:00
profile : "user" ,
2026-03-14 03:46:34 +00:00
timeoutMs : 5 ,
} ) ,
) ,
) . rejects . toThrow (
2026-03-14 04:15:25 +00:00
/browser proxy timed out for GET \/snapshot after 5ms; ws-backed browser action; profile=user; status\(running=true, cdpHttp=true, cdpReady=false, transport=chrome-mcp\)/ ,
2026-03-14 03:46:34 +00:00
) ;
} ) ;
2026-03-15 08:22:48 -07:00
it ( "redacts sensitive cdpUrl details in timeout diagnostics" , async ( ) = > {
dispatcherMocks . dispatch
. mockImplementationOnce ( async ( ) = > {
await new Promise ( ( ) = > { } ) ;
} )
. mockResolvedValueOnce ( {
status : 200 ,
body : {
running : true ,
cdpHttp : true ,
cdpReady : false ,
cdpUrl :
"https://alice:supersecretpasswordvalue1234@example.com/chrome?token=supersecrettokenvalue1234567890" ,
} ,
} ) ;
await expect (
runBrowserProxyCommand (
JSON . stringify ( {
method : "GET" ,
path : "/snapshot" ,
profile : "remote" ,
timeoutMs : 5 ,
} ) ,
) ,
) . rejects . toThrow (
/status\(running=true, cdpHttp=true, cdpReady=false, cdpUrl=https:\/\/example\.com\/chrome\?token=supers…7890\)/ ,
) ;
} ) ;
2026-03-08 23:45:59 +00:00
it ( "keeps non-timeout browser errors intact" , async ( ) = > {
dispatcherMocks . dispatch . mockResolvedValue ( {
status : 500 ,
body : { error : "tab not found" } ,
} ) ;
await expect (
runBrowserProxyCommand (
JSON . stringify ( {
method : "POST" ,
path : "/act" ,
2026-03-14 04:15:25 +00:00
profile : "chrome-relay" ,
2026-03-08 23:45:59 +00:00
timeoutMs : 50 ,
} ) ,
) ,
) . rejects . toThrow ( "tab not found" ) ;
} ) ;
} ) ;