test(onboarding): remove formatter bridges (#122120)

This commit is contained in:
Peter Steinberger
2026-08-11 09:40:27 -07:00
committed by GitHub
parent 1dcac5b15f
commit 18f126326a
6 changed files with 39 additions and 85 deletions
@@ -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<PropertyKey, unknown>)[
Symbol.for("openclaw.onboardSkillsTestApi")
] as OnboardSkillsTestApi;
}
export const testing: OnboardSkillsTestApi = {
formatSkillHint(skill) {
return getTestApi().formatSkillHint(skill);
},
summarizeInstallFailure(message) {
return getTestApi().summarizeInstallFailure(message);
},
};
+30 -10
View File
@@ -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([
-7
View File
@@ -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<PropertyKey, unknown>)[Symbol.for("openclaw.onboardSkillsTestApi")] =
testing;
}
const SKIP_REASON_LABELS = {
brew: "Homebrew",
go: `Go toolchain (${MIN_AUTO_GO_VERSION}+)`,
@@ -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<PropertyKey, unknown>)[
Symbol.for("openclaw.onboardingPluginInstallTestApi")
] as OnboardingPluginInstallTestApi;
}
export const testing: OnboardingPluginInstallTestApi = {
formatInstallErrorDetail(message) {
return getTestApi().formatInstallErrorDetail(message);
},
summarizeInstallError(message) {
return getTestApi().summarizeInstallError(message);
},
};
+9 -18
View File
@@ -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<T>(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 () => {
@@ -580,14 +580,6 @@ async function notePluginInstallFailure(
);
}
const testing = { formatInstallErrorDetail, summarizeInstallError };
if (process.env.VITEST || process.env.NODE_ENV === "test") {
(globalThis as Record<PropertyKey, unknown>)[
Symbol.for("openclaw.onboardingPluginInstallTestApi")
] = testing;
}
function isTimeoutError(error: unknown): boolean {
return error instanceof Error && error.message === "timeout";
}