refactor: simplify rectification conversation chrome
This commit is contained in:
+19
-3
@@ -707,9 +707,25 @@
|
||||
- 用户现象:生时校正右侧直接显示浏览器或操作系统默认滚动条,与站内温和、低对比的编辑式界面不一致。
|
||||
- 触发条件:生时校正历史内容超过消息区高度,在桌面浏览器出现纵向滚动条。
|
||||
- 根因:`.rectification-message-list` 只声明了 `overflow-y: auto`,没有提供跨浏览器的产品内滚动条颜色、宽度和交互状态。
|
||||
- 修复:为生时校正消息区增加细宽、透明轨道、低对比圆角拇指,并在 hover 时适度加深;Firefox 使用标准 scrollbar 属性,Chromium / Safari 使用 WebKit 伪元素,颜色继续取现有设计 token。
|
||||
- 验证:CSS 契约锁定标准与 WebKit 两套样式,聚焦组件测试、目标 ESLint、production build 与生产浏览器 smoke。
|
||||
- 防复发:独立滚动容器必须复用产品 token,并同时覆盖标准 scrollbar 属性和 WebKit 伪元素;不得引入渐变、重阴影或高饱和装饰。
|
||||
- 修复:为生时校正消息区增加细宽、透明轨道、低对比圆角拇指;默认隐藏拇指,仅在指针移动、列表滚动或键盘焦点进入消息区时短暂显示,停止操作后自动隐藏。Firefox 使用标准 scrollbar 属性,Chromium / Safari 使用 WebKit 伪元素,颜色继续取现有设计 token。
|
||||
- 验证:CSS 契约锁定默认透明、交互显现及标准与 WebKit 两套样式,聚焦组件测试、目标 ESLint、production build 与生产浏览器 smoke。
|
||||
- 防复发:独立滚动容器必须复用产品 token,并同时覆盖标准 scrollbar 属性和 WebKit 伪元素;默认态不得持续抢占视觉注意力,也不得引入渐变、重阴影或高饱和装饰。
|
||||
- 相关记录:BUG-041
|
||||
- 复发自:无
|
||||
- 修复版本:本次简约滚动条修复提交
|
||||
|
||||
## BUG-043 | 生时校正把后台证据状态重复渲染成可展开管理面板
|
||||
|
||||
- 状态:resolved
|
||||
- 首次发现:2026-07-23
|
||||
- 最近更新:2026-07-23
|
||||
- 影响面:生时校正消息流、候选进度、历史经历与更正入口
|
||||
- 用户现象:Agent 已经在自然对话中确认和追问经历,消息区底部仍额外显示“当前候选 · 待验证”、候选范围、历史经历列表和“更正”按钮;用户需要理解并操作第二套记录界面,破坏一问一答的连续性。
|
||||
- 触发条件:任何已有候选或至少一条 evidence recap 的生时校正案例。
|
||||
- 根因:语言交互改版后仍保留旧产品流程的 `<details>` 进度与证据管理面板,把本应仅供后台评分和恢复使用的结构化状态再次暴露给用户。
|
||||
- 修复:从生时校正消息流移除整块候选进度与历史经历管理面板,不再显示候选状态、范围、经历列表或逐条更正按钮;后台 evidence、评分与持久化保持不变,最终可确认状态仍通过明确确认动作呈现。
|
||||
- 验证:组件与真实 Chromium 回归锁定页面不包含候选进度、历史经历面板或更正按钮,同时保留自然对话、流式回答、撤回窗口、自动贴底和最终确认能力。
|
||||
- 防复发:结构化 evidence 是 Agent 的后台推理与持久化输入,不得在语言优先界面重复渲染成需要用户管理的卡片或表单;需要纠正时继续通过自然语言表达。
|
||||
- 相关记录:BUG-020、BUG-034、BUG-042
|
||||
- 复发自:BUG-020
|
||||
- 修复版本:待提交
|
||||
|
||||
@@ -788,16 +788,26 @@ input:disabled, select:disabled { color: var(--color-ink-tertiary); background:
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
padding-bottom: var(--space-6);
|
||||
scrollbar-color: color-mix(in srgb, var(--color-ink-tertiary) 46%, transparent) transparent;
|
||||
scrollbar-color: transparent transparent;
|
||||
scrollbar-gutter: stable;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
.rectification-message-list.is-scrollbar-visible,
|
||||
.rectification-message-list:focus-within {
|
||||
scrollbar-color: color-mix(in srgb, var(--color-ink-tertiary) 46%, transparent) transparent;
|
||||
}
|
||||
.rectification-message-list::-webkit-scrollbar { width: 10px; }
|
||||
.rectification-message-list::-webkit-scrollbar-track { background: transparent; }
|
||||
.rectification-message-list::-webkit-scrollbar-thumb {
|
||||
min-height: 40px;
|
||||
border: 3px solid transparent;
|
||||
border-radius: 999px;
|
||||
background: transparent;
|
||||
background-clip: padding-box;
|
||||
transition: background-color 160ms ease;
|
||||
}
|
||||
.rectification-message-list.is-scrollbar-visible::-webkit-scrollbar-thumb,
|
||||
.rectification-message-list:focus-within::-webkit-scrollbar-thumb {
|
||||
background: color-mix(in srgb, var(--color-ink-tertiary) 42%, transparent);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
@@ -805,19 +815,13 @@ input:disabled, select:disabled { color: var(--color-ink-tertiary); background:
|
||||
background: color-mix(in srgb, var(--color-ink-secondary) 62%, transparent);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
.rectification-message-details { margin-top: var(--space-3); padding-top: var(--space-2); border-top: 1px solid var(--color-border); color: var(--color-ink-secondary); font-size: var(--type-caption); }
|
||||
.rectification-message-details summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; font-size: var(--type-body-sm); font-weight: 600; }
|
||||
.rectification-message-details p { margin: 0 0 var(--space-2); font-size: var(--type-caption); line-height: 1.6; }
|
||||
.rectification-message-details ul { display: grid; gap: var(--space-2); margin: var(--space-3) 0 0; padding: 0; list-style: none; }
|
||||
.rectification-message-details li { min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--space-3); padding-top: var(--space-2); border-top: 1px solid var(--color-border); }
|
||||
.rectification-message-details button, .rectification-correction-target button { min-height: 44px; padding-inline: var(--space-3); border: 0; background: transparent; color: var(--color-action); cursor: pointer; }
|
||||
.rectification-correction-target button { min-height: 44px; padding-inline: var(--space-3); border: 0; background: transparent; color: var(--color-action); cursor: pointer; }
|
||||
.rectification-composer-wrap { position: static; flex: 0 0 auto; }
|
||||
.rectification-correction-target { width: min(760px, 100%); display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin: 0 auto var(--space-2); color: var(--color-ink-secondary); font-size: var(--type-caption); }
|
||||
.rectification-correction-target p { margin: 0; }
|
||||
.conversational-empty-state { width: min(760px, 100%); margin: var(--space-8) auto; color: var(--color-ink-secondary); }
|
||||
|
||||
@media (max-width: 430px) {
|
||||
.rectification-message-details li { align-items: stretch; grid-template-columns: minmax(0, 1fr); }
|
||||
.rectification-correction-target { align-items: stretch; display: grid; }
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
} from "../hooks/use-conversational-rectification.ts";
|
||||
import type {
|
||||
ConversationalRectificationResponse,
|
||||
ConversationalRectificationTurn,
|
||||
} from "../lib/conversational-rectification/contracts.ts";
|
||||
|
||||
type SurfaceProps = Readonly<{
|
||||
@@ -28,13 +27,6 @@ function safely(request: Promise<unknown>) {
|
||||
void request.catch(() => undefined);
|
||||
}
|
||||
|
||||
function candidateStatus(turn: ConversationalRectificationTurn): string {
|
||||
if (turn.status === "completed" && turn.candidate.status === "confirmed") return "已确认";
|
||||
if (turn.status === "completed") return "范围已保存,分钟未确认";
|
||||
if (turn.candidate.status === "ready_for_confirmation") return "待确认,尚未验证";
|
||||
return "待验证";
|
||||
}
|
||||
|
||||
export function ConversationalRectificationSurface({
|
||||
controller,
|
||||
openingAssistantText = "",
|
||||
@@ -44,6 +36,7 @@ export function ConversationalRectificationSurface({
|
||||
}: SurfaceProps) {
|
||||
const composer = useRef<HTMLTextAreaElement>(null);
|
||||
const messageList = useRef<HTMLDivElement>(null);
|
||||
const scrollbarHideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const undoTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const [submission, setSubmission] = useState<Readonly<{
|
||||
text: string;
|
||||
@@ -77,6 +70,7 @@ export function ConversationalRectificationSurface({
|
||||
]);
|
||||
useEffect(() => () => {
|
||||
if (undoTimer.current) clearTimeout(undoTimer.current);
|
||||
if (scrollbarHideTimer.current) clearTimeout(scrollbarHideTimer.current);
|
||||
}, []);
|
||||
const pendingQuestion = turn?.status === "completed"
|
||||
? turn.pendingConsultationQuestion
|
||||
@@ -132,10 +126,31 @@ export function ConversationalRectificationSurface({
|
||||
setSubmission(null);
|
||||
requestAnimationFrame(() => composer.current?.focus());
|
||||
};
|
||||
const revealScrollbar = () => {
|
||||
const list = messageList.current;
|
||||
if (!list) return;
|
||||
list.classList.add("is-scrollbar-visible");
|
||||
if (scrollbarHideTimer.current) clearTimeout(scrollbarHideTimer.current);
|
||||
scrollbarHideTimer.current = setTimeout(() => {
|
||||
list.classList.remove("is-scrollbar-visible");
|
||||
scrollbarHideTimer.current = null;
|
||||
}, 900);
|
||||
};
|
||||
const hideScrollbar = () => {
|
||||
if (scrollbarHideTimer.current) clearTimeout(scrollbarHideTimer.current);
|
||||
scrollbarHideTimer.current = null;
|
||||
messageList.current?.classList.remove("is-scrollbar-visible");
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="rectification-chat" aria-busy={busy} aria-label="生时校正对话">
|
||||
<div ref={messageList} className="message-list rectification-message-list">
|
||||
<div
|
||||
ref={messageList}
|
||||
className="message-list rectification-message-list"
|
||||
onPointerLeave={hideScrollbar}
|
||||
onPointerMove={revealScrollbar}
|
||||
onScroll={revealScrollbar}
|
||||
>
|
||||
<span className="sr-only" aria-live="polite">{submission?.phase === "undo" ? "消息已发送,可以撤回修改" : controller.pending ? "Jyotisha 正在核对经历" : ""}</span>
|
||||
{(controller.messages ?? [{
|
||||
role: "assistant" as const,
|
||||
@@ -157,41 +172,6 @@ export function ConversationalRectificationSurface({
|
||||
message={{ role: "user", text: submission.text, renderKey: "pending-evidence", state: "settled" }}
|
||||
/>
|
||||
)}
|
||||
<details className="rectification-message-details rectification-progress-details">
|
||||
<summary>
|
||||
{turn.candidate.representativeTime
|
||||
? `当前候选 ${turn.candidate.representativeTime} · ${candidateStatus(turn)}`
|
||||
: `校正进度 · ${candidateStatus(turn)}`}
|
||||
</summary>
|
||||
<p>
|
||||
{turn.candidate.rangeStart && turn.candidate.rangeEnd
|
||||
? `候选范围 ${turn.candidate.rangeStart}—${turn.candidate.rangeEnd};已记录 ${turn.evidenceRecap.length} 条经历。`
|
||||
: `已记录 ${turn.evidenceRecap.length} 条经历,尚未缩小候选范围。`}
|
||||
</p>
|
||||
<p>候选只用于继续验证;这一步不会自动采用候选,未经发布门禁与明确确认不会成为当前排盘时间。</p>
|
||||
{turn.evidenceRecap.length > 0 && (
|
||||
<ul aria-label="已记录的真实经历">
|
||||
{turn.evidenceRecap.map((entry) => (
|
||||
<li key={entry.id}>
|
||||
<span>{entry.dateLabel} · {entry.summary}{entry.isCorrection ? "(已修订)" : ""}</span>
|
||||
{canAnswer && (
|
||||
<button
|
||||
aria-label={`更正这条经历:${entry.summary}`}
|
||||
disabled={busy}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
controller.beginEvidenceCorrection(entry.id);
|
||||
composer.current?.focus();
|
||||
}}
|
||||
>
|
||||
更正
|
||||
</button>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</details>
|
||||
{controller.pending && canAnswer && (
|
||||
controller.streamingAssistantText
|
||||
? <ChatMessageRow message={{
|
||||
|
||||
@@ -93,8 +93,8 @@ test("rectification is a language-first exchange with one free-text answer path"
|
||||
|
||||
assert.match(markup, /当前判断/);
|
||||
assert.match(markup, /D9 与 D10/);
|
||||
assert.match(markup, /2021 年 7 月 · 开始第一份长期工作/);
|
||||
assert.ok(markup.indexOf("当前判断") < markup.indexOf("当前候选 05:18"));
|
||||
assert.doesNotMatch(markup, /已记录的经历|已记录的真实经历|更正这条经历/);
|
||||
assert.doesNotMatch(markup, /当前候选 05:18/);
|
||||
assert.doesNotMatch(markup, /目前已经形成一个待确认候选/);
|
||||
assert.match(markup, /<textarea[^>]+id="conversational-rectification-answer"/);
|
||||
assert.match(markup, /像聊天一样回答即可/);
|
||||
@@ -104,7 +104,7 @@ test("rectification is a language-first exchange with one free-text answer path"
|
||||
assert.doesNotMatch(markup, /2006[^<]*2011|BirthTimeChoiceQuestion|birth-time-choice-question/);
|
||||
});
|
||||
|
||||
test("a resumed legacy turn preserves its Agent narrative and keeps evidence in progress details", () => {
|
||||
test("a resumed legacy turn preserves its Agent narrative without a separate evidence panel", () => {
|
||||
const legacyTurn = {
|
||||
...turn,
|
||||
status: "active",
|
||||
@@ -119,7 +119,7 @@ test("a resumed legacy turn preserves its Agent narrative and keeps evidence in
|
||||
|
||||
assert.match(markup, /05:30 是范围内的待验证候选/);
|
||||
assert.match(markup, /D1 保持稳定/);
|
||||
assert.match(markup, /2021 年 7 月 · 开始第一份长期工作/);
|
||||
assert.doesNotMatch(markup, /2021 年 7 月 · 开始第一份长期工作|已记录的经历/);
|
||||
assert.doesNotMatch(markup, /范围暂未变化不代表提交失败/);
|
||||
});
|
||||
|
||||
@@ -194,28 +194,23 @@ test("the first Agent guidance streams into the empty rectification surface", ()
|
||||
assert.doesNotMatch(markup, /正在建立校正记录/);
|
||||
});
|
||||
|
||||
test("evidence is correctable, secondary controls stay hidden, and confirmation is explicit", () => {
|
||||
test("history management stays hidden while final confirmation remains explicit", () => {
|
||||
const markup = renderToStaticMarkup(React.createElement(
|
||||
ConversationalRectificationSurface,
|
||||
{ controller: controller() },
|
||||
));
|
||||
|
||||
assert.match(markup, /已记录的真实经历/);
|
||||
assert.match(markup, /2021 年 7 月/);
|
||||
assert.match(markup, /更正这条经历:开始第一份长期工作/);
|
||||
assert.doesNotMatch(markup, /已记录的真实经历|2021 年 7 月|更正这条经历/);
|
||||
assert.doesNotMatch(markup, /本轮分析|等待经历验证/);
|
||||
assert.doesNotMatch(markup, /本轮技术回执|rectification-technical-v1|consult-d9/);
|
||||
assert.match(markup, /当前候选 05:18/);
|
||||
assert.match(markup, /待确认,尚未验证/);
|
||||
assert.doesNotMatch(markup, /当前候选 05:18/);
|
||||
assert.match(markup, /确认采用 05:18(尚未验证)/);
|
||||
assert.match(markup, /aria-label="确认将 05:18 设为当前排盘时间;当前分钟尚未验证"/);
|
||||
assert.match(markup, /已记录 1 条经历/);
|
||||
assert.match(markup, /候选只用于继续验证/);
|
||||
assert.match(markup, /这一步不会自动采用候选/);
|
||||
assert.doesNotMatch(markup, /已记录 1 条经历|候选只用于继续验证|这一步不会自动采用候选/);
|
||||
assert.doesNotMatch(markup, /暂停,稍后继续|继续校正|放弃本次校正/);
|
||||
});
|
||||
|
||||
test("correction mode identifies its durable target, can be cancelled, and marks revised recaps", () => {
|
||||
test("an existing correction target can still be cancelled without rendering history management", () => {
|
||||
const revisedTurn = {
|
||||
...turn,
|
||||
evidenceRecap: [{ ...turn.evidenceRecap[0]!, isCorrection: true }],
|
||||
@@ -241,7 +236,7 @@ test("correction mode identifies its durable target, can be cancelled, and marks
|
||||
assert.match(markup, /正在更正/);
|
||||
assert.match(markup, /开始第一份长期工作/);
|
||||
assert.match(markup, /取消更正/);
|
||||
assert.match(markup, /(已修订)/);
|
||||
assert.doesNotMatch(markup, /(已修订)|已记录的经历|更正这条经历/);
|
||||
});
|
||||
|
||||
test("pending markup and responsive CSS expose accessibility contracts", () => {
|
||||
@@ -287,10 +282,12 @@ test("pending markup and responsive CSS expose accessibility contracts", () => {
|
||||
assert.match(css, /\.conversation\.is-rectification[^}]*padding-bottom:\s*0/);
|
||||
assert.match(css, /\.rectification-chat[^}]*height:\s*100%[^}]*display:\s*flex/);
|
||||
assert.match(css, /\.rectification-message-list[^}]*flex:\s*1[^}]*overflow-y:\s*auto/);
|
||||
assert.match(css, /\.rectification-message-list[^}]*scrollbar-color:\s*transparent transparent/);
|
||||
assert.match(css, /\.rectification-message-list[^}]*scrollbar-width:\s*thin/);
|
||||
assert.match(css, /\.rectification-message-list::\-webkit-scrollbar-thumb[^}]*background-clip:\s*padding-box/);
|
||||
assert.match(css, /\.rectification-message-list::\-webkit-scrollbar-thumb[^}]*background:\s*transparent[^}]*background-clip:\s*padding-box/);
|
||||
assert.match(css, /\.rectification-message-list\.is-scrollbar-visible::\-webkit-scrollbar-thumb[^}]*color-mix/);
|
||||
assert.match(css, /\.rectification-message-list::\-webkit-scrollbar-thumb:hover[^}]*color-mix/);
|
||||
assert.match(css, /\.rectification-message-details button[^}]*min-height:\s*44px/);
|
||||
assert.match(css, /\.rectification-correction-target button[^}]*min-height:\s*44px/);
|
||||
assert.match(css, /\.composer:focus-within[^}]*border-color:/);
|
||||
assert.match(css, /\.composer textarea[^}]*border:\s*0/);
|
||||
assert.match(css, /\.rectification-composer-wrap[^}]*position:\s*static/);
|
||||
@@ -298,8 +295,11 @@ test("pending markup and responsive CSS expose accessibility contracts", () => {
|
||||
assert.doesNotMatch(css, /\.conversational-domain-picker|\.conversational-event-date/);
|
||||
assert.doesNotMatch(css, /button\[aria-label\$="下一步建议"\]/);
|
||||
assert.match(css, /@media\s*\(prefers-reduced-motion:\s*reduce\)/);
|
||||
assert.match(css, /@media\s*\(max-width:\s*430px\)[\s\S]*\.rectification-message-details/);
|
||||
assert.doesNotMatch(css, /\.rectification-message-details/);
|
||||
assert.doesNotMatch(component, /确认放弃且不应用候选|本轮技术回执/);
|
||||
assert.match(component, /onPointerMove=\{revealScrollbar\}/);
|
||||
assert.match(component, /onScroll=\{revealScrollbar\}/);
|
||||
assert.match(component, /classList\.remove\("is-scrollbar-visible"\)/);
|
||||
assert.match(component, /controller\.answer\(undefined, text\)/);
|
||||
assert.match(component, /event\.key === "Enter" && !event\.shiftKey/);
|
||||
assert.match(component, /onPendingChange/);
|
||||
@@ -802,8 +802,9 @@ test("real Chromium at 390px verifies layout, keyboard focus, streamlined contro
|
||||
);
|
||||
await cdp.evaluate("globalThis.__rectificationHarness.setTurn('activeA1')");
|
||||
await waitFor(
|
||||
() => cdp?.evaluate<boolean>(`document.body.textContent.includes('当前候选 05:18')
|
||||
&& document.body.textContent.includes('2021-07 · 开始第一份长期工作')`) ?? Promise.resolve(false),
|
||||
() => cdp?.evaluate<boolean>(`document.body.textContent.includes('当前判断')
|
||||
&& !document.body.textContent.includes('当前候选 05:18')
|
||||
&& !document.body.textContent.includes('已记录的经历')`) ?? Promise.resolve(false),
|
||||
"streamlined async initial turn",
|
||||
);
|
||||
|
||||
@@ -833,23 +834,6 @@ test("real Chromium at 390px verifies layout, keyboard focus, streamlined contro
|
||||
assert.equal(layout.selectCount, 0, "language-first flow should not render date selects");
|
||||
assert.equal(layout.domainChoiceCount, 0, "language-first flow should not render domain buttons");
|
||||
|
||||
await cdp.evaluate("document.querySelector('.rectification-message-details').open = true");
|
||||
await cdp.evaluate("document.querySelector('[aria-label^=\"更正这条经历\"]').click()");
|
||||
await waitFor(
|
||||
() => cdp?.evaluate<boolean>(`(() => {
|
||||
const textarea = document.getElementById('conversational-rectification-answer');
|
||||
return document.body.textContent.includes('正在更正')
|
||||
&& document.body.textContent.includes('开始第一份长期工作')
|
||||
&& textarea?.value === '';
|
||||
})()`) ?? Promise.resolve(false),
|
||||
"durable correction target selection without polluting the new answer",
|
||||
);
|
||||
await cdp.evaluate("[...document.querySelectorAll('button')].find((button) => button.textContent.includes('取消更正')).click()");
|
||||
await waitFor(
|
||||
() => cdp?.evaluate<boolean>("!document.body.textContent.includes('正在更正') && document.getElementById('conversational-rectification-answer').value === ''") ?? Promise.resolve(false),
|
||||
"correction cancellation",
|
||||
);
|
||||
|
||||
const mistakenAnswer = "2020年9月离职写错了";
|
||||
await cdp.evaluate(`(() => {
|
||||
const textarea = document.getElementById('conversational-rectification-answer');
|
||||
@@ -874,8 +858,9 @@ test("real Chromium at 390px verifies layout, keyboard focus, streamlined contro
|
||||
await waitFor(
|
||||
() => cdp?.evaluate<boolean>(`(() => {
|
||||
const text = document.body.textContent;
|
||||
return text.includes('当前候选')
|
||||
&& !text.includes('候选时间')
|
||||
return text.includes('当前判断')
|
||||
&& !text.includes('当前候选 05:18')
|
||||
&& !text.includes('已记录的经历')
|
||||
&& !text.includes('本轮技术回执')
|
||||
&& !text.includes('暂停,稍后继续')
|
||||
&& !text.includes('放弃本次校正')
|
||||
|
||||
@@ -68,7 +68,7 @@ test("visible rectification copy does not replace a tailored Agent answer with a
|
||||
assert.match(narrative, /事业转折/);
|
||||
});
|
||||
|
||||
test("the rectification chat renders the controller's alternating message history", () => {
|
||||
test("the rectification chat renders alternating messages without a separate evidence panel", () => {
|
||||
const source = readFileSync(
|
||||
new URL("../src/components/conversational-birth-time-rectification.tsx", import.meta.url),
|
||||
"utf8",
|
||||
@@ -76,9 +76,5 @@ test("the rectification chat renders the controller's alternating message histor
|
||||
|
||||
assert.match(source, /controller\.messages/);
|
||||
assert.match(source, /controller\.messages[\s\S]*?\.map\(\(message\)/);
|
||||
const messageHistoryIndex = source.indexOf("controller.messages");
|
||||
const progressDetailsIndex = source.indexOf("rectification-progress-details");
|
||||
const evidenceRecapIndex = source.indexOf("turn.evidenceRecap.map");
|
||||
assert.ok(messageHistoryIndex >= 0 && messageHistoryIndex < progressDetailsIndex);
|
||||
assert.ok(evidenceRecapIndex > progressDetailsIndex);
|
||||
assert.doesNotMatch(source, /rectification-progress-details|turn\.evidenceRecap\.map|更正这条经历/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user