98 lines
3.4 KiB
TypeScript
98 lines
3.4 KiB
TypeScript
import { describe, expect, mock, test } from "bun:test";
|
|
import { screen, waitFor } from "@testing-library/react";
|
|
import { createElement } from "react";
|
|
|
|
import { HighlightBlock } from "../../../../src/web/features/chat/parts/HighlightBlock";
|
|
import { renderWithProviders } from "../../test-utils";
|
|
|
|
describe("HighlightBlock JSON 高亮", () => {
|
|
test("非流式状态渲染 shiki 高亮 HTML", async () => {
|
|
const code = JSON.stringify({ key: "value" }, null, 2);
|
|
|
|
const { container } = renderWithProviders(
|
|
createElement(HighlightBlock, { code, isStreaming: false, lang: "json" }),
|
|
);
|
|
|
|
expect(screen.getByText("json")).toBeTruthy();
|
|
|
|
await waitFor(() => {
|
|
expect(container.querySelector(".code-block-body")).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
test("流式状态渲染纯 <pre><code> 无高亮", () => {
|
|
const code = JSON.stringify({ key: "value" }, null, 2);
|
|
|
|
const { container } = renderWithProviders(createElement(HighlightBlock, { code, isStreaming: true, lang: "json" }));
|
|
|
|
const pre = container.querySelector("pre.code-block");
|
|
expect(pre).toBeTruthy();
|
|
expect(pre!.textContent).toContain("key");
|
|
expect(container.querySelector(".code-block-header")).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("HighlightBlock 复制按钮", () => {
|
|
test("非流式状态显示复制按钮", () => {
|
|
const code = "const x = 1;";
|
|
|
|
renderWithProviders(createElement(HighlightBlock, { code, isStreaming: false, lang: "text" }));
|
|
|
|
expect(screen.getByText("text")).toBeTruthy();
|
|
const buttons = screen.getAllByRole("button");
|
|
expect(buttons.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
test("复制按钮调用 clipboard.writeText", () => {
|
|
const code = JSON.stringify({ a: 1 }, null, 2);
|
|
const writeTextMock = mock(() => Promise.resolve());
|
|
Object.defineProperty(navigator, "clipboard", {
|
|
value: { writeText: writeTextMock },
|
|
writable: true,
|
|
configurable: true,
|
|
});
|
|
|
|
renderWithProviders(createElement(HighlightBlock, { code, isStreaming: false, lang: "json" }));
|
|
|
|
const button = screen.getByRole("button");
|
|
button.click();
|
|
|
|
expect(writeTextMock).toHaveBeenCalledWith(code);
|
|
});
|
|
});
|
|
|
|
describe("HighlightBlock 纯文本", () => {
|
|
test("lang=text 时头部显示 text", () => {
|
|
renderWithProviders(createElement(HighlightBlock, { code: "hello world", isStreaming: false, lang: "text" }));
|
|
|
|
expect(screen.getByText("text")).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
describe("HighlightBlock 边界情况", () => {
|
|
test("code 为空时渲染空代码块不触发异步高亮", () => {
|
|
const { container } = renderWithProviders(
|
|
createElement(HighlightBlock, { code: "", isStreaming: false, lang: "json" }),
|
|
);
|
|
|
|
expect(container.querySelector(".code-block")).toBeTruthy();
|
|
expect(container.querySelector("code")).toBeTruthy();
|
|
expect(container.querySelector("code")!.textContent).toBe("");
|
|
});
|
|
|
|
test("流式切换到非流式后触发高亮", async () => {
|
|
const code = JSON.stringify({ x: 1 }, null, 2);
|
|
const { container, rerender } = renderWithProviders(
|
|
createElement(HighlightBlock, { code, isStreaming: true, lang: "json" }),
|
|
);
|
|
|
|
expect(container.querySelector("pre.code-block")).toBeTruthy();
|
|
|
|
rerender(createElement(HighlightBlock, { code, isStreaming: false, lang: "json" }));
|
|
|
|
await waitFor(() => {
|
|
expect(container.querySelector(".code-block-body")).toBeTruthy();
|
|
});
|
|
});
|
|
});
|