11import { beforeEach , describe , expect , it , vi } from "vitest" ;
22
3- const gatewayClientMock = vi . hoisted ( ( ) => {
4- const request = vi . fn ( async ( _method ?: string , _params ?: unknown , _opts ?: unknown ) => ( {
5- ok : true ,
6- } ) ) ;
7- const stopAndWait = vi . fn ( async ( ) => { } ) ;
8- const stop = vi . fn ( ) ;
9- const constructorCalls : Array < Record < string , unknown > > = [ ] ;
10- let startMode : "hello" | "connect-error" = "hello" ;
11-
12- class MockGatewayClient {
13- private readonly options : Record < string , unknown > ;
14-
15- constructor ( options : Record < string , unknown > ) {
16- this . options = options ;
17- constructorCalls . push ( options ) ;
18- }
19-
20- start ( ) {
21- queueMicrotask ( ( ) => {
22- if ( startMode === "connect-error" ) {
23- const onConnectError = this . options . onConnectError ;
24- if ( typeof onConnectError === "function" ) {
25- onConnectError ( new Error ( "connect boom" ) ) ;
26- }
27- return ;
28- }
29- const onHelloOk = this . options . onHelloOk ;
30- if ( typeof onHelloOk === "function" ) {
31- onHelloOk ( { } ) ;
32- }
33- } ) ;
34- }
35-
36- async request ( method : string , params ?: unknown , opts ?: unknown ) {
37- return await request ( method , params , opts ) ;
38- }
39-
40- async stopAndWait ( ) {
41- await stopAndWait ( ) ;
42- }
43-
44- stop ( ) {
45- stop ( ) ;
46- }
47- }
48-
3+ const gatewayRpcMock = vi . hoisted ( ( ) => {
4+ const callGatewayFromCli = vi . fn ( async ( ) => ( { ok : true } ) ) ;
495 return {
50- MockGatewayClient,
51- request,
52- stopAndWait,
53- stop,
54- constructorCalls,
6+ callGatewayFromCli,
557 reset ( ) {
56- request . mockReset ( ) . mockResolvedValue ( { ok : true } ) ;
57- stopAndWait . mockReset ( ) . mockResolvedValue ( undefined ) ;
58- stop . mockReset ( ) ;
59- constructorCalls . splice ( 0 , constructorCalls . length ) ;
60- startMode = "hello" ;
61- } ,
62- setStartMode ( mode : "hello" | "connect-error" ) {
63- startMode = mode ;
8+ callGatewayFromCli . mockReset ( ) . mockResolvedValue ( { ok : true } ) ;
649 } ,
6510 } ;
6611} ) ;
6712
6813vi . mock ( "./runtime-api.js" , ( ) => ( {
69- GatewayClient : gatewayClientMock . MockGatewayClient ,
14+ callGatewayFromCli : gatewayRpcMock . callGatewayFromCli ,
7015} ) ) ;
7116
7217import { startQaGatewayRpcClient } from "./gateway-rpc-client.js" ;
7318
7419describe ( "startQaGatewayRpcClient" , ( ) => {
7520 beforeEach ( ( ) => {
76- gatewayClientMock . reset ( ) ;
21+ gatewayRpcMock . reset ( ) ;
7722 } ) ;
7823
79- it ( "starts a gateway client without device identity and forwards requests" , async ( ) => {
24+ it ( "calls the in-process gateway cli helper with the qa runtime env" , async ( ) => {
25+ const originalHome = process . env . OPENCLAW_HOME ;
26+ delete process . env . OPENCLAW_HOME ;
27+ delete process . env . OPENCLAW_QA_TEST_ONLY ;
28+
29+ gatewayRpcMock . callGatewayFromCli . mockImplementationOnce ( async ( ) => {
30+ expect ( process . env . OPENCLAW_HOME ) . toBe ( "/tmp/openclaw-home" ) ;
31+ expect ( process . env . OPENCLAW_QA_TEST_ONLY ) . toBe ( "1" ) ;
32+ return { ok : true } ;
33+ } ) ;
34+
8035 const client = await startQaGatewayRpcClient ( {
8136 wsUrl : "ws://127.0.0.1:18789" ,
8237 token : "qa-token" ,
38+ env : {
39+ OPENCLAW_HOME : "/tmp/openclaw-home" ,
40+ OPENCLAW_QA_TEST_ONLY : "1" ,
41+ } as NodeJS . ProcessEnv ,
8342 logs : ( ) => "qa logs" ,
8443 } ) ;
8544
86- expect ( gatewayClientMock . constructorCalls [ 0 ] ) . toEqual (
87- expect . objectContaining ( {
88- url : "ws://127.0.0.1:18789" ,
89- token : "qa-token" ,
90- deviceIdentity : null ,
91- scopes : [
92- "operator.admin" ,
93- "operator.read" ,
94- "operator.write" ,
95- "operator.approvals" ,
96- "operator.pairing" ,
97- "operator.talk.secrets" ,
98- ] ,
99- } ) ,
100- ) ;
101-
10245 await expect (
10346 client . request ( "agent.run" , { prompt : "hi" } , { expectFinal : true , timeoutMs : 45_000 } ) ,
10447 ) . resolves . toEqual ( { ok : true } ) ;
10548
106- expect ( gatewayClientMock . request ) . toHaveBeenCalledWith (
49+ expect ( gatewayRpcMock . callGatewayFromCli ) . toHaveBeenCalledWith (
10750 "agent.run" ,
51+ {
52+ url : "ws://127.0.0.1:18789" ,
53+ token : "qa-token" ,
54+ timeout : "45000" ,
55+ expectFinal : true ,
56+ json : true ,
57+ } ,
10858 { prompt : "hi" } ,
10959 {
11060 expectFinal : true ,
111- timeoutMs : 45_000 ,
61+ progress : false ,
11262 } ,
11363 ) ;
11464
115- await client . stop ( ) ;
116- expect ( gatewayClientMock . stopAndWait ) . toHaveBeenCalledTimes ( 1 ) ;
65+ expect ( process . env . OPENCLAW_HOME ) . toBe ( originalHome ) ;
66+ expect ( process . env . OPENCLAW_QA_TEST_ONLY ) . toBeUndefined ( ) ;
11767 } ) ;
11868
11969 it ( "wraps request failures with gateway logs" , async ( ) => {
120- gatewayClientMock . request . mockRejectedValueOnce ( new Error ( "gateway not connected" ) ) ;
70+ gatewayRpcMock . callGatewayFromCli . mockRejectedValueOnce ( new Error ( "gateway not connected" ) ) ;
12171 const client = await startQaGatewayRpcClient ( {
12272 wsUrl : "ws://127.0.0.1:18789" ,
12373 token : "qa-token" ,
74+ env : { OPENCLAW_HOME : "/tmp/openclaw-home" } as NodeJS . ProcessEnv ,
12475 logs : ( ) => "qa logs" ,
12576 } ) ;
12677
@@ -129,15 +80,18 @@ describe("startQaGatewayRpcClient", () => {
12980 ) ;
13081 } ) ;
13182
132- it ( "wraps connect failures with gateway logs" , async ( ) => {
133- gatewayClientMock . setStartMode ( "connect-error" ) ;
83+ it ( "rejects new requests after stop" , async ( ) => {
84+ const client = await startQaGatewayRpcClient ( {
85+ wsUrl : "ws://127.0.0.1:18789" ,
86+ token : "qa-token" ,
87+ env : { OPENCLAW_HOME : "/tmp/openclaw-home" } as NodeJS . ProcessEnv ,
88+ logs : ( ) => "qa logs" ,
89+ } ) ;
90+
91+ await client . stop ( ) ;
13492
135- await expect (
136- startQaGatewayRpcClient ( {
137- wsUrl : "ws://127.0.0.1:18789" ,
138- token : "qa-token" ,
139- logs : ( ) => "qa logs" ,
140- } ) ,
141- ) . rejects . toThrow ( "connect boom\nGateway logs:\nqa logs" ) ;
93+ await expect ( client . request ( "health" ) ) . rejects . toThrow (
94+ "gateway rpc client already stopped\nGateway logs:\nqa logs" ,
95+ ) ;
14296 } ) ;
14397} ) ;
0 commit comments