| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- import { fireEvent, render, screen, waitFor } from '@testing-library/react';
- import { beforeEach, expect, test, vi } from 'vitest';
- import BusinessAssistantPage from '@/pages/BusinessAssistant';
- import { apiRequest } from '@/services/api';
- vi.mock('@/services/api', () => ({
- apiRequest: vi.fn(),
- jsonOptions: vi.fn((method, body) => ({ method, body: JSON.stringify(body) })),
- }));
- vi.mock('@/contexts/BotAccess', () => ({
- useBotAccess: () => ({
- bot: {
- bot_id: 'primary',
- label: 'Test Bot',
- enabled: true,
- bot_token_configured: true,
- sudo_users_id: [],
- log_group_id: '0',
- gban_log_group_id: '0',
- message_dump_chat: '0',
- role_ids: ['business_assistant_manager'],
- permissions: ['business_assistant.manage'],
- identity: {
- id: '999',
- username: 'business_bot',
- name: 'Business Bot',
- can_connect_to_business: true,
- },
- business_assistant: {
- base_url: 'https://models.example.com/v1',
- api_key_configured: true,
- model: 'support-model',
- timeout_seconds: 30,
- max_output_tokens: 600,
- configured: true,
- },
- ready_to_connect: true,
- runtime: { state: 'running' },
- },
- }),
- }));
- const settings = {
- connection_id: 'conn-a',
- assistant_enabled: true,
- system_prompt: '只依据知识库回答。',
- language: 'zh-CN',
- tone: 'professional',
- account_daily_limit: 200,
- customer_daily_limit: 20,
- human_pause_hours: 24,
- notification_destination: 'both',
- ops_group_id: '-100123',
- timezone: 'Asia/Shanghai',
- digest_enabled: false,
- digest_time: '09:00',
- handoff_message: '请稍候,已转人工。',
- unsupported_message: '该消息需要人工处理。',
- };
- beforeEach(() => {
- vi.mocked(apiRequest).mockClear();
- vi.mocked(apiRequest).mockImplementation(async (path) => {
- if (path === '/business-assistant/status') {
- return {
- polling_state: 'running',
- business_mode_supported: true,
- webhook_conflict: false,
- webhook_url: '',
- model_configured: true,
- usage: { ai_calls: 8, customers: 3, conversations: 3, handoffs: 1, human_paused: 1 },
- };
- }
- if (path.startsWith('/business-assistant/connections')) {
- return {
- items: [
- {
- connection_id: 'conn-a',
- user: { id: '900', username: 'owner', first_name: '店主' },
- user_chat_id: '900',
- rights: { can_reply: true, can_read_messages: true },
- is_enabled: true,
- last_event_at: '2026-08-14T08:00:00Z',
- settings,
- },
- ],
- total: 1,
- page: 1,
- page_size: 100,
- };
- }
- if (path.startsWith('/business-assistant/settings')) return settings;
- if (path.startsWith('/business-assistant/knowledge')) {
- return {
- items: [
- {
- entry_id: 'entry-1',
- connection_id: 'conn-a',
- question: '营业时间是什么?',
- aliases: ['几点营业'],
- keywords: ['营业时间'],
- answer: '每天 09:00 至 18:00 营业。',
- tags: ['营业'],
- priority: 10,
- enabled: true,
- },
- ],
- total: 1,
- page: 1,
- page_size: 20,
- };
- }
- if (path.startsWith('/business-assistant/conversations')) {
- return {
- items: [
- {
- conversation_id: 'conversation-1',
- connection_id: 'conn-a',
- chat_id: '501',
- customer: { id: '501', first_name: '客户甲' },
- status: 'handoff',
- summary: '客户询问退款。',
- handoff_reason: 'sensitive_request',
- last_message_at: '2026-08-14T08:01:00Z',
- },
- ],
- total: 1,
- page: 1,
- page_size: 20,
- };
- }
- if (path.startsWith('/business-assistant/usage')) {
- return { ai_calls: 8, customers: 3, conversations: 3, handoffs: 1, human_paused: 1 };
- }
- throw new Error(`Unexpected request: ${path}`);
- });
- });
- test('展示运行状态、连接权限,并用最新搜索词查询知识库', async () => {
- render(<BusinessAssistantPage />);
- expect(screen.getByRole('heading', { name: '智能接待' })).toBeInTheDocument();
- expect((await screen.findAllByText('店主')).length).toBeGreaterThan(0);
- expect(screen.getByText('允许回复')).toBeInTheDocument();
- expect(screen.getByText('允许标记已读')).toBeInTheDocument();
- fireEvent.click(await screen.findByRole('tab', { name: /知识库/ }));
- expect(await screen.findByText('营业时间是什么?')).toBeInTheDocument();
- const search = screen.getByLabelText('搜索知识库');
- fireEvent.change(search, { target: { value: '配送' } });
- fireEvent.keyDown(search, { key: 'Enter', code: 'Enter' });
- await waitFor(() => {
- expect(
- vi.mocked(apiRequest).mock.calls.some(([path]) =>
- String(path).includes('query=%E9%85%8D%E9%80%81'),
- ),
- ).toBe(true);
- });
- });
|