159 lines
4.1 KiB
TypeScript
159 lines
4.1 KiB
TypeScript
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: () => <div>navbar</div>,
|
|
}));
|
|
|
|
vi.mock('../../components/LeftSidebar', () => ({
|
|
default: ({
|
|
onUploadClick,
|
|
onRequireAuth,
|
|
canUploadAnonymously,
|
|
}: {
|
|
onUploadClick: () => void;
|
|
onRequireAuth: () => void;
|
|
canUploadAnonymously: boolean;
|
|
}) => (
|
|
<div>
|
|
<button onClick={onUploadClick}>open-upload</button>
|
|
<button onClick={onRequireAuth}>open-auth</button>
|
|
<span>{canUploadAnonymously ? 'guest-allowed' : 'guest-blocked'}</span>
|
|
</div>
|
|
),
|
|
}));
|
|
|
|
vi.mock('../../components/FilePreview', () => ({
|
|
default: ({ file }: { file: { id: string } | null }) => <div>{file ? `preview:${file.id}` : 'preview-empty'}</div>,
|
|
}));
|
|
|
|
vi.mock('../../components/ResultPanel', () => ({
|
|
default: () => <div>result</div>,
|
|
}));
|
|
|
|
vi.mock('../../components/UploadModal', () => ({
|
|
default: () => <div>upload-modal</div>,
|
|
}));
|
|
|
|
vi.mock('../../components/UserGuide', () => ({
|
|
default: () => null,
|
|
}));
|
|
|
|
vi.mock('../../components/AuthModal', () => ({
|
|
default: () => <div>auth-modal</div>,
|
|
}));
|
|
|
|
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(<App />);
|
|
|
|
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(<App />);
|
|
|
|
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(<App />);
|
|
|
|
await waitFor(() => {
|
|
expect(uploadService.getTaskList).toHaveBeenCalled();
|
|
});
|
|
|
|
expect(screen.getByText('preview-empty')).toBeInTheDocument();
|
|
expect(screen.queryByText('preview:task-1')).not.toBeInTheDocument();
|
|
});
|
|
});
|