fix: handle missing tailscale binary

This commit is contained in:
Peter Steinberger
2026-04-25 04:28:27 +01:00
parent 678ed5d512
commit 05fbdd4b28
2 changed files with 37 additions and 4 deletions

View File

@@ -40,6 +40,19 @@ function createProc(params?: { code?: number; stdout?: string }) {
return proc;
}
function createErrorProc() {
const proc = new EventEmitter() as EventEmitter & {
stdout: EventEmitter;
kill: ReturnType<typeof vi.fn>;
};
proc.stdout = new EventEmitter();
proc.kill = vi.fn();
setTimeout(() => {
proc.emit("error", Object.assign(new Error("spawn tailscale ENOENT"), { code: "ENOENT" }));
}, 0);
return proc;
}
describe("voice-call tailscale helpers", () => {
beforeEach(() => {
vi.clearAllMocks();
@@ -83,6 +96,12 @@ describe("voice-call tailscale helpers", () => {
await expect(getTailscaleSelfInfo()).resolves.toBeNull();
});
it("treats missing tailscale binary as unavailable instead of leaking spawn errors", async () => {
spawnMock.mockReturnValueOnce(createErrorProc());
await expect(getTailscaleSelfInfo()).resolves.toBeNull();
});
it("sets up and cleans up exposure routes with the selected mode", async () => {
spawnMock
.mockReturnValueOnce(

View File

@@ -16,18 +16,32 @@ function runTailscaleCommand(
});
let stdout = "";
let settled = false;
let timer: ReturnType<typeof setTimeout>;
const finish = (result: { code: number; stdout: string }) => {
if (settled) {
return;
}
settled = true;
clearTimeout(timer);
resolve(result);
};
proc.stdout.on("data", (data) => {
stdout += data;
});
const timer = setTimeout(() => {
timer = setTimeout(() => {
proc.kill("SIGKILL");
resolve({ code: -1, stdout: "" });
finish({ code: -1, stdout: "" });
}, timeoutMs);
proc.on("error", () => {
finish({ code: -1, stdout: "" });
});
proc.on("close", (code) => {
clearTimeout(timer);
resolve({ code: code ?? -1, stdout });
finish({ code: code ?? -1, stdout });
});
});
}