/** * @vitest-environment happy-dom */ import fs from "node:fs"; import path from "node:path"; import type { ReactNode } from "react"; import { act } from "react"; import { createRoot } from "react-dom/client"; import { NextIntlClientProvider } from "next-intl"; import { describe, expect, test, vi } from "vitest"; import UsageDocPage from "@/app/[locale]/usage-doc/page"; import { UsageDocAuthProvider } from "@/app/[locale]/usage-doc/_components/usage-doc-auth-context"; vi.mock("@/i18n/routing", () => ({ Link: ({ href, children, ...rest }: { href: string; children: ReactNode; className?: string; }) => ( {children} ), })); function loadUsageMessages(locale: string) { return JSON.parse( fs.readFileSync(path.join(process.cwd(), "messages", locale, "usage.json"), "utf8") ); } async function renderWithIntl(locale: string, node: ReactNode) { const container = document.createElement("div"); document.body.appendChild(container); const root = createRoot(container); const usageMessages = loadUsageMessages(locale); await act(async () => { root.render( {node} ); }); return { unmount: async () => { await act(async () => root.unmount()); container.remove(); }, }; } describe("UsageDocPage - 目录/快速链接交互", () => { test("should render skip links and show dashboard link when logged in", async () => { Object.defineProperty(window, "scrollTo", { value: vi.fn(), writable: true, }); const { unmount } = await renderWithIntl( "en", ); expect(document.querySelector('a[href="#main-content"]')).not.toBeNull(); expect(document.querySelector('a[href="#toc-navigation"]')).not.toBeNull(); const dashboardLink = document.querySelector('a[href="/dashboard"]'); expect(dashboardLink).not.toBeNull(); await unmount(); }); test("ru 语言不应显示中文占位符与代码块注释", async () => { const { unmount } = await renderWithIntl("ru", ); const text = document.body.textContent || ""; expect(text).not.toContain("你的用户名"); expect(text).not.toContain("检查环境变量"); expect(text).not.toContain("添加到 PATH"); expect(text).toContain("C:\\Users\\your-username"); await unmount(); }); test("目录项点击后应触发平滑滚动", async () => { const scrollToMock = vi.fn(); Object.defineProperty(window, "scrollTo", { value: scrollToMock, writable: true, }); const { unmount } = await renderWithIntl("en", ); const tocNav = document.querySelector("#toc-navigation nav"); expect(tocNav).not.toBeNull(); let tocButtons = tocNav?.querySelectorAll("button") ?? []; for (let i = 0; i < 10 && tocButtons.length === 0; i++) { await act(async () => { await new Promise((r) => setTimeout(r, 0)); }); tocButtons = tocNav?.querySelectorAll("button") ?? []; } expect(tocButtons.length).toBeGreaterThan(0); await act(async () => { (tocButtons[0] as HTMLButtonElement).click(); }); expect(scrollToMock).toHaveBeenCalled(); await unmount(); }); });