blob: 8dd2ea58a479b9f5f5cd7de64b3e8315f15f7ce9 [file] [log] [blame]
刘嘉昕8a3c6ab2025-06-09 17:44:13 +08001import { describe, it, expect, vi, beforeEach } from 'vitest';
2import { render, screen, waitFor } from '@testing-library/react';
3import userEvent from '@testing-library/user-event';
4import { MemoryRouter, useParams, useNavigate, useLocation } from 'react-router-dom';
5import TorrentDetailcomplain from '../components/TorrentDetailcomplain';
6import axios from 'axios';
7
8// 模拟 axios
9vi.mock('axios');
10
11// 模拟 react-router-dom 的 hooks
12vi.mock('react-router-dom', async () => {
13 const actual = await vi.importActual('react-router-dom');
14 return {
15 ...actual,
16 useParams: vi.fn(),
17 useNavigate: vi.fn(),
18 useLocation: vi.fn(),
19 };
20});
21
22describe('TorrentDetailcomplain 组件', () => {
23 const mockTorrent = {
24 torrentid: 1,
25 filename: '测试种子文件',
26 torrentSize: 1024 * 1024 * 10, // 10MB
27 uploader_id: 123,
28 uploadTime: '2023-01-01T12:00:00',
29 downloadCount: 100,
30 promotionid: 1,
31 description: '这是一个测试种子',
32 coverImagePath: 'http://example.com/cover.jpg',
33 };
34
35 const mockNavigate = vi.fn();
36 const mockLocation = {
37 state: {
38 duser: 456,
39 torrentid: 1,
40 },
41 };
42
43 beforeEach(() => {
44 vi.clearAllMocks();
45
46 // 设置模拟的路由 hooks
47 vi.mocked(useParams).mockReturnValue({ id: '1' });
48 vi.mocked(useNavigate).mockReturnValue(mockNavigate);
49 vi.mocked(useLocation).mockReturnValue(mockLocation);
50
51 // 模拟 axios.get 返回种子详情
52 axios.get.mockResolvedValueOnce({ data: mockTorrent });
53 });
54
55 it('应该正确渲染而不崩溃', async () => {
56 render(
57 <MemoryRouter>
58 <TorrentDetailcomplain />
59 </MemoryRouter>
60 );
61
62 // 等待数据加载
63 await waitFor(() => {
64 expect(screen.getByText('种子详情')).toBeInTheDocument();
65 });
66
67 // 验证一些基本元素是否存在
68 expect(screen.getByText('ID: 1')).toBeInTheDocument();
69 expect(screen.getByText('文件名: 测试种子文件')).toBeInTheDocument();
70 expect(screen.getByText('大小: 10.00 MB')).toBeInTheDocument();
71 expect(screen.getByText('上传者ID: 123')).toBeInTheDocument();
72 expect(screen.getByText('上传时间: 2023/01/01 12:00')).toBeInTheDocument();
73 expect(screen.getByText('下载次数: 100')).toBeInTheDocument();
74 expect(screen.getByText('促销: 上传加倍')).toBeInTheDocument();
75 expect(screen.getByText('描述: 这是一个测试种子')).toBeInTheDocument();
76 });
77
78 it('应该加载种子详情数据', async () => {
79 render(
80 <MemoryRouter>
81 <TorrentDetailcomplain />
82 </MemoryRouter>
83 );
84
85 // 等待数据加载
86 await waitFor(() => {
87 expect(axios.get).toHaveBeenCalledWith('http://localhost:8080/torrent/1');
88 });
89 });
90
91 it('应该正确显示封面图片', async () => {
92 render(
93 <MemoryRouter>
94 <TorrentDetailcomplain />
95 </MemoryRouter>
96 );
97
98 // 等待数据加载
99 await waitFor(() => {
100 expect(screen.getByText('种子详情')).toBeInTheDocument();
101 });
102
103 // 验证封面图片是否渲染
104 const image = screen.getByAltText('种子封面');
105 expect(image).toBeInTheDocument();
106 expect(image).toHaveAttribute('src', 'http://example.com/cover.jpg');
107 });
108
109 it('应该正确处理删除种子按钮点击', async () => {
110 // 模拟 confirm 对话框
111 vi.mocked(axios.delete).mockResolvedValueOnce({});
112
113 render(
114 <MemoryRouter>
115 <TorrentDetailcomplain />
116 </MemoryRouter>
117 );
118
119 // 等待数据加载
120 await waitFor(() => {
121 expect(screen.getByText('种子详情')).toBeInTheDocument();
122 });
123
124 // 点击删除按钮
125 const deleteButton = screen.getByText('删除');
126 userEvent.click(deleteButton);
127
128 // 验证 confirm 对话框是否被调用
129 // 注意:由于我们使用了 antd 的 Modal.confirm,我们需要检查 axios.delete 是否被调用
130 // 这里我们直接验证 axios.delete 是否被调用
131 await waitFor(() => {
132 expect(axios.delete).toHaveBeenCalledWith('http://localhost:8080/torrent/delete/1', {
133 params: { userid: 1 },
134 });
135 });
136
137 // 验证导航是否被调用
138 await waitFor(() => {
139 expect(mockNavigate).toHaveBeenCalledWith(-1);
140 });
141
142 // 验证成功消息是否被调用
143 expect(vi.mocked(message.success)).toHaveBeenCalledWith('种子删除成功');
144 });
145
146 it('应该正确处理下载种子按钮点击', async () => {
147 render(
148 <MemoryRouter>
149 <TorrentDetailcomplain />
150 </MemoryRouter>
151 );
152
153 // 等待数据加载
154 await waitFor(() => {
155 expect(screen.getByText('种子详情')).toBeInTheDocument();
156 });
157
158 // 点击下载按钮
159 const downloadButton = screen.getByText('下载');
160 userEvent.click(downloadButton);
161
162 // 验证 axios.get 是否被调用(注意:我们实际上使用了 window.open)
163 // 由于我们直接使用了 window.open,我们需要验证它是否被调用
164 // 这里我们无法直接验证 window.open,但可以验证没有错误发生
165 // 我们可以验证组件没有崩溃
166 expect(screen.getByText('种子详情')).toBeInTheDocument();
167 });
168
169 it('应该正确处理扣除保种积分按钮点击', async () => {
170 // 模拟 axios.post
171 vi.mocked(axios.post).mockResolvedValueOnce({ data: { success: true } });
172
173 render(
174 <MemoryRouter>
175 <TorrentDetailcomplain />
176 </MemoryRouter>
177 );
178
179 // 等待数据加载
180 await waitFor(() => {
181 expect(screen.getByText('种子详情')).toBeInTheDocument();
182 });
183
184 // 点击扣除保种积分按钮
185 const creditButton = screen.getByText('扣除保种积分');
186 userEvent.click(creditButton);
187
188 // 验证 axios.post 是否被调用
189 await waitFor(() => {
190 expect(axios.post).toHaveBeenCalledWith(
191 'http://localhost:8080/torrent/deducecredit',
192 'manageid=1&userid=456&credit=3',
193 {
194 headers: {
195 'Content-Type': 'application/x-www-form-urlencoded',
196 },
197 }
198 );
199 });
200
201 // 验证成功消息是否被调用
202 expect(vi.mocked(message.success)).toHaveBeenCalledWith('成功扣除 3 保种积分');
203 });
204
205 it('应该正确处理删除种子失败的情况', async () => {
206 // 模拟 axios.delete 失败
207 vi.mocked(axios.delete).mockRejectedValueOnce({
208 response: {
209 status: 403,
210 data: '无权删除此种子',
211 },
212 });
213
214 render(
215 <MemoryRouter>
216 <TorrentDetailcomplain />
217 </MemoryRouter>
218 );
219
220 // 等待数据加载
221 await waitFor(() => {
222 expect(screen.getByText('种子详情')).toBeInTheDocument();
223 });
224
225 // 点击删除按钮
226 const deleteButton = screen.getByText('删除');
227 userEvent.click(deleteButton);
228
229 // 验证 axios.delete 是否被调用
230 await waitFor(() => {
231 expect(axios.delete).toHaveBeenCalledWith('http://localhost:8080/torrent/delete/1', {
232 params: { userid: 1 },
233 });
234 });
235
236 // 验证错误消息是否被调用
237 expect(vi.mocked(message.error)).toHaveBeenCalledWith('无权删除此种子');
238 });
239
240 it('应该正确处理下载种子失败的情况', async () => {
241 // 模拟 window.open 失败(我们无法直接模拟 window.open,所以这个测试可能有限)
242 // 由于我们直接使用了 window.open,我们无法直接测试它的失败情况
243 // 我们可以测试组件在点击按钮后没有崩溃
244 render(
245 <MemoryRouter>
246 <TorrentDetailcomplain />
247 </MemoryRouter>
248 );
249
250 // 等待数据加载
251 await waitFor(() => {
252 expect(screen.getByText('种子详情')).toBeInTheDocument();
253 });
254
255 // 点击下载按钮
256 const downloadButton = screen.getByText('下载');
257 userEvent.click(downloadButton);
258
259 // 验证组件没有崩溃
260 expect(screen.getByText('种子详情')).toBeInTheDocument();
261 });
262
263 it('应该正确处理扣除保种积分失败的情况', async () => {
264 // 模拟 axios.post 失败
265 vi.mocked(axios.post).mockRejectedValueOnce({
266 response: {
267 status: 500,
268 data: { message: '服务器错误' },
269 },
270 });
271
272 render(
273 <MemoryRouter>
274 <TorrentDetailcomplain />
275 </MemoryRouter>
276 );
277
278 // 等待数据加载
279 await waitFor(() => {
280 expect(screen.getByText('种子详情')).toBeInTheDocument();
281 });
282
283 // 点击扣除保种积分按钮
284 const creditButton = screen.getByText('扣除保种积分');
285 userEvent.click(creditButton);
286
287 // 验证 axios.post 是否被调用
288 await waitFor(() => {
289 expect(axios.post).toHaveBeenCalledWith(
290 'http://localhost:8080/torrent/deducecredit',
291 'manageid=1&userid=456&credit=3',
292 {
293 headers: {
294 'Content-Type': 'application/x-www-form-urlencoded',
295 },
296 }
297 );
298 });
299
300 // 验证错误消息是否被调用
301 expect(vi.mocked(message.error)).toHaveBeenCalledWith('服务器错误: 服务器错误');
302 });
303
304 it('应该正确处理种子不存在的情况', async () => {
305 // 模拟 axios.get 返回 404
306 axios.get.mockRejectedValueOnce({
307 response: {
308 status: 404,
309 },
310 });
311
312 render(
313 <MemoryRouter>
314 <TorrentDetailcomplain />
315 </MemoryRouter>
316 );
317
318 // 等待错误状态
319 await waitFor(() => {
320 expect(screen.queryByText('种子详情')).not.toBeInTheDocument();
321 });
322
323 // 验证错误消息是否显示
324 expect(screen.getByText('种子不存在')).toBeInTheDocument();
325 expect(screen.getByText('抱歉,您查找的种子不存在或已被删除。')).toBeInTheDocument();
326 });
327
328 it('应该正确处理网络错误的情况', async () => {
329 // 模拟 axios.get 网络错误
330 axios.get.mockRejectedValueOnce({
331 message: '网络错误',
332 });
333
334 render(
335 <MemoryRouter>
336 <TorrentDetailcomplain />
337 </MemoryRouter>
338 );
339
340 // 等待错误状态
341 await waitFor(() => {
342 expect(screen.queryByText('种子详情')).not.toBeInTheDocument();
343 });
344
345 // 验证错误消息是否显示
346 expect(screen.getByText('网络错误,请稍后重试')).toBeInTheDocument();
347 });
348});