blob: 5a68ecfc98bc6aae5bb6bf79941542ee3b05a99c [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这是第二行内容',
DREWae420b22025-06-02 14:07:20 +080024 createTime: '2023-01-01T00:00:00Z',
DREWae420b22025-06-02 14:07:20 +080025 };
26
27 beforeEach(() => {
DREWae420b22025-06-02 14:07:20 +080028 mockNavigate.mockClear();
223010806af19da2025-06-03 16:57:13 +080029
DREWae420b22025-06-02 14:07:20 +080030 // 设置模拟的 API 响应
31 announcementApi.getAnnouncementDetail.mockResolvedValue({
32 data: {
33 code: 200,
34 data: {
223010806af19da2025-06-03 16:57:13 +080035 announcement: mockAnnouncement,
36 },
37 },
DREWae420b22025-06-02 14:07:20 +080038 });
39
223010806af19da2025-06-03 16:57:13 +080040 // 模拟钩子
DREWae420b22025-06-02 14:07:20 +080041 useParams.mockReturnValue({ id: '1' });
223010806af19da2025-06-03 16:57:13 +080042 useLocation.mockReturnValue({ state: { fromTab: 'announcement' } });
DREWae420b22025-06-02 14:07:20 +080043 });
44
45 const renderComponent = () => {
46 return render(
47 <MemoryRouter initialEntries={['/announcement/1']}>
48 <Routes>
49 <Route path="/announcement/:id" element={<AnnouncementDetail />} />
DREWae420b22025-06-02 14:07:20 +080050 <Route path="/dashboard/announcement" element={<div>公告列表</div>} />
51 </Routes>
52 </MemoryRouter>
53 );
54 };
55
56 it('应该正确加载和显示公告详情', async () => {
57 renderComponent();
58
DREWae420b22025-06-02 14:07:20 +080059 await waitFor(() => {
60 expect(screen.getByText('测试公告标题')).toBeInTheDocument();
61 expect(screen.getByText('这是测试公告内容')).toBeInTheDocument();
62 expect(screen.getByText('这是第二行内容')).toBeInTheDocument();
63 });
64 });
65
66 it('应该处理公告加载失败的情况', async () => {
DREWae420b22025-06-02 14:07:20 +080067 announcementApi.getAnnouncementDetail.mockResolvedValue({
223010806af19da2025-06-03 16:57:13 +080068 data: { code: 404, message: '公告不存在' },
DREWae420b22025-06-02 14:07:20 +080069 });
70
71 renderComponent();
72
73 await waitFor(() => {
74 expect(screen.getByText('公告不存在')).toBeInTheDocument();
75 });
76 });
77
78 it('应该能够返回公告区', async () => {
79 renderComponent();
223010806af19da2025-06-03 16:57:13 +080080
DREWae420b22025-06-02 14:07:20 +080081 await waitFor(() => {
82 expect(screen.getByText('测试公告标题')).toBeInTheDocument();
83 });
223010806af19da2025-06-03 16:57:13 +080084
DREWae420b22025-06-02 14:07:20 +080085 fireEvent.click(screen.getByRole('button', { name: /返回/i }));
223010806af19da2025-06-03 16:57:13 +080086
DREWae420b22025-06-02 14:07:20 +080087 // 检查是否导航回公告区
88 expect(mockNavigate).toHaveBeenCalledWith('/dashboard/announcement');
89 });
90
91 it('应该显示加载错误时的UI', async () => {
DREWae420b22025-06-02 14:07:20 +080092 announcementApi.getAnnouncementDetail.mockRejectedValue(new Error('网络错误'));
93
94 renderComponent();
95
96 await waitFor(() => {
97 expect(screen.getByText('获取公告详情失败')).toBeInTheDocument();
98 });
99 });
223010806af19da2025-06-03 16:57:13 +0800100
101 // 边界测试 - 测试公告ID不存在
102 it('应该处理不存在的公告ID', async () => {
103 announcementApi.getAnnouncementDetail.mockResolvedValue({
104 data: { code: 404, message: '公告不存在' },
105 });
106
107 renderComponent();
108
109 await waitFor(() => {
110 expect(screen.getByText('公告不存在')).toBeInTheDocument();
111 });
112 });
113
114 // 边界测试 - 测试其他API错误
115 it('应该处理服务器错误', async () => {
116 announcementApi.getAnnouncementDetail.mockResolvedValue({
117 data: { code: 500, message: '服务器错误' },
118 });
119
120 renderComponent();
121
122 await waitFor(() => {
123 expect(screen.getByText('服务器错误')).toBeInTheDocument();
124 });
125 });
126});