mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
test: point guards at the split provider modules
The page-walk exception for the Google Health list walk follows forEachDataPointPage into data-points.ts, and the workout provenance guard reads the raw Polar and Strava sport labels where the mappers now live. The write-step helper's tests assert the result it returns, including a failed fold and a caller that re-warms the status cards itself.
This commit is contained in:
1 parent
8b3c095df5
commit
c2a63307ed
3 files changed
+29
-7
No files matched your search
@@ -35,7 +35,7 @@ const LIB = join(process.cwd(), "src", "lib");
|
||||
* three outcomes cannot carry.
|
||||
*/
|
||||
const EXCEPTIONS: Readonly<Record<string, { matches: number; why: string }>> = {
|
||||
"google-health/client.ts": {
|
||||
"google-health/data-points.ts": {
|
||||
matches: 1,
|
||||
why: "progress-bounded streaming list walk with slice budget and resume (forEachDataPointPage)",
|
||||
},
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in new issue
Block a user