mirror of https://github.com/openclaw/openclaw.git
test(skills): add status-to-install apt fallback coverage
This commit is contained in:
parent
c8e110e2e3
commit
3c467baa2d
|
|
@ -3,6 +3,7 @@ import os from "node:os";
|
|||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { installSkill } from "./skills-install.js";
|
||||
import { buildWorkspaceSkillStatus } from "./skills-status.js";
|
||||
|
||||
const runCommandWithTimeoutMock = vi.fn();
|
||||
const scanDirectoryWithSummaryMock = vi.fn();
|
||||
|
|
@ -24,29 +25,31 @@ vi.mock("../security/skill-scanner.js", async (importOriginal) => {
|
|||
};
|
||||
});
|
||||
|
||||
vi.mock("../shared/config-eval.js", () => ({
|
||||
hasBinary: (...args: unknown[]) => hasBinaryMock(...args),
|
||||
}));
|
||||
vi.mock("../shared/config-eval.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../shared/config-eval.js")>();
|
||||
return {
|
||||
...actual,
|
||||
hasBinary: (...args: unknown[]) => hasBinaryMock(...args),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../infra/brew.js", () => ({
|
||||
resolveBrewExecutable: () => undefined,
|
||||
}));
|
||||
|
||||
async function writeSkillWithInstaller(
|
||||
async function writeSkillWithInstallers(
|
||||
workspaceDir: string,
|
||||
name: string,
|
||||
kind: string,
|
||||
extra: Record<string, string>,
|
||||
installSpecs: Array<Record<string, string>>,
|
||||
): Promise<string> {
|
||||
const skillDir = path.join(workspaceDir, "skills", name);
|
||||
await fs.mkdir(skillDir, { recursive: true });
|
||||
const installSpec = { id: "deps", kind, ...extra };
|
||||
await fs.writeFile(
|
||||
path.join(skillDir, "SKILL.md"),
|
||||
`---
|
||||
name: ${name}
|
||||
description: test skill
|
||||
metadata: ${JSON.stringify({ openclaw: { install: [installSpec] } })}
|
||||
metadata: ${JSON.stringify({ openclaw: { install: installSpecs } })}
|
||||
---
|
||||
|
||||
# ${name}
|
||||
|
|
@ -57,11 +60,22 @@ metadata: ${JSON.stringify({ openclaw: { install: [installSpec] } })}
|
|||
return skillDir;
|
||||
}
|
||||
|
||||
async function writeSkillWithInstaller(
|
||||
workspaceDir: string,
|
||||
name: string,
|
||||
kind: string,
|
||||
extra: Record<string, string>,
|
||||
): Promise<string> {
|
||||
return writeSkillWithInstallers(workspaceDir, name, [{ id: "deps", kind, ...extra }]);
|
||||
}
|
||||
|
||||
describe("skills-install fallback edge cases", () => {
|
||||
let workspaceDir: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks();
|
||||
runCommandWithTimeoutMock.mockReset();
|
||||
scanDirectoryWithSummaryMock.mockReset();
|
||||
hasBinaryMock.mockReset();
|
||||
workspaceDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-fallback-test-"));
|
||||
scanDirectoryWithSummaryMock.mockResolvedValue({ critical: 0, warn: 0, findings: [] });
|
||||
});
|
||||
|
|
@ -119,6 +133,43 @@ describe("skills-install fallback edge cases", () => {
|
|||
expect(aptCalls).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("status-selected go installer fails gracefully when apt fallback needs sudo", async () => {
|
||||
await writeSkillWithInstallers(workspaceDir, "go-tool", [
|
||||
{ id: "brew", kind: "brew", formula: "go" },
|
||||
{ id: "go", kind: "go", module: "example.com/tool@latest" },
|
||||
]);
|
||||
|
||||
// no go/brew, but apt and sudo are present
|
||||
hasBinaryMock.mockImplementation((bin: string) => {
|
||||
if (bin === "go" || bin === "brew") {
|
||||
return false;
|
||||
}
|
||||
if (bin === "apt-get" || bin === "sudo") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
runCommandWithTimeoutMock.mockResolvedValueOnce({
|
||||
code: 1,
|
||||
stdout: "",
|
||||
stderr: "sudo: a password is required",
|
||||
});
|
||||
|
||||
const status = buildWorkspaceSkillStatus(workspaceDir);
|
||||
const skill = status.skills.find((entry) => entry.name === "go-tool");
|
||||
expect(skill?.install[0]?.id).toBe("go");
|
||||
|
||||
const result = await installSkill({
|
||||
workspaceDir,
|
||||
skillName: "go-tool",
|
||||
installId: skill?.install[0]?.id ?? "",
|
||||
});
|
||||
|
||||
expect(result.ok).toBe(false);
|
||||
expect(result.message).toContain("sudo is not usable");
|
||||
});
|
||||
|
||||
it("handles sudo probe spawn failures without throwing", async () => {
|
||||
await writeSkillWithInstaller(workspaceDir, "go-tool", "go", {
|
||||
module: "example.com/tool@latest",
|
||||
|
|
|
|||
Loading…
Reference in New Issue