diff --git a/src/__tests__/page-walk-guard.test.ts b/src/__tests__/page-walk-guard.test.ts index a08129755..29133cff6 100644 --- a/src/__tests__/page-walk-guard.test.ts +++ b/src/__tests__/page-walk-guard.test.ts @@ -35,7 +35,7 @@ const LIB = join(process.cwd(), "src", "lib"); * three outcomes cannot carry. */ const EXCEPTIONS: Readonly> = { - "google-health/client.ts": { + "google-health/data-points.ts": { matches: 1, why: "progress-bounded streaming list walk with slice budget and resume (forEachDataPointPage)", }, diff --git a/src/__tests__/workout-sport-provenance-guard.test.ts b/src/__tests__/workout-sport-provenance-guard.test.ts index 280c7fe55..f7aecd2e6 100644 --- a/src/__tests__/workout-sport-provenance-guard.test.ts +++ b/src/__tests__/workout-sport-provenance-guard.test.ts @@ -83,7 +83,7 @@ const PROVIDER_INGESTS: ProviderIngest[] = [ provider: "Polar", mapper: "mapPolarSportType", mapperFile: "lib/polar/sport-map.ts", - captureFile: "lib/polar/client.ts", + captureFile: "lib/polar/map.ts", captureField: "detailed_sport_info", writeFile: "lib/polar/sync-workouts.ts", metadataKey: "polarSport", @@ -92,7 +92,7 @@ const PROVIDER_INGESTS: ProviderIngest[] = [ provider: "Strava", mapper: "mapStravaSportType", mapperFile: "lib/strava/sport-map.ts", - captureFile: "lib/strava/client.ts", + captureFile: "lib/strava/map.ts", captureField: "rawSportType", writeFile: "lib/strava/sync.ts", metadataKey: "stravaType", diff --git a/src/lib/rollups/__tests__/after-measurement-mutation.test.ts b/src/lib/rollups/__tests__/after-measurement-mutation.test.ts index cf80d3cb6..17fd3ca91 100644 --- a/src/lib/rollups/__tests__/after-measurement-mutation.test.ts +++ b/src/lib/rollups/__tests__/after-measurement-mutation.test.ts @@ -93,7 +93,9 @@ describe("afterMeasurementMutation", () => { }); it("is a no-op for an empty row set", async () => { - await afterMeasurementMutation("user-1", [], { source: "manual" }); + await expect( + afterMeasurementMutation("user-1", [], { source: "manual" }), + ).resolves.toEqual({ rollupFailed: false }); expect(mocks.recompute).not.toHaveBeenCalled(); expect(mocks.invalidate).not.toHaveBeenCalled(); }); @@ -101,8 +103,9 @@ describe("afterMeasurementMutation", () => { it("still invalidates status insights when the rollup recompute fails", async () => { mocks.recompute.mockRejectedValue(new Error("populator down")); const warn = vi.spyOn(console, "warn").mockImplementation(() => {}); + let result: { rollupFailed: boolean } | undefined; try { - await afterMeasurementMutation( + result = await afterMeasurementMutation( "user-1", [ { @@ -115,10 +118,29 @@ describe("afterMeasurementMutation", () => { } finally { warn.mockRestore(); } - // The rollup failure never bubbles AND never gates the second leg. + // The rollup failure never bubbles AND never gates the second leg; the + // caller learns of it from the result. + expect(result).toEqual({ rollupFailed: true }); expect(mocks.invalidate).toHaveBeenCalledTimes(1); }); + it("leaves the status cards alone when the caller invalidates them itself", async () => { + await expect( + afterMeasurementMutation( + "user-1", + [ + { + type: "WEIGHT" as MeasurementType, + measuredAt: day("2026-05-10T08:00:00Z"), + }, + ], + { source: "sync", invalidateStatus: false }, + ), + ).resolves.toEqual({ rollupFailed: false }); + expect(mocks.recompute).toHaveBeenCalledTimes(1); + expect(mocks.invalidate).not.toHaveBeenCalled(); + }); + it("never rejects when the status-insight invalidation fails", async () => { mocks.invalidate.mockRejectedValue(new Error("cache down")); const warn = vi.spyOn(console, "warn").mockImplementation(() => {}); @@ -134,7 +156,7 @@ describe("afterMeasurementMutation", () => { ], { source: "manual" }, ), - ).resolves.toBeUndefined(); + ).resolves.toEqual({ rollupFailed: false }); // Let the fire-and-forget rejection settle inside the helper's catch. await new Promise((resolve) => setImmediate(resolve)); } finally {