mirror of
https://github.com/moltbot/moltbot.git
synced 2026-05-20 05:07:34 +00:00
test: tighten daemon lifecycle assertions
This commit is contained in:
@@ -55,6 +55,29 @@ const loadConfig = vi.hoisted(() => vi.fn(() => ({})));
|
||||
const recoverInstalledLaunchAgent = vi.hoisted(() => vi.fn());
|
||||
const repairLoadedGatewayServiceForStart = vi.hoisted(() => vi.fn());
|
||||
|
||||
function requireMockCallArg(
|
||||
mockFn: { mock: { calls: unknown[][] } },
|
||||
label: string,
|
||||
index = 0,
|
||||
): Record<string, unknown> {
|
||||
const arg = mockFn.mock.calls[index]?.[0] as Record<string, unknown> | undefined;
|
||||
if (!arg) {
|
||||
throw new Error(`expected ${label} call #${index + 1}`);
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
async function expectRestartError(
|
||||
promise: Promise<unknown>,
|
||||
): Promise<Error & { hints?: string[] }> {
|
||||
try {
|
||||
await promise;
|
||||
} catch (error) {
|
||||
return error as Error & { hints?: string[] };
|
||||
}
|
||||
throw new Error("expected restart to fail");
|
||||
}
|
||||
|
||||
vi.mock("../../config/config.js", () => ({
|
||||
getRuntimeConfig: () => loadConfig(),
|
||||
loadConfig: () => loadConfig(),
|
||||
@@ -329,18 +352,22 @@ describe("runDaemonRestart health checks", () => {
|
||||
|
||||
await runDaemonStart({ json: true });
|
||||
|
||||
expect(repairLoadedGatewayServiceForStart).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
service,
|
||||
json: true,
|
||||
state: expect.objectContaining({
|
||||
command: expect.objectContaining({
|
||||
environment: { OPENCLAW_SERVICE_VERSION: "2026.4.24" },
|
||||
}),
|
||||
}),
|
||||
issues: [expect.objectContaining({ code: "version-mismatch" })],
|
||||
}),
|
||||
);
|
||||
const repairParams = requireMockCallArg(
|
||||
repairLoadedGatewayServiceForStart,
|
||||
"repairLoadedGatewayServiceForStart",
|
||||
) as {
|
||||
service?: unknown;
|
||||
json?: unknown;
|
||||
state?: { command?: { environment?: unknown } };
|
||||
issues?: Array<{ code?: unknown }>;
|
||||
};
|
||||
expect(repairParams.service).toBe(service);
|
||||
expect(repairParams.json).toBe(true);
|
||||
expect(repairParams.state?.command?.environment).toEqual({
|
||||
OPENCLAW_SERVICE_VERSION: "2026.4.24",
|
||||
});
|
||||
expect(repairParams.issues).toHaveLength(1);
|
||||
expect(repairParams.issues?.[0]?.code).toBe("version-mismatch");
|
||||
});
|
||||
|
||||
it("kills stale gateway pids and retries restart", async () => {
|
||||
@@ -398,13 +425,12 @@ describe("runDaemonRestart health checks", () => {
|
||||
};
|
||||
waitForGatewayHealthyRestart.mockResolvedValue(unhealthy);
|
||||
|
||||
await expect(runDaemonRestart({ json: true })).rejects.toMatchObject({
|
||||
message: "Gateway restart timed out after 60s waiting for health checks.",
|
||||
hints: [
|
||||
formatCliCommand("openclaw gateway status --deep"),
|
||||
formatCliCommand("openclaw doctor"),
|
||||
],
|
||||
});
|
||||
const error = await expectRestartError(runDaemonRestart({ json: true }));
|
||||
expect(error.message).toBe("Gateway restart timed out after 60s waiting for health checks.");
|
||||
expect(error.hints).toEqual([
|
||||
formatCliCommand("openclaw gateway status --deep"),
|
||||
formatCliCommand("openclaw doctor"),
|
||||
]);
|
||||
expect(terminateStaleGatewayPids).not.toHaveBeenCalled();
|
||||
expect(renderRestartDiagnostics).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
@@ -420,14 +446,19 @@ describe("runDaemonRestart health checks", () => {
|
||||
|
||||
await runDaemonRestart({ json: true });
|
||||
|
||||
expect(waitForGatewayHealthyRestart).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
attempts: 360,
|
||||
delayMs: 500,
|
||||
includeUnknownListenersAsStale: true,
|
||||
port: 18789,
|
||||
}),
|
||||
);
|
||||
const waitParams = requireMockCallArg(
|
||||
waitForGatewayHealthyRestart,
|
||||
"waitForGatewayHealthyRestart",
|
||||
) as {
|
||||
attempts?: unknown;
|
||||
delayMs?: unknown;
|
||||
includeUnknownListenersAsStale?: unknown;
|
||||
port?: unknown;
|
||||
};
|
||||
expect(waitParams.attempts).toBe(360);
|
||||
expect(waitParams.delayMs).toBe(500);
|
||||
expect(waitParams.includeUnknownListenersAsStale).toBe(true);
|
||||
expect(waitParams.port).toBe(18789);
|
||||
});
|
||||
|
||||
it("fails restart with a stopped-free message when the waiter exits early", async () => {
|
||||
@@ -442,14 +473,14 @@ describe("runDaemonRestart health checks", () => {
|
||||
};
|
||||
waitForGatewayHealthyRestart.mockResolvedValue(unhealthy);
|
||||
|
||||
await expect(runDaemonRestart({ json: true })).rejects.toMatchObject({
|
||||
message:
|
||||
"Gateway restart failed after 13s: service stayed stopped and health checks never came up.",
|
||||
hints: [
|
||||
formatCliCommand("openclaw gateway status --deep"),
|
||||
formatCliCommand("openclaw doctor"),
|
||||
],
|
||||
});
|
||||
const error = await expectRestartError(runDaemonRestart({ json: true }));
|
||||
expect(error.message).toBe(
|
||||
"Gateway restart failed after 13s: service stayed stopped and health checks never came up.",
|
||||
);
|
||||
expect(error.hints).toEqual([
|
||||
formatCliCommand("openclaw gateway status --deep"),
|
||||
formatCliCommand("openclaw doctor"),
|
||||
]);
|
||||
expect(terminateStaleGatewayPids).not.toHaveBeenCalled();
|
||||
expect(renderRestartDiagnostics).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
@@ -472,12 +503,12 @@ describe("runDaemonRestart health checks", () => {
|
||||
|
||||
await runDaemonStop({ json: true, disable: true });
|
||||
|
||||
expect(runServiceStop).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
opts: { json: true, disable: true },
|
||||
stopWhenNotLoaded: true,
|
||||
}),
|
||||
);
|
||||
const stopParams = requireMockCallArg(runServiceStop, "runServiceStop") as {
|
||||
opts?: unknown;
|
||||
stopWhenNotLoaded?: unknown;
|
||||
};
|
||||
expect(stopParams.opts).toEqual({ json: true, disable: true });
|
||||
expect(stopParams.stopWhenNotLoaded).toBe(true);
|
||||
});
|
||||
|
||||
it("skips gateway port resolution on stop when the service manager handles the stop", async () => {
|
||||
|
||||
Reference in New Issue
Block a user