Files
openclaw/src/cron/service.list-page-sort-guards.test.ts
Sid 29a55948d6 fix(cron): guard list sorting against malformed legacy jobs (#28896)
* fix(cron): guard list sorting against malformed legacy jobs

Prevent list operations from crashing when old or corrupted cron entries are missing name/id fields by hardening sort comparators.

Closes #28862

* cron: format list sort guard test imports

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 07:01:36 -06:00

54 lines
1.8 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { createMockCronStateForJobs } from "./service.test-harness.js";
import { listPage } from "./service/ops.js";
import type { CronJob } from "./types.js";
function createBaseJob(overrides?: Partial<CronJob>): CronJob {
return {
id: "job-1",
name: "job",
enabled: true,
schedule: { kind: "cron", expr: "*/5 * * * *", tz: "UTC" },
sessionTarget: "main",
wakeMode: "now",
payload: { kind: "systemEvent", text: "tick" },
state: { nextRunAtMs: Date.parse("2026-02-27T15:30:00.000Z") },
createdAtMs: Date.parse("2026-02-27T15:00:00.000Z"),
updatedAtMs: Date.parse("2026-02-27T15:05:00.000Z"),
...overrides,
};
}
describe("cron listPage sort guards", () => {
it("does not throw when sorting by name with malformed name fields", async () => {
const jobs = [
createBaseJob({ id: "job-a", name: undefined as unknown as string }),
createBaseJob({ id: "job-b", name: "beta" }),
];
const state = createMockCronStateForJobs({ jobs });
const page = await listPage(state, { sortBy: "name", sortDir: "asc" });
expect(page.jobs).toHaveLength(2);
});
it("does not throw when tie-break sorting encounters missing ids", async () => {
const nextRunAtMs = Date.parse("2026-02-27T15:30:00.000Z");
const jobs = [
createBaseJob({
id: undefined as unknown as string,
name: "alpha",
state: { nextRunAtMs },
}),
createBaseJob({
id: undefined as unknown as string,
name: "alpha",
state: { nextRunAtMs },
}),
];
const state = createMockCronStateForJobs({ jobs });
const page = await listPage(state, { sortBy: "nextRunAtMs", sortDir: "asc" });
expect(page.jobs).toHaveLength(2);
});
});