88 lines
3.0 KiB
TypeScript
88 lines
3.0 KiB
TypeScript
import { describe, expect, mock, test } from "bun:test";
|
|
import { screen, waitFor } from "@testing-library/react";
|
|
import { createElement } from "react";
|
|
|
|
import { renderWithProviders } from "../../test-utils";
|
|
|
|
void mock.module("../../../../src/web/shared/hooks/use-is-dark", () => ({
|
|
useIsDark: () => false,
|
|
}));
|
|
|
|
void mock.module("shiki", () => ({
|
|
codeToHtml: (code: string, options: { lang: string; theme: string }) =>
|
|
Promise.resolve(`<pre class="shiki ${options.theme}"><code>${code}</code></pre>`),
|
|
}));
|
|
|
|
import { CodeBlock } from "../../../../src/web/features/chat/parts/CodeBlock";
|
|
|
|
function createCodeChild(text: string, lang = "javascript"): React.ReactElement {
|
|
return createElement("code", { className: `language-${lang}` }, text);
|
|
}
|
|
|
|
describe("CodeBlock 流式期间纯文本渲染", () => {
|
|
test("流式时渲染为纯文本 pre", () => {
|
|
const child = createCodeChild("const x = 1;");
|
|
|
|
renderWithProviders(createElement(CodeBlock, { children: child, isStreaming: true }));
|
|
|
|
const pre = document.querySelector(".code-block");
|
|
expect(pre).toBeTruthy();
|
|
expect(pre!.tagName).toBe("PRE");
|
|
expect(screen.getByText("const x = 1;")).toBeTruthy();
|
|
expect(document.querySelector(".code-block-header")).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("CodeBlock 非流式高亮渲染", () => {
|
|
test("非流式时显示语言标签和复制按钮", () => {
|
|
const child = createCodeChild("const x = 1;");
|
|
|
|
renderWithProviders(createElement(CodeBlock, { children: child, isStreaming: false }));
|
|
|
|
expect(document.querySelector(".code-block-header")).toBeTruthy();
|
|
expect(document.querySelector(".code-block-lang")).toBeTruthy();
|
|
expect(screen.getByText("javascript")).toBeTruthy();
|
|
});
|
|
|
|
test("非流式时异步高亮代码", async () => {
|
|
const child = createCodeChild("const x = 1;");
|
|
|
|
renderWithProviders(createElement(CodeBlock, { children: child, isStreaming: false }));
|
|
|
|
await waitFor(() => {
|
|
const body = document.querySelector(".code-block-body");
|
|
expect(body).toBeTruthy();
|
|
expect(body!.innerHTML).toContain("const x = 1;");
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("CodeBlock 复制按钮", () => {
|
|
test("复制按钮存在且可点击", () => {
|
|
const child = createCodeChild("test code");
|
|
|
|
renderWithProviders(createElement(CodeBlock, { children: child, isStreaming: false }));
|
|
|
|
const button = document.querySelector(".code-block-header button");
|
|
expect(button).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
describe("CodeBlock 语言标签显示", () => {
|
|
test("常见语言显示正确", () => {
|
|
const child = createCodeChild("print('hello')", "python");
|
|
|
|
renderWithProviders(createElement(CodeBlock, { children: child, isStreaming: false }));
|
|
|
|
expect(screen.getByText("python")).toBeTruthy();
|
|
});
|
|
|
|
test("无语言时显示 text", () => {
|
|
const child = createElement("code", { className: "" }, "plain text");
|
|
|
|
renderWithProviders(createElement(CodeBlock, { children: child, isStreaming: false }));
|
|
|
|
expect(screen.getByText("text")).toBeTruthy();
|
|
});
|
|
});
|