Files
NianToB/tests/unit/chat-message.test.tsx
2026-05-13 23:52:11 +08:00

147 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, expect, it } from 'vitest';
import { render, screen } from '@testing-library/react';
import { ChatMessage } from '@/pages/Chat/ChatMessage';
import type { RawMessage } from '@/stores/chat';
import { appendBusinessResponseGuidance } from '../../shared/business-guidance';
describe('ChatMessage attachment dedupe', () => {
it('keeps attachment-only assistant replies visible even when process attachments are suppressed', () => {
const message: RawMessage = {
role: 'assistant',
content: [],
_attachedFiles: [
{
fileName: 'artifact.png',
mimeType: 'image/png',
fileSize: 0,
preview: '/tmp/artifact.png',
filePath: '/tmp/artifact.png',
source: 'tool-result',
},
],
};
render(
<ChatMessage
message={message}
suppressProcessAttachments
/>,
);
expect(screen.getByAltText('artifact.png')).toBeInTheDocument();
});
});
describe('ChatMessage LaTeX rendering', () => {
it('renders inline `$...$` math with KaTeX', () => {
const message: RawMessage = {
role: 'assistant',
content: 'Mass-energy equivalence: $E=mc^2$ is famous.',
};
const { container } = render(<ChatMessage message={message} />);
expect(container.querySelector('.katex')).not.toBeNull();
});
it('renders display `$$...$$` math as a block', () => {
const message: RawMessage = {
role: 'assistant',
content: 'Definite integral:\n\n$$\n\\int_0^1 x\\,dx = \\frac{1}{2}\n$$\n',
};
const { container } = render(<ChatMessage message={message} />);
expect(container.querySelector('.katex-display')).not.toBeNull();
});
it('renders `\\(...\\)` inline math (OpenAI-style escaping)', () => {
const message: RawMessage = {
role: 'assistant',
content: 'Quadratic formula: \\(x = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}\\).',
};
const { container } = render(<ChatMessage message={message} />);
expect(container.querySelector('.katex')).not.toBeNull();
expect(container.querySelector('.katex-display')).toBeNull();
});
it('renders `\\[...\\]` block math (OpenAI-style escaping)', () => {
const message: RawMessage = {
role: 'assistant',
content: 'Sum formula:\n\n\\[\\sum_{i=1}^n i = \\frac{n(n+1)}{2}\\]',
};
const { container } = render(<ChatMessage message={message} />);
expect(container.querySelector('.katex-display')).not.toBeNull();
});
it('does not rewrite `\\(` inside code fences', () => {
const message: RawMessage = {
role: 'assistant',
content: 'Code sample:\n\n```\nprintf("\\(hello\\)")\n```\n',
};
const { container } = render(<ChatMessage message={message} />);
expect(container.textContent).toContain('\\(hello\\)');
expect(container.querySelector('.katex')).toBeNull();
});
});
describe('ChatMessage business answer rendering', () => {
it('renders a business summary panel for structured operational replies', () => {
const message: RawMessage = {
role: 'assistant',
content: [
'状态:需处理,携程渠道房态与 PMS 不一致。',
'依据:携程 0508 房型显示可售 3 间PMS 为 0 间。',
'影响:可能产生超售风险。',
'下一步:请先暂停该房型自动售卖,并复核渠道登录态。',
].join('\n'),
};
render(<ChatMessage message={message} />);
const panel = screen.getByTestId('business-answer-panel');
expect(panel).toHaveTextContent('业务摘要');
expect(panel).toHaveTextContent('需处理,携程渠道房态与 PMS 不一致');
expect(panel).toHaveTextContent('携程 0508 房型显示可售 3 间');
expect(panel).toHaveTextContent('请先暂停该房型自动售卖');
});
it('does not add the business panel to ordinary assistant chat', () => {
const message: RawMessage = {
role: 'assistant',
content: '你好,我可以帮你处理问题。',
};
render(<ChatMessage message={message} />);
expect(screen.queryByTestId('business-answer-panel')).not.toBeInTheDocument();
});
});
describe('ChatMessage markdown rendering', () => {
it('hides legacy injected business guidance from visible user messages', () => {
const message: RawMessage = {
role: 'user',
content: appendBusinessResponseGuidance('会话中的 markdown 结构化,表格也可以加强 UI 渲染'),
};
render(<ChatMessage message={message} />);
expect(screen.getByText('会话中的 markdown 结构化,表格也可以加强 UI 渲染')).toBeInTheDocument();
expect(screen.queryByText(/YINIAN_BUSINESS_RESPONSE_GUIDANCE/)).not.toBeInTheDocument();
expect(screen.queryByText(/请按智念业务员工/)).not.toBeInTheDocument();
});
it('renders markdown tables inside the enhanced table shell', () => {
const message: RawMessage = {
role: 'assistant',
content: [
'| 渠道 | 房型 | 状态 |',
'| --- | --- | --- |',
'| 携程 | 豪华大床房 | 需复核 |',
].join('\n'),
};
render(<ChatMessage message={message} />);
expect(screen.getByTestId('markdown-table-scroll')).toBeInTheDocument();
expect(screen.getByTestId('markdown-table')).toHaveTextContent('豪华大床房');
});
});