import { render, screen, fireEvent } from '@testing-library/react'; import { vi, test, expect, beforeEach } from 'vitest'; import FileExplorer from '../../src/components/FileExplorer'; import { listDocuments } from '../../src/api/client'; vi.mock('../../src/api/client'); beforeEach(() => { vi.mocked(listDocuments).mockReset(); }); test('renders folders and files returned by listDocuments for the root path', async () => { vi.mocked(listDocuments).mockResolvedValue({ folders: ['产品文档'], files: [{ key: '需求说明.md', name: '需求说明.md', size: 100, modifiedAt: '2026-08-01T10:00:00Z' }], }); render(); expect(await screen.findByText('产品文档')).toBeInTheDocument(); expect(await screen.findByText('需求说明.md')).toBeInTheDocument(); expect(listDocuments).toHaveBeenCalledWith(''); }); test('clicking a file calls onSelectFile with its key', async () => { vi.mocked(listDocuments).mockResolvedValue({ folders: [], files: [{ key: '架构设计.md', name: '架构设计.md', size: 200, modifiedAt: '2026-08-01T10:00:00Z' }], }); const onSelectFile = vi.fn(); render(); const fileRow = await screen.findByText('架构设计.md'); fireEvent.click(fileRow); expect(onSelectFile).toHaveBeenCalledWith('架构设计.md'); }); test('clicking a folder loads and shows its nested contents', async () => { vi.mocked(listDocuments).mockImplementation((path: string) => { if (path === '') { return Promise.resolve({ folders: ['产品文档'], files: [] }); } if (path === '产品文档') { return Promise.resolve({ folders: [], files: [{ key: '产品文档/架构设计.md', name: '架构设计.md', size: 300, modifiedAt: '2026-08-01T10:00:00Z' }], }); } return Promise.resolve({ folders: [], files: [] }); }); render(); const folderRow = await screen.findByText('产品文档'); fireEvent.click(folderRow); expect(await screen.findByText('架构设计.md')).toBeInTheDocument(); expect(listDocuments).toHaveBeenCalledWith('产品文档'); }); test('shows an error message when listDocuments rejects', async () => { vi.mocked(listDocuments).mockRejectedValue(new Error('network error')); render(); expect(await screen.findByTestId('file-explorer-error')).toBeInTheDocument(); });