






















@@ -1,10 +1,11 @@
1-import { describe, expect, it, vi } from "vitest";
1+import { afterEach, describe, expect, it, vi } from "vitest";
22import {
33applyConfigSnapshot,
44applyConfig,
55ensureAgentConfigEntry,
66findAgentConfigEntryIndex,
77loadConfig,
8+openConfigFile,
89resetConfigPendingChanges,
910runUpdate,
1011saveConfig,
@@ -64,6 +65,10 @@ function requireRequestCall(request: ReturnType<typeof vi.fn>, index = 0): unkno
6465return call;
6566}
666768+afterEach(() => {
69+vi.unstubAllGlobals();
70+});
71+6772describe("applyConfigSnapshot", () => {
6873it("does not clobber form edits while dirty", () => {
6974const state = createState();
@@ -271,6 +276,57 @@ describe("loadConfig", () => {
271276});
272277});
273278279+describe("openConfigFile", () => {
280+it("surfaces failed open responses and copies the returned config path", async () => {
281+const request = vi.fn().mockResolvedValue({
282+ok: false,
283+path: "/tmp/openclaw.json",
284+error: "Cannot open file in headless environment.",
285+});
286+const writeText = vi.fn().mockResolvedValue(undefined);
287+vi.stubGlobal("navigator", { clipboard: { writeText } });
288+289+const state = createState();
290+state.connected = true;
291+state.client = { request } as unknown as ConfigState["client"];
292+state.lastError = "stale error";
293+294+await openConfigFile(state);
295+296+expect(request).toHaveBeenCalledWith("config.openFile", {});
297+expect(writeText).toHaveBeenCalledWith("/tmp/openclaw.json");
298+expect(state.lastError).toBe(
299+"Cannot open file in headless environment.\n\nFile path copied to clipboard: /tmp/openclaw.json",
300+);
301+});
302+303+it("includes the config path in the visible error when clipboard fallback fails", async () => {
304+const request = vi.fn().mockResolvedValue({
305+ok: false,
306+error: "Failed to open config file",
307+});
308+const writeText = vi.fn().mockRejectedValue(new Error("clipboard denied"));
309+vi.stubGlobal("navigator", { clipboard: { writeText } });
310+311+const state = createState();
312+state.connected = true;
313+state.client = { request } as unknown as ConfigState["client"];
314+state.configSnapshot = {
315+config: {},
316+path: "/tmp/from-snapshot.json",
317+valid: true,
318+issues: [],
319+};
320+321+await openConfigFile(state);
322+323+expect(writeText).toHaveBeenCalledWith("/tmp/from-snapshot.json");
324+expect(state.lastError).toBe(
325+"Failed to open config file\n\nFile path: /tmp/from-snapshot.json",
326+);
327+});
328+});
329+274330describe("updateConfigFormValue", () => {
275331it("seeds from snapshot when form is null", () => {
276332const state = createState();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。