Cap planet captions at 30 degrees with a third ring, fall back only within the current person's sessions, and load self when the people catalog fails.
67 lines
4.0 KiB
TypeScript
67 lines
4.0 KiB
TypeScript
import assert from "node:assert/strict";
|
||
import { readFileSync } from "node:fs";
|
||
import test from "node:test";
|
||
|
||
const provider = readFileSync(new URL("../src/lib/session-list-context.tsx", import.meta.url), "utf8");
|
||
const accountRead = readFileSync(new URL("../src/lib/current-subject.ts", import.meta.url), "utf8");
|
||
const layout = readFileSync(new URL("../src/app/(app)/layout.tsx", import.meta.url), "utf8");
|
||
const page = readFileSync(new URL("../src/app/(app)/page.tsx", import.meta.url), "utf8");
|
||
const sessionHook = readFileSync(new URL("../src/hooks/use-session-management.ts", import.meta.url), "utf8");
|
||
|
||
test("the app layout owns one SessionListProvider and one SidebarProvider", () => {
|
||
assert.match(layout, /<SessionListProvider>/);
|
||
assert.equal(layout.match(/<SessionListProvider>/g)?.length, 1);
|
||
assert.match(layout, /<SidebarProvider escapeBlocked=\{registration\?\.escapeBlocked \?\? false\}>/);
|
||
assert.equal(layout.match(/<SidebarProvider/g)?.length, 1);
|
||
assert.match(layout, /<AppSidebar/);
|
||
assert.doesNotMatch(page, /<SidebarProvider/);
|
||
assert.doesNotMatch(page, /<AppSidebar/);
|
||
});
|
||
|
||
test("the provider fetches the session list once and home does not fetch it again", () => {
|
||
assert.match(provider, /fetch\(`\/api\/sessions\?limit=\$\{SESSION_PAGE_SIZE\}&subject=\$\{encodeURIComponent\(subjectId\)\}`/);
|
||
// 原值:provider 自己 fetch("/api/account")。
|
||
// 新值:provider 调用 readBootAccount,fetch 在 current-subject.ts,同一次加载只打一次。
|
||
// 原因:人物目录和会话列表要共享账户结果。
|
||
assert.match(provider, /readBootAccount\(\)/);
|
||
assert.match(accountRead, /fetch\("\/api\/account"/);
|
||
// 原值: page.tsx 里 `await sessionListReady;`
|
||
// 新值: page.tsx 把 sessionListReady 交给 runHomeBootstrap,函数里 `await deps.sessionListReady`。
|
||
// 原因: 启动流程搬出首页后,会话列表仍只由 provider 拉一次。
|
||
const bootstrapRun = readFileSync(new URL("../src/lib/home-bootstrap-run.ts", import.meta.url), "utf8");
|
||
assert.match(page, /sessionListReady,/);
|
||
// 原值 / 新值 / 原因:固定 ready promise / 当前 reload gate / 切人期间回 Home 必须等新绑定,不能读空 boot 误登出。
|
||
assert.match(bootstrapRun, /await \(deps\.waitForSessionList\?\.\(\) \?\? deps\.sessionListReady\);/);
|
||
assert.match(page, /waitForSessionList,/);
|
||
assert.doesNotMatch(page, /fetchSessions\(/);
|
||
assert.doesNotMatch(page, /fetchAccount\(/);
|
||
assert.match(page, /useHomeShellRegistration\(/);
|
||
});
|
||
|
||
test("a 401 clears the list and marks signedOut", () => {
|
||
// 原值:provider 里 accountResponse.status === 401。
|
||
// 新值:readBootAccount 返回 status 401,provider 写成 accountResult.status === 401,仍 signedOut。
|
||
// 原因:账户读取挪到共享函数后,401 仍先于会话请求结束,不串第二次账户请求。
|
||
assert.match(provider, /accountResult\.status === 401/);
|
||
assert.match(accountRead, /response\.status === 401/);
|
||
assert.match(provider, /sessionResponse\.status === 401/);
|
||
assert.match(provider, /signedOut: true/);
|
||
assert.doesNotMatch(provider, /localStorage|sessionStorage|document\.cookie|indexedDB/i);
|
||
});
|
||
|
||
test("session writes no longer invalidate a second cache", () => {
|
||
assert.doesNotMatch(sessionHook, /invalidateSidebarCache/);
|
||
});
|
||
|
||
test("only the shell consumes registration and it passes Home children through unchanged", () => {
|
||
assert.match(layout, /const registration = useShellRegistration\(\)/);
|
||
assert.match(layout, /sessionListSidebarModel\(list, registration\)/);
|
||
assert.doesNotMatch(layout, /list\.registration|cloneElement/);
|
||
assert.match(layout, /<SidebarInset[\s\S]*>\s*\{children\}\s*<\/SidebarInset>/);
|
||
assert.doesNotMatch(page, /useShellRegistration/);
|
||
const dataValue = provider.slice(provider.indexOf("const value = useMemo"), provider.indexOf("return (", provider.indexOf("const value = useMemo")));
|
||
assert.doesNotMatch(dataValue, /\bregistration\b/);
|
||
assert.match(dataValue, /registerShellControls/);
|
||
assert.match(provider, /<ShellRegistrationContext\.Provider value=\{registration\}>\s*\{children\}/);
|
||
});
|