对保种积分进行处理

Change-Id: Ifd893a39ebd6e9f105b0db6beeb94a4af8ed0eab
diff --git a/src/test/TorrentDetailhelp.test.jsx b/src/test/TorrentDetailhelp.test.jsx
new file mode 100644
index 0000000..8dd2ea5
--- /dev/null
+++ b/src/test/TorrentDetailhelp.test.jsx
@@ -0,0 +1,348 @@
+import { describe, it, expect, vi, beforeEach } from 'vitest';
+import { render, screen, waitFor } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import { MemoryRouter, useParams, useNavigate, useLocation } from 'react-router-dom';
+import TorrentDetailcomplain from '../components/TorrentDetailcomplain';
+import axios from 'axios';
+
+// 模拟 axios
+vi.mock('axios');
+
+// 模拟 react-router-dom 的 hooks
+vi.mock('react-router-dom', async () => {
+  const actual = await vi.importActual('react-router-dom');
+  return {
+    ...actual,
+    useParams: vi.fn(),
+    useNavigate: vi.fn(),
+    useLocation: vi.fn(),
+  };
+});
+
+describe('TorrentDetailcomplain 组件', () => {
+  const mockTorrent = {
+    torrentid: 1,
+    filename: '测试种子文件',
+    torrentSize: 1024 * 1024 * 10, // 10MB
+    uploader_id: 123,
+    uploadTime: '2023-01-01T12:00:00',
+    downloadCount: 100,
+    promotionid: 1,
+    description: '这是一个测试种子',
+    coverImagePath: 'http://example.com/cover.jpg',
+  };
+
+  const mockNavigate = vi.fn();
+  const mockLocation = {
+    state: {
+      duser: 456,
+      torrentid: 1,
+    },
+  };
+
+  beforeEach(() => {
+    vi.clearAllMocks();
+    
+    // 设置模拟的路由 hooks
+    vi.mocked(useParams).mockReturnValue({ id: '1' });
+    vi.mocked(useNavigate).mockReturnValue(mockNavigate);
+    vi.mocked(useLocation).mockReturnValue(mockLocation);
+    
+    // 模拟 axios.get 返回种子详情
+    axios.get.mockResolvedValueOnce({ data: mockTorrent });
+  });
+
+  it('应该正确渲染而不崩溃', async () => {
+    render(
+      <MemoryRouter>
+        <TorrentDetailcomplain />
+      </MemoryRouter>
+    );
+
+    // 等待数据加载
+    await waitFor(() => {
+      expect(screen.getByText('种子详情')).toBeInTheDocument();
+    });
+
+    // 验证一些基本元素是否存在
+    expect(screen.getByText('ID: 1')).toBeInTheDocument();
+    expect(screen.getByText('文件名: 测试种子文件')).toBeInTheDocument();
+    expect(screen.getByText('大小: 10.00 MB')).toBeInTheDocument();
+    expect(screen.getByText('上传者ID: 123')).toBeInTheDocument();
+    expect(screen.getByText('上传时间: 2023/01/01 12:00')).toBeInTheDocument();
+    expect(screen.getByText('下载次数: 100')).toBeInTheDocument();
+    expect(screen.getByText('促销: 上传加倍')).toBeInTheDocument();
+    expect(screen.getByText('描述: 这是一个测试种子')).toBeInTheDocument();
+  });
+
+  it('应该加载种子详情数据', async () => {
+    render(
+      <MemoryRouter>
+        <TorrentDetailcomplain />
+      </MemoryRouter>
+    );
+
+    // 等待数据加载
+    await waitFor(() => {
+      expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/torrent/1');
+    });
+  });
+
+  it('应该正确显示封面图片', async () => {
+    render(
+      <MemoryRouter>
+        <TorrentDetailcomplain />
+      </MemoryRouter>
+    );
+
+    // 等待数据加载
+    await waitFor(() => {
+      expect(screen.getByText('种子详情')).toBeInTheDocument();
+    });
+
+    // 验证封面图片是否渲染
+    const image = screen.getByAltText('种子封面');
+    expect(image).toBeInTheDocument();
+    expect(image).toHaveAttribute('src', 'http://example.com/cover.jpg');
+  });
+
+  it('应该正确处理删除种子按钮点击', async () => {
+    // 模拟 confirm 对话框
+    vi.mocked(axios.delete).mockResolvedValueOnce({});
+
+    render(
+      <MemoryRouter>
+        <TorrentDetailcomplain />
+      </MemoryRouter>
+    );
+
+    // 等待数据加载
+    await waitFor(() => {
+      expect(screen.getByText('种子详情')).toBeInTheDocument();
+    });
+
+    // 点击删除按钮
+    const deleteButton = screen.getByText('删除');
+    userEvent.click(deleteButton);
+
+    // 验证 confirm 对话框是否被调用
+    // 注意:由于我们使用了 antd 的 Modal.confirm,我们需要检查 axios.delete 是否被调用
+    // 这里我们直接验证 axios.delete 是否被调用
+    await waitFor(() => {
+      expect(axios.delete).toHaveBeenCalledWith('http://localhost:8080/torrent/delete/1', {
+        params: { userid: 1 },
+      });
+    });
+
+    // 验证导航是否被调用
+    await waitFor(() => {
+      expect(mockNavigate).toHaveBeenCalledWith(-1);
+    });
+
+    // 验证成功消息是否被调用
+    expect(vi.mocked(message.success)).toHaveBeenCalledWith('种子删除成功');
+  });
+
+  it('应该正确处理下载种子按钮点击', async () => {
+    render(
+      <MemoryRouter>
+        <TorrentDetailcomplain />
+      </MemoryRouter>
+    );
+
+    // 等待数据加载
+    await waitFor(() => {
+      expect(screen.getByText('种子详情')).toBeInTheDocument();
+    });
+
+    // 点击下载按钮
+    const downloadButton = screen.getByText('下载');
+    userEvent.click(downloadButton);
+
+    // 验证 axios.get 是否被调用(注意:我们实际上使用了 window.open)
+    // 由于我们直接使用了 window.open,我们需要验证它是否被调用
+    // 这里我们无法直接验证 window.open,但可以验证没有错误发生
+    // 我们可以验证组件没有崩溃
+    expect(screen.getByText('种子详情')).toBeInTheDocument();
+  });
+
+  it('应该正确处理扣除保种积分按钮点击', async () => {
+    // 模拟 axios.post
+    vi.mocked(axios.post).mockResolvedValueOnce({ data: { success: true } });
+
+    render(
+      <MemoryRouter>
+        <TorrentDetailcomplain />
+      </MemoryRouter>
+    );
+
+    // 等待数据加载
+    await waitFor(() => {
+      expect(screen.getByText('种子详情')).toBeInTheDocument();
+    });
+
+    // 点击扣除保种积分按钮
+    const creditButton = screen.getByText('扣除保种积分');
+    userEvent.click(creditButton);
+
+    // 验证 axios.post 是否被调用
+    await waitFor(() => {
+      expect(axios.post).toHaveBeenCalledWith(
+        'http://localhost:8080/torrent/deducecredit',
+        'manageid=1&userid=456&credit=3',
+        {
+          headers: {
+            'Content-Type': 'application/x-www-form-urlencoded',
+          },
+        }
+      );
+    });
+
+    // 验证成功消息是否被调用
+    expect(vi.mocked(message.success)).toHaveBeenCalledWith('成功扣除 3 保种积分');
+  });
+
+  it('应该正确处理删除种子失败的情况', async () => {
+    // 模拟 axios.delete 失败
+    vi.mocked(axios.delete).mockRejectedValueOnce({
+      response: {
+        status: 403,
+        data: '无权删除此种子',
+      },
+    });
+
+    render(
+      <MemoryRouter>
+        <TorrentDetailcomplain />
+      </MemoryRouter>
+    );
+
+    // 等待数据加载
+    await waitFor(() => {
+      expect(screen.getByText('种子详情')).toBeInTheDocument();
+    });
+
+    // 点击删除按钮
+    const deleteButton = screen.getByText('删除');
+    userEvent.click(deleteButton);
+
+    // 验证 axios.delete 是否被调用
+    await waitFor(() => {
+      expect(axios.delete).toHaveBeenCalledWith('http://localhost:8080/torrent/delete/1', {
+        params: { userid: 1 },
+      });
+    });
+
+    // 验证错误消息是否被调用
+    expect(vi.mocked(message.error)).toHaveBeenCalledWith('无权删除此种子');
+  });
+
+  it('应该正确处理下载种子失败的情况', async () => {
+    // 模拟 window.open 失败(我们无法直接模拟 window.open,所以这个测试可能有限)
+    // 由于我们直接使用了 window.open,我们无法直接测试它的失败情况
+    // 我们可以测试组件在点击按钮后没有崩溃
+    render(
+      <MemoryRouter>
+        <TorrentDetailcomplain />
+      </MemoryRouter>
+    );
+
+    // 等待数据加载
+    await waitFor(() => {
+      expect(screen.getByText('种子详情')).toBeInTheDocument();
+    });
+
+    // 点击下载按钮
+    const downloadButton = screen.getByText('下载');
+    userEvent.click(downloadButton);
+
+    // 验证组件没有崩溃
+    expect(screen.getByText('种子详情')).toBeInTheDocument();
+  });
+
+  it('应该正确处理扣除保种积分失败的情况', async () => {
+    // 模拟 axios.post 失败
+    vi.mocked(axios.post).mockRejectedValueOnce({
+      response: {
+        status: 500,
+        data: { message: '服务器错误' },
+      },
+    });
+
+    render(
+      <MemoryRouter>
+        <TorrentDetailcomplain />
+      </MemoryRouter>
+    );
+
+    // 等待数据加载
+    await waitFor(() => {
+      expect(screen.getByText('种子详情')).toBeInTheDocument();
+    });
+
+    // 点击扣除保种积分按钮
+    const creditButton = screen.getByText('扣除保种积分');
+    userEvent.click(creditButton);
+
+    // 验证 axios.post 是否被调用
+    await waitFor(() => {
+      expect(axios.post).toHaveBeenCalledWith(
+        'http://localhost:8080/torrent/deducecredit',
+        'manageid=1&userid=456&credit=3',
+        {
+          headers: {
+            'Content-Type': 'application/x-www-form-urlencoded',
+          },
+        }
+      );
+    });
+
+    // 验证错误消息是否被调用
+    expect(vi.mocked(message.error)).toHaveBeenCalledWith('服务器错误: 服务器错误');
+  });
+
+  it('应该正确处理种子不存在的情况', async () => {
+    // 模拟 axios.get 返回 404
+    axios.get.mockRejectedValueOnce({
+      response: {
+        status: 404,
+      },
+    });
+
+    render(
+      <MemoryRouter>
+        <TorrentDetailcomplain />
+      </MemoryRouter>
+    );
+
+    // 等待错误状态
+    await waitFor(() => {
+      expect(screen.queryByText('种子详情')).not.toBeInTheDocument();
+    });
+
+    // 验证错误消息是否显示
+    expect(screen.getByText('种子不存在')).toBeInTheDocument();
+    expect(screen.getByText('抱歉,您查找的种子不存在或已被删除。')).toBeInTheDocument();
+  });
+
+  it('应该正确处理网络错误的情况', async () => {
+    // 模拟 axios.get 网络错误
+    axios.get.mockRejectedValueOnce({
+      message: '网络错误',
+    });
+
+    render(
+      <MemoryRouter>
+        <TorrentDetailcomplain />
+      </MemoryRouter>
+    );
+
+    // 等待错误状态
+    await waitFor(() => {
+      expect(screen.queryByText('种子详情')).not.toBeInTheDocument();
+    });
+
+    // 验证错误消息是否显示
+    expect(screen.getByText('网络错误,请稍后重试')).toBeInTheDocument();
+  });
+});
\ No newline at end of file