Download test/cli-json-stdout.hooks.e2e.test.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 8.7 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/test/cli-json-stdout.hooks.e2e.test.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/test/cli-json-stdout.hooks.e2e.test.ts
-
curl -L -o cli-json-stdout.hooks.e2e.test.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/test/cli-json-stdout.hooks.e2e.test.ts
8.7 kB
| import fs from "node:fs/promises"; | |
| import path from "node:path"; | |
| import { withTempHome } from "openclaw/plugin-sdk/test-env"; | |
| import { describe, expect, it } from "vitest"; | |
| import { runBuiltCli } from "./cli-json-stdout.test-support.js"; | |
| describe("cli json stdout contract", () => { | |
| it.each([ | |
| { | |
| name: "bare report with parent JSON", | |
| args: ["hooks", "--agent", "retired", "--json"], | |
| }, | |
| { | |
| name: "list report with leaf JSON", | |
| args: ["hooks", "list", "--agent", "retired", "--json"], | |
| }, | |
| { | |
| name: "list report with parent JSON", | |
| args: ["hooks", "--json", "list", "--agent", "retired"], | |
| }, | |
| { | |
| name: "info report with leaf JSON", | |
| args: ["hooks", "info", "demo", "--agent", "retired", "--json"], | |
| }, | |
| { | |
| name: "info report with parent JSON", | |
| args: ["hooks", "--json", "info", "demo", "--agent", "retired"], | |
| }, | |
| { | |
| name: "check report with leaf JSON", | |
| args: ["hooks", "check", "--agent", "retired", "--json"], | |
| }, | |
| { | |
| name: "check report with parent JSON", | |
| args: ["hooks", "--json", "check", "--agent", "retired"], | |
| }, | |
| { | |
| name: "blank leaf agent", | |
| args: ["hooks", "list", "--agent", "", "--json"], | |
| message: "--agent must not be blank", | |
| }, | |
| { | |
| name: "blank parent agent", | |
| args: ["hooks", "--agent", "", "--json", "list"], | |
| message: "--agent must not be blank", | |
| }, | |
| { | |
| name: "human report", | |
| args: ["hooks", "list", "--agent", "retired"], | |
| human: true, | |
| }, | |
| { | |
| name: "forced Commander report", | |
| args: ["hooks", "list", "--agent", "retired", "--json"], | |
| commander: true, | |
| }, | |
| { | |
| name: "dual-TTY report", | |
| args: ["hooks", "check", "--agent", "retired", "--json"], | |
| tty: true, | |
| }, | |
| { | |
| name: "configured remote Gateway missing its URL", | |
| args: ["hooks", "list", "--json"], | |
| message: "gateway remote mode misconfigured: gateway.remote.url missing", | |
| remoteMissing: true, | |
| }, | |
| ...[ | |
| { name: "default report", args: ["hooks", "--json"] }, | |
| { name: "list report", args: ["hooks", "list", "--json"] }, | |
| { name: "info report", args: ["hooks", "info", "demo", "--json"] }, | |
| { name: "check report", args: ["hooks", "check", "--json"] }, | |
| ].map(({ name, args }) => ({ | |
| name: `${name} after an explicit environment Gateway fails`, | |
| args, | |
| message: "AUTOQA_SELECTED_GATEWAY_FAILURE", | |
| explicitGateway: true, | |
| })), | |
| { | |
| name: "injected local report failure", | |
| args: ["hooks", "list", "--json"], | |
| message: "injected hook report loading failure", | |
| reportFailure: true, | |
| }, | |
| { | |
| name: "missing hook with leaf JSON", | |
| args: ["hooks", "info", "missing-hook", "--json"], | |
| message: 'Hook "missing-hook" not found.', | |
| missingHook: true, | |
| }, | |
| { | |
| name: "missing hook with parent JSON", | |
| args: ["hooks", "--json", "info", "missing-hook"], | |
| message: 'Hook "missing-hook" not found.', | |
| missingHook: true, | |
| }, | |
| { | |
| name: "missing hook through dual-TTY finalization", | |
| args: ["hooks", "info", "missing-hook", "--json"], | |
| message: 'Hook "missing-hook" not found.', | |
| missingHook: true, | |
| tty: true, | |
| }, | |
| { | |
| name: "missing hook in human mode", | |
| args: ["hooks", "info", "missing-hook"], | |
| message: 'Hook "missing-hook" not found. Run `openclaw hooks list` to see available hooks.', | |
| missingHook: true, | |
| human: true, | |
| }, | |
| ])("renders hooks read failures through their canonical owner for $name", async (testCase) => { | |
| await withTempHome( | |
| async (tempHome) => { | |
| const stateDir = path.join(tempHome, "isolated-state"); | |
| const configPath = path.join(tempHome, "missing-openclaw.json"); | |
| const workspaceHooksDir = path.join(stateDir, "workspace", "hooks"); | |
| if ("remoteMissing" in testCase) { | |
| await fs.writeFile(configPath, JSON.stringify({ gateway: { mode: "remote" } })); | |
| } | |
| if ("reportFailure" in testCase) { | |
| await fs.mkdir(workspaceHooksDir, { recursive: true }); | |
| } | |
| const socketError = | |
| "explicitGateway" in testCase | |
| ? "AUTOQA_SELECTED_GATEWAY_FAILURE" | |
| : "AUTOQA_NETWORK_FORBIDDEN"; | |
| const socketErrorDetails = | |
| "explicitGateway" in testCase ? "{}" : '{ code: "ECONNREFUSED" }'; | |
| const preload = Buffer.from( | |
| [ | |
| 'import net from "node:net";', | |
| `net.Socket.prototype.connect = function () { throw Object.assign(new Error(${JSON.stringify(socketError)}), ${socketErrorDetails}); };`, | |
| 'globalThis.fetch = async () => { throw new Error("AUTOQA_NETWORK_FORBIDDEN"); };', | |
| ...("reportFailure" in testCase | |
| ? [ | |
| 'import fs from "node:fs";', | |
| "const originalReadDir = fs.readdirSync;", | |
| `fs.readdirSync = (target, ...args) => { if (String(target) === ${JSON.stringify(workspaceHooksDir)}) { throw new Error("injected hook report loading failure"); } return originalReadDir(target, ...args); };`, | |
| ] | |
| : []), | |
| ...("tty" in testCase | |
| ? [ | |
| 'Object.defineProperty(process.stdout, "isTTY", { value: true, configurable: true });', | |
| 'Object.defineProperty(process.stderr, "isTTY", { value: true, configurable: true });', | |
| ] | |
| : []), | |
| ].join("\n"), | |
| ).toString("base64"); | |
| const result = runBuiltCli(tempHome, testCase.args, { | |
| NODE_OPTIONS: `--import=data:text/javascript;base64,${preload}`, | |
| OPENCLAW_CONFIG_PATH: configPath, | |
| OPENCLAW_DISABLE_BUNDLED_PLUGINS: "1", | |
| OPENCLAW_GATEWAY_PORT: "29791", | |
| OPENCLAW_STATE_DIR: stateDir, | |
| ...("explicitGateway" in testCase | |
| ? { | |
| OPENCLAW_GATEWAY_URL: "ws://127.0.0.1:9", | |
| OPENCLAW_GATEWAY_TOKEN: "fixture-token", | |
| } | |
| : {}), | |
| ...("commander" in testCase ? { OPENCLAW_DISABLE_ROUTE_FIRST: "1" } : {}), | |
| ...("tty" in testCase ? { FORCE_COLOR: "1" } : {}), | |
| }); | |
| const message = | |
| "remoteMissing" in testCase | |
| ? [ | |
| testCase.message, | |
| `Config: ${configPath}`, | |
| "Fix: set gateway.remote.url, or set gateway.mode=local.", | |
| ].join("\n") | |
| : (testCase.message ?? | |
| 'Unknown agent id "retired". Run openclaw agents list to see configured agents.'); | |
| expect(result.status, result.stderr).toBe(1); | |
| expect(result.stdout, result.stderr).not.toMatch(/[\u001B\u0007]/u); | |
| if ("human" in testCase) { | |
| if ("missingHook" in testCase) { | |
| expect(result.stdout.trim()).toBe(message); | |
| } else { | |
| expect(result.stdout).toBe(""); | |
| expect(result.stderr).toContain(`Error: ${message}`); | |
| } | |
| } else { | |
| expect(JSON.parse(result.stdout)).toEqual({ | |
| ok: false, | |
| error: { type: "cli_error", message }, | |
| ...("missingHook" in testCase ? { hook: "missing-hook" } : {}), | |
| }); | |
| if (!("missingHook" in testCase)) { | |
| expect(result.stderr).toContain(message); | |
| } | |
| } | |
| expect(result.stderr).not.toContain("AUTOQA_NETWORK_FORBIDDEN"); | |
| if ("tty" in testCase) { | |
| expect(result.stderr).toContain("\u001B[?25h"); | |
| } | |
| if ("remoteMissing" in testCase) { | |
| await expect(fs.readFile(configPath, "utf8")).resolves.toBe( | |
| JSON.stringify({ gateway: { mode: "remote" } }), | |
| ); | |
| } else { | |
| await expect(fs.stat(configPath)).rejects.toMatchObject({ code: "ENOENT" }); | |
| } | |
| }, | |
| { prefix: "openclaw-hooks-json-failure-e2e-" }, | |
| ); | |
| }); | |
| it("preserves successful hooks report JSON and offline discovery", async () => { | |
| await withTempHome( | |
| async (tempHome) => { | |
| const result = runBuiltCli(tempHome, ["hooks", "--json", "list"], { | |
| OPENCLAW_CONFIG_PATH: path.join(tempHome, "missing-openclaw.json"), | |
| OPENCLAW_DISABLE_BUNDLED_PLUGINS: "1", | |
| OPENCLAW_GATEWAY_PORT: "1", | |
| OPENCLAW_STATE_DIR: path.join(tempHome, "isolated-state"), | |
| }); | |
| expect(result.status, result.stderr).toBe(0); | |
| expect(JSON.parse(result.stdout)).toEqual( | |
| expect.objectContaining({ hooks: expect.any(Array) }), | |
| ); | |
| expect(result.stderr).toBe(""); | |
| }, | |
| { prefix: "openclaw-hooks-json-success-e2e-" }, | |
| ); | |
| }); | |
| }); | |