Fixes the inconsistency where switching the memo list to update_time
left the activity heatmap aggregating by created_time. The heatmap
now follows the same time basis as the list it sits next to.
Backend
- UserStats gains memo_updated_timestamps (additive proto field, tag 8).
- GetUserStats and ListAllUserStats populate it alongside the existing
memo_created_timestamps. No DB migration; memo.updated_ts already
exists on every row.
Frontend
- useFilteredMemoStats reads timeBasis from ViewContext and selects
the matching timestamp source.
- StatisticsView and MonthNavigator forward timeBasis through to
MonthCalendar / YearCalendar so tooltip text matches the basis
("X memos in DATE" vs "X memos updated on DATE").
- Falls back to memoCreatedTimestamps when an old server returns an
empty memoUpdatedTimestamps array (detected by length divergence,
since protobuf-es deserializes missing repeated fields as []).
Tests
- Backend: TestGetUserStats_MemoUpdatedTimestamps verifies the field
is populated and reflects post-creation updates.
- Frontend: filtered-memo-stats covers create/update source switching
and the old-server fallback path; activity-calendar-tooltip covers
basis-aware label selection.
Spec and implementation plan committed under docs/superpowers/.
26 lines
1.1 KiB
TypeScript
26 lines
1.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { getTooltipText } from "@/components/ActivityCalendar/utils";
|
|
|
|
// Minimal stub for the i18n translate fn — returns a deterministic string we can assert on.
|
|
const t = ((key: string, vars?: Record<string, unknown>) => {
|
|
if (!vars) return key;
|
|
const parts = Object.entries(vars).map(([k, v]) => `${k}=${String(v)}`);
|
|
return `${key}|${parts.join(",")}`;
|
|
}) as Parameters<typeof getTooltipText>[2];
|
|
|
|
describe("getTooltipText", () => {
|
|
it("returns just the date when count is 0", () => {
|
|
expect(getTooltipText(0, "2026-05-02", t)).toBe("2026-05-02");
|
|
});
|
|
|
|
it("uses the created-tooltip key for create_time basis (default)", () => {
|
|
const out = getTooltipText(3, "2026-05-02", t);
|
|
expect(out.toLowerCase()).toContain("memo.count-memos-in-date");
|
|
expect(out.toLowerCase()).not.toContain("updated");
|
|
});
|
|
|
|
it("uses the updated-tooltip key for update_time basis", () => {
|
|
const out = getTooltipText(3, "2026-05-02", t, "update_time");
|
|
expect(out.toLowerCase()).toContain("memo.count-memos-updated-in-date");
|
|
});
|
|
});
|