Files
Jyotisha/frontend/tests/account-dialog-overlay.test.ts
T
Jesse_ChenandCursor dc6598d7e4 fix(web): keep the settings dialog one size and move billing into it (BUG-554)
The four account panes now share a fixed frame, chart profiles open as list then detail, and membership lives in the homepage dialog instead of a separate page.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-06 18:29:51 +08:00

91 lines
3.2 KiB
TypeScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { createElement, createRef } from "react";
import { renderToString } from "react-dom/server";
import test from "node:test";
import {
AccountDialogOverlay,
type AccountOverlayModel,
} from "../src/components/account-dialog-overlay.tsx";
function overlayModel(overrides: Partial<AccountOverlayModel> = {}): AccountOverlayModel {
const overlayRef = createRef<HTMLElement | null>() as AccountOverlayModel["overlayRef"];
const closeButtonRef = createRef<HTMLButtonElement | null>() as AccountOverlayModel["closeButtonRef"];
return {
title: "个人资料",
dialogClass: "settings-modal",
signingOut: false,
close() {},
navigate() {},
overlayRef,
closeButtonRef,
renderProfile() { return null; },
renderChartLibrary() { return null; },
renderBilling() { return null; },
renderGeneral() { return null; },
renderLogout() { return null; },
...overrides,
};
}
test("a closed account overlay does not render profile or logout content", () => {
let profileRenders = 0;
let logoutRenders = 0;
const model = overlayModel({
renderProfile() {
profileRenders += 1;
return null;
},
renderLogout() {
logoutRenders += 1;
return null;
},
});
const html = renderToString(createElement(AccountDialogOverlay, {
open: false,
dialog: null,
model,
}));
assert.equal(html, "");
assert.equal(profileRenders, 0);
assert.equal(logoutRenders, 0);
});
test("home does not write overlay epoch or chat actions during render", () => {
const page = readFileSync(new URL("../src/app/page.tsx", import.meta.url), "utf8");
const overlay = readFileSync(new URL("../src/components/account-dialog-overlay.tsx", import.meta.url), "utf8");
assert.match(overlay, /model: AccountOverlayModel \| null/);
assert.doesNotMatch(overlay, /openEpoch/);
assert.doesNotMatch(overlay, /modelRef/);
assert.doesNotMatch(page, /accountOverlayEpochRef/);
assert.doesNotMatch(page, /sessionsRef\.current = sessions/);
assert.match(page, /queueMicrotask\(\(\) => setActiveChartId\(storedChartId\)\)/);
assert.match(page, /useEffect\(\(\) => \{\s*chatActionsRef\.current = \{/);
});
test("settings navigation lists four panes and billing can be current", () => {
const overlay = readFileSync(new URL("../src/components/account-dialog-overlay.tsx", import.meta.url), "utf8");
const styles = readFileSync(new URL("../src/app/globals.css", import.meta.url), "utf8");
const html = renderToString(createElement(AccountDialogOverlay, {
open: true,
dialog: "billing",
model: overlayModel({ title: "账户与点数" }),
}));
assert.match(overlay, /dialog: "profile"/);
assert.match(overlay, /dialog: "chart-library"/);
assert.match(overlay, /dialog: "billing"/);
assert.match(overlay, /dialog: "general"/);
assert.doesNotMatch(overlay, /openRedeem/);
assert.match(html, /个人资料/);
assert.match(html, /星盘资料/);
assert.match(html, /账户与点数/);
assert.match(html, /通用设置/);
assert.match(html, /aria-current="page"/);
assert.match(styles, /\.settings-modal \{[^}]*width:[^}]*height:/);
assert.doesNotMatch(styles, /chart-library-modal|profile-modal/);
});