File size: 3,618 Bytes
f778c12 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | import { describe, expect, it } from "vitest";
import {
applyExistingStreamSchedulePatch,
resolveCronCreateScheduleFromArgs,
resolveCronEditScheduleRequest,
} from "./schedule-options.js";
describe("resolveCronCreateScheduleFromArgs --stream-command", () => {
it("builds an argv stream schedule with batching and match options", () => {
expect(
resolveCronCreateScheduleFromArgs({
streamCommand: '["node","events.mjs"]',
streamCwd: "/repo",
streamMode: "match",
streamMatch: "^ready:",
streamBatchMs: "100",
streamMaxBatchBytes: "2048",
}),
).toEqual({
kind: "stream",
command: ["node", "events.mjs"],
cwd: "/repo",
mode: "match",
match: "^ready:",
batchMs: 100,
maxBatchBytes: 2048,
});
});
it("requires a valid argv array and match expression when requested", () => {
expect(() => resolveCronCreateScheduleFromArgs({ streamCommand: "node events.mjs" })).toThrow(
"JSON array",
);
expect(() =>
resolveCronCreateScheduleFromArgs({
streamCommand: '["node","events.mjs"]',
streamMode: "match",
}),
).toThrow("--stream-match is required");
});
it("rejects stream-only options without a stream command", () => {
expect(() => resolveCronCreateScheduleFromArgs({ every: "1m", streamBatchMs: "250" })).toThrow(
"require --stream-command",
);
});
it("patches an existing stream back to line mode without restating argv", () => {
const request = resolveCronEditScheduleRequest({ streamMode: "line" });
expect(request.kind).toBe("patch-existing-stream");
if (request.kind !== "patch-existing-stream") {
throw new Error("expected stream patch");
}
expect(
applyExistingStreamSchedulePatch(
{
kind: "stream",
command: ["node", "events.mjs"],
mode: "match",
match: "^ready:",
batchMs: 100,
},
request,
),
).toEqual({
kind: "stream",
command: ["node", "events.mjs"],
mode: "line",
match: undefined,
batchMs: 100,
cwd: undefined,
maxBatchBytes: undefined,
});
});
it("defers command replacement metadata checks until existing match settings are merged", () => {
const commandAndMatch = resolveCronEditScheduleRequest({
streamCommand: '["node","replacement.mjs"]',
streamMatch: "^updated:",
});
expect(commandAndMatch.kind).toBe("direct");
const matchPatch = resolveCronEditScheduleRequest({ streamMatch: "^updated:" });
expect(matchPatch.kind).toBe("patch-existing-stream");
if (matchPatch.kind !== "patch-existing-stream") {
throw new Error("expected stream patch");
}
expect(
applyExistingStreamSchedulePatch(
{
kind: "stream",
command: ["node", "events.mjs"],
mode: "match",
match: "^ready:",
},
matchPatch,
),
).toMatchObject({ mode: "match", match: "^updated:" });
expect(() =>
resolveCronEditScheduleRequest({
streamCommand: '["node","replacement.mjs"]',
streamMode: "match",
}),
).not.toThrow();
});
it("rejects time-schedule modifiers mixed into stream metadata edits", () => {
expect(() => resolveCronEditScheduleRequest({ streamBatchMs: "100", tz: "UTC" })).toThrow(
"not valid with stream schedule edits",
);
expect(() => resolveCronEditScheduleRequest({ streamMode: "line", exact: true })).toThrow(
"not valid with stream schedule edits",
);
});
});
|