mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-12 12:40:42 +00:00
test: hoist gateway helper imports
This commit is contained in:
@@ -1,32 +1,28 @@
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { callGatewayTool, resolveGatewayOptions } from "./gateway.js";
|
||||
|
||||
const callGatewayMock = vi.fn();
|
||||
const configState = vi.hoisted(() => ({
|
||||
value: {} as Record<string, unknown>,
|
||||
const mocks = vi.hoisted(() => ({
|
||||
callGateway: vi.fn(),
|
||||
configState: {
|
||||
value: {} as Record<string, unknown>,
|
||||
},
|
||||
}));
|
||||
vi.mock("../../config/config.js", () => ({
|
||||
getRuntimeConfig: () => configState.value,
|
||||
getRuntimeConfig: () => mocks.configState.value,
|
||||
resolveGatewayPort: () => 18789,
|
||||
}));
|
||||
vi.mock("../../gateway/call.js", () => ({
|
||||
callGateway: (...args: unknown[]) => callGatewayMock(...args),
|
||||
callGateway: (...args: unknown[]) => mocks.callGateway(...args),
|
||||
}));
|
||||
|
||||
let callGatewayTool: typeof import("./gateway.js").callGatewayTool;
|
||||
let resolveGatewayOptions: typeof import("./gateway.js").resolveGatewayOptions;
|
||||
|
||||
describe("gateway tool defaults", () => {
|
||||
const envSnapshot = {
|
||||
openclaw: process.env.OPENCLAW_GATEWAY_TOKEN,
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
({ callGatewayTool, resolveGatewayOptions } = await import("./gateway.js"));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
callGatewayMock.mockClear();
|
||||
configState.value = {};
|
||||
mocks.callGateway.mockClear();
|
||||
mocks.configState.value = {};
|
||||
delete process.env.OPENCLAW_GATEWAY_TOKEN;
|
||||
});
|
||||
|
||||
@@ -44,13 +40,13 @@ describe("gateway tool defaults", () => {
|
||||
});
|
||||
|
||||
it("accepts allowlisted gatewayUrl overrides (SSRF hardening)", async () => {
|
||||
callGatewayMock.mockResolvedValueOnce({ ok: true });
|
||||
mocks.callGateway.mockResolvedValueOnce({ ok: true });
|
||||
await callGatewayTool(
|
||||
"health",
|
||||
{ gatewayUrl: "ws://127.0.0.1:18789", gatewayToken: "t", timeoutMs: 5000 },
|
||||
{},
|
||||
);
|
||||
expect(callGatewayMock).toHaveBeenCalledWith(
|
||||
expect(mocks.callGateway).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
url: "ws://127.0.0.1:18789",
|
||||
token: "t",
|
||||
@@ -68,7 +64,7 @@ describe("gateway tool defaults", () => {
|
||||
});
|
||||
|
||||
it("falls back to config gateway.auth.token when env is unset for local overrides", () => {
|
||||
configState.value = {
|
||||
mocks.configState.value = {
|
||||
gateway: {
|
||||
auth: { token: "config-token" },
|
||||
},
|
||||
@@ -78,7 +74,7 @@ describe("gateway tool defaults", () => {
|
||||
});
|
||||
|
||||
it("uses gateway.remote.token for allowlisted remote overrides", () => {
|
||||
configState.value = {
|
||||
mocks.configState.value = {
|
||||
gateway: {
|
||||
remote: {
|
||||
url: "wss://gateway.example",
|
||||
@@ -93,7 +89,7 @@ describe("gateway tool defaults", () => {
|
||||
|
||||
it("does not leak local env/config tokens to remote overrides", () => {
|
||||
process.env.OPENCLAW_GATEWAY_TOKEN = "local-env-token";
|
||||
configState.value = {
|
||||
mocks.configState.value = {
|
||||
gateway: {
|
||||
auth: { token: "local-config-token" },
|
||||
remote: {
|
||||
@@ -106,7 +102,7 @@ describe("gateway tool defaults", () => {
|
||||
});
|
||||
|
||||
it("ignores unresolved local token SecretRef for strict remote overrides", () => {
|
||||
configState.value = {
|
||||
mocks.configState.value = {
|
||||
gateway: {
|
||||
auth: {
|
||||
mode: "token",
|
||||
@@ -128,7 +124,7 @@ describe("gateway tool defaults", () => {
|
||||
|
||||
it("explicit gatewayToken overrides fallback token resolution", () => {
|
||||
process.env.OPENCLAW_GATEWAY_TOKEN = "local-env-token";
|
||||
configState.value = {
|
||||
mocks.configState.value = {
|
||||
gateway: {
|
||||
remote: {
|
||||
url: "wss://gateway.example",
|
||||
@@ -144,9 +140,9 @@ describe("gateway tool defaults", () => {
|
||||
});
|
||||
|
||||
it("uses least-privilege write scope for write methods", async () => {
|
||||
callGatewayMock.mockResolvedValueOnce({ ok: true });
|
||||
mocks.callGateway.mockResolvedValueOnce({ ok: true });
|
||||
await callGatewayTool("wake", {}, { mode: "now", text: "hi" });
|
||||
expect(callGatewayMock).toHaveBeenCalledWith(
|
||||
expect(mocks.callGateway).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
method: "wake",
|
||||
scopes: ["operator.write"],
|
||||
@@ -155,9 +151,9 @@ describe("gateway tool defaults", () => {
|
||||
});
|
||||
|
||||
it("uses admin scope only for admin methods", async () => {
|
||||
callGatewayMock.mockResolvedValueOnce({ ok: true });
|
||||
mocks.callGateway.mockResolvedValueOnce({ ok: true });
|
||||
await callGatewayTool("cron.add", {}, { id: "job-1" });
|
||||
expect(callGatewayMock).toHaveBeenCalledWith(
|
||||
expect(mocks.callGateway).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
method: "cron.add",
|
||||
scopes: ["operator.admin"],
|
||||
@@ -166,14 +162,14 @@ describe("gateway tool defaults", () => {
|
||||
});
|
||||
|
||||
it("allows explicit scope overrides for dynamic callers", async () => {
|
||||
callGatewayMock.mockResolvedValueOnce({ ok: true });
|
||||
mocks.callGateway.mockResolvedValueOnce({ ok: true });
|
||||
await callGatewayTool(
|
||||
"node.pair.approve",
|
||||
{},
|
||||
{ requestId: "req-1" },
|
||||
{ scopes: ["operator.admin"] },
|
||||
);
|
||||
expect(callGatewayMock).toHaveBeenCalledWith(
|
||||
expect(mocks.callGateway).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
method: "node.pair.approve",
|
||||
scopes: ["operator.admin"],
|
||||
@@ -182,9 +178,9 @@ describe("gateway tool defaults", () => {
|
||||
});
|
||||
|
||||
it("default-denies unknown methods by sending no scopes", async () => {
|
||||
callGatewayMock.mockResolvedValueOnce({ ok: true });
|
||||
mocks.callGateway.mockResolvedValueOnce({ ok: true });
|
||||
await callGatewayTool("nonexistent.method", {}, {});
|
||||
expect(callGatewayMock).toHaveBeenCalledWith(
|
||||
expect(mocks.callGateway).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
method: "nonexistent.method",
|
||||
scopes: [],
|
||||
|
||||
Reference in New Issue
Block a user