旧的结构化报告页已由另一单删除,标识留在现在用的阅读页。测试不再读取那个文件。更新日志和 Bug 历史两边都保留。 自测:tsc 退出码 0;lint 0 error、123 warning;修复单点名的 3 个测试 7 通过、0 失败、0 取消。 Co-Authored-By: Grok (agent loop)
71 lines
3.1 KiB
TypeScript
71 lines
3.1 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { createElement, createRef } from "react";
|
|
import { readFileSync } from "node:fs";
|
|
import test from "node:test";
|
|
import { renderToStaticMarkup } from "react-dom/server";
|
|
|
|
import { ChatComposer } from "../src/components/chat-composer.tsx";
|
|
import { PersonalReportMarkdownView } from "../src/components/personal-report/personal-report-markdown-view.tsx";
|
|
import {
|
|
CHAT_AI_NOTICE_EN,
|
|
CHAT_AI_NOTICE_ZH,
|
|
REPORT_AI_NOTICE_EN,
|
|
REPORT_AI_NOTICE_ZH,
|
|
} from "../src/lib/ai-generated-notice.ts";
|
|
|
|
const styles = readFileSync(new URL("../src/app/globals.css", import.meta.url), "utf8");
|
|
const page = readFileSync(new URL("../src/app/(app)/page.tsx", import.meta.url), "utf8");
|
|
const rectification = readFileSync(new URL("../src/components/rectification-agentic-chat.tsx", import.meta.url), "utf8");
|
|
|
|
function composerHtml(): string {
|
|
return renderToStaticMarkup(createElement(ChatComposer, {
|
|
inputRef: createRef<HTMLTextAreaElement>(),
|
|
value: "",
|
|
inputLabel: "输入你的问题",
|
|
placeholder: "想聊什么都可以",
|
|
maxLength: 500,
|
|
inputDisabled: false,
|
|
submitLabel: "发送",
|
|
submitBlocked: false,
|
|
stopVisible: false,
|
|
stopLabel: "停止回答",
|
|
stopTitle: "停止回答",
|
|
onSubmit() {},
|
|
onChange() {},
|
|
onKeyDown() {},
|
|
onStop() {},
|
|
}));
|
|
}
|
|
|
|
test("both chat surfaces share the composer notice, under the field and not over the send control", () => {
|
|
assert.equal(CHAT_AI_NOTICE_ZH, "回答由 AI 生成,仅供参考,不构成医疗、法律或投资建议。");
|
|
assert.equal(CHAT_AI_NOTICE_EN, "AI-generated. For reference only; not medical, legal or financial advice.");
|
|
const html = composerHtml();
|
|
const noticeAt = html.indexOf("composer-ai-notice");
|
|
const sendAt = html.indexOf("发送");
|
|
assert.ok(noticeAt > sendAt, "the notice follows the send control");
|
|
assert.match(html, new RegExp(CHAT_AI_NOTICE_ZH));
|
|
assert.match(page, /<ChatComposer/);
|
|
assert.match(rectification, /<ChatComposer/);
|
|
assert.doesNotMatch(page, /CHAT_AI_NOTICE_ZH|composer-ai-notice/);
|
|
assert.doesNotMatch(rectification, /CHAT_AI_NOTICE_ZH|composer-ai-notice/);
|
|
assert.match(styles, /\.composer-ai-notice\s*\{[^}]*white-space:\s*nowrap/);
|
|
assert.match(styles, /\.composer-ai-notice\s*\{[^}]*overflow:\s*hidden/);
|
|
assert.doesNotMatch(styles, /\.composer-footer\s*\{/);
|
|
});
|
|
|
|
test("report readers show the AI notice in Chinese and English under the title", () => {
|
|
assert.equal(REPORT_AI_NOTICE_ZH, "本报告由 AI 生成,仅供参考。");
|
|
assert.equal(REPORT_AI_NOTICE_EN, "This report is AI-generated and for reference only.");
|
|
const chinese = renderToStaticMarkup(createElement(PersonalReportMarkdownView, {
|
|
markdown: "# 虚构报告\n\n一段说明。",
|
|
language: "zh",
|
|
}));
|
|
const english = renderToStaticMarkup(createElement(PersonalReportMarkdownView, {
|
|
markdown: "# Fictional report\n\nA paragraph.",
|
|
language: "en",
|
|
}));
|
|
assert.ok(chinese.indexOf("<h1>") < chinese.indexOf(REPORT_AI_NOTICE_ZH));
|
|
assert.match(english, new RegExp(REPORT_AI_NOTICE_EN.replaceAll(".", "\\.")));
|
|
});
|