blob: 8ec34c2ea4e943514193c53bdcc286792e2cf8eb [file] [log] [blame]
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { MemoryRouter, Route, Routes } from 'react-router-dom';
import RequestDetail from './RequestDetail';
import { isFormData } from 'axios';
const mockNavigate = jest.fn();
// 明确 mock API 模块
jest.mock('../api/requestPost', () => ({
getRequestPostDetail: jest.fn(),
addRequestPostComment: jest.fn(),
likeRequestPost: jest.fn(),
deleteRequestPost: jest.fn()
}));
jest.mock('../api/requestComment', () => ({
likeRequestPostComment: jest.fn(),
getRequestCommentReplies: jest.fn(),
addRequestCommentReply: jest.fn(),
deleteRequestComment: jest.fn()
}));
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: () => mockNavigate,
useLocation: jest.fn()
}));
// 导入 mock 后的 API
import * as requestPostApi from '../api/requestPost';
import * as requestCommentApi from '../api/requestComment';
describe('RequestDetail 组件', () => {
const mockPost = {
id: '1',
title: '测试求种帖',
content: '这是一个测试求种内容',
authorId: 'user1',
createTime: '2023-01-01T00:00:00Z',
likeCount: 5,
replyCount: 3,
isSolved: false,
};
const mockComments = [
{
id: 'c1',
content: '测试评论1',
authorId: 'user2',
createTime: '2023-01-01T01:00:00Z',
likeCount: 2,
replies: [
{
id: 'c1r1',
content: '测试回复1',
authorId: 'user3',
createTime: '2023-01-01T02:00:00Z',
likeCount: 1,
}
]
}
];
beforeEach(() => {
jest.clearAllMocks();
requestPostApi.getRequestPostDetail.mockResolvedValue({
data: {
code: 200,
data: {
post: mockPost,
comments: mockComments,
}
}
});
// 模拟 useLocation
require('react-router-dom').useLocation.mockReturnValue({
state: { fromTab: 'request' }
});
// 模拟 localStorage
Storage.prototype.getItem = jest.fn((key) => {
if (key === 'username') return 'testuser';
return null;
});
});
const renderComponent = () => {
return render(
<MemoryRouter initialEntries={['/request/1']}>
<Routes>
<Route path="/request/:id" element={<RequestDetail />} />
{/* 添加一个模拟的求助列表路由用于导航测试 */}
<Route path="/dashboard/request" element={<div>求助列表</div>} />
</Routes>
</MemoryRouter>
);
};
it('应该正确加载和显示求助帖详情', async () => {
renderComponent();
// 检查加载状态
expect(screen.getByText('加载中...')).toBeInTheDocument();
// 增加超时时间
await waitFor(() => {
expect(screen.getByText(mockPost.title)).toBeInTheDocument();
}, { timeout: 3000 });
// 等待数据加载完成
await waitFor(() => {
expect(screen.getByText(mockPost.title)).toBeInTheDocument();
expect(screen.getByText(mockPost.content)).toBeInTheDocument();
expect(screen.getByText(mockPost.authorId)).toBeInTheDocument();
});
});
it('应该能够点赞帖子', async () => {
renderComponent();
await waitFor(() => {
expect(screen.getByText(mockPost.title)).toBeInTheDocument();
});
const likeButton = screen.getByRole('button', { name: /点赞 \(\d+\)/ });
fireEvent.click(likeButton);
await waitFor(() => {
expect(requestPostApi.likeRequestPost).toHaveBeenCalledWith('1');
});
});
it('应该能够提交评论', async () => {
renderComponent();
await waitFor(() => {
expect(screen.getByText(mockPost.title)).toBeInTheDocument();
});
const commentInput = screen.getByPlaceholderText('写下你的评论...');
fireEvent.change(commentInput, { target: { value: '新评论' } });
const submitButton = screen.getByRole('button', { name: '发表评论' });
fireEvent.click(submitButton);
await waitFor(() => {
expect(requestPostApi.addRequestPostComment).toHaveBeenCalled();
});
});
it('应该能够点赞评论', async () => {
renderComponent();
await waitFor(() => {
expect(screen.getByText(mockComments[0].content)).toBeInTheDocument();
});
const likeButtons = screen.getAllByRole('button', { name: /👍 \(\d+\)/ });
fireEvent.click(likeButtons[0]);
await waitFor(() => {
expect(requestCommentApi.likeRequestPostComment).toHaveBeenCalledWith('c1');
});
});
it('应该能够打开和关闭回复模态框', async () => {
renderComponent();
await waitFor(() => {
expect(screen.getByText(mockComments[0].content)).toBeInTheDocument();
});
// 点击回复按钮
const replyButtons = screen.getAllByRole('button', { name: '回复' });
fireEvent.click(replyButtons[0]);
// 检查模态框是否打开
await waitFor(() => {
expect(screen.getByText(`回复 @${mockComments[0].authorId}`)).toBeInTheDocument();
});
// 点击关闭按钮
const closeButton = screen.getByRole('button', { name: '×' });
fireEvent.click(closeButton);
// 检查模态框是否关闭
await waitFor(() => {
expect(screen.queryByText(`回复 @${mockComments[0].authorId}`)).not.toBeInTheDocument();
});
});
it('应该能够返回求助区', async () => {
renderComponent();
await waitFor(() => {
expect(screen.getByText(mockPost.title)).toBeInTheDocument();
});
const backButton = screen.getByRole('button', { name: /返回/i });
fireEvent.click(backButton);
expect(mockNavigate).toHaveBeenCalledWith('/dashboard/request');
});
});