import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import App from '../../App'; import { uploadService } from '../../lib/uploadService'; const { useAuthMock } = vi.hoisted(() => ({ useAuthMock: vi.fn(), })); vi.mock('../../contexts/AuthContext', () => ({ useAuth: () => useAuthMock(), })); vi.mock('../../contexts/LanguageContext', () => ({ useLanguage: () => ({ t: { common: { loading: '加载中', processing: '处理中' }, alerts: { taskTimeout: '超时', networkError: '网络错误', uploadFailed: '上传失败', }, }, }), })); vi.mock('../../lib/uploadService', () => ({ uploadService: { getTaskList: vi.fn().mockResolvedValue({ task_list: [], total: 0 }), getTaskResult: vi.fn(), calculateMD5: vi.fn(), uploadFile: vi.fn(), createRecognitionTask: vi.fn(), }, })); vi.mock('../../components/Navbar', () => ({ default: () =>
navbar
, })); vi.mock('../../components/LeftSidebar', () => ({ default: ({ onUploadClick, onRequireAuth, canUploadAnonymously, }: { onUploadClick: () => void; onRequireAuth: () => void; canUploadAnonymously: boolean; }) => (
{canUploadAnonymously ? 'guest-allowed' : 'guest-blocked'}
), })); vi.mock('../../components/FilePreview', () => ({ default: ({ file }: { file: { id: string } | null }) =>
{file ? `preview:${file.id}` : 'preview-empty'}
, })); vi.mock('../../components/ResultPanel', () => ({ default: () =>
result
, })); vi.mock('../../components/UploadModal', () => ({ default: () =>
upload-modal
, })); vi.mock('../../components/UserGuide', () => ({ default: () => null, })); vi.mock('../../components/AuthModal', () => ({ default: () =>
auth-modal
, })); describe('App anonymous usage limit', () => { beforeEach(() => { vi.clearAllMocks(); localStorage.clear(); localStorage.setItem('hasSeenGuide', 'true'); useAuthMock.mockReturnValue({ user: null, initializing: false, }); }); it('allows anonymous upload before the limit', () => { localStorage.setItem('texpixel_guest_usage_count', '2'); render(); expect(screen.getByText('guest-allowed')).toBeInTheDocument(); fireEvent.click(screen.getByText('open-upload')); expect(screen.getByText('upload-modal')).toBeInTheDocument(); }); it('forces login after three anonymous uses', () => { localStorage.setItem('texpixel_guest_usage_count', '3'); render(); expect(screen.getByText('guest-blocked')).toBeInTheDocument(); fireEvent.click(screen.getByText('open-upload')); expect(screen.getByText('auth-modal')).toBeInTheDocument(); expect(screen.queryByText('upload-modal')).not.toBeInTheDocument(); }); }); describe('App initial selection', () => { beforeEach(() => { vi.clearAllMocks(); localStorage.clear(); localStorage.setItem('hasSeenGuide', 'true'); }); it('does not auto-select the first history record on initial load', async () => { useAuthMock.mockReturnValue({ user: { id: 'u1' }, initializing: false, }); vi.mocked(uploadService.getTaskList).mockResolvedValue({ total: 1, task_list: [ { task_id: 'task-1', file_name: 'sample.png', status: 2, origin_url: 'https://example.com/sample.png', task_type: 'FORMULA', created_at: '2026-03-06T00:00:00Z', latex: '', markdown: 'content', mathml: '', mml: '', image_blob: '', docx_url: '', pdf_url: '', }, ], }); render(); await waitFor(() => { expect(uploadService.getTaskList).toHaveBeenCalled(); }); expect(screen.getByText('preview-empty')).toBeInTheDocument(); expect(screen.queryByText('preview:task-1')).not.toBeInTheDocument(); }); });