mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-21 16:41:56 +00:00
test: consolidate sudo fallback edge-case scenarios
This commit is contained in:
@@ -70,15 +70,16 @@ async function writeSkillWithInstaller(
|
||||
return writeSkillWithInstallers(workspaceDir, name, [{ id: "deps", kind, ...extra }]);
|
||||
}
|
||||
|
||||
function mockBinaryAvailability(availableBinaries: string[]) {
|
||||
const available = new Set(availableBinaries);
|
||||
function mockAvailableBinaries(binaries: string[]) {
|
||||
const available = new Set(binaries);
|
||||
hasBinaryMock.mockImplementation((bin: string) => available.has(bin));
|
||||
}
|
||||
|
||||
function getAptGetCalls() {
|
||||
return runCommandWithTimeoutMock.mock.calls.filter(
|
||||
function assertNoAptGetFallbackCalls() {
|
||||
const aptCalls = runCommandWithTimeoutMock.mock.calls.filter(
|
||||
(call) => Array.isArray(call[0]) && (call[0] as string[]).includes("apt-get"),
|
||||
);
|
||||
expect(aptCalls).toHaveLength(0);
|
||||
}
|
||||
|
||||
describe("skills-install fallback edge cases", () => {
|
||||
@@ -109,41 +110,55 @@ describe("skills-install fallback edge cases", () => {
|
||||
await fs.rm(workspaceDir, { recursive: true, force: true }).catch(() => undefined);
|
||||
});
|
||||
|
||||
it("apt-get available but sudo missing/unusable returns helpful error for go install", async () => {
|
||||
// go not available, brew not available, apt-get + sudo are available, sudo check fails
|
||||
mockBinaryAvailability(["apt-get", "sudo"]);
|
||||
it("handles sudo probe failures for go install without apt fallback", async () => {
|
||||
for (const testCase of [
|
||||
{
|
||||
label: "sudo returns password required",
|
||||
setup: () =>
|
||||
runCommandWithTimeoutMock.mockResolvedValueOnce({
|
||||
code: 1,
|
||||
stdout: "",
|
||||
stderr: "sudo: a password is required",
|
||||
}),
|
||||
assert: (result: { message: string; stderr: string }) => {
|
||||
expect(result.message).toContain("sudo");
|
||||
expect(result.message).toContain("https://go.dev/doc/install");
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "sudo probe throws executable-not-found",
|
||||
setup: () =>
|
||||
runCommandWithTimeoutMock.mockRejectedValueOnce(
|
||||
new Error('Executable not found in $PATH: "sudo"'),
|
||||
),
|
||||
assert: (result: { message: string; stderr: string }) => {
|
||||
expect(result.message).toContain("sudo is not usable");
|
||||
expect(result.stderr).toContain("Executable not found");
|
||||
},
|
||||
},
|
||||
]) {
|
||||
runCommandWithTimeoutMock.mockClear();
|
||||
mockAvailableBinaries(["apt-get", "sudo"]);
|
||||
testCase.setup();
|
||||
|
||||
// sudo -n true fails (no passwordless sudo)
|
||||
runCommandWithTimeoutMock.mockResolvedValueOnce({
|
||||
code: 1,
|
||||
stdout: "",
|
||||
stderr: "sudo: a password is required",
|
||||
});
|
||||
const result = await installSkill({
|
||||
workspaceDir,
|
||||
skillName: "go-tool-single",
|
||||
installId: "deps",
|
||||
});
|
||||
|
||||
const result = await installSkill({
|
||||
workspaceDir,
|
||||
skillName: "go-tool-single",
|
||||
installId: "deps",
|
||||
});
|
||||
|
||||
expect(result.ok).toBe(false);
|
||||
expect(result.message).toContain("sudo");
|
||||
expect(result.message).toContain("https://go.dev/doc/install");
|
||||
|
||||
// Verify sudo -n true was called
|
||||
expect(runCommandWithTimeoutMock).toHaveBeenCalledWith(
|
||||
["sudo", "-n", "true"],
|
||||
expect.objectContaining({ timeoutMs: 5_000 }),
|
||||
);
|
||||
|
||||
// Verify apt-get install was NOT called
|
||||
const aptCalls = getAptGetCalls();
|
||||
expect(aptCalls).toHaveLength(0);
|
||||
expect(result.ok, testCase.label).toBe(false);
|
||||
testCase.assert(result);
|
||||
expect(runCommandWithTimeoutMock, testCase.label).toHaveBeenCalledWith(
|
||||
["sudo", "-n", "true"],
|
||||
expect.objectContaining({ timeoutMs: 5_000 }),
|
||||
);
|
||||
assertNoAptGetFallbackCalls();
|
||||
}
|
||||
});
|
||||
|
||||
it("status-selected go installer fails gracefully when apt fallback needs sudo", async () => {
|
||||
// no go/brew, but apt and sudo are present
|
||||
mockBinaryAvailability(["apt-get", "sudo"]);
|
||||
mockAvailableBinaries(["apt-get", "sudo"]);
|
||||
|
||||
runCommandWithTimeoutMock.mockResolvedValueOnce({
|
||||
code: 1,
|
||||
@@ -165,32 +180,8 @@ describe("skills-install fallback edge cases", () => {
|
||||
expect(result.message).toContain("sudo is not usable");
|
||||
});
|
||||
|
||||
it("handles sudo probe spawn failures without throwing", async () => {
|
||||
// go not available, brew not available, apt-get + sudo appear available
|
||||
mockBinaryAvailability(["apt-get", "sudo"]);
|
||||
|
||||
runCommandWithTimeoutMock.mockRejectedValueOnce(
|
||||
new Error('Executable not found in $PATH: "sudo"'),
|
||||
);
|
||||
|
||||
const result = await installSkill({
|
||||
workspaceDir,
|
||||
skillName: "go-tool-single",
|
||||
installId: "deps",
|
||||
});
|
||||
|
||||
expect(result.ok).toBe(false);
|
||||
expect(result.message).toContain("sudo is not usable");
|
||||
expect(result.stderr).toContain("Executable not found");
|
||||
|
||||
// Verify apt-get install was NOT called
|
||||
const aptCalls = getAptGetCalls();
|
||||
expect(aptCalls).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("uv not installed and no brew returns helpful error without curl auto-install", async () => {
|
||||
// uv not available, brew not available, curl IS available
|
||||
mockBinaryAvailability(["curl"]);
|
||||
mockAvailableBinaries(["curl"]);
|
||||
|
||||
const result = await installSkill({
|
||||
workspaceDir,
|
||||
|
||||
Reference in New Issue
Block a user