mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 21:10:59 +00:00
fix(admin): point status-card CTAs at real anchor IDs
Every "Manage users" / "View backups" CTA reloaded `/admin` to the top
because the hrefs were pointing at sub-routes that never shipped
(`/admin/users`, `/admin/audit-log`) and at anchors whose IDs do not
exist (`/admin#integrations`, `#monitoring`, `#backups`,
`#maintenance`). The actual section IDs in `src/app/admin/page.tsx`
follow a `section-admin-*` / `section-user-management` pattern.
Six href fixes plus a tightened test: instead of `startsWith("/admin")`
the test now asserts each href is `/admin#section-<known-id>` and that
the anchor is a member of the source-of-truth ID set rendered by the
admin page. Adding a new section requires adding the ID here too —
which is exactly the visibility we want to keep CTAs honest.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
c8ee28d2b0
commit
4aeb8c904e
2 files changed
+33
-8
No files matched your search
@@ -99,11 +99,36 @@ describe("buildCards()", () => {
|
||||
expect(cards[5].severity).toBe("info"); // audit log
|
||||
});
|
||||
|
||||
it("links each card to a manageable destination", () => {
|
||||
it("links each card to a real anchor on the admin page", () => {
|
||||
// Source-of-truth list of section IDs rendered by `src/app/admin/page.tsx`.
|
||||
// If you add a new section to the admin page, add the ID here. The test
|
||||
// proves every status-card href can actually scroll to something —
|
||||
// `startsWith("/admin")` was too lax and let the v1.4.5 regression slip
|
||||
// (every CTA bounced to `/admin#integrations` which does not exist).
|
||||
const realAnchorIds = new Set([
|
||||
"section-system-status",
|
||||
"section-admin-general",
|
||||
"section-admin-services",
|
||||
"section-admin-umami",
|
||||
"section-admin-glitchtip",
|
||||
"section-admin-webpush",
|
||||
"section-admin-bugreport",
|
||||
"section-admin-feedback",
|
||||
"section-admin-reminders",
|
||||
"section-user-management",
|
||||
"section-api-tokens",
|
||||
"section-login-overview",
|
||||
"section-danger-zone",
|
||||
]);
|
||||
|
||||
const cards = buildCards(mockOverview);
|
||||
for (const card of cards) {
|
||||
expect(card.href.startsWith("/admin")).toBe(true);
|
||||
expect(card.cta.length).toBeGreaterThan(0);
|
||||
// Hrefs must be `/admin#section-...` — sub-routes like `/admin/users`
|
||||
// do not exist as of v1.4.6 and were the original regression.
|
||||
expect(card.href).toMatch(/^\/admin#section-/);
|
||||
const anchor = card.href.replace(/^\/admin#/, "");
|
||||
expect(realAnchorIds.has(anchor)).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ export function buildCards(data: StatusOverview): StatusCardProps[] {
|
||||
{ label: "Admins", value: data.users.admins },
|
||||
{ label: "New 7d", value: data.users.newThisWeek },
|
||||
],
|
||||
href: "/admin/users",
|
||||
href: "/admin#section-user-management",
|
||||
cta: "Manage users",
|
||||
},
|
||||
{
|
||||
@@ -156,7 +156,7 @@ export function buildCards(data: StatusOverview): StatusCardProps[] {
|
||||
{ label: "moodLog", value: data.integrations.moodLog },
|
||||
{ label: "Push", value: data.integrations.webPush },
|
||||
],
|
||||
href: "/admin#integrations",
|
||||
href: "/admin#section-admin-umami",
|
||||
cta: "Configure",
|
||||
},
|
||||
{
|
||||
@@ -174,7 +174,7 @@ export function buildCards(data: StatusOverview): StatusCardProps[] {
|
||||
},
|
||||
{ label: "Last err", value: fmtRelative(data.monitoring.lastErrorAt) },
|
||||
],
|
||||
href: "/admin#monitoring",
|
||||
href: "/admin#section-admin-glitchtip",
|
||||
cta: "View monitoring",
|
||||
},
|
||||
{
|
||||
@@ -186,7 +186,7 @@ export function buildCards(data: StatusOverview): StatusCardProps[] {
|
||||
{ label: "Users", value: data.backups.backedUpUsers },
|
||||
{ label: "Retain", value: `${data.backups.retentionDays}d` },
|
||||
],
|
||||
href: "/admin#backups",
|
||||
href: "/admin#section-system-status",
|
||||
cta: "View backups",
|
||||
},
|
||||
{
|
||||
@@ -207,7 +207,7 @@ export function buildCards(data: StatusOverview): StatusCardProps[] {
|
||||
value: fmtRelative(data.maintenance.lastIdempotencyCleanup),
|
||||
},
|
||||
],
|
||||
href: "/admin#maintenance",
|
||||
href: "/admin#section-admin-reminders",
|
||||
cta: "View jobs",
|
||||
},
|
||||
{
|
||||
@@ -219,7 +219,7 @@ export function buildCards(data: StatusOverview): StatusCardProps[] {
|
||||
{ label: "Last login", value: fmtRelative(data.auditLog.lastLoginAt) },
|
||||
{ label: "—", value: "" },
|
||||
],
|
||||
href: "/admin/audit-log",
|
||||
href: "/admin#section-login-overview",
|
||||
cta: "Open viewer",
|
||||
},
|
||||
];
|
||||
|
||||
Reference in new issue
Block a user