import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; const page = readFileSync(new URL("../src/app/page.tsx", import.meta.url), "utf8"); const sidebar = readFileSync(new URL("../src/components/app-sidebar.tsx", import.meta.url), "utf8"); const overlay = readFileSync(new URL("../src/components/account-dialog-overlay.tsx", import.meta.url), "utf8"); function between(source: string, start: string, end: string) { const startIndex = source.indexOf(start); const endIndex = source.indexOf(end, startIndex + start.length); assert.notEqual(startIndex, -1, `missing start marker: ${start}`); assert.notEqual(endIndex, -1, `missing end marker: ${end}`); return source.slice(startIndex, endIndex); } test("account menu exposes the four MVP settings sections", () => { assert.match(sidebar, /个人资料<\/span>/); assert.match(sidebar, /星盘资料<\/span>/); assert.match(sidebar, /通用设置<\/span>/); assert.match(sidebar, /账户与点数<\/span>/); assert.match(sidebar, /onOpenGeneral/); }); test("personal profile is limited to account basics and links to chart settings", () => { const profile = between(page, " renderProfile() {", " renderChartLibrary() {"); assert.match(profile, /账户信息/); assert.match(profile, /登录邮箱/); assert.match(profile, /管理星盘资料/); assert.doesNotMatch(profile, / { const charts = between(page, " renderChartLibrary() {", " renderGeneral() {"); assert.match(charts, /编辑本人资料/); assert.match(charts, /onSubmit=\{saveProfile\}/); assert.match(charts, /onSubmit=\{saveOtherChart\}/); assert.match(charts, /setEditingSelfChart\(true\)/); }); test("the general dialog renders the shared theme preference panel", () => { assert.match(overlay, /dialog: "profile" \| "chart-library" \| "general" \| "logout"/); assert.match(overlay, /renderGeneral: \(\) => ReactNode/); assert.match(overlay, /return model\.renderGeneral\(\)/); assert.match(page, /renderGeneral\(\) \{\s*return ;/); });