Files
Jyotisha/frontend/tests/chat-chart-panel-state.test.ts
T
Jesse_ChenandClaude Opus 5.5 e80bc64d93
Independent Staging Quality Gate / validate (push) Successful in 15m27s
Independent Staging Quality Gate / publish (push) Successful in 4m27s
Chart page on one sheet with a clickable North/South board (issue #114)
The chart page is now one page: board and inspector beside the nine-body
table, house themes, dasha strip and summary, with four deep-reading tabs
below (time, strength, yogas, chart book). Clicking a body or house draws its
rulership and aspect lines and fills the inspector. Shadbala, yogas and the
birth tithi come from the natal packet; ashtakavarga and house strength are a
new lazy layer; the transit layer takes any date. The chat's natal panel
carries the same board, opens by default, and is a bottom sheet on phones.

Logged two engine bugs found on the way (BUG-1462 sunrise, BUG-1463
/api/shadbala); neither is fixed here.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Ad9rqAB8pXXvyzh7f4X8v
2026-10-27 12:47:14 +08:00

83 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
import {
CHAT_CHART_OPEN_STORAGE_KEY,
CHAT_CHART_WIDTH_DEFAULT,
CHAT_CHART_WIDTH_MAX,
CHAT_CHART_WIDTH_MIN,
CHAT_CHART_WIDTH_STORAGE_KEY,
clampChatChartWidth,
readStoredChatChartOpen,
readStoredChatChartWidth,
writeStoredChatChartOpen,
writeStoredChatChartWidth,
type ChatChartStorage,
} from "../src/lib/chat-chart-panel-state.ts";
function memoryStorage(seed: Record<string, string> = {}): ChatChartStorage & { values: Map<string, string> } {
const values = new Map(Object.entries(seed));
return {
values,
getItem: (key) => values.get(key) ?? null,
setItem: (key, value) => { values.set(key, String(value)); },
};
}
test("chat natal panel remembers open and width on this machine", () => {
const storage = memoryStorage();
// 原值:没存过 → false(默认收起)
// 新值:没存过 → true(默认打开);用户收起后记住 false
// 原因:issue #114 Q8 A,产品 2026-10-27 定「一进聊天就出现盘」
assert.equal(readStoredChatChartOpen(storage), true);
assert.equal(readStoredChatChartWidth(storage), CHAT_CHART_WIDTH_DEFAULT);
writeStoredChatChartOpen(true, storage);
writeStoredChatChartWidth(480, storage);
assert.equal(storage.values.get(CHAT_CHART_OPEN_STORAGE_KEY), "1");
assert.equal(readStoredChatChartOpen(storage), true);
assert.equal(readStoredChatChartWidth(storage), 480);
writeStoredChatChartOpen(false, storage);
assert.equal(readStoredChatChartOpen(storage), false);
assert.equal(readStoredChatChartWidth(storage), 480);
});
// 原值:宽度 280~560;新值:320~760(默认 440);原因:issue #114 M8 右栏装完整盘面、检视和九曜表
test("chat natal panel width stays between 320 and 760", () => {
assert.equal(CHAT_CHART_WIDTH_MIN, 320);
assert.equal(CHAT_CHART_WIDTH_MAX, 760);
assert.equal(clampChatChartWidth(10), CHAT_CHART_WIDTH_MIN);
assert.equal(clampChatChartWidth(900), CHAT_CHART_WIDTH_MAX);
assert.equal(clampChatChartWidth(Number.NaN), CHAT_CHART_WIDTH_DEFAULT);
const storage = memoryStorage();
writeStoredChatChartWidth(12, storage);
assert.equal(storage.values.get(CHAT_CHART_WIDTH_STORAGE_KEY), String(CHAT_CHART_WIDTH_MIN));
assert.equal(readStoredChatChartWidth(memoryStorage({ [CHAT_CHART_WIDTH_STORAGE_KEY]: "nope" })), CHAT_CHART_WIDTH_DEFAULT);
});
// 原值:手机没有入口(`if (!ready || isMobile) return null`)
// 新值:手机有「看本命盘」按钮,点了才按需加载底部抽屉 chat-chart-sheet
// 原因:issue #114 Q8 后半句,产品 2026-10-27 同意「手机从底部拉起盘面」
test("the chat page loads the natal split only when the panel opens, and phones load a bottom sheet on demand", () => {
const page = readFileSync(new URL("../src/app/(app)/page.tsx", import.meta.url), "utf8");
const frame = readFileSync(new URL("../src/components/chat-chart-frame.tsx", import.meta.url), "utf8");
const split = readFileSync(new URL("../src/components/chat-chart-split.tsx", import.meta.url), "utf8");
assert.match(page, /<ChatChartToggle \/>/);
assert.match(page, /<ChatChartFrame>/);
assert.doesNotMatch(page, /react-resizable-panels|vedic-chart-svg|chat-chart-split/);
assert.match(frame, /打开本命盘/);
assert.match(frame, /收起本命盘/);
assert.match(frame, /if \(!ready\) return null/);
assert.match(frame, /看本命盘/);
assert.match(frame, /import\("@\/components\/chat-chart-sheet"\)/);
assert.match(frame, /import\("@\/components\/chat-chart-split"\)/);
// 原值:split 里要有 ResizablePanelGroup 和 collapsible
// 新值:split 用 useDragWidth,拖到最小以下调 onOpenChange(false) 收起
// 原因:组里只剩右栏一个面板时把手拖不动(BUG-1456);聊天列不能进组(BUG-1448),所以改成不依赖分组的把手
assert.match(split, /useDragWidth\(/);
assert.match(split, /onCollapse: \(\) => onOpenChange\(false\)/);
assert.doesNotMatch(split, /data-onboarding-draw/);
});