Files
openclaw-zero-token/commands/gateway-status/helpers.test.ts
sjhu 571e14a236 feat: upgrade to upstream v2026.3.28
Major upgrade from e26988a38 to upstream v2026.3.28 (f9b107928).
Key changes:
- Upstream src/, ui/, extensions/ (89 bundled extensions)
- Zero-token web providers preserved in src/zero-token/
- AskOnce plugin restored and registered as CLI command
- Added missing packages: @anthropic-ai/vertex-sdk, @modelcontextprotocol/sdk
- Fixed tsconfig rootDir, skipLibCheck for plugin-sdk DTS build
- Added askonce to bundled plugin metadata and package.json exports
- Fixed AskOnce CLI command registration (missing commands metadata)
- Restored AskOnce adapter imports (correct 5-level relative paths)
- Removed stale migration artifacts from root directory
2026-03-30 17:58:12 +08:00

353 lines
9.2 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { withEnvAsync } from "../../test-utils/env.js";
import {
extractConfigSummary,
isProbeReachable,
isScopeLimitedProbeFailure,
renderProbeSummaryLine,
resolveProbeBudgetMs,
resolveAuthForTarget,
} from "./helpers.js";
describe("extractConfigSummary", () => {
it("marks SecretRef-backed gateway auth credentials as configured", () => {
const summary = extractConfigSummary({
path: "/tmp/openclaw.json",
exists: true,
valid: true,
issues: [],
legacyIssues: [],
config: {
secrets: {
defaults: {
env: "default",
},
},
gateway: {
auth: {
mode: "token",
token: { source: "env", provider: "default", id: "OPENCLAW_GATEWAY_TOKEN" },
password: { source: "env", provider: "default", id: "OPENCLAW_GATEWAY_PASSWORD" },
},
remote: {
url: "wss://remote.example:18789",
token: { source: "env", provider: "default", id: "REMOTE_GATEWAY_TOKEN" },
password: { source: "env", provider: "default", id: "REMOTE_GATEWAY_PASSWORD" },
},
},
},
});
expect(summary.gateway.authTokenConfigured).toBe(true);
expect(summary.gateway.authPasswordConfigured).toBe(true);
expect(summary.gateway.remoteTokenConfigured).toBe(true);
expect(summary.gateway.remotePasswordConfigured).toBe(true);
});
it("still treats empty plaintext auth values as not configured", () => {
const summary = extractConfigSummary({
path: "/tmp/openclaw.json",
exists: true,
valid: true,
issues: [],
legacyIssues: [],
config: {
gateway: {
auth: {
mode: "token",
token: " ",
password: "",
},
remote: {
token: " ",
password: "",
},
},
},
});
expect(summary.gateway.authTokenConfigured).toBe(false);
expect(summary.gateway.authPasswordConfigured).toBe(false);
expect(summary.gateway.remoteTokenConfigured).toBe(false);
expect(summary.gateway.remotePasswordConfigured).toBe(false);
});
});
describe("resolveAuthForTarget", () => {
function createConfigRemoteTarget() {
return {
id: "configRemote",
kind: "configRemote" as const,
url: "wss://remote.example:18789",
active: true,
};
}
function createRemoteGatewayTargetConfig(params?: { mode?: "none" | "password" | "token" }) {
return {
secrets: {
providers: {
default: { source: "env" as const },
},
},
gateway: {
...(params?.mode
? {
auth: {
mode: params.mode,
},
}
: {}),
remote: {
token: { source: "env" as const, provider: "default", id: "REMOTE_GATEWAY_TOKEN" },
},
},
};
}
it("resolves local auth token SecretRef before probing local targets", async () => {
await withEnvAsync(
{
OPENCLAW_GATEWAY_TOKEN: undefined,
OPENCLAW_GATEWAY_PASSWORD: undefined,
LOCAL_GATEWAY_TOKEN: "resolved-local-token",
},
async () => {
const auth = await resolveAuthForTarget(
{
secrets: {
providers: {
default: { source: "env" },
},
},
gateway: {
auth: {
token: { source: "env", provider: "default", id: "LOCAL_GATEWAY_TOKEN" },
},
},
},
{
id: "localLoopback",
kind: "localLoopback",
url: "ws://127.0.0.1:18789",
active: true,
},
{},
);
expect(auth).toEqual({ token: "resolved-local-token", password: undefined });
},
);
});
it("resolves remote auth token SecretRef before probing remote targets", async () => {
await withEnvAsync(
{
REMOTE_GATEWAY_TOKEN: "resolved-remote-token",
},
async () => {
const auth = await resolveAuthForTarget(
createRemoteGatewayTargetConfig(),
createConfigRemoteTarget(),
{},
);
expect(auth).toEqual({ token: "resolved-remote-token", password: undefined });
},
);
});
it("resolves remote auth even when local auth mode is none", async () => {
await withEnvAsync(
{
REMOTE_GATEWAY_TOKEN: "resolved-remote-token",
},
async () => {
const auth = await resolveAuthForTarget(
createRemoteGatewayTargetConfig({ mode: "none" }),
createConfigRemoteTarget(),
{},
);
expect(auth).toEqual({ token: "resolved-remote-token", password: undefined });
},
);
});
it("does not force remote auth type from local auth mode", async () => {
const auth = await resolveAuthForTarget(
{
gateway: {
auth: {
mode: "password",
},
remote: {
token: "remote-token",
password: "remote-password", // pragma: allowlist secret
},
},
},
{
id: "configRemote",
kind: "configRemote",
url: "wss://remote.example:18789",
active: true,
},
{},
);
expect(auth).toEqual({ token: "remote-token", password: undefined });
});
it("redacts resolver internals from unresolved SecretRef diagnostics", async () => {
await withEnvAsync(
{
MISSING_GATEWAY_TOKEN: undefined,
},
async () => {
const auth = await resolveAuthForTarget(
{
secrets: {
providers: {
default: { source: "env" },
},
},
gateway: {
auth: {
mode: "token",
token: { source: "env", provider: "default", id: "MISSING_GATEWAY_TOKEN" },
},
},
},
{
id: "localLoopback",
kind: "localLoopback",
url: "ws://127.0.0.1:18789",
active: true,
},
{},
);
expect(auth.diagnostics).toContain(
"gateway.auth.token SecretRef is unresolved (env:default:MISSING_GATEWAY_TOKEN).",
);
expect(auth.diagnostics?.join("\n")).not.toContain("missing or empty");
},
);
});
});
describe("probe reachability classification", () => {
it("treats missing-scope RPC failures as scope-limited and reachable", () => {
const probe = {
ok: false,
url: "ws://127.0.0.1:18789",
connectLatencyMs: 51,
error: "missing scope: operator.read",
close: null,
health: null,
status: null,
presence: null,
configSnapshot: null,
};
expect(isScopeLimitedProbeFailure(probe)).toBe(true);
expect(isProbeReachable(probe)).toBe(true);
expect(renderProbeSummaryLine(probe, false)).toContain("RPC: limited");
});
it("keeps non-scope RPC failures as unreachable", () => {
const probe = {
ok: false,
url: "ws://127.0.0.1:18789",
connectLatencyMs: 43,
error: "unknown method: status",
close: null,
health: null,
status: null,
presence: null,
configSnapshot: null,
};
expect(isScopeLimitedProbeFailure(probe)).toBe(false);
expect(isProbeReachable(probe)).toBe(false);
expect(renderProbeSummaryLine(probe, false)).toContain("RPC: failed");
});
});
describe("resolveProbeBudgetMs", () => {
it("lets active local loopback probes use the full caller budget", () => {
expect(
resolveProbeBudgetMs(15_000, {
kind: "localLoopback",
active: true,
url: "ws://127.0.0.1:18789",
}),
).toBe(15_000);
expect(
resolveProbeBudgetMs(3_000, {
kind: "localLoopback",
active: true,
url: "ws://127.0.0.1:18789",
}),
).toBe(3_000);
});
it("keeps inactive local loopback probes on the short cap", () => {
expect(
resolveProbeBudgetMs(15_000, {
kind: "localLoopback",
active: false,
url: "ws://127.0.0.1:18789",
}),
).toBe(800);
expect(
resolveProbeBudgetMs(500, {
kind: "localLoopback",
active: false,
url: "ws://127.0.0.1:18789",
}),
).toBe(500);
});
it("lets explicit loopback URLs use the full caller budget", () => {
expect(
resolveProbeBudgetMs(15_000, {
kind: "explicit",
active: true,
url: "ws://127.0.0.1:18789",
}),
).toBe(15_000);
expect(
resolveProbeBudgetMs(2_500, {
kind: "explicit",
active: true,
url: "wss://localhost:18789/ws",
}),
).toBe(2_500);
});
it("keeps non-local probe caps unchanged", () => {
expect(
resolveProbeBudgetMs(15_000, {
kind: "configRemote",
active: true,
url: "wss://gateway.example/ws",
}),
).toBe(1500);
expect(
resolveProbeBudgetMs(15_000, {
kind: "explicit",
active: true,
url: "wss://gateway.example/ws",
}),
).toBe(1500);
expect(
resolveProbeBudgetMs(15_000, {
kind: "sshTunnel",
active: true,
url: "wss://gateway.example/ws",
}),
).toBe(2000);
});
});