完成上传下载连接,公告管理与详情页面,求种区页面,轮播图折扣显示,修改部分bug

Change-Id: I86fc294e32911cb3426a8b16f90aca371f975c11
diff --git a/src/components/AnnouncementDetail.test.jsx b/src/components/AnnouncementDetail.test.jsx
new file mode 100644
index 0000000..7f44ecd
--- /dev/null
+++ b/src/components/AnnouncementDetail.test.jsx
@@ -0,0 +1,116 @@
+import React from 'react';
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
+import { MemoryRouter, Route, Routes, useNavigate, useParams, useLocation } from 'react-router-dom';
+import AnnouncementDetail from './AnnouncementDetail';
+import * as announcementApi from '../api/announcement';
+
+// Mock API 模块
+jest.mock('../api/announcement');
+
+// Mock 路由钩子
+const mockNavigate = jest.fn();
+jest.mock('react-router-dom', () => ({
+  ...jest.requireActual('react-router-dom'),
+  useNavigate: () => mockNavigate,
+  useParams: jest.fn(),
+  useLocation: jest.fn(),
+}));
+
+describe('AnnouncementDetail 组件', () => {
+  const mockAnnouncement = {
+    id: 1,
+    title: '测试公告标题',
+    content: '这是测试公告内容\n这是第二行内容',
+    
+    createTime: '2023-01-01T00:00:00Z',
+    
+  };
+
+  beforeEach(() => {
+    // 重置 mock 函数
+    mockNavigate.mockClear();
+    
+    // 设置模拟的 API 响应
+    announcementApi.getAnnouncementDetail.mockResolvedValue({
+      data: {
+        code: 200,
+        data: {
+          announcement: mockAnnouncement
+        }
+      }
+    });
+
+    // 模拟 useParams
+    useParams.mockReturnValue({ id: '1' });
+
+    // 模拟 useLocation
+    useLocation.mockReturnValue({
+      state: { fromTab: 'announcement' }
+    });
+  });
+
+  const renderComponent = () => {
+    return render(
+      <MemoryRouter initialEntries={['/announcement/1']}>
+        <Routes>
+          <Route path="/announcement/:id" element={<AnnouncementDetail />} />
+          {/* 添加一个模拟的公告列表路由用于导航测试 */}
+          <Route path="/dashboard/announcement" element={<div>公告列表</div>} />
+        </Routes>
+      </MemoryRouter>
+    );
+  };
+
+  it('应该正确加载和显示公告详情', async () => {
+    renderComponent();
+
+    
+
+    // 等待数据加载完成
+    await waitFor(() => {
+      expect(screen.getByText('测试公告标题')).toBeInTheDocument();
+      expect(screen.getByText('这是测试公告内容')).toBeInTheDocument();
+      expect(screen.getByText('这是第二行内容')).toBeInTheDocument();
+    });
+  });
+
+  it('应该处理公告加载失败的情况', async () => {
+    // 模拟 API 返回错误
+    announcementApi.getAnnouncementDetail.mockResolvedValue({
+      data: {
+        code: 404,
+        message: '公告不存在'
+      }
+    });
+
+    renderComponent();
+
+    await waitFor(() => {
+      expect(screen.getByText('公告不存在')).toBeInTheDocument();
+    });
+  });
+
+  it('应该能够返回公告区', async () => {
+    renderComponent();
+  
+    await waitFor(() => {
+      expect(screen.getByText('测试公告标题')).toBeInTheDocument();
+    });
+  
+    fireEvent.click(screen.getByRole('button', { name: /返回/i }));
+  
+    // 检查是否导航回公告区
+    expect(mockNavigate).toHaveBeenCalledWith('/dashboard/announcement');
+  });
+
+  it('应该显示加载错误时的UI', async () => {
+    // 模拟 API 抛出错误
+    announcementApi.getAnnouncementDetail.mockRejectedValue(new Error('网络错误'));
+
+    renderComponent();
+
+    await waitFor(() => {
+      expect(screen.getByText('获取公告详情失败')).toBeInTheDocument();
+    });
+  });
+});
\ No newline at end of file