From 158ebbb2ed580bfc1b97cc2b50efb54b1b31d81c Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 19 Apr 2026 00:22:42 +0100 Subject: [PATCH] test: share gateway config onboard harness --- .../local/gateway-config.test.ts | 122 ++++++------------ 1 file changed, 43 insertions(+), 79 deletions(-) diff --git a/src/commands/onboard-non-interactive/local/gateway-config.test.ts b/src/commands/onboard-non-interactive/local/gateway-config.test.ts index e285262b53c..7be5ead4bb6 100644 --- a/src/commands/onboard-non-interactive/local/gateway-config.test.ts +++ b/src/commands/onboard-non-interactive/local/gateway-config.test.ts @@ -33,6 +33,29 @@ const SAMPLE_SECRET_REF = { id: "OPENCLAW_GATEWAY_TOKEN_REF", }; +function createTokenConfig(token: unknown): OpenClawConfig { + return { + gateway: { auth: { mode: "token", token } }, + } as unknown as OpenClawConfig; +} + +function applyGatewayConfig({ + nextConfig = {} as OpenClawConfig, + opts = baseOpts, + runtime = createRuntime(), +}: { + nextConfig?: OpenClawConfig; + opts?: OnboardOptions; + runtime?: ReturnType; +} = {}) { + return applyNonInteractiveGatewayConfig({ + nextConfig, + opts, + runtime: runtime as never, + defaultPort: 18789, + }); +} + describe("applyNonInteractiveGatewayConfig token resolution chain", () => { const originalEnvToken = process.env.OPENCLAW_GATEWAY_TOKEN; const originalRefValue = process.env[SAMPLE_SECRET_REF.id]; @@ -59,16 +82,9 @@ describe("applyNonInteractiveGatewayConfig token resolution chain", () => { // --- Plaintext preservation (the original regression) --- it("preserves existing plaintext gateway.auth.token when no flag or env override is provided", () => { - const nextConfig = { - gateway: { auth: { mode: "token", token: "existing-user-token" } }, - } as OpenClawConfig; + const nextConfig = createTokenConfig("existing-user-token"); - const result = applyNonInteractiveGatewayConfig({ - nextConfig, - opts: baseOpts, - runtime: createRuntime() as never, - defaultPort: 18789, - }); + const result = applyGatewayConfig({ nextConfig }); expect(result?.nextConfig.gateway?.auth?.token).toBe("existing-user-token"); expect(randomToken).not.toHaveBeenCalled(); @@ -78,31 +94,20 @@ describe("applyNonInteractiveGatewayConfig token resolution chain", () => { // A stale shell/launchd OPENCLAW_GATEWAY_TOKEN must not rotate a // persisted token — that would break already-paired clients. process.env.OPENCLAW_GATEWAY_TOKEN = "stale-env-token"; - const nextConfig = { - gateway: { auth: { mode: "token", token: "existing-user-token" } }, - } as OpenClawConfig; + const nextConfig = createTokenConfig("existing-user-token"); - const result = applyNonInteractiveGatewayConfig({ - nextConfig, - opts: baseOpts, - runtime: createRuntime() as never, - defaultPort: 18789, - }); + const result = applyGatewayConfig({ nextConfig }); expect(result?.nextConfig.gateway?.auth?.token).toBe("existing-user-token"); expect(randomToken).not.toHaveBeenCalled(); }); it("prefers --gateway-token flag over existing plaintext token", () => { - const nextConfig = { - gateway: { auth: { mode: "token", token: "existing-user-token" } }, - } as OpenClawConfig; + const nextConfig = createTokenConfig("existing-user-token"); - const result = applyNonInteractiveGatewayConfig({ + const result = applyGatewayConfig({ nextConfig, opts: { gatewayToken: "flag-token" } as OnboardOptions, - runtime: createRuntime() as never, - defaultPort: 18789, }); expect(result?.nextConfig.gateway?.auth?.token).toBe("flag-token"); @@ -112,24 +117,14 @@ describe("applyNonInteractiveGatewayConfig token resolution chain", () => { it("uses OPENCLAW_GATEWAY_TOKEN to fill an empty config on first-run", () => { process.env.OPENCLAW_GATEWAY_TOKEN = "env-token"; - const result = applyNonInteractiveGatewayConfig({ - nextConfig: {} as OpenClawConfig, - opts: baseOpts, - runtime: createRuntime() as never, - defaultPort: 18789, - }); + const result = applyGatewayConfig(); expect(result?.nextConfig.gateway?.auth?.token).toBe("env-token"); expect(randomToken).not.toHaveBeenCalled(); }); it("generates a random token only when flag, env, and existing config are all empty", () => { - const result = applyNonInteractiveGatewayConfig({ - nextConfig: {} as OpenClawConfig, - opts: baseOpts, - runtime: createRuntime() as never, - defaultPort: 18789, - }); + const result = applyGatewayConfig(); expect(randomToken).toHaveBeenCalledOnce(); expect(result?.nextConfig.gateway?.auth?.token).toBe("generated-random-token"); @@ -138,16 +133,9 @@ describe("applyNonInteractiveGatewayConfig token resolution chain", () => { // --- SecretRef preservation --- it("preserves an existing SecretRef when no flag or env override is provided", () => { - const nextConfig = { - gateway: { auth: { mode: "token", token: SAMPLE_SECRET_REF } }, - } as unknown as OpenClawConfig; + const nextConfig = createTokenConfig(SAMPLE_SECRET_REF); - const result = applyNonInteractiveGatewayConfig({ - nextConfig, - opts: baseOpts, - runtime: createRuntime() as never, - defaultPort: 18789, - }); + const result = applyGatewayConfig({ nextConfig }); expect(result?.nextConfig.gateway?.auth?.token).toEqual(SAMPLE_SECRET_REF); expect(randomToken).not.toHaveBeenCalled(); @@ -156,16 +144,9 @@ describe("applyNonInteractiveGatewayConfig token resolution chain", () => { it("preserves an existing SecretRef even when ambient OPENCLAW_GATEWAY_TOKEN is set", () => { // A stale ambient env must not declassify a configured SecretRef. process.env.OPENCLAW_GATEWAY_TOKEN = "stale-env-token"; - const nextConfig = { - gateway: { auth: { mode: "token", token: SAMPLE_SECRET_REF } }, - } as unknown as OpenClawConfig; + const nextConfig = createTokenConfig(SAMPLE_SECRET_REF); - const result = applyNonInteractiveGatewayConfig({ - nextConfig, - opts: baseOpts, - runtime: createRuntime() as never, - defaultPort: 18789, - }); + const result = applyGatewayConfig({ nextConfig }); expect(result?.nextConfig.gateway?.auth?.token).toEqual(SAMPLE_SECRET_REF); expect(randomToken).not.toHaveBeenCalled(); @@ -173,31 +154,20 @@ describe("applyNonInteractiveGatewayConfig token resolution chain", () => { it("leaves env-source SecretRef resolution to the health probe path", () => { process.env[SAMPLE_SECRET_REF.id] = "resolved-secret-value"; - const nextConfig = { - gateway: { auth: { mode: "token", token: SAMPLE_SECRET_REF } }, - } as unknown as OpenClawConfig; + const nextConfig = createTokenConfig(SAMPLE_SECRET_REF); - const result = applyNonInteractiveGatewayConfig({ - nextConfig, - opts: baseOpts, - runtime: createRuntime() as never, - defaultPort: 18789, - }); + const result = applyGatewayConfig({ nextConfig }); expect(result?.nextConfig.gateway?.auth?.token).toEqual(SAMPLE_SECRET_REF); expect(randomToken).not.toHaveBeenCalled(); }); it("overrides an existing SecretRef when --gateway-token flag is provided", () => { - const nextConfig = { - gateway: { auth: { mode: "token", token: SAMPLE_SECRET_REF } }, - } as unknown as OpenClawConfig; + const nextConfig = createTokenConfig(SAMPLE_SECRET_REF); - const result = applyNonInteractiveGatewayConfig({ + const result = applyGatewayConfig({ nextConfig, opts: { gatewayToken: "flag-token" } as OnboardOptions, - runtime: createRuntime() as never, - defaultPort: 18789, }); expect(result?.nextConfig.gateway?.auth?.token).toBe("flag-token"); @@ -208,15 +178,11 @@ describe("applyNonInteractiveGatewayConfig token resolution chain", () => { const newRefId = "OPENCLAW_GATEWAY_TOKEN_NEW_REF"; process.env[newRefId] = "resolved-new-ref-value"; try { - const nextConfig = { - gateway: { auth: { mode: "token", token: SAMPLE_SECRET_REF } }, - } as unknown as OpenClawConfig; + const nextConfig = createTokenConfig(SAMPLE_SECRET_REF); - const result = applyNonInteractiveGatewayConfig({ + const result = applyGatewayConfig({ nextConfig, opts: { gatewayTokenRefEnv: newRefId } as OnboardOptions, - runtime: createRuntime() as never, - defaultPort: 18789, }); const newToken = result?.nextConfig.gateway?.auth?.token; @@ -231,11 +197,9 @@ describe("applyNonInteractiveGatewayConfig token resolution chain", () => { it("fails when --gateway-token-ref-env points to a missing env var", () => { const runtime = createRuntime(); - const result = applyNonInteractiveGatewayConfig({ - nextConfig: {} as OpenClawConfig, + const result = applyGatewayConfig({ opts: { gatewayTokenRefEnv: "MISSING_GATEWAY_TOKEN_ENV" } as OnboardOptions, - runtime: runtime as never, - defaultPort: 18789, + runtime, }); expect(result).toBeNull();