// Upload.test.jsx | |
import React from 'react'; | |
import { render, screen, waitFor, fireEvent } from '@testing-library/react'; | |
import { MemoryRouter, useNavigate, useLocation } from 'react-router-dom'; | |
import Upload from './Upload'; | |
import { getUserTorrents, deleteTorrent } from '../../api/personal'; | |
// Mock API 调用 | |
jest.mock('../../api/personal', () => ({ | |
getUserTorrents: jest.fn(), | |
deleteTorrent: jest.fn() | |
})); | |
// Mock react-router-dom hooks | |
jest.mock('react-router-dom', () => ({ | |
...jest.requireActual('react-router-dom'), | |
useNavigate: jest.fn(), | |
useLocation: jest.fn() | |
})); | |
// Mock window.confirm | |
global.confirm = jest.fn(() => true); | |
describe('Upload Component', () => { | |
const mockNavigate = jest.fn(); | |
const mockLocation = { | |
pathname: '/personal/upload', | |
state: { dashboardTab: 'uploads' } | |
}; | |
const mockTorrents = [ | |
{ | |
id: 1, | |
torrentName: 'Test Torrent 1', | |
formattedSize: '1.2 GB', | |
createTime: '2023-01-01T12:00:00Z', | |
downloadCount: 10 | |
}, | |
{ | |
id: 2, | |
torrentName: 'Test Torrent 2', | |
formattedSize: '2.5 GB', | |
createTime: '2023-01-02T12:00:00Z', | |
downloadCount: 5 | |
} | |
]; | |
beforeEach(() => { | |
useNavigate.mockReturnValue(mockNavigate); | |
useLocation.mockReturnValue(mockLocation); | |
jest.clearAllMocks(); | |
getUserTorrents.mockResolvedValue({ | |
records: mockTorrents, | |
total: 10 | |
}); | |
deleteTorrent.mockResolvedValue({ success: true }); | |
}); | |
it('应该正确加载并显示上传记录', async () => { | |
render( | |
<MemoryRouter> | |
<Upload /> | |
</MemoryRouter> | |
); | |
// 初始加载状态 | |
expect(screen.getByText('加载中...')).toBeInTheDocument(); | |
// 等待数据加载完成 | |
await waitFor(() => { | |
expect(screen.getByText('上传记录')).toBeInTheDocument(); | |
expect(screen.getByText('Test Torrent 1')).toBeInTheDocument(); | |
expect(screen.getByText('Test Torrent 2')).toBeInTheDocument(); | |
expect(screen.getByText('1.2 GB')).toBeInTheDocument(); | |
expect(screen.getByText('2.5 GB')).toBeInTheDocument(); | |
expect(screen.getAllByText('删除')).toHaveLength(2); | |
}); | |
}); | |
it('应该处理删除操作', async () => { | |
render( | |
<MemoryRouter> | |
<Upload /> | |
</MemoryRouter> | |
); | |
await waitFor(() => { | |
const deleteButtons = screen.getAllByText('删除'); | |
fireEvent.click(deleteButtons[0]); | |
}); | |
expect(global.confirm).toHaveBeenCalledWith('确定要删除这个种子吗?此操作不可撤销!'); | |
await waitFor(() => { | |
expect(deleteTorrent).toHaveBeenCalledWith(1); | |
expect(getUserTorrents).toHaveBeenCalledTimes(2); // 初始加载 + 删除后刷新 | |
}); | |
}); | |
it('应该处理分页变化', async () => { | |
render( | |
<MemoryRouter> | |
<Upload /> | |
</MemoryRouter> | |
); | |
await waitFor(() => { | |
const nextPageButton = screen.getByText('下一页'); | |
fireEvent.click(nextPageButton); | |
}); | |
await waitFor(() => { | |
expect(getUserTorrents).toHaveBeenLastCalledWith(2, 5); | |
}); | |
}); | |
it('应该处理直接跳转页码', async () => { | |
render( | |
<MemoryRouter> | |
<Upload /> | |
</MemoryRouter> | |
); | |
await waitFor(() => { | |
const pageInput = screen.getByRole('spinbutton'); | |
fireEvent.change(pageInput, { target: { value: '2' } }); | |
fireEvent.keyDown(pageInput, { key: 'Enter' }); | |
}); | |
await waitFor(() => { | |
expect(getUserTorrents).toHaveBeenLastCalledWith(2, 5); | |
}, { timeout: 1000 }); | |
}); | |
it('应该处理返回按钮点击', async () => { | |
render( | |
<MemoryRouter> | |
<Upload /> | |
</MemoryRouter> | |
); | |
await waitFor(() => { | |
const backButton = screen.getByText((content) => | |
content.includes('返回个人中心') | |
); | |
fireEvent.click(backButton); | |
expect(mockNavigate).toHaveBeenCalledWith('/personal', { | |
state: { | |
fromSubpage: true, | |
dashboardTab: 'uploads' | |
}, | |
replace: true | |
}); | |
}); | |
}); | |
it('应该显示错误信息当API调用失败', async () => { | |
getUserTorrents.mockRejectedValue(new Error('获取上传记录失败')); | |
render( | |
<MemoryRouter> | |
<Upload /> | |
</MemoryRouter> | |
); | |
await waitFor(() => { | |
expect(screen.getByText('错误: 获取上传记录失败')).toBeInTheDocument(); | |
}); | |
}); | |
it('应该禁用分页按钮当在第一页或最后一页', async () => { | |
render( | |
<MemoryRouter> | |
<Upload /> | |
</MemoryRouter> | |
); | |
await waitFor(() => { | |
const prevButton = screen.getByText('上一页'); | |
const firstPageButton = screen.getByText('首页'); | |
expect(prevButton).toBeDisabled(); | |
expect(firstPageButton).toBeDisabled(); | |
}); | |
}); | |
it('应该显示正确的页码导航', async () => { | |
// 模拟有更多页的情况 | |
getUserTorrents.mockResolvedValue({ | |
records: mockTorrents, | |
total: 50 | |
}); | |
render( | |
<MemoryRouter> | |
<Upload /> | |
</MemoryRouter> | |
); | |
await waitFor(() => { | |
expect(screen.getByText('...')).toBeInTheDocument(); | |
expect(screen.getByText('共 10 页')).toBeInTheDocument(); | |
}); | |
}); | |
}); |