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:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-09 01:28:55 +02:00
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);
}
});
+6 -6
View File
@@ -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",
},
];