import { render, screen } from '@testing-library/react'; import { describe, it, expect, vi } from 'vitest'; import { StatsTable } from '@/pages/Stats/StatsTable'; import type { Provider, UsageStats } from '@/types'; const mockProviders: Provider[] = [ { id: 'openai', name: 'OpenAI', apiKey: 'sk-test', baseUrl: 'https://api.openai.com/v1', enabled: true, createdAt: '2024-01-01T00:00:00Z', updatedAt: '2024-01-01T00:00:00Z', }, { id: 'anthropic', name: 'Anthropic', apiKey: 'sk-ant-test', baseUrl: 'https://api.anthropic.com', enabled: true, createdAt: '2024-01-02T00:00:00Z', updatedAt: '2024-01-02T00:00:00Z', }, ]; const mockStats: UsageStats[] = [ { id: '1', providerId: 'openai', modelName: 'gpt-4o', requestCount: 100, date: '2024-01-15', }, { id: '2', providerId: 'anthropic', modelName: 'claude-3-opus', requestCount: 50, date: '2024-01-15', }, ]; const defaultProps = { providers: mockProviders, stats: mockStats, loading: false, providerId: undefined, modelName: undefined, dateRange: null, onProviderIdChange: vi.fn(), onModelNameChange: vi.fn(), onDateRangeChange: vi.fn(), }; describe('StatsTable', () => { it('renders stats table with data', () => { render(); expect(screen.getByText('gpt-4o')).toBeInTheDocument(); expect(screen.getByText('claude-3-opus')).toBeInTheDocument(); const dateCells = screen.getAllByText('2024-01-15'); expect(dateCells.length).toBe(2); expect(screen.getByText('100')).toBeInTheDocument(); expect(screen.getByText('50')).toBeInTheDocument(); }); it('shows provider name from providers prop instead of providerId', () => { render(); expect(screen.getByText('OpenAI')).toBeInTheDocument(); const allAnthropic = screen.getAllByText('Anthropic'); expect(allAnthropic.length).toBeGreaterThanOrEqual(1); }); it('renders filter controls with Select, Input, and DatePicker', () => { render(); const selects = document.querySelectorAll('.ant-select'); expect(selects.length).toBeGreaterThanOrEqual(1); const modelInput = screen.getByPlaceholderText('模型名称'); expect(modelInput).toBeInTheDocument(); expect(screen.getByText('所有供应商')).toBeInTheDocument(); const rangePicker = document.querySelector('.ant-picker-range'); expect(rangePicker).toBeInTheDocument(); }); it('renders table headers correctly', () => { render(); expect(screen.getAllByText('供应商').length).toBeGreaterThanOrEqual(1); expect(screen.getAllByText('模型').length).toBeGreaterThanOrEqual(1); expect(screen.getAllByText('日期').length).toBeGreaterThanOrEqual(1); expect(screen.getAllByText('请求数').length).toBeGreaterThanOrEqual(1); }); it('falls back to providerId when provider not found in providers prop', () => { const limitedProviders = [mockProviders[0]]; render(); expect(screen.getByText('OpenAI')).toBeInTheDocument(); expect(screen.getByText('anthropic')).toBeInTheDocument(); }); it('renders with empty stats data', () => { render(); expect(screen.getAllByText('供应商').length).toBeGreaterThanOrEqual(1); expect(screen.getAllByText('模型').length).toBeGreaterThanOrEqual(1); }); it('shows loading state', () => { render(); expect(document.querySelector('.ant-spin')).toBeInTheDocument(); }); it('shows custom empty text when stats data is empty', () => { render(); expect(screen.getByText('暂无统计数据')).toBeInTheDocument(); }); });