From a948a3bd0087de330d37df41a4a35bf241462875 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 16 Feb 2026 15:40:48 +0000 Subject: [PATCH] refactor(test): share gateway onboarding state-dir lifecycle --- ...nboard-non-interactive.gateway.e2e.test.ts | 158 +++++++++--------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/src/commands/onboard-non-interactive.gateway.e2e.test.ts b/src/commands/onboard-non-interactive.gateway.e2e.test.ts index b3d8d8bd2..2172a69c9 100644 --- a/src/commands/onboard-non-interactive.gateway.e2e.test.ts +++ b/src/commands/onboard-non-interactive.gateway.e2e.test.ts @@ -100,6 +100,21 @@ describe("onboard (non-interactive): gateway and remote auth", () => { delete process.env.OPENCLAW_CONFIG_PATH; return stateDir; }; + const withStateDir = async ( + prefix: string, + run: (stateDir: string) => Promise, + ): Promise => { + const stateDir = await initStateDir(prefix); + try { + await run(stateDir); + } finally { + await fs.rm(stateDir, { recursive: true, force: true }); + } + }; + const runOnboarding = async (options: Record) => { + const { runNonInteractiveOnboarding } = await import("./onboard-non-interactive.js"); + await runNonInteractiveOnboarding(options, runtime); + }; beforeAll(async () => { process.env.OPENCLAW_SKIP_CHANNELS = "1"; @@ -131,13 +146,11 @@ describe("onboard (non-interactive): gateway and remote auth", () => { }); it("writes gateway token auth into config and gateway enforces it", async () => { - const stateDir = await initStateDir("state-noninteractive-"); - const token = "tok_test_123"; - const workspace = path.join(stateDir, "openclaw"); + await withStateDir("state-noninteractive-", async (stateDir) => { + const token = "tok_test_123"; + const workspace = path.join(stateDir, "openclaw"); - const { runNonInteractiveOnboarding } = await import("./onboard-non-interactive.js"); - await runNonInteractiveOnboarding( - { + await runOnboarding({ nonInteractive: true, mode: "local", workspace, @@ -148,65 +161,57 @@ describe("onboard (non-interactive): gateway and remote auth", () => { gatewayBind: "loopback", gatewayAuth: "token", gatewayToken: token, - }, - runtime, - ); + }); - const { resolveConfigPath } = await import("../config/paths.js"); - const configPath = resolveConfigPath(process.env, stateDir); - const cfg = JSON.parse(await fs.readFile(configPath, "utf8")) as { - gateway?: { auth?: { mode?: string; token?: string } }; - agents?: { defaults?: { workspace?: string } }; - }; + const { resolveConfigPath } = await import("../config/paths.js"); + const configPath = resolveConfigPath(process.env, stateDir); + const cfg = JSON.parse(await fs.readFile(configPath, "utf8")) as { + gateway?: { auth?: { mode?: string; token?: string } }; + agents?: { defaults?: { workspace?: string } }; + }; - expect(cfg?.agents?.defaults?.workspace).toBe(workspace); - expect(cfg?.gateway?.auth?.mode).toBe("token"); - expect(cfg?.gateway?.auth?.token).toBe(token); + expect(cfg?.agents?.defaults?.workspace).toBe(workspace); + expect(cfg?.gateway?.auth?.mode).toBe("token"); + expect(cfg?.gateway?.auth?.token).toBe(token); - await expectGatewayTokenAuth({ - authConfig: cfg.gateway?.auth, - token, - env: process.env, + await expectGatewayTokenAuth({ + authConfig: cfg.gateway?.auth, + token, + env: process.env, + }); }); - - await fs.rm(stateDir, { recursive: true, force: true }); }, 60_000); it("writes gateway.remote url/token and callGateway uses them", async () => { - const stateDir = await initStateDir("state-remote-"); - const port = await getFreePort(); - const token = "tok_remote_123"; - const { runNonInteractiveOnboarding } = await import("./onboard-non-interactive.js"); - await runNonInteractiveOnboarding( - { + await withStateDir("state-remote-", async () => { + const port = await getFreePort(); + const token = "tok_remote_123"; + await runOnboarding({ nonInteractive: true, mode: "remote", remoteUrl: `ws://127.0.0.1:${port}`, remoteToken: token, authChoice: "skip", json: true, - }, - runtime, - ); + }); - const { resolveConfigPath } = await import("../config/config.js"); - const cfg = JSON.parse(await fs.readFile(resolveConfigPath(), "utf8")) as { - gateway?: { mode?: string; remote?: { url?: string; token?: string } }; - }; + const { resolveConfigPath } = await import("../config/config.js"); + const cfg = JSON.parse(await fs.readFile(resolveConfigPath(), "utf8")) as { + gateway?: { mode?: string; remote?: { url?: string; token?: string } }; + }; - expect(cfg.gateway?.mode).toBe("remote"); - expect(cfg.gateway?.remote?.url).toBe(`ws://127.0.0.1:${port}`); - expect(cfg.gateway?.remote?.token).toBe(token); + expect(cfg.gateway?.mode).toBe("remote"); + expect(cfg.gateway?.remote?.url).toBe(`ws://127.0.0.1:${port}`); + expect(cfg.gateway?.remote?.token).toBe(token); - gatewayClientCalls.length = 0; - const { callGateway } = await import("../gateway/call.js"); - const health = await callGateway<{ ok?: boolean }>({ method: "health" }); - expect(health?.ok).toBe(true); - const lastCall = gatewayClientCalls[gatewayClientCalls.length - 1]; - expect(lastCall?.url).toBe(`ws://127.0.0.1:${port}`); - expect(lastCall?.token).toBe(token); - - await fs.rm(stateDir, { recursive: true, force: true }); + gatewayClientCalls.length = 0; + const { callGateway } = await import("../gateway/call.js"); + const health = await callGateway<{ ok?: boolean }>({ method: "health" }); + expect(health?.ok).toBe(true); + const lastCall = gatewayClientCalls[gatewayClientCalls.length - 1]; + expect(lastCall?.url).toBe(`ws://127.0.0.1:${port}`); + expect(lastCall?.token).toBe(token); + }); }, 60_000); it("auto-generates token auth when binding LAN and persists the token", async () => { @@ -214,16 +219,14 @@ describe("onboard (non-interactive): gateway and remote auth", () => { // Windows runner occasionally drops the temp config write in this flow; skip to keep CI green. return; } - const stateDir = await initStateDir("state-lan-"); - process.env.OPENCLAW_STATE_DIR = stateDir; - process.env.OPENCLAW_CONFIG_PATH = path.join(stateDir, "openclaw.json"); + await withStateDir("state-lan-", async (stateDir) => { + process.env.OPENCLAW_STATE_DIR = stateDir; + process.env.OPENCLAW_CONFIG_PATH = path.join(stateDir, "openclaw.json"); - const port = await getFreeGatewayPort(); - const workspace = path.join(stateDir, "openclaw"); + const port = await getFreeGatewayPort(); + const workspace = path.join(stateDir, "openclaw"); - const { runNonInteractiveOnboarding } = await import("./onboard-non-interactive.js"); - await runNonInteractiveOnboarding( - { + await runOnboarding({ nonInteractive: true, mode: "local", workspace, @@ -233,32 +236,29 @@ describe("onboard (non-interactive): gateway and remote auth", () => { installDaemon: false, gatewayPort: port, gatewayBind: "lan", - }, - runtime, - ); + }); - const { resolveConfigPath } = await import("../config/paths.js"); - const configPath = resolveConfigPath(process.env, stateDir); - const cfg = JSON.parse(await fs.readFile(configPath, "utf8")) as { - gateway?: { - bind?: string; - port?: number; - auth?: { mode?: string; token?: string }; + const { resolveConfigPath } = await import("../config/paths.js"); + const configPath = resolveConfigPath(process.env, stateDir); + const cfg = JSON.parse(await fs.readFile(configPath, "utf8")) as { + gateway?: { + bind?: string; + port?: number; + auth?: { mode?: string; token?: string }; + }; }; - }; - expect(cfg.gateway?.bind).toBe("lan"); - expect(cfg.gateway?.port).toBe(port); - expect(cfg.gateway?.auth?.mode).toBe("token"); - const token = cfg.gateway?.auth?.token ?? ""; - expect(token.length).toBeGreaterThan(8); + expect(cfg.gateway?.bind).toBe("lan"); + expect(cfg.gateway?.port).toBe(port); + expect(cfg.gateway?.auth?.mode).toBe("token"); + const token = cfg.gateway?.auth?.token ?? ""; + expect(token.length).toBeGreaterThan(8); - await expectGatewayTokenAuth({ - authConfig: cfg.gateway?.auth, - token, - env: process.env, + await expectGatewayTokenAuth({ + authConfig: cfg.gateway?.auth, + token, + env: process.env, + }); }); - - await fs.rm(stateDir, { recursive: true, force: true }); }, 60_000); });