test(01-11): specify rolling weekly overdue identity

- pin the prior-day Mounjaro occurrence across local midnight and DST
- cover resolution state, band end, schedule siblings, and era isolation
This commit is contained in:
Marc-André Bombeck committed 2026-07-29 14:19:03 +02:00
1 parent 18d0facdfe
commit d5f473d672
2 files changed
+179

No files matched your search

@@ -558,3 +558,144 @@ describe("as-needed (zero schedules) — never due", () => {
expect(display).toBeNull();
});
});
describe("Mounjaro rolling weekly — canonical overdue band after day change", () => {
const lastTaken = d("2026-07-21T06:00:00.000Z"); // Jul 21 08:00 Berlin
const missedOccurrence = d("2026-07-28T06:00:00.000Z"); // Jul 28 08:00
const nextOccurrence = d("2026-08-04T06:00:00.000Z"); // Aug 4 08:00
const medication = makeMedication({
startsOn: d("2026-01-01T00:00:00.000Z"),
});
const schedule = makeRollingSchedule({
id: "mounjaro-weekly",
timesOfDay: ["08:00"],
});
const identifiedMark = (
at: Date,
identity: Record<string, unknown>,
): ResolvedSlotMark =>
({
...mark(at),
...identity,
}) as ResolvedSlotMark;
it("keeps yesterday's unresolved occurrence overdue on the following local day", () => {
const display = computeDisplayDue({
medication,
schedules: [schedule],
now: d("2026-07-29T10:00:00.000Z"),
userTz: BERLIN,
lastIntakeAt: lastTaken,
resolvedSlots: [],
});
expect(display).toMatchObject({
at: missedOccurrence,
overdue: true,
});
});
it("keeps the occurrence through the exact canonical band end, then closes it", () => {
const atBandEnd = computeDisplayDue({
medication,
schedules: [schedule],
now: d("2026-08-02T06:00:00.000Z"),
userTz: BERLIN,
lastIntakeAt: lastTaken,
resolvedSlots: [],
});
expect(atBandEnd).toMatchObject({
at: missedOccurrence,
overdue: true,
});
const afterBandEnd = computeDisplayDue({
medication,
schedules: [schedule],
now: d("2026-08-02T06:00:00.001Z"),
userTz: BERLIN,
lastIntakeAt: lastTaken,
resolvedSlots: [],
});
expect(afterBandEnd).toBeNull();
});
it.each(["taken", "skipped", "autoMissed"] as const)(
"an exact %s row suppresses only this occurrence and advances",
(status) => {
const display = computeDisplayDue({
medication,
schedules: [schedule],
now: d("2026-07-29T10:00:00.000Z"),
userTz: BERLIN,
lastIntakeAt:
status === "taken"
? d("2026-07-28T06:10:00.000Z")
: lastTaken,
resolvedSlots: [
identifiedMark(missedOccurrence, {
scheduleId: "mounjaro-weekly",
status,
}),
],
});
expect(display).toMatchObject({
at: nextOccurrence,
overdue: false,
});
},
);
it("does not let a sibling schedule's resolved occurrence suppress this schedule", () => {
const sibling = makeRollingSchedule({
id: "mounjaro-sibling",
timesOfDay: ["10:00"],
windowStart: "10:00",
windowEnd: "10:00",
});
const display = computeDisplayDue({
medication,
schedules: [schedule, sibling],
now: d("2026-07-29T10:00:00.000Z"),
userTz: BERLIN,
lastIntakeAt: lastTaken,
resolvedSlots: [
identifiedMark(missedOccurrence, {
scheduleId: "mounjaro-weekly",
status: "skipped",
}),
],
});
expect(display).toMatchObject({
at: d("2026-07-28T08:00:00.000Z"),
overdue: true,
scheduleId: "mounjaro-sibling",
});
});
it("does not let an action from the archived era suppress the live-era occurrence", () => {
const liveEraStart = d("2026-07-27T12:00:00.000Z");
const display = computeDisplayDue({
medication,
schedules: [schedule],
now: d("2026-07-29T10:00:00.000Z"),
userTz: BERLIN,
lastIntakeAt: lastTaken,
eraStart: liveEraStart,
resolvedSlots: [
identifiedMark(missedOccurrence, {
scheduleId: "mounjaro-weekly",
actionAt: d("2026-07-27T11:59:59.000Z"),
}),
],
});
expect(display).toMatchObject({
at: missedOccurrence,
overdue: true,
scheduleId: "mounjaro-weekly",
});
});
});
@@ -473,6 +473,44 @@ describe("occurrencesBetween — rolling", () => {
});
});
describe("rolling occurrence identity across a local-day change", () => {
it.each([
{
label: "ordinary Berlin week",
lastIntake: "2026-07-21T06:00:00.000Z",
now: "2026-07-29T10:00:00.000Z",
expected: "2026-07-28T06:00:00.000Z",
},
{
label: "Berlin spring DST week",
lastIntake: "2026-03-22T07:00:00.000Z",
now: "2026-03-30T10:00:00.000Z",
expected: "2026-03-29T06:00:00.000Z",
},
])(
"retains the unresolved prior-day slot for an $label",
({ lastIntake, now, expected }) => {
const schedule = makeSchedule({
id: "mounjaro-weekly",
rollingIntervalDays: 7,
timesOfDay: ["08:00"],
});
const ctx = makeCtx({
lastIntakeAt: d(lastIntake),
medication: { startsOn: d("2026-01-01T00:00:00.000Z") },
});
const occurrence = nextOccurrenceAfter(schedule, d(now), ctx);
expect(occurrence).toMatchObject({
scheduleId: "mounjaro-weekly",
at: d(expected),
timeOfDay: "08:00",
});
},
);
});
// ────────────────────────────────────────────────────────────────────
// One-shot
// ────────────────────────────────────────────────────────────────────