From 5acd64996bb7077035e0d122fd4456d5f9eca903 Mon Sep 17 00:00:00 2001 From: Lucas Winther Date: Thu, 27 Aug 2026 02:15:01 +0200 Subject: [PATCH] Move the movesOccurrences tests to the task that writes it Pre-flight scan finding. The function is implemented in Task 2 and its four tests sat in Task 4's block, so Task 2 would have shipped untested code and Task 4 would have tested a function it did not write. Task 2's stated count of 23 already assumed the corrected placement. Co-Authored-By: Claude Opus 5 (1M context) --- .../2026-08-27-recurring-custom-events.md | 73 ++++++++++--------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/docs/superpowers/plans/2026-08-27-recurring-custom-events.md b/docs/superpowers/plans/2026-08-27-recurring-custom-events.md index 0b8412a..6250fcb 100644 --- a/docs/superpowers/plans/2026-08-27-recurring-custom-events.md +++ b/docs/superpowers/plans/2026-08-27-recurring-custom-events.md @@ -362,6 +362,42 @@ describe("occurrence ids", () => { expect(CustomEventId.safeParse("myevent:k3f9qa2m01#2026-09-01").success).toBe(false); }); }); + +describe("movesOccurrences", () => { + const rule = (startsAt: string, interval: number) => ({ + startsAt, + repeat: { unit: "weeks" as const, interval, until: null }, + }); + + test("a changed anchor or interval re-keys every occurrence", () => { + const a = rule("2026-09-01T07:00:00.000Z", 2); + expect(movesOccurrences(a, rule("2026-09-02T07:00:00.000Z", 2))).toBe(true); + expect(movesOccurrences(a, rule("2026-09-01T07:00:00.000Z", 3))).toBe(true); + }); + + test("changing only `until` does not", () => { + // It truncates the series; it does not move what is already in it, so no + // mark is stranded and the reader should not be warned that one is. + const a = rule("2026-09-01T07:00:00.000Z", 2); + const b = { + startsAt: "2026-09-01T07:00:00.000Z", + repeat: { unit: "weeks" as const, interval: 2, until: "2027-01-01T00:00:00.000Z" }, + }; + expect(movesOccurrences(a, b)).toBe(false); + }); + + test("adding or dropping a rule entirely counts as a move", () => { + const plain = { startsAt: "2026-09-01T07:00:00.000Z", repeat: null }; + expect(movesOccurrences(plain, rule("2026-09-01T07:00:00.000Z", 2))).toBe(true); + expect(movesOccurrences(rule("2026-09-01T07:00:00.000Z", 2), plain)).toBe(true); + }); + + test("an untouched schedule moves nothing", () => { + const a = rule("2026-09-01T07:00:00.000Z", 2); + expect(movesOccurrences(a, rule("2026-09-01T07:00:00.000Z", 2))).toBe(false); + }); +}); + ``` - [ ] **Step 2: Run test to verify it fails** @@ -689,41 +725,6 @@ MSG Append to `test/recurrence.test.ts`, adding `nextOccurrences, occurrencesOf, type RepeatingEvent` to the `recurrence.ts` import. ```ts -describe("movesOccurrences", () => { - const rule = (startsAt: string, interval: number) => ({ - startsAt, - repeat: { unit: "weeks" as const, interval, until: null }, - }); - - test("a changed anchor or interval re-keys every occurrence", () => { - const a = rule("2026-09-01T07:00:00.000Z", 2); - expect(movesOccurrences(a, rule("2026-09-02T07:00:00.000Z", 2))).toBe(true); - expect(movesOccurrences(a, rule("2026-09-01T07:00:00.000Z", 3))).toBe(true); - }); - - test("changing only `until` does not", () => { - // It truncates the series; it does not move what is already in it, so no - // mark is stranded and the reader should not be warned that one is. - const a = rule("2026-09-01T07:00:00.000Z", 2); - const b = { - startsAt: "2026-09-01T07:00:00.000Z", - repeat: { unit: "weeks" as const, interval: 2, until: "2027-01-01T00:00:00.000Z" }, - }; - expect(movesOccurrences(a, b)).toBe(false); - }); - - test("adding or dropping a rule entirely counts as a move", () => { - const plain = { startsAt: "2026-09-01T07:00:00.000Z", repeat: null }; - expect(movesOccurrences(plain, rule("2026-09-01T07:00:00.000Z", 2))).toBe(true); - expect(movesOccurrences(rule("2026-09-01T07:00:00.000Z", 2), plain)).toBe(true); - }); - - test("an untouched schedule moves nothing", () => { - const a = rule("2026-09-01T07:00:00.000Z", 2); - expect(movesOccurrences(a, rule("2026-09-01T07:00:00.000Z", 2))).toBe(false); - }); -}); - describe("occurrencesOf", () => { function rule(over: Partial = {}): RepeatingEvent { return { @@ -1034,7 +1035,7 @@ export function nextOccurrences( - [ ] **Step 4: Run tests and typecheck** Run: `bun test test/recurrence.test.ts` -Expected: PASS, 36 tests. +Expected: PASS, 35 tests. Run: `bun run typecheck` Expected: exit 0.