Self-hosted multi-platform broadcast newsroom for activist collectives: publishing pipeline with group approval and DST-proof scheduling, TweetDeck-style column wall with hostile-content-safe rendering, live control room with Auto Director, bridged chat governance with polls and quorum, distributed sandboxed transcode workers, encrypted content-addressed archive, monthly analytics. MIT licensed. See README.md and docs/.
27 lines
1.4 KiB
TypeScript
27 lines
1.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { nextOccurrences } from "./occurrences_extra.js";
|
|
|
|
const ISO = (o: { fireAtUtc: number }) => new Date(o.fireAtUtc).toISOString().replace(".000Z", "Z");
|
|
|
|
describe("count boundary semantics", () => {
|
|
it("never returns more than count", () => {
|
|
for (const count of [1, 2, 5, 17]) {
|
|
const out = nextOccurrences({ cron: "*/15 * * * *", timezone: "America/New_York" }, "2024-03-09T00:00:00Z", count);
|
|
expect(out.length).toBe(count);
|
|
}
|
|
});
|
|
it("stops at the collapse edge with the latest collapsed label", () => {
|
|
// Exclusive from 05:00Z (== 00:00 local): the first slot is 00:15. The
|
|
// eighth occurrence is the collapse edge — nominal slots 02:00..03:00 all
|
|
// materialize onto 07:00Z — and it carries the LATEST label (03:00), with
|
|
// nothing beyond the edge emitted.
|
|
const out = nextOccurrences({ cron: "*/15 * * * *", timezone: "America/New_York" }, "2024-03-10T05:00:00Z", 8);
|
|
expect(out.length).toBe(8);
|
|
expect(out.map(ISO)[7]).toBe("2024-03-10T07:00:00Z");
|
|
expect(out[7]!.nominalLocal).toBe("2024-03-10T03:00");
|
|
// The same result whether the boundary is reached with 8 or 80 requested,
|
|
// because generation stops at the first slot after the boundary instant.
|
|
const wide = nextOccurrences({ cron: "*/15 * * * *", timezone: "America/New_York" }, "2024-03-10T05:00:00Z", 80);
|
|
expect(wide[7]!.nominalLocal).toBe("2024-03-10T03:00");
|
|
});
|
|
});
|