test: clear ui cron broad matchers

This commit is contained in:
Peter Steinberger
2026-05-10 13:54:03 +01:00
parent 3616d5b81a
commit c66afd8481

View File

@@ -70,6 +70,35 @@ function findRequestCall(
return call;
}
function requireRecord(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new Error(`expected ${label} to be a record`);
}
return value as Record<string, unknown>;
}
function expectRecordFields(record: Record<string, unknown>, fields: Record<string, unknown>) {
for (const [key, value] of Object.entries(fields)) {
expect(record[key]).toEqual(value);
}
}
function expectNestedRecordFields(
record: Record<string, unknown>,
key: string,
fields: Record<string, unknown>,
) {
expectRecordFields(requireRecord(record[key], key), fields);
}
function requestPayload(call: readonly [method: string, payload?: unknown]) {
return requireRecord(call[1], `${call[0]} payload`);
}
function requestPatch(call: readonly [method: string, payload?: unknown]) {
return requireRecord(requestPayload(call).patch, `${call[0]} patch`);
}
describe("cron controller", () => {
it("loads model suggestions from the configured model view", async () => {
const request = vi.fn(async () => ({
@@ -150,9 +179,13 @@ describe("cron controller", () => {
await addCronJob(state);
const addCall = findRequestCall(request.mock.calls, "cron.add");
expect(addCall[1]).toMatchObject({
const payload = requestPayload(addCall);
expectRecordFields(payload, {
name: "webhook job",
delivery: { mode: "webhook", to: "https://example.invalid/cron" },
});
expectNestedRecordFields(payload, "delivery", {
mode: "webhook",
to: "https://example.invalid/cron",
});
});
@@ -189,9 +222,13 @@ describe("cron controller", () => {
await addCronJob(state);
const addCall = findRequestCall(request.mock.calls, "cron.add");
expect(addCall[1]).toMatchObject({
const payload = requestPayload(addCall);
expectRecordFields(payload, {
sessionKey: "agent:ops:main",
delivery: { mode: "announce", accountId: "ops-bot" },
});
expectNestedRecordFields(payload, "delivery", {
mode: "announce",
accountId: "ops-bot",
});
});
@@ -228,8 +265,8 @@ describe("cron controller", () => {
await addCronJob(state);
const addCall = findRequestCall(request.mock.calls, "cron.add");
expect(addCall[1]).toMatchObject({
delivery: { mode: "announce" },
expectRecordFields(requireRecord(requestPayload(addCall).delivery, "delivery"), {
mode: "announce",
});
expect(
(addCall[1] as { delivery?: { channel?: string } } | undefined)?.delivery?.channel,
@@ -267,8 +304,9 @@ describe("cron controller", () => {
await addCronJob(state);
const addCall = findRequestCall(request.mock.calls, "cron.add");
expect(addCall[1]).toMatchObject({
payload: { kind: "agentTurn", lightContext: true },
expectNestedRecordFields(requestPayload(addCall), "payload", {
kind: "agentTurn",
lightContext: true,
});
});
@@ -391,7 +429,7 @@ describe("cron controller", () => {
await addCronJob(state);
const addCall = findRequestCall(request.mock.calls, "cron.add");
expect(addCall[1]).toMatchObject({
expectRecordFields(requestPayload(addCall), {
name: "main job",
});
// Delivery is explicitly sent as { mode: "none" } to clear the announce delivery on the backend.
@@ -440,17 +478,17 @@ describe("cron controller", () => {
await addCronJob(state);
const updateCall = findRequestCall(request.mock.calls, "cron.update");
expect(updateCall[1]).toMatchObject({
expectRecordFields(requestPayload(updateCall), {
id: "job-1",
patch: {
name: "edited job",
description: "",
agentId: null,
deleteAfterRun: false,
schedule: { kind: "cron", expr: "0 8 * * *", staggerMs: 0 },
payload: { kind: "systemEvent", text: "updated" },
delivery: { mode: "none" },
},
});
expectRecordFields(requestPatch(updateCall), {
name: "edited job",
description: "",
agentId: null,
deleteAfterRun: false,
schedule: { kind: "cron", expr: "0 8 * * *", staggerMs: 0 },
payload: { kind: "systemEvent", text: "updated" },
delivery: { mode: "none" },
});
expect(state.cronEditingJobId).toBeNull();
});
@@ -504,14 +542,12 @@ describe("cron controller", () => {
await addCronJob(state);
const updateCall = findRequestCall(request.mock.calls, "cron.update");
expect(updateCall[1]).toMatchObject({
expectRecordFields(requestPayload(updateCall), {
id: "job-clear-account-id",
patch: {
delivery: {
mode: "announce",
accountId: "",
},
},
});
expectRecordFields(requireRecord(requestPatch(updateCall).delivery, "delivery"), {
mode: "announce",
accountId: "",
});
});
@@ -587,11 +623,12 @@ describe("cron controller", () => {
await addCronJob(state);
const updateCall = findRequestCall(request.mock.calls, "cron.update");
expect(updateCall[1]).toMatchObject({
expectRecordFields(requestPayload(updateCall), {
id: "job-implicit-delivery",
patch: {
delivery: { mode: "announce", to: "123" },
},
});
expectRecordFields(requireRecord(requestPatch(updateCall).delivery, "delivery"), {
mode: "announce",
to: "123",
});
expect(
(updateCall[1] as { patch?: { delivery?: { channel?: string } } } | undefined)?.patch
@@ -676,19 +713,23 @@ describe("cron controller", () => {
await addCronJob(state);
const updateCall = findRequestCall(request.mock.calls, "cron.update");
expect(updateCall[1]).toMatchObject({
expectRecordFields(requestPayload(updateCall), {
id: "job-2",
patch: {
schedule: { kind: "cron", expr: "0 9 * * *", staggerMs: 30_000 },
payload: {
kind: "agentTurn",
message: "run it",
model: "opus",
thinking: "low",
},
delivery: { mode: "announce", bestEffort: true },
});
const patch = requestPatch(updateCall);
expectRecordFields(patch, {
schedule: { kind: "cron", expr: "0 9 * * *", staggerMs: 30_000 },
payload: {
kind: "agentTurn",
message: "run it",
model: "opus",
thinking: "low",
},
});
expectNestedRecordFields(patch, "delivery", {
mode: "announce",
bestEffort: true,
});
});
it("sends lightContext=false in cron.update when clearing prior light-context setting", async () => {
@@ -735,14 +776,12 @@ describe("cron controller", () => {
await addCronJob(state);
const updateCall = findRequestCall(request.mock.calls, "cron.update");
expect(updateCall[1]).toMatchObject({
expectRecordFields(requestPayload(updateCall), {
id: "job-clear-light",
patch: {
payload: {
kind: "agentTurn",
lightContext: false,
},
},
});
expectRecordFields(requireRecord(requestPatch(updateCall).payload, "payload"), {
kind: "agentTurn",
lightContext: false,
});
});
@@ -778,18 +817,16 @@ describe("cron controller", () => {
await addCronJob(state);
const updateCall = findRequestCall(request.mock.calls, "cron.update");
expect(updateCall[1]).toMatchObject({
expectRecordFields(requestPayload(updateCall), {
id: "job-alert",
patch: {
failureAlert: {
after: 3,
cooldownMs: 120_000,
channel: "telegram",
to: "123456",
mode: "announce",
accountId: undefined,
},
},
});
expectRecordFields(requireRecord(requestPatch(updateCall).failureAlert, "failureAlert"), {
after: 3,
cooldownMs: 120_000,
channel: "telegram",
to: "123456",
mode: "announce",
accountId: undefined,
});
});
@@ -824,15 +861,13 @@ describe("cron controller", () => {
await addCronJob(state);
const updateCall = findRequestCall(request.mock.calls, "cron.update");
expect(updateCall[1]).toMatchObject({
expectRecordFields(requestPayload(updateCall), {
id: "job-alert-mode",
patch: {
failureAlert: {
after: 1,
mode: "webhook",
accountId: "bot-a",
},
},
});
expectRecordFields(requireRecord(requestPatch(updateCall).failureAlert, "failureAlert"), {
after: 1,
mode: "webhook",
accountId: "bot-a",
});
});
@@ -872,15 +907,13 @@ describe("cron controller", () => {
await addCronJob(state);
const updateCall = findRequestCall(request.mock.calls, "cron.update");
expect(updateCall[1]).toMatchObject({
expectRecordFields(requestPayload(updateCall), {
id: "job-alert-implicit-channel",
patch: {
failureAlert: {
after: 2,
to: "123",
mode: "announce",
},
},
});
expectRecordFields(requireRecord(requestPatch(updateCall).failureAlert, "failureAlert"), {
after: 2,
to: "123",
mode: "announce",
});
expect(
(updateCall[1] as { patch?: { failureAlert?: { channel?: string } } } | undefined)?.patch
@@ -963,15 +996,13 @@ describe("cron controller", () => {
await addCronJob(state);
const updateCall = findRequestCall(request.mock.calls, "cron.update");
expect(updateCall[1]).toMatchObject({
expectRecordFields(requestPayload(updateCall), {
id: "job-alert-no-cooldown",
patch: {
failureAlert: {
after: 3,
channel: "telegram",
to: "123456",
},
},
});
expectRecordFields(requireRecord(requestPatch(updateCall).failureAlert, "failureAlert"), {
after: 3,
channel: "telegram",
to: "123456",
});
expect(
(updateCall[1] as { patch?: { failureAlert?: { cooldownMs?: number } } })?.patch
@@ -1007,10 +1038,10 @@ describe("cron controller", () => {
await addCronJob(state);
const updateCall = findRequestCall(request.mock.calls, "cron.update");
expect(updateCall[1]).toMatchObject({
expectRecordFields(requestPayload(updateCall), {
id: "job-no-alert",
patch: { failureAlert: false },
});
expect(requestPatch(updateCall).failureAlert).toBe(false);
});
it("maps cron stagger, model, thinking, and best effort into form", () => {
@@ -1109,7 +1140,7 @@ describe("cron controller", () => {
});
await addCronJob(state);
expect(request).not.toHaveBeenCalled();
expect(state.cronFieldErrors).toMatchObject({
expectRecordFields(state.cronFieldErrors, {
name: "cron.errors.nameRequired",
payloadText: "cron.errors.agentMessageRequired",
});
@@ -1215,7 +1246,7 @@ describe("cron controller", () => {
it("loads paged jobs with query/filter/sort params", async () => {
const request = vi.fn(async (method: string, payload?: unknown) => {
if (method === "cron.list") {
expect(payload).toMatchObject({
expectRecordFields(requireRecord(payload, "cron.list payload"), {
limit: 50,
offset: 0,
query: "daily",
@@ -1346,7 +1377,10 @@ describe("cron controller", () => {
it("runs cron job in due mode when requested", async () => {
const request = vi.fn(async (method: string, payload?: unknown) => {
if (method === "cron.run") {
expect(payload).toMatchObject({ id: "job-due", mode: "due" });
expectRecordFields(requireRecord(payload, "cron.run payload"), {
id: "job-due",
mode: "due",
});
return { ok: true };
}
if (method === "cron.runs") {