上传种子以及接管求助帖
Change-Id: Icba99400a2dc4f706c9e184b16fc47cde5ebf12a
diff --git a/src/test/TorrentUpload.test.jsx b/src/test/TorrentUpload.test.jsx
new file mode 100644
index 0000000..482184e
--- /dev/null
+++ b/src/test/TorrentUpload.test.jsx
@@ -0,0 +1,489 @@
+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('上传成功!');
+ });
+});
\ No newline at end of file