test: clear cron dispatch broad matchers

This commit is contained in:
Peter Steinberger
2026-05-10 11:01:38 +01:00
parent 26945167fb
commit a7aa5d98e3

View File

@@ -183,6 +183,34 @@ function makeBaseParams(overrides: {
};
}
function requireRecord(value: unknown, label: string): Record<string, unknown> {
expect(value, label).toBeTypeOf("object");
expect(value, label).not.toBeNull();
return value as Record<string, unknown>;
}
function outboundDeliveryCall(callIndex = 0) {
const call = vi.mocked(deliverOutboundPayloads).mock.calls[callIndex];
if (!call) {
throw new Error(`expected outbound delivery call ${callIndex}`);
}
return requireRecord(call[0], `outbound delivery call ${callIndex}`);
}
function expectFields(actual: Record<string, unknown>, expected: Record<string, unknown>) {
for (const [key, value] of Object.entries(expected)) {
expect(actual[key], key).toEqual(value);
}
}
function expectDeliveryCall(callIndex: number, expected: Record<string, unknown>) {
expectFields(outboundDeliveryCall(callIndex), expected);
}
function expectResultFields(result: unknown, expected: Record<string, unknown>) {
expectFields(requireRecord(result, "cron delivery result"), expected);
}
// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------
@@ -278,16 +306,12 @@ describe("dispatchCronDelivery — double-announce guard", () => {
expect(state.deliveryAttempted).toBe(true);
expect(state.delivered).toBe(true);
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(1);
expect(deliverOutboundPayloads).toHaveBeenCalledWith(
expect.objectContaining({
channel: "telegram",
to: "123456",
payloads: [{ text: "Detailed child result, everything finished successfully." }],
}),
);
expect(deliverOutboundPayloads).toHaveBeenCalledWith(
expect.objectContaining({ skipQueue: true }),
);
expectDeliveryCall(0, {
channel: "telegram",
to: "123456",
payloads: [{ text: "Detailed child result, everything finished successfully." }],
skipQueue: true,
});
});
it("uses the run-scoped session key for isolated cron descendant fallback delivery", async () => {
@@ -319,11 +343,9 @@ describe("dispatchCronDelivery — double-announce guard", () => {
});
expect(state.deliveryAttempted).toBe(true);
expect(state.delivered).toBe(true);
expect(deliverOutboundPayloads).toHaveBeenCalledWith(
expect.objectContaining({
payloads: [{ text: "Run-scoped child result, everything finished successfully." }],
}),
);
expectDeliveryCall(0, {
payloads: [{ text: "Run-scoped child result, everything finished successfully." }],
});
});
it("normal text delivery sends exactly once and sets deliveryAttempted=true", async () => {
@@ -384,29 +406,29 @@ describe("dispatchCronDelivery — double-announce guard", () => {
expect(state.deliveryAttempted).toBe(true);
expect(state.delivered).toBe(true);
expect(maybeApplyTtsToPayloadMock).toHaveBeenCalledWith(
expect.objectContaining({
cfg: params.cfgWithAgentDefaults,
channel: "telegram",
kind: "final",
agentId: "main",
accountId: undefined,
}),
);
expect(deliverOutboundPayloads).toHaveBeenCalledWith(
expect.objectContaining({
channel: "telegram",
to: "123456",
payloads: [
{
text: "Morning briefing complete.",
mediaUrl: "file:///tmp/cron-tts.mp3",
audioAsVoice: true,
spokenText: "Morning briefing complete.",
},
],
}),
);
const ttsCall = maybeApplyTtsToPayloadMock.mock.calls[0];
if (!ttsCall) {
throw new Error("expected TTS payload call");
}
expectFields(requireRecord(ttsCall[0], "TTS payload params"), {
cfg: params.cfgWithAgentDefaults,
channel: "telegram",
kind: "final",
agentId: "main",
accountId: undefined,
});
expectDeliveryCall(0, {
channel: "telegram",
to: "123456",
payloads: [
{
text: "Morning briefing complete.",
mediaUrl: "file:///tmp/cron-tts.mp3",
audioAsVoice: true,
spokenText: "Morning briefing complete.",
},
],
});
});
it("preserves all successful text payloads for direct delivery", async () => {
@@ -423,13 +445,11 @@ describe("dispatchCronDelivery — double-announce guard", () => {
expect(state.deliveryAttempted).toBe(true);
expect(state.delivered).toBe(true);
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(1);
expect(deliverOutboundPayloads).toHaveBeenCalledWith(
expect.objectContaining({
channel: "telegram",
to: "123456",
payloads: [{ text: "Working on it..." }, { text: "Final weather summary" }],
}),
);
expectDeliveryCall(0, {
channel: "telegram",
to: "123456",
payloads: [{ text: "Working on it..." }, { text: "Final weather summary" }],
});
});
it("queues main-session awareness for isolated cron jobs with explicit delivery targets", async () => {
@@ -488,11 +508,9 @@ describe("dispatchCronDelivery — double-announce guard", () => {
expect(state.delivered).toBe(true);
expect(state.deliveryAttempted).toBe(true);
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(1);
expect(deliverOutboundPayloads).toHaveBeenCalledWith(
expect.objectContaining({
payloads: [{ mediaUrl: "https://example.com/image.png", text: undefined }],
}),
);
expectDeliveryCall(0, {
payloads: [{ mediaUrl: "https://example.com/image.png", text: undefined }],
});
expect(enqueueSystemEvent).not.toHaveBeenCalled();
});
@@ -559,13 +577,11 @@ describe("dispatchCronDelivery — double-announce guard", () => {
const state = await dispatchCronDelivery(params);
expect(state.result).toEqual(
expect.objectContaining({
status: "ok",
delivered: false,
deliveryAttempted: true,
}),
);
expectResultFields(state.result, {
status: "ok",
delivered: false,
deliveryAttempted: true,
});
expect(deliverOutboundPayloads).not.toHaveBeenCalled();
expect(
shouldEnqueueCronMainSummary({
@@ -628,12 +644,10 @@ describe("dispatchCronDelivery — double-announce guard", () => {
const state = await dispatchCronDelivery(params);
expect(state.result).toEqual(
expect.objectContaining({
status: "ok",
delivered: false,
}),
);
expectResultFields(state.result, {
status: "ok",
delivered: false,
});
expect(deliverOutboundPayloads).not.toHaveBeenCalled();
expect(callGateway).toHaveBeenCalledWith({
method: "sessions.delete",
@@ -679,12 +693,10 @@ describe("dispatchCronDelivery — double-announce guard", () => {
const state = await dispatchCronDelivery(params);
expect(state.result).toEqual(
expect.objectContaining({
status: "ok",
delivered: false,
}),
);
expectResultFields(state.result, {
status: "ok",
delivered: false,
});
expect(retireSessionMcpRuntime).toHaveBeenCalledWith({
sessionId: "test-session-id",
reason: "cron-delete-after-run-fallback",
@@ -759,18 +771,12 @@ describe("dispatchCronDelivery — double-announce guard", () => {
expect(secondState.delivered).toBe(true);
expect(secondState.deliveryAttempted).toBe(true);
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(2);
expect(deliverOutboundPayloads).toHaveBeenNthCalledWith(
1,
expect.objectContaining({
payloads: [{ text: "8:00 AM cron update." }],
}),
);
expect(deliverOutboundPayloads).toHaveBeenNthCalledWith(
2,
expect.objectContaining({
payloads: [{ text: "9:00 AM cron update." }],
}),
);
expectDeliveryCall(0, {
payloads: [{ text: "8:00 AM cron update." }],
});
expectDeliveryCall(1, {
payloads: [{ text: "9:00 AM cron update." }],
});
});
it("does not cache partial bestEffort delivery replays as delivered", async () => {
@@ -823,13 +829,11 @@ describe("dispatchCronDelivery — double-announce guard", () => {
const state = await dispatchCronDelivery(params);
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(1);
expect(state.result).toEqual(
expect.objectContaining({
status: "error",
error: "Error: chat not found",
deliveryAttempted: true,
}),
);
expectResultFields(state.result, {
status: "error",
error: "Error: chat not found",
deliveryAttempted: true,
});
});
it("surfaces structured direct delivery failures without retry when best-effort is disabled", async () => {
@@ -842,13 +846,11 @@ describe("dispatchCronDelivery — double-announce guard", () => {
const state = await dispatchCronDelivery(params);
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(1);
expect(state.result).toEqual(
expect.objectContaining({
status: "error",
error: "Error: boom",
deliveryAttempted: true,
}),
);
expectResultFields(state.result, {
status: "error",
error: "Error: boom",
deliveryAttempted: true,
});
});
it("ignores structured direct delivery failures when best-effort is enabled", async () => {
@@ -893,14 +895,12 @@ describe("dispatchCronDelivery — double-announce guard", () => {
expect(state.deliveryAttempted).toBe(true);
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(1);
expect(deliverOutboundPayloads).toHaveBeenCalledWith(
expect.objectContaining({
channel: "telegram",
to: "123456",
payloads: [{ text: "Daily digest ready." }],
skipQueue: true,
}),
);
expectDeliveryCall(0, {
channel: "telegram",
to: "123456",
payloads: [{ text: "Daily digest ready." }],
skipQueue: true,
});
});
it("structured/thread delivery also bypasses the write-ahead queue", async () => {
@@ -914,9 +914,7 @@ describe("dispatchCronDelivery — double-announce guard", () => {
await dispatchCronDelivery(params);
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(1);
expect(deliverOutboundPayloads).toHaveBeenCalledWith(
expect.objectContaining({ skipQueue: true }),
);
expectDeliveryCall(0, { skipQueue: true });
});
it("transient retry delivers exactly once with skipQueue on both attempts", async () => {
@@ -938,9 +936,8 @@ describe("dispatchCronDelivery — double-announce guard", () => {
// Two calls total: first failed transiently, second succeeded.
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(2);
const calls = vi.mocked(deliverOutboundPayloads).mock.calls;
expect(calls[0][0]).toEqual(expect.objectContaining({ skipQueue: true }));
expect(calls[1][0]).toEqual(expect.objectContaining({ skipQueue: true }));
expectDeliveryCall(0, { skipQueue: true });
expectDeliveryCall(1, { skipQueue: true });
} finally {
vi.unstubAllEnvs();
}
@@ -958,13 +955,11 @@ describe("dispatchCronDelivery — double-announce guard", () => {
// NO_REPLY must be filtered out before reaching the outbound adapter.
expect(deliverOutboundPayloads).not.toHaveBeenCalled();
expect(state.result).toEqual(
expect.objectContaining({
status: "ok",
delivered: false,
deliveryAttempted: true,
}),
);
expectResultFields(state.result, {
status: "ok",
delivered: false,
deliveryAttempted: true,
});
// deliveryAttempted must be true so the heartbeat timer does not fire
// a fallback enqueueSystemEvent with the NO_REPLY sentinel text.
expect(state.deliveryAttempted).toBe(true);
@@ -993,17 +988,15 @@ describe("dispatchCronDelivery — double-announce guard", () => {
expect(state.delivered).toBe(true);
expect(state.deliveryAttempted).toBe(true);
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(1);
expect(deliverOutboundPayloads).toHaveBeenCalledWith(
expect.objectContaining({
channel: "telegram",
to: "123456",
accountId: undefined,
threadId: undefined,
bestEffort: false,
skipQueue: true,
payloads: [{ text: "hello from cron" }],
}),
);
expectDeliveryCall(0, {
channel: "telegram",
to: "123456",
accountId: undefined,
threadId: undefined,
bestEffort: false,
skipQueue: true,
payloads: [{ text: "hello from cron" }],
});
});
it("keeps unresolved message-tool delivery out of delivered status", async () => {
@@ -1024,13 +1017,11 @@ describe("dispatchCronDelivery — double-announce guard", () => {
expect(deliverOutboundPayloads).not.toHaveBeenCalled();
expect(state.delivered).toBe(false);
expect(state.deliveryAttempted).toBe(false);
expect(state.result).toEqual(
expect.objectContaining({
status: "error",
errorKind: "delivery-target",
deliveryAttempted: false,
}),
);
expectResultFields(state.result, {
status: "error",
errorKind: "delivery-target",
deliveryAttempted: false,
});
expect(state.result?.error).toContain(
"sessionKey is required to resolve delivery.channel=last",
);
@@ -1075,14 +1066,12 @@ describe("dispatchCronDelivery — double-announce guard", () => {
expect(state.result).toBeUndefined();
expect(state.delivered).toBe(true);
expect(deliverOutboundPayloads).toHaveBeenCalledWith(
expect.objectContaining({
channel: "telegram",
to: "123456",
threadId: 42,
payloads: [{ text: "Final weather summary" }],
}),
);
expectDeliveryCall(0, {
channel: "telegram",
to: "123456",
threadId: 42,
payloads: [{ text: "Final weather summary" }],
});
});
it("cleans up the direct cron session after threaded direct delivery when deleteAfterRun is enabled", async () => {
@@ -1135,13 +1124,11 @@ describe("dispatchCronDelivery — double-announce guard", () => {
expect(state.result).toBeUndefined();
expect(state.delivered).toBe(true);
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(1);
expect(deliverOutboundPayloads).toHaveBeenCalledWith(
expect.objectContaining({
channel: "telegram",
to: "123456",
payloads: [{ text: "HEARTBEAT_OK", mediaUrl: "https://example.com/img.png" }],
}),
);
expectDeliveryCall(0, {
channel: "telegram",
to: "123456",
payloads: [{ text: "HEARTBEAT_OK", mediaUrl: "https://example.com/img.png" }],
});
});
it("cleans up the direct cron session after structured direct delivery when deleteAfterRun is enabled", async () => {
@@ -1180,13 +1167,11 @@ describe("dispatchCronDelivery — double-announce guard", () => {
const state = await dispatchCronDelivery(params);
expect(deliverOutboundPayloads).not.toHaveBeenCalled();
expect(state.result).toEqual(
expect.objectContaining({
status: "ok",
delivered: false,
deliveryAttempted: true,
}),
);
expectResultFields(state.result, {
status: "ok",
delivered: false,
deliveryAttempted: true,
});
expect(state.deliveryAttempted).toBe(true);
expect(
@@ -1209,12 +1194,10 @@ describe("dispatchCronDelivery — double-announce guard", () => {
const state = await dispatchCronDelivery(params);
expect(deliverOutboundPayloads).not.toHaveBeenCalled();
expect(state.result).toEqual(
expect.objectContaining({
status: "ok",
delivered: false,
}),
);
expectResultFields(state.result, {
status: "ok",
delivered: false,
});
expect(
shouldEnqueueCronMainSummary({
summaryText: "No_Reply",
@@ -1237,13 +1220,11 @@ describe("dispatchCronDelivery — double-announce guard", () => {
const state = await dispatchCronDelivery(params);
expect(state.result).toEqual(
expect.objectContaining({
status: "ok",
delivered: false,
deliveryAttempted: true,
}),
);
expectResultFields(state.result, {
status: "ok",
delivered: false,
deliveryAttempted: true,
});
expect(callGateway).toHaveBeenCalledWith({
method: "sessions.delete",
params: {
@@ -1267,9 +1248,11 @@ describe("dispatchCronDelivery — double-announce guard", () => {
const state = await dispatchCronDelivery(params);
expect(deliverOutboundPayloads).not.toHaveBeenCalled();
expect(state.result).toEqual(
expect.objectContaining({ status: "ok", delivered: false, deliveryAttempted: true }),
);
expectResultFields(state.result, {
status: "ok",
delivered: false,
deliveryAttempted: true,
});
});
it("suppresses trailing NO_REPLY after summary text in text delivery (#64976)", async () => {
@@ -1282,9 +1265,11 @@ describe("dispatchCronDelivery — double-announce guard", () => {
const state = await dispatchCronDelivery(params);
expect(deliverOutboundPayloads).not.toHaveBeenCalled();
expect(state.result).toEqual(
expect.objectContaining({ status: "ok", delivered: false, deliveryAttempted: true }),
);
expectResultFields(state.result, {
status: "ok",
delivered: false,
deliveryAttempted: true,
});
});
it("suppresses mixed-case trailing No_Reply after summary text (#64976)", async () => {
@@ -1297,9 +1282,11 @@ describe("dispatchCronDelivery — double-announce guard", () => {
const state = await dispatchCronDelivery(params);
expect(deliverOutboundPayloads).not.toHaveBeenCalled();
expect(state.result).toEqual(
expect.objectContaining({ status: "ok", delivered: false, deliveryAttempted: true }),
);
expectResultFields(state.result, {
status: "ok",
delivered: false,
deliveryAttempted: true,
});
});
it("delivers substantive text that mentions NO_REPLY in non-trailing content (text delivery)", async () => {
@@ -1364,10 +1351,8 @@ describe("dispatchCronDelivery — double-announce guard", () => {
expect(state.deliveryAttempted).toBe(true);
expect(state.delivered).toBe(true);
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(1);
expect(deliverOutboundPayloads).toHaveBeenCalledWith(
expect.objectContaining({
payloads: [{ text: "Working on it..." }],
}),
);
expectDeliveryCall(0, {
payloads: [{ text: "Working on it..." }],
});
});
});