fix(web): 无用户行钉顶、闲置不上留白,并修会话列表 tsc 两错
Independent Staging Quality Gate / validate (push) Failing after 6m27s
Independent Staging Quality Gate / publish (push) Skipped

This commit is contained in:
jesse-ux
2026-09-17 22:25:53 +08:00
parent b5e16b96f4
commit cc1a89802e
8 changed files with 135 additions and 16 deletions
+4 -1
View File
@@ -86,7 +86,10 @@ test("sidebar titles drop the chart-name prefix and only subtitle others", () =>
archivedAt: null,
messagesHydrated: true,
};
assert.equal(sessionSidebarTitle(base, library), "半年内换工作时机");
// 原值: sessionSidebarTitle(base, library)
// 新值: sessionSidebarTitle(base)
// 原因: sessionSidebarTitle 只吃 session;第二参是 e4e73f56 的 TS 错,挡住 tsc / next build
assert.equal(sessionSidebarTitle(base), "半年内换工作时机");
assert.equal(sessionSidebarSubtitle(base, library), "9月14日 12:14");
const other = { ...base, chartProfileId: "other-1", chartProfileName: "对方", chartProfileRole: "other" as const };
assert.equal(sessionSidebarSubtitle(other, library), "9月14日 12:14 · 资料已删除 · 对方");
@@ -235,6 +235,49 @@ test("turn spacer uses conversation viewport variables and is not sticky", () =>
assert.equal(scroller.style.getPropertyValue("--latest-turn-head-height"), "");
});
test("a turn with no user row pins the new assistant and uses a full-viewport spacer", () => {
const priorUser = fakeRow("message-user", 8, 40);
const priorAssistant = fakeRow("message-assistant", 56, 80);
const laterUser = fakeRow("message-user", 152, 40);
const laterAssistant = fakeRow("message-assistant", 200, 80);
const incoming = fakeRow("message-assistant", 480, 80);
const scroller = fakeScroller([priorUser, priorAssistant, laterUser, laterAssistant, incoming], 600);
const head = resolveTurnHead(asElement(scroller));
assert.equal(head, asElement(incoming));
applyTurnSpacer(asElement(scroller), head);
assert.equal(scroller.style.getPropertyValue("--latest-turn-head-height"), "0px");
scroller.scrollTop = pinTurnScrollTop(asElement(scroller), asElement(incoming), 16);
assert.equal(scroller.scrollTop, incoming.offsetTop - 16);
const start = scroller.scrollTop;
for (let i = 0; i < 3; i += 1) {
incoming.offsetHeight += 80;
scroller.scrollHeight += 80;
applyFollowBottom(scroller, false);
}
assert.equal(scroller.scrollTop, start);
});
test("idle history does not write a spacer when the reader has only scrolled up", () => {
// 原值: follow() 在 !anchored 时无条件 applyTurnSpacer
// 新值: 只在 pinnedHeadRef 非空时写留白
// 原因: BUG-932 闲置会话上滑后子元素尺寸变化不应把最后一条助手行撑开
assert.match(
anchorSource,
/if \(anchoredRef\.current\) \{\s*element\.scrollTop = element\.scrollHeight;\s*\} else if \(pinnedHeadRef\.current\) \{\s*applyTurnSpacer\(element, pinnedHeadRef\.current\);/,
);
assert.match(anchorSource, /pinnedHeadRef\.current = null;\s*if \(element\) \{\s*clearTurnSpacer\(element\);/);
const user = fakeRow("message-user", 8, 40);
const assistant = fakeRow("message-assistant", 56, 900);
const scroller = fakeScroller([user, assistant], 600);
scroller.scrollTop = scroller.scrollHeight - scroller.clientHeight;
scroller.scrollTop = Math.max(0, scroller.scrollTop - 400);
const start = scroller.scrollTop;
assistant.offsetHeight += 30;
scroller.scrollHeight += 30;
assert.equal(scroller.style.getPropertyValue("--conversation-viewport"), "");
assert.equal(Math.abs(scroller.scrollTop - start) <= 1, true);
});
test("consultation send and rectification new turns call pinLatestTurn", () => {
const chat = readFileSync(new URL("../src/components/rectification-agentic-chat.tsx", import.meta.url), "utf8");
const pins = chat.match(/conversationAnchor\.pinLatestTurn\(\)/g) ?? [];