test(insights): pin the clock in the two-service workout collapse case

The case built its sessions from the real clock: one copy a day before
now, the other 30 s later. The cross-source workout picker groups sessions
into fixed five-minute slots of the epoch, so whenever the suite ran in
the last 30 s of a slot the two copies landed in different slots and
counted twice. It had nothing to do with day boundaries or time zones: the
outcome followed the minute of the wall clock alone.

The case now pins Date to an instant well inside a slot. With the pin at
12:04:45Z or 23:59:45Z the case failed under UTC, Europe/Berlin and
Pacific/Kiritimati alike; at the committed 12:02:00Z it passes under all
three.

The production code reads no clock here (the block takes `now` from its
caller). What the flake exposed is the fixed slot grid itself: two copies
of one session that straddle a slot edge are not collapsed. That is a
change to the picker every workout surface shares, so it is left for a
change of its own.
This commit is contained in:
Marc-André Bombeck committed 2026-10-22 05:58:45 +02:00
1 parent 9bdd0b1a60
commit 1915f91526
1 file changed
+16 -4
+16 -4
View File
@@ -559,6 +559,14 @@ describe("extractFeatures — v1.22 workouts block", () => {
});
it("counts a session synced by two services once", async () => {
// The cross-source picker groups sessions into fixed five-minute slots
// of the epoch (`pick-canonical-workout-rows.ts`). With a start taken
// from the real clock, the 30 s gap between the two copies crossed a
// slot edge whenever the test ran in the last 30 s of a slot, and the
// pair counted twice. The clock is pinned to an instant well inside a
// slot, so the case tests the collapse rather than the time of day.
vi.useFakeTimers({ toFake: ["Date"] });
vi.setSystemTime(Date.parse("2026-10-22T12:02:00Z"));
const startedAt = new Date(Date.now() - 1 * DAY_MS);
prismaMock.workout.findMany.mockResolvedValue([
{
@@ -576,10 +584,14 @@ describe("extractFeatures — v1.22 workouts block", () => {
totalDistanceM: 5010,
},
]);
const f = await extractFeatures("user-1", false);
expect(f.workouts?.last7.count).toBe(1);
expect(f.workouts?.last7.totalDurationMin).toBe(30);
expect(f.workouts?.last7.totalDistanceKm).toBe(5);
try {
const f = await extractFeatures("user-1", false);
expect(f.workouts?.last7.count).toBe(1);
expect(f.workouts?.last7.totalDurationMin).toBe(30);
expect(f.workouts?.last7.totalDistanceKm).toBe(5);
} finally {
vi.useRealTimers();
}
});
});