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.
146 lines
6.2 KiB
TypeScript
146 lines
6.2 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import test from "node:test";
|
|
|
|
import { homeSurface as page } from "./home-surface.ts";
|
|
import {
|
|
composerLocksAsRectification,
|
|
consultSendBlockedByRectificationSession,
|
|
dropRectificationStoredPending,
|
|
fallbackSessionId,
|
|
missingActiveSessionSendAction,
|
|
RECTIFICATION_OPENING_COMPOSER_PLACEHOLDER,
|
|
RECTIFICATION_REOPEN_LABEL,
|
|
rectificationOrdinaryComposerReopen,
|
|
SESSION_NOT_CONSULTATION_CODE,
|
|
} from "../src/lib/rectification-session-composer-guard.ts";
|
|
|
|
const read = (relativePath: string) => readFileSync(new URL(relativePath, import.meta.url), "utf8");
|
|
const run = read("../src/hooks/use-consultation-run.ts");
|
|
const sessions = read("../src/hooks/use-session-management.ts");
|
|
const consultRoute = read("../src/app/api/consult/route.ts");
|
|
const pageSource = read("../src/app/(app)/page.tsx");
|
|
const sendFn = run.slice(run.indexOf("async function send("), run.indexOf('await fetch("/api/consult"'));
|
|
|
|
test("a rectification session blocks consult send and keeps the draft", () => {
|
|
assert.equal(consultSendBlockedByRectificationSession({ sessionType: "birth_time_rectification" }), true);
|
|
assert.equal(consultSendBlockedByRectificationSession({ sessionType: "consultation" }), false);
|
|
assert.match(sendFn, /consultSendBlockedByRectificationSession\(currentSession\)/);
|
|
assert.match(sendFn, /setDraft\(originalQuestion\)/);
|
|
assert.match(sendFn, /openRectificationSession\(currentSession\.id\)/);
|
|
assert.doesNotMatch(sendFn, /fetch\("\/api\/consult"/);
|
|
});
|
|
|
|
test("pending consult replay pointing at a rectification session is dropped", () => {
|
|
assert.equal(
|
|
dropRectificationStoredPending(
|
|
{ sessionId: "r1" },
|
|
[{ id: "r1", sessionType: "birth_time_rectification" }],
|
|
),
|
|
null,
|
|
);
|
|
assert.deepEqual(
|
|
dropRectificationStoredPending(
|
|
{ sessionId: "c1" },
|
|
[{ id: "c1", sessionType: "consultation" }],
|
|
),
|
|
{ sessionId: "c1" },
|
|
);
|
|
assert.match(run, /if \(consultSendBlockedByRectificationSession\(session\)\) \{[\s\S]*sessionStorage\.removeItem\(pendingConsultationStorageKey\)/);
|
|
});
|
|
|
|
test("consult POST splits missing session from wrong session type", () => {
|
|
assert.match(consultRoute, /if \(!chatSession\) \{[\s\S]*咨询会话不存在[\s\S]*status: 404/);
|
|
assert.match(
|
|
consultRoute,
|
|
/if \(chatSession\.session_type !== "consultation"\) \{[\s\S]*session_not_consultation[\s\S]*status: 409/,
|
|
);
|
|
assert.match(consultRoute, /这是生时校正会话/);
|
|
assert.match(consultRoute, /请在生时校正里继续。/);
|
|
assert.equal(SESSION_NOT_CONSULTATION_CODE, "session_not_consultation");
|
|
assert.match(run, /caught\.code === SESSION_NOT_CONSULTATION_CODE/);
|
|
});
|
|
|
|
test("ordinary composer is locked on a rectification session until the surface opens", () => {
|
|
assert.equal(RECTIFICATION_OPENING_COMPOSER_PLACEHOLDER, "正在打开生时校正…");
|
|
assert.equal(RECTIFICATION_REOPEN_LABEL, "重新打开生时校正");
|
|
assert.match(pageSource, /inputDisabled=\{[^}]*activeRectificationSession/);
|
|
assert.match(pageSource, /submitBlocked=\{[^}]*activeRectificationSession/);
|
|
assert.match(pageSource, /ordinaryComposerPlaceholder\(/);
|
|
assert.match(pageSource, /RectificationComposerReopen/);
|
|
assert.equal(
|
|
rectificationOrdinaryComposerReopen({
|
|
activeRectificationSession: true,
|
|
error: "生时校正会话暂时无法打开,请稍后重试。",
|
|
errorSessionId: "s1",
|
|
sessionId: "s1",
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
rectificationOrdinaryComposerReopen({
|
|
activeRectificationSession: true,
|
|
error: "",
|
|
errorSessionId: null,
|
|
sessionId: "s1",
|
|
}),
|
|
false,
|
|
);
|
|
});
|
|
|
|
test("delete and popstate fallbacks do not setActiveSessionId onto a rectification session", () => {
|
|
assert.equal(
|
|
fallbackSessionId([
|
|
{ id: "r1", sessionType: "birth_time_rectification" },
|
|
{ id: "c1", sessionType: "consultation" },
|
|
]),
|
|
"c1",
|
|
);
|
|
assert.equal(
|
|
fallbackSessionId([{ id: "r1", sessionType: "birth_time_rectification" }]),
|
|
"r1",
|
|
);
|
|
assert.match(sessions, /function activateFallbackSession/);
|
|
assert.match(sessions, /if \(fallback\?\.sessionType === "birth_time_rectification"\) \{\s*selectSession\(fallbackId\);/);
|
|
assert.match(sessions, /if \(activeSessionId === session.id\) \{\s*activateFallbackSession\(nextSessions\);/);
|
|
// 原值:回退取整份列表的第一条非校正会话。
|
|
// 新值:先按当前人物过滤,再取回退。
|
|
// 原因:删除或地址回退后不能打开上一个人的对话。
|
|
assert.match(sessions, /fallbackSessionId\(listed\.filter\(\(session\) => sessionMatchesSubject\(session, readCurrentSubjectId\(\)\)\)\)/);
|
|
// 原值:首页第二条回退只排除校正会话。
|
|
// 新值:同一条还要 sessionMatchesSubject(当前人物)。
|
|
// 原因:当前会话对不上时,不能改打开另一个人的普通对话。
|
|
assert.match(page, /sessions\.find\(\(session\) => session\.sessionType !== "birth_time_rectification" && sessionMatchesSubject\(session, readCurrentSubjectId\(\)\)\)/);
|
|
});
|
|
|
|
test("an empty active session still locks the composer when the list is only rectification", () => {
|
|
assert.equal(
|
|
composerLocksAsRectification(undefined, [{ sessionType: "birth_time_rectification" }]),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
composerLocksAsRectification(undefined, [{ sessionType: "consultation" }]),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
composerLocksAsRectification({ sessionType: "consultation" }, [{ sessionType: "birth_time_rectification" }]),
|
|
false,
|
|
);
|
|
assert.deepEqual(
|
|
missingActiveSessionSendAction([{ id: "r1", sessionType: "birth_time_rectification" }]),
|
|
{ openSessionId: "r1" },
|
|
);
|
|
assert.deepEqual(
|
|
missingActiveSessionSendAction([]),
|
|
{ notice: "请先选一条对话,或点上方「新建对话」。" },
|
|
);
|
|
assert.match(pageSource, /composerLocksAsRectification\(activeSession, sessions\)/);
|
|
assert.match(sendFn, /missingActiveSessionSendAction\(sessions\)/);
|
|
assert.match(sendFn, /openRectificationSession\(action\.openSessionId\)/);
|
|
assert.match(sendFn, /setComposerNotice\(action\.notice\)/);
|
|
assert.doesNotMatch(
|
|
sendFn,
|
|
/if \(!question \|\| !currentSession \|\| !modelCatalog \|\| !account\) return false;/,
|
|
);
|
|
});
|