blob: 7f44ecd4b4bb0e249a11b47e34305233b1e0320c [file] [log] [blame]
DREWae420b22025-06-02 14:07:20 +08001import React from 'react';
2import { render, screen, fireEvent, waitFor } from '@testing-library/react';
3import { MemoryRouter, Route, Routes, useNavigate, useParams, useLocation } from 'react-router-dom';
4import AnnouncementDetail from './AnnouncementDetail';
5import * as announcementApi from '../api/announcement';
6
7// Mock API 模块
8jest.mock('../api/announcement');
9
10// Mock 路由钩子
11const mockNavigate = jest.fn();
12jest.mock('react-router-dom', () => ({
13 ...jest.requireActual('react-router-dom'),
14 useNavigate: () => mockNavigate,
15 useParams: jest.fn(),
16 useLocation: jest.fn(),
17}));
18
19describe('AnnouncementDetail 组件', () => {
20 const mockAnnouncement = {
21 id: 1,
22 title: '测试公告标题',
23 content: '这是测试公告内容\n这是第二行内容',
24
25 createTime: '2023-01-01T00:00:00Z',
26
27 };
28
29 beforeEach(() => {
30 // 重置 mock 函数
31 mockNavigate.mockClear();
32
33 // 设置模拟的 API 响应
34 announcementApi.getAnnouncementDetail.mockResolvedValue({
35 data: {
36 code: 200,
37 data: {
38 announcement: mockAnnouncement
39 }
40 }
41 });
42
43 // 模拟 useParams
44 useParams.mockReturnValue({ id: '1' });
45
46 // 模拟 useLocation
47 useLocation.mockReturnValue({
48 state: { fromTab: 'announcement' }
49 });
50 });
51
52 const renderComponent = () => {
53 return render(
54 <MemoryRouter initialEntries={['/announcement/1']}>
55 <Routes>
56 <Route path="/announcement/:id" element={<AnnouncementDetail />} />
57 {/* 添加一个模拟的公告列表路由用于导航测试 */}
58 <Route path="/dashboard/announcement" element={<div>公告列表</div>} />
59 </Routes>
60 </MemoryRouter>
61 );
62 };
63
64 it('应该正确加载和显示公告详情', async () => {
65 renderComponent();
66
67
68
69 // 等待数据加载完成
70 await waitFor(() => {
71 expect(screen.getByText('测试公告标题')).toBeInTheDocument();
72 expect(screen.getByText('这是测试公告内容')).toBeInTheDocument();
73 expect(screen.getByText('这是第二行内容')).toBeInTheDocument();
74 });
75 });
76
77 it('应该处理公告加载失败的情况', async () => {
78 // 模拟 API 返回错误
79 announcementApi.getAnnouncementDetail.mockResolvedValue({
80 data: {
81 code: 404,
82 message: '公告不存在'
83 }
84 });
85
86 renderComponent();
87
88 await waitFor(() => {
89 expect(screen.getByText('公告不存在')).toBeInTheDocument();
90 });
91 });
92
93 it('应该能够返回公告区', async () => {
94 renderComponent();
95
96 await waitFor(() => {
97 expect(screen.getByText('测试公告标题')).toBeInTheDocument();
98 });
99
100 fireEvent.click(screen.getByRole('button', { name: /返回/i }));
101
102 // 检查是否导航回公告区
103 expect(mockNavigate).toHaveBeenCalledWith('/dashboard/announcement');
104 });
105
106 it('应该显示加载错误时的UI', async () => {
107 // 模拟 API 抛出错误
108 announcementApi.getAnnouncementDetail.mockRejectedValue(new Error('网络错误'));
109
110 renderComponent();
111
112 await waitFor(() => {
113 expect(screen.getByText('获取公告详情失败')).toBeInTheDocument();
114 });
115 });
116});