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>
91 lines
3.2 KiB
TypeScript
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/);
|
|
});
|