Tests: move cron heartbeat skip to seam

This commit is contained in:
Peter Steinberger
2026-04-07 09:50:14 +08:00
parent 7a289940cd
commit add2b8e9f0
3 changed files with 40 additions and 18 deletions

View File

@@ -232,22 +232,6 @@ describe("runCronIsolatedAgentTurn", () => {
setupIsolatedAgentTurnMocks({ fast: true });
});
it("skips announce for heartbeat-only output", async () => {
await withTelegramAnnounceFixture(async ({ home, storePath, deps }) => {
mockAgentPayloads([{ text: "HEARTBEAT_OK" }]);
const res = await runTelegramAnnounceTurn({
home,
storePath,
deps,
delivery: { mode: "announce", channel: "telegram", to: "123" },
});
expect(res.status).toBe("ok");
expect(runSubagentAnnounceFlow).not.toHaveBeenCalled();
expect(deps.sendMessageTelegram).not.toHaveBeenCalled();
});
});
it("does not mark NO_REPLY output as delivered when no direct send occurs", async () => {
await withTelegramAnnounceFixture(async ({ home, storePath, deps }) => {
mockAgentPayloads([{ text: "NO_REPLY" }]);

View File

@@ -2,6 +2,7 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest";
import {
clearFastTestEnv,
dispatchCronDeliveryMock,
isHeartbeatOnlyResponseMock,
loadRunCronIsolatedAgentTurn,
mockRunCronFallbackPassthrough,
resetRunCronIsolatedAgentTurnHarness,
@@ -94,6 +95,37 @@ describe("runCronIsolatedAgentTurn message tool policy", () => {
expect(runEmbeddedPiAgentMock.mock.calls[0]?.[0]?.disableMessageTool).toBe(false);
});
it("skips cron delivery when output is heartbeat-only", async () => {
mockRunCronFallbackPassthrough();
resolveCronDeliveryPlanMock.mockReturnValue({
requested: true,
mode: "announce",
channel: "telegram",
to: "123",
});
isHeartbeatOnlyResponseMock.mockReturnValue(true);
await runCronIsolatedAgentTurn({
...makeParams(),
job: {
id: "message-tool-policy",
name: "Message Tool Policy",
schedule: { kind: "every", everyMs: 60_000 },
sessionTarget: "isolated",
payload: { kind: "agentTurn", message: "send a message" },
delivery: { mode: "announce", channel: "telegram", to: "123" },
} as never,
});
expect(dispatchCronDeliveryMock).toHaveBeenCalledTimes(1);
expect(dispatchCronDeliveryMock.mock.calls[0]?.[0]).toEqual(
expect.objectContaining({
deliveryRequested: true,
skipHeartbeatDelivery: true,
}),
);
});
it("skips cron delivery when a shared caller already sent to the same target", async () => {
mockRunCronFallbackPassthrough();
const params = makeParams();

View File

@@ -64,6 +64,8 @@ export const resolveCronPayloadOutcomeMock = createMock();
export const resolveCronDeliveryPlanMock = createMock();
export const resolveDeliveryTargetMock = createMock();
export const dispatchCronDeliveryMock = createMock();
export const isHeartbeatOnlyResponseMock = createMock();
export const resolveHeartbeatAckMaxCharsMock = createMock();
export const resolveSessionAuthProfileOverrideMock = createMock();
export const resolveFastModeStateMock = createMock();
@@ -176,13 +178,13 @@ vi.mock("./delivery-dispatch.js", async () => {
});
vi.mock("./helpers.js", () => ({
isHeartbeatOnlyResponse: vi.fn().mockReturnValue(false),
isHeartbeatOnlyResponse: isHeartbeatOnlyResponseMock,
pickLastDeliverablePayload: vi.fn().mockReturnValue(undefined),
pickLastNonEmptyTextFromPayloads: pickLastNonEmptyTextFromPayloadsMock,
pickSummaryFromOutput: vi.fn().mockReturnValue("summary"),
pickSummaryFromPayloads: vi.fn().mockReturnValue("summary"),
resolveCronPayloadOutcome: resolveCronPayloadOutcomeMock,
resolveHeartbeatAckMaxChars: vi.fn().mockReturnValue(100),
resolveHeartbeatAckMaxChars: resolveHeartbeatAckMaxCharsMock,
}));
vi.mock("./session.js", () => ({
@@ -360,6 +362,10 @@ function resetRunOutcomeMocks(): void {
deliveryPayloads,
}),
);
isHeartbeatOnlyResponseMock.mockReset();
isHeartbeatOnlyResponseMock.mockReturnValue(false);
resolveHeartbeatAckMaxCharsMock.mockReset();
resolveHeartbeatAckMaxCharsMock.mockReturnValue(100);
resolveSessionAuthProfileOverrideMock.mockReset();
resolveSessionAuthProfileOverrideMock.mockResolvedValue(undefined);
}