diff --git a/src/lib/__tests__/dashboard-layout.test.ts b/src/lib/__tests__/dashboard-layout.test.ts index 0c7a64a69..9ccf98a25 100644 --- a/src/lib/__tests__/dashboard-layout.test.ts +++ b/src/lib/__tests__/dashboard-layout.test.ts @@ -154,6 +154,21 @@ describe("DEFAULT_DASHBOARD_LAYOUT contract", () => { expect(widget?.tileVisible).toBe(true); }); + it("ships the vo2Max strip tile default-on, chart row default-off (v1.18.9)", () => { + // VO2max is ingested from Withings / Apple Health / Fitbit / Oura but + // the tile used to be opt-in, so accounts that already synced a sample + // saw nothing on the dashboard. The strip tile is now on by default + // (it still self-gates on having a VO2_MAX sample in page.tsx), while + // the chart row stays off because VO2max charts live on the + // /insights/cardio-fitness sub-page. + const widget = DEFAULT_DASHBOARD_LAYOUT.widgets.find( + (w) => w.id === "vo2Max", + ); + expect(widget).toBeDefined(); + expect(widget?.tileVisible).toBe(true); + expect(widget?.visible).toBe(false); + }); + it("does NOT advertise a retired insightsPreview widget (v1.4.27 B1)", () => { // v1.4.27 B1 retired the standalone dashboard preview because it // duplicated the much-richer `/insights` advisor surface. The diff --git a/src/lib/dashboard-layout.ts b/src/lib/dashboard-layout.ts index 9657d5390..a6ff10679 100644 --- a/src/lib/dashboard-layout.ts +++ b/src/lib/dashboard-layout.ts @@ -29,11 +29,12 @@ export const DASHBOARD_WIDGET_IDS = [ "bpInTarget", "oxygenSaturation", "achievements", - // v1.4.25 W8d — VO2 max trend tile (opt-in, secondary-metric pattern). - // Self-gates on having any VO2_MAX sample; default-invisible so - // existing dashboards stay unchanged until the user enables it in - // Settings → Dashboard. Only the tile-strip surface; chart row - // lands alongside the iOS-app body-composition sub-page in v1.5. + // v1.4.25 W8d — VO2 max trend tile (secondary-metric pattern). The + // strip tile is on by default and self-gates on having any VO2_MAX + // sample, so accounts that sync cardio fitness see it without enabling + // it in Settings → Dashboard, while empty accounts get a clean tile + // strip. Only the tile-strip surface; the chart row lives on the + // /insights/cardio-fitness sub-page. "vo2Max", // v1.4.32 — "Recent workouts" tile. Surfaces the three most-recent // canonical workouts; self-gates on at least one row. Default-on @@ -379,11 +380,14 @@ export const DEFAULT_DASHBOARD_LAYOUT: DashboardLayout = { // `tileVisible` is forced false because there is no tile surface // for this widget; only the chart-row card. { id: "achievements", visible: true, tileVisible: false, order: 13 }, - // v1.4.25 W8d — VO2 max trend tile. Default-invisible on both - // surfaces; opt-in via Settings → Dashboard. Only the tile-strip - // representation today (`visible` stays false so the chart-row - // gate never fires; the chart card lands in v1.5). - { id: "vo2Max", visible: false, tileVisible: false, order: 14 }, + // v1.4.25 W8d — VO2 max trend tile. The strip tile is on by default + // (`tileVisible: true`) so accounts that already sync a VO2max sample + // see cardio fitness without hunting through Settings → Dashboard; the + // tile self-gates on having any VO2_MAX sample (see `showVo2Tile` in + // page.tsx), so accounts with no sample still get a clean dashboard. + // The chart row stays off (`visible: false`) — VO2max charts live on + // the /insights/cardio-fitness and /insights/pulse sub-pages. + { id: "vo2Max", visible: false, tileVisible: true, order: 14 }, // v1.4.32 — Recent workouts dashboard tile. Default-visible so // brand-new accounts discover the workout surface without // hunting through Settings; the tile self-gates on a non-empty