import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { createTranslator } from "next-intl"; import type { ReactNode } from "react"; import { renderToStaticMarkup } from "react-dom/server"; import { describe, expect, it, vi } from "vitest"; const state = vi.hoisted(() => ({ data: { support: 2 as number | null, friendRequests: 3 as number | null, registeredEvent: false as | false | null | { id: number; title: string; startsAt: Date }, }, })); vi.mock("@/lib/services/dashboard-tasks", () => ({ loadDashboardTasks: async () => state.data, })); vi.mock("@/components/link", () => ({ default: ({ href, children, ...props }: { href: string; children: ReactNode; }) => ( {children} ), })); vi.mock("next-intl/server", () => ({ getTranslations: async () => { const flat = JSON.parse( readFileSync("docs/task-account-i18n.json", "utf8"), ).it; const messages = Object.fromEntries( Object.entries(flat).map(([key, value]) => [ key.replace("pages.myDashboard.tasks.", ""), value, ]), ); return createTranslator({ locale: "it", messages }); }, getFormatter: async () => ({ dateTime: (date: Date) => new Intl.DateTimeFormat("it", { dateStyle: "medium", timeStyle: "short", timeZone: "UTC", }).format(date), }), })); import DashboardTasks from "./DashboardTasks"; describe("dashboard task presentation", () => { it("renders actionable links from real task data", async () => { state.data = { support: 2, friendRequests: 3, registeredEvent: { id: 7, title: "Un evento con un titolo molto lungo per verificare la visualizzazione sullo schermo del telefono", startsAt: new Date("2026-09-12T15:00:00Z"), }, }; const html = renderToStaticMarkup( await DashboardTasks({ userId: 42, rewardAvailable: true }), ); expect(html).toContain('href="/help/tickets"'); expect(html).toContain('href="/friends"'); expect(html).toContain('href="#referral-reward"'); expect(html).toContain("-7"); if (process.env.ACCOUNT_VISUAL_FIXTURE) { const css = readFileSync( "src/app/(site)/me/dashboard.module.css", "utf8", ).replaceAll(/\.([\w]+)(?=[\s.{:#>])/g, ".$1"); // Vitest CSS modules are scoped; reproduce those class names for the fixture. const taskClass = html.match(/