import { describe, expect, it, vi } from "vitest"; import { render } from "@testing-library/react"; import { MantineProvider } from "@mantine/core"; import type { UIMessage } from "@ai-sdk/react"; // Stub react-i18next (the component reads `useTranslation`). Mirrors the other // message-item specs. vi.mock("react-i18next", () => ({ useTranslation: () => ({ t: (key: string) => key }), })); import MessageItem from "./message-item"; import { messageSignature } from "@/features/ai-chat/utils/message-signature.ts"; // The REAL canonical renderer (NOT the spy the memo test installs): this file // exercises the actual markdown output so the visual-regression assertions below // compare against genuine HTML (incl. the schema's `
` wrappers).
import { renderChatMarkdown } from "@/features/ai-chat/utils/markdown.ts";
import classes from "./ai-chat.module.css";
const msg = (
parts: UIMessage["parts"],
extra?: Partial ` case
// the scoped CSS tightens), inline emphasis, and multiple paragraphs.
const ANSWER = [
"# Заголовок",
"",
"Первый абзац с **жирным** и `кодом`.",
"",
"- пункт один",
"- пункт два",
"",
"Второй абзац.",
].join("\n");
describe("MessageItem final render — visual parity with the canonical pipeline", () => {
it("a finalized text part renders exactly renderChatMarkdown(text)", () => {
const { container } = renderRow(
msg([{ type: "text", text: ANSWER, state: "done" }]),
);
const block = container.querySelector(`.${classes.markdown}`);
expect(block).not.toBeNull();
// Byte-for-byte the canonical output (the SAME whole-text pass the pre-#492
// MarkdownPart produced), including ` …