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) <[email protected]>
This commit is contained in:
Lucas Winther
2026-08-28 05:04:39 +02:00
co-authored by Claude Opus 5
parent 81ed1013c0
commit 5acd64996b
@@ -362,6 +362,42 @@ describe("occurrence ids", () => {
expect(CustomEventId.safeParse("myevent:k3f9qa2m01#2026-09-01").success).toBe(false); 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** - [ ] **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. Append to `test/recurrence.test.ts`, adding `nextOccurrences, occurrencesOf, type RepeatingEvent` to the `recurrence.ts` import.
```ts ```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", () => { describe("occurrencesOf", () => {
function rule(over: Partial<RepeatingEvent> = {}): RepeatingEvent { function rule(over: Partial<RepeatingEvent> = {}): RepeatingEvent {
return { return {
@@ -1034,7 +1035,7 @@ export function nextOccurrences(
- [ ] **Step 4: Run tests and typecheck** - [ ] **Step 4: Run tests and typecheck**
Run: `bun test test/recurrence.test.ts` Run: `bun test test/recurrence.test.ts`
Expected: PASS, 36 tests. Expected: PASS, 35 tests.
Run: `bun run typecheck` Run: `bun run typecheck`
Expected: exit 0. Expected: exit 0.