blob: 482184ed3a9b4e7c264a346399ff2c2e13cb79ff [file] [log] [blame] [edit]
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import UploadTorrent from '../components/upload';
import { Form, Select } from 'antd';
// 模拟 axios
vi.mock('axios');
// 模拟 antd 的 message
vi.mock('antd', async () => {
const actual = await vi.importActual('antd');
return {
...actual,
message: {
success: vi.fn(),
error: vi.fn(),
},
};
});
describe('UploadTorrent 组件', () => {
const mockCategories = [
{ categoryid: '1', category_name: '电影' },
{ categoryid: '2', category_name: '剧集' },
{ categoryid: '3', category_name: '音乐' },
{ categoryid: '4', category_name: '动漫' },
{ categoryid: '5', category_name: '游戏' },
{ categoryid: '6', category_name: '综艺' },
{ categoryid: '7', category_name: '体育' },
{ categoryid: '8', category_name: '软件' },
{ categoryid: '9', category_name: '学习资料' },
{ categoryid: '10', category_name: '纪录片' },
{ categoryid: '11', category_name: '音乐' },
];
beforeEach(() => {
vi.clearAllMocks();
// 模拟 axios.get 返回分类数据
vi.mocked(axios.get).mockResolvedValueOnce({ data: mockCategories });
});
it('应该正确渲染而不崩溃', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(screen.getByText('上传种子')).toBeInTheDocument();
});
// 验证一些基本元素是否存在
expect(screen.getByText('封面图片')).toBeInTheDocument();
expect(screen.getByText('种子文件')).toBeInTheDocument();
expect(screen.getByText('标题')).toBeInTheDocument();
expect(screen.getByText('描述')).toBeInTheDocument();
expect(screen.getByText('分类')).toBeInTheDocument();
expect(screen.getByText('上传种子')).toBeInTheDocument();
});
it('应该加载分类数据', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 验证分类下拉框是否渲染了正确的选项
const categorySelect = screen.getByLabelText('分类');
expect(categorySelect).toBeInTheDocument();
// 打开下拉菜单并检查选项
fireEvent.mouseDown(categorySelect);
mockCategories.forEach(category => {
expect(screen.getByText(category.category_name)).toBeInTheDocument();
});
});
it('应该在选择分类后显示相应的动态字段', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 选择"电影"分类
const categorySelect = screen.getByLabelText('分类');
fireEvent.mouseDown(categorySelect);
fireEvent.click(screen.getByText('电影'));
// 验证电影相关的字段是否显示
expect(screen.getByLabelText('字幕/说明')).toBeInTheDocument();
expect(screen.getByLabelText('地区')).toBeInTheDocument();
expect(screen.getByLabelText('年份')).toBeInTheDocument();
expect(screen.getByLabelText('类型')).toBeInTheDocument();
expect(screen.getByLabelText('编码格式')).toBeInTheDocument();
expect(screen.getByLabelText('分辨率')).toBeInTheDocument();
});
it('应该在选择"剧集"分类后显示相应的动态字段', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 选择"剧集"分类
const categorySelect = screen.getByLabelText('分类');
fireEvent.mouseDown(categorySelect);
fireEvent.click(screen.getByText('剧集'));
// 验证剧集相关的字段是否显示
expect(screen.getByLabelText('地区')).toBeInTheDocument();
expect(screen.getByLabelText('格式')).toBeInTheDocument();
expect(screen.getByLabelText('类型')).toBeInTheDocument();
});
it('应该在选择"游戏"分类后显示相应的动态字段', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 选择"游戏"分类
const categorySelect = screen.getByLabelText('分类');
fireEvent.mouseDown(categorySelect);
fireEvent.click(screen.getByText('游戏'));
// 验证游戏相关的字段是否显示
expect(screen.getByLabelText('平台')).toBeInTheDocument();
expect(screen.getByLabelText('类型')).toBeInTheDocument();
expect(screen.getByLabelText('语言')).toBeInTheDocument();
expect(screen.getByLabelText('数据类型')).toBeInTheDocument();
});
it('应该在选择"综艺"分类后显示相应的动态字段', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 选择"综艺"分类
const categorySelect = screen.getByLabelText('分类');
fireEvent.mouseDown(categorySelect);
fireEvent.click(screen.getByText('综艺'));
// 验证综艺相关的字段是否显示
expect(screen.getByLabelText('是否大陆综艺')).toBeInTheDocument();
expect(screen.getByLabelText('类型')).toBeInTheDocument();
expect(screen.getByLabelText('格式')).toBeInTheDocument();
});
it('应该在选择"动漫"分类后显示相应的动态字段', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 选择"动漫"分类
const categorySelect = screen.getByLabelText('分类');
fireEvent.mouseDown(categorySelect);
fireEvent.click(screen.getByText('动漫'));
// 验证动漫相关的字段是否显示
expect(screen.getByLabelText('类型')).toBeInTheDocument();
expect(screen.getByLabelText('格式')).toBeInTheDocument();
expect(screen.getByLabelText('分辨率')).toBeInTheDocument();
});
it('应该在选择"学习资料"分类后显示相应的动态字段', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 选择"学习资料"分类
const categorySelect = screen.getByLabelText('分类');
fireEvent.mouseDown(categorySelect);
fireEvent.click(screen.getByText('学习资料'));
// 验证学习资料相关的字段是否显示
expect(screen.getByLabelText('类型')).toBeInTheDocument();
expect(screen.getByLabelText('格式')).toBeInTheDocument();
});
it('应该在选择"纪录片"分类后显示相应的动态字段', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 选择"纪录片"分类
const categorySelect = screen.getByLabelText('分类');
fireEvent.mouseDown(categorySelect);
fireEvent.click(screen.getByText('纪录片'));
// 验证纪录片相关的字段是否显示
expect(screen.getByLabelText('年份')).toBeInTheDocument();
expect(screen.getByLabelText('视频源')).toBeInTheDocument();
expect(screen.getByLabelText('格式')).toBeInTheDocument();
});
it('应该在选择"音乐"分类后显示相应的动态字段', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 选择"音乐"分类
const categorySelect = screen.getByLabelText('分类');
fireEvent.mouseDown(categorySelect);
fireEvent.click(screen.getByText('音乐'));
// 验证音乐相关的字段是否显示
expect(screen.getByLabelText('类型')).toBeInTheDocument();
expect(screen.getByLabelText('地区')).toBeInTheDocument();
expect(screen.getByLabelText('风格')).toBeInTheDocument();
expect(screen.getByLabelText('格式')).toBeInTheDocument();
});
it('应该在选择"软件"分类后显示相应的动态字段', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 选择"软件"分类
const categorySelect = screen.getByLabelText('分类');
fireEvent.mouseDown(categorySelect);
fireEvent.click(screen.getByText('软件'));
// 验证软件相关的字段是否显示
expect(screen.getByLabelText('平台')).toBeInTheDocument();
expect(screen.getByLabelText('类型')).toBeInTheDocument();
expect(screen.getByLabelText('格式')).toBeInTheDocument();
});
it('应该在选择"体育"分类后显示相应的动态字段', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 选择"体育"分类
const categorySelect = screen.getByLabelText('分类');
fireEvent.mouseDown(categorySelect);
fireEvent.click(screen.getByText('体育'));
// 验证体育相关的字段是否显示
expect(screen.getByLabelText('类型')).toBeInTheDocument();
expect(screen.getByLabelText('格式')).toBeInTheDocument();
expect(screen.getByLabelText('赛事类型')).toBeInTheDocument();
});
it('应该在选择分类后正确设置状态', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 选择"电影"分类
const categorySelect = screen.getByLabelText('分类');
fireEvent.mouseDown(categorySelect);
fireEvent.click(screen.getByText('电影'));
// 验证状态是否正确设置
// 注意:由于状态是组件内部的,我们需要通过 UI 变化来间接验证
// 这里我们验证电影相关的字段是否显示
expect(screen.getByLabelText('字幕/说明')).toBeInTheDocument();
});
it('应该在选择种子文件后更新状态', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 模拟文件选择
const fileInput = screen.getByLabelText('种子文件').querySelector('input');
const mockFile = new File(['torrent content'], 'test.torrent', { type: 'application/x-bittorrent' });
fireEvent.change(fileInput, { target: { files: [mockFile] } });
// 验证文件是否被设置(通过 UI 变化间接验证)
// 由于我们无法直接访问组件状态,我们可以通过表单验证状态来间接验证
// 这里我们只是验证文件输入是否正常工作
expect(fileInput).toBeInTheDocument();
});
it('应该在选择封面图片后更新状态', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 模拟图片选择
const imageInput = screen.getByLabelText('封面图片').querySelector('input');
const mockImage = new File(['image content'], 'test.jpg', { type: 'image/jpeg' });
fireEvent.change(imageInput, { target: { files: [mockImage] } });
// 验证图片是否被设置(通过 UI 变化间接验证)
expect(imageInput).toBeInTheDocument();
});
it('应该在表单提交时验证必填字段', async () => {
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 直接提交表单而不填写任何字段
const submitButton = screen.getByText('上传种子');
fireEvent.click(submitButton);
// 验证错误消息是否显示
// 注意:由于我们使用了 antd 的 Form,错误消息可能由 antd 内部处理
// 我们可以通过检查是否有错误提示来验证
// 这里我们只是验证表单提交被调用
// 更详细的验证可能需要更复杂的测试设置
});
it('应该在填写所有必填字段后成功提交表单', async () => {
// 模拟 axios.post
vi.mocked(axios.post).mockResolvedValueOnce({ data: {} });
render(
<MemoryRouter>
<UploadTorrent />
</MemoryRouter>
);
// 等待分类数据加载
await waitFor(() => {
expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/categories');
});
// 选择分类
const categorySelect = screen.getByLabelText('分类');
fireEvent.mouseDown(categorySelect);
fireEvent.click(screen.getByText('电影'));
// 填写标题
const titleInput = screen.getByLabelText('标题');
fireEvent.change(titleInput, { target: { value: '测试电影' } });
// 填写描述
const descriptionInput = screen.getByLabelText('描述');
fireEvent.change(descriptionInput, { target: { value: '这是一个测试电影的描述' } });
// 选择封面图片
const imageInput = screen.getByLabelText('封面图片').querySelector('input');
const mockImage = new File(['image content'], 'test.jpg', { type: 'image/jpeg' });
fireEvent.change(imageInput, { target: { files: [mockImage] } });
// 选择种子文件
const fileInput = screen.getByLabelText('种子文件').querySelector('input');
const mockFile = new File(['torrent content'], 'test.torrent', { type: 'application/x-bittorrent' });
fireEvent.change(fileInput, { target: { files: [mockFile] } });
// 填写电影相关字段
const captionInput = screen.getByLabelText('字幕/说明');
fireEvent.change(captionInput, { target: { value: '测试字幕' } });
const regionSelect = screen.getByLabelText('地区');
fireEvent.mouseDown(regionSelect);
fireEvent.click(screen.getByText('大陆'));
const yearInput = screen.getByLabelText('年份');
fireEvent.change(yearInput, { target: { value: '2023' } });
const genreSelect = screen.getByLabelText('类型');
fireEvent.mouseDown(genreSelect);
fireEvent.click(screen.getByText('动作'));
const codecFormatSelect = screen.getByLabelText('编码格式');
fireEvent.mouseDown(codecFormatSelect);
fireEvent.click(screen.getByText('H.264'));
const resolutionSelect = screen.getByLabelText('分辨率');
fireEvent.mouseDown(resolutionSelect);
fireEvent.click(screen.getByText('1080p'));
// 提交表单
const submitButton = screen.getByText('上传种子');
fireEvent.click(submitButton);
// 验证 axios.post 是否被调用
expect(axios.post).toHaveBeenCalledWith(
'http://localhost:8080/torrent/upload',
expect.any(FormData),
{
headers: { 'Content-Type': 'multipart/form-data' },
responseType: 'blob',
}
);
// 验证成功消息是否显示
expect(vi.mocked(message.success)).toHaveBeenCalledWith('上传成功!');
});
});