From 18f126326a397b4ecfe0aa4b319bfb60740f52ed Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 11 Aug 2026 09:40:27 -0700 Subject: [PATCH] test(onboarding): remove formatter bridges (#122120) --- src/commands/onboard-skills.test-support.ts | 21 ---------- src/commands/onboard-skills.test.ts | 40 ++++++++++++++----- src/commands/onboard-skills.ts | 7 ---- .../onboarding-plugin-install.test-support.ts | 21 ---------- .../onboarding-plugin-install.test.ts | 27 +++++-------- src/commands/onboarding-plugin-install.ts | 8 ---- 6 files changed, 39 insertions(+), 85 deletions(-) delete mode 100644 src/commands/onboard-skills.test-support.ts delete mode 100644 src/commands/onboarding-plugin-install.test-support.ts diff --git a/src/commands/onboard-skills.test-support.ts b/src/commands/onboard-skills.test-support.ts deleted file mode 100644 index 9e5aa6431bab..000000000000 --- a/src/commands/onboard-skills.test-support.ts +++ /dev/null @@ -1,21 +0,0 @@ -import "./onboard-skills.js"; - -type OnboardSkillsTestApi = { - formatSkillHint(skill: { description?: string; install: Array<{ label: string }> }): string; - summarizeInstallFailure(message: string): string | undefined; -}; - -function getTestApi(): OnboardSkillsTestApi { - return (globalThis as Record)[ - Symbol.for("openclaw.onboardSkillsTestApi") - ] as OnboardSkillsTestApi; -} - -export const testing: OnboardSkillsTestApi = { - formatSkillHint(skill) { - return getTestApi().formatSkillHint(skill); - }, - summarizeInstallFailure(message) { - return getTestApi().summarizeInstallFailure(message); - }, -}; diff --git a/src/commands/onboard-skills.test.ts b/src/commands/onboard-skills.test.ts index d87847002b16..7cc5aceeea2e 100644 --- a/src/commands/onboard-skills.test.ts +++ b/src/commands/onboard-skills.test.ts @@ -33,16 +33,6 @@ vi.mock("./onboard-helpers.js", () => ({ })); import { setupSkills } from "./onboard-skills.js"; -import { testing } from "./onboard-skills.test-support.js"; - -describe("skill onboarding text bounds", () => { - it("keeps install failures and hints UTF-16 well-formed", () => { - expect(testing.summarizeInstallFailure(`${"x".repeat(138)}🚀tail`)).toBe(`${"x".repeat(138)}…`); - expect(testing.formatSkillHint({ description: `${"x".repeat(88)}🚀tail`, install: [] })).toBe( - `${"x".repeat(88)}…`, - ); - }); -}); function createBundledSkill(params: { name: string; @@ -205,6 +195,36 @@ describe("setupSkills", () => { mocks.resolveInstallerKindReadiness.mockResolvedValue({ ready: true }); }); + it("bounds skill hints and install failures through the onboarding flow", async () => { + const hintPrefix = "x".repeat(88); + const failurePrefix = "y".repeat(138); + mockMissingBrewStatus([ + createBundledSkill({ + name: "node-helper", + description: `${hintPrefix}🚀tail`, + bins: ["node-helper"], + installLabel: "", + installKind: "node", + }), + ]); + mocks.installSkill.mockResolvedValueOnce({ + ok: false, + message: `Install failed: ${failurePrefix}🚀tail`, + stdout: "", + stderr: "", + code: 1, + }); + const stop = vi.fn(); + const { prompter } = createPrompter({ multiselect: ["node-helper"] }); + vi.mocked(prompter.progress).mockReturnValue({ update: vi.fn(), stop }); + + await setupSkills({} as OpenClawConfig, "/tmp/ws", runtime, prompter); + + const options = vi.mocked(prompter.multiselect).mock.calls[0]?.[0].options ?? []; + expect(options.find((option) => option.value === "node-helper")?.hint).toBe(`${hintPrefix}…`); + expect(stop).toHaveBeenCalledWith(expect.stringContaining(`${failurePrefix}…`)); + }); + it("hides brew-only installs in Linux containers when brew is missing", async () => { await withPlatform("linux", async () => { mockMissingBrewStatus([ diff --git a/src/commands/onboard-skills.ts b/src/commands/onboard-skills.ts index 56e504aa9219..eb2d8b49a5f9 100644 --- a/src/commands/onboard-skills.ts +++ b/src/commands/onboard-skills.ts @@ -65,13 +65,6 @@ function formatSkillHint(skill: { return combined.length > maxLen ? `${truncateUtf16Safe(combined, maxLen - 1)}…` : combined; } -const testing = { formatSkillHint, summarizeInstallFailure }; - -if (process.env.VITEST || process.env.NODE_ENV === "test") { - (globalThis as Record)[Symbol.for("openclaw.onboardSkillsTestApi")] = - testing; -} - const SKIP_REASON_LABELS = { brew: "Homebrew", go: `Go toolchain (${MIN_AUTO_GO_VERSION}+)`, diff --git a/src/commands/onboarding-plugin-install.test-support.ts b/src/commands/onboarding-plugin-install.test-support.ts deleted file mode 100644 index b249412e6ad3..000000000000 --- a/src/commands/onboarding-plugin-install.test-support.ts +++ /dev/null @@ -1,21 +0,0 @@ -import "./onboarding-plugin-install.js"; - -type OnboardingPluginInstallTestApi = { - formatInstallErrorDetail(message: string): string; - summarizeInstallError(message: string): string; -}; - -function getTestApi(): OnboardingPluginInstallTestApi { - return (globalThis as Record)[ - Symbol.for("openclaw.onboardingPluginInstallTestApi") - ] as OnboardingPluginInstallTestApi; -} - -export const testing: OnboardingPluginInstallTestApi = { - formatInstallErrorDetail(message) { - return getTestApi().formatInstallErrorDetail(message); - }, - summarizeInstallError(message) { - return getTestApi().summarizeInstallError(message); - }, -}; diff --git a/src/commands/onboarding-plugin-install.test.ts b/src/commands/onboarding-plugin-install.test.ts index 18b4442bc0e3..d1ca21b192e2 100644 --- a/src/commands/onboarding-plugin-install.test.ts +++ b/src/commands/onboarding-plugin-install.test.ts @@ -125,21 +125,6 @@ vi.mock("../utils/with-timeout.js", () => ({ })); import { ensureOnboardingPluginInstalled } from "./onboarding-plugin-install.js"; -import { testing } from "./onboarding-plugin-install.test-support.js"; - -describe("plugin install error summaries", () => { - it("keeps bounded terminal text UTF-16 well-formed", () => { - expect(testing.summarizeInstallError(`${"x".repeat(178)}🚀tail`)).toBe(`${"x".repeat(178)}…`); - }); - - it("keeps copyable line breaks while bounding detailed installer output", () => { - expect(testing.formatInstallErrorDetail("first\nsecond\tvalue")).toBe("first\nsecond\\tvalue"); - const detailed = testing.formatInstallErrorDetail(`start\n${"x".repeat(20_000)}`); - expect(detailed).toContain("start\n"); - expect(detailed).toHaveLength(12_000); - expect(detailed.endsWith("… (installer output truncated)")).toBe(true); - }); -}); function requireCapturedPrompt(captured: T | undefined): T { if (!captured) { @@ -1215,10 +1200,11 @@ describe("ensureOnboardingPluginInstalled", () => { it("returns bounded multiline ClawHub failure detail to non-interactive callers", async () => { const runtimeError = vi.fn(); + const summaryPrefix = "x".repeat(178); installPluginFromClawHub.mockResolvedValueOnce({ ok: false, code: "archive_integrity_mismatch", - error: `first line\n${"x".repeat(20_000)}`, + error: `Install failed: ${summaryPrefix}🚀tail\tvalue\nsecond\tline\n${"y".repeat(20_000)}`, }); const result = await ensureOnboardingPluginInstalled({ @@ -1242,10 +1228,15 @@ describe("ensureOnboardingPluginInstalled", () => { promptInstall: false, }); - expect(result.error).toMatch(/^first line\n/); + expect(result.error).toMatch(/^Install failed: x{178}🚀tail/); + expect(result.error).toContain("\\tvalue"); + expect(result.error).toContain("\nsecond\\tline\n"); + expect(result.error).not.toContain(""); expect(result.error?.endsWith("\n… (installer output truncated)")).toBe(true); expect(result.error?.length).toBe(12_000); - expect(readFirstMockCall(runtimeError, "runtime.error")[0]).toHaveLength(203); + const runtimeMessage = String(readFirstMockCall(runtimeError, "runtime.error")[0]); + expect(runtimeMessage).toContain(`${summaryPrefix}…`); + expect(runtimeMessage).not.toContain(""); }); it("does not offer local installs when the workspace only has a spoofed .git marker", async () => { diff --git a/src/commands/onboarding-plugin-install.ts b/src/commands/onboarding-plugin-install.ts index b2109fc90f39..157aeec8baef 100644 --- a/src/commands/onboarding-plugin-install.ts +++ b/src/commands/onboarding-plugin-install.ts @@ -580,14 +580,6 @@ async function notePluginInstallFailure( ); } -const testing = { formatInstallErrorDetail, summarizeInstallError }; - -if (process.env.VITEST || process.env.NODE_ENV === "test") { - (globalThis as Record)[ - Symbol.for("openclaw.onboardingPluginInstallTestApi") - ] = testing; -} - function isTimeoutError(error: unknown): boolean { return error instanceof Error && error.message === "timeout"; }