blob: d44ddb3925485bf38af2d3434a9528ef4759efab [file] [log] [blame]
/**
* 帖子服务单元测试
*
* 测试覆盖所有帖子相关的API接口
* 包括:帖子列表、详情、评论、收藏、点赞、发布、审核、举报等功能
*/
import * as postService from '../../src/services/post';
// Mock request module
jest.mock('@umijs/max', () => ({
request: jest.fn(),
}));
const { request } = require('@umijs/max');
describe('Post Service', () => {
beforeEach(() => {
jest.clearAllMocks();
});
// 帖子列表相关测试
describe('getPostList', () => {
it('应该成功获取帖子列表', async () => {
const mockResponse = {
code: 200,
rows: [
{
postId: 1,
title: '测试帖子',
content: '测试内容',
author: 'testuser',
views: 100,
comments: 5,
favorites: 10,
likes: 15,
tags: 'tag1,tag2',
publishTime: '2024-01-01 12:00:00',
status: '1'
}
],
total: 1
};
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.getPostList({ pageNum: 1, pageSize: 10 });
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/list', {
method: 'GET',
params: { pageNum: 1, pageSize: 10 },
});
});
it('应该处理带标签筛选的帖子列表请求', async () => {
const mockResponse = { code: 200, rows: [], total: 0 };
(request as jest.Mock).mockResolvedValue(mockResponse);
await postService.getPostList({ pageNum: 1, pageSize: 10, tags: '日剧' });
expect(request).toHaveBeenCalledWith('/api/post-center/list', {
method: 'GET',
params: { pageNum: 1, pageSize: 10, tags: '日剧' },
});
});
it('应该处理搜索关键词的请求', async () => {
const mockResponse = { code: 200, rows: [], total: 0 };
(request as jest.Mock).mockResolvedValue(mockResponse);
await postService.getPostList({ pageNum: 1, pageSize: 10, title: '搜索关键词' });
expect(request).toHaveBeenCalledWith('/api/post-center/list', {
method: 'GET',
params: { pageNum: 1, pageSize: 10, title: '搜索关键词' },
});
});
});
// 帖子详情相关测试
describe('getPostDetail', () => {
it('应该成功获取帖子详情', async () => {
const mockResponse = {
code: 200,
data: {
post: {
postId: 1,
title: '测试帖子',
content: '测试内容',
author: 'testuser',
views: 100,
comments: 5,
favorites: 10,
likes: 15,
tags: 'tag1,tag2',
publishTime: '2024-01-01 12:00:00',
status: '1'
},
tags: [],
comments: [],
recommendedPosts: [],
favorited: false
}
};
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.getPostDetail(1);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/1', {
method: 'GET',
});
});
it('应该处理获取不存在帖子的情况', async () => {
const mockResponse = { code: 404, msg: '帖子不存在' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.getPostDetail(999);
expect(result).toEqual(mockResponse);
});
});
// 评论相关测试
describe('addComment', () => {
it('应该成功添加评论', async () => {
const mockResponse = { code: 200, msg: '评论成功', data: { commentId: 1 } };
(request as jest.Mock).mockResolvedValue(mockResponse);
const commentData = {
postId: 1,
content: '这是一条测试评论',
parentId: 0
};
const result = await postService.addComment(commentData);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/comment', {
method: 'POST',
data: commentData,
});
});
it('应该处理空评论内容', async () => {
const mockResponse = { code: 400, msg: '评论内容不能为空' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.addComment({ postId: 1, content: '' });
expect(result).toEqual(mockResponse);
});
});
// 收藏相关测试
describe('toggleFavorite', () => {
it('应该成功收藏帖子', async () => {
const mockResponse = { code: 200, msg: '收藏成功' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.toggleFavorite(1, true);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/favorite/1', {
method: 'POST',
params: { favorite: true },
});
});
it('应该成功取消收藏帖子', async () => {
const mockResponse = { code: 200, msg: '取消收藏成功' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.toggleFavorite(1, false);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/favorite/1', {
method: 'POST',
params: { favorite: false },
});
});
});
// 点赞相关测试
describe('toggleLike', () => {
it('应该成功点赞帖子', async () => {
const mockResponse = { code: 200, msg: '点赞成功' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.toggleLike(1, true);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/like/1', {
method: 'POST',
params: { like: true },
});
});
it('应该成功取消点赞帖子', async () => {
const mockResponse = { code: 200, msg: '取消点赞成功' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.toggleLike(1, false);
expect(result).toEqual(mockResponse);
});
});
// 评论点赞测试
describe('toggleCommentLike', () => {
it('应该成功点赞评论', async () => {
const mockResponse = { code: 200, msg: '点赞成功' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.toggleCommentLike(1, true);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/comment/like/1', {
method: 'POST',
params: { like: true },
});
});
});
// 发布帖子测试
describe('publishPost', () => {
it('应该成功发布帖子', async () => {
const mockResponse = { code: 200, msg: '发布成功' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const postData = {
title: '新帖子标题',
content: '新帖子内容',
summary: '新帖子摘要',
tags: 'tag1,tag2',
promotionPlan: 1
};
const result = await postService.publishPost(postData);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/publish', {
method: 'POST',
data: postData,
});
});
it('应该处理发布帖子失败的情况', async () => {
const mockResponse = { code: 400, msg: '标题不能为空' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.publishPost({
title: '',
content: '内容',
summary: '摘要',
tags: 'tag1'
});
expect(result).toEqual(mockResponse);
});
});
// 个人帖子列表测试
describe('getMyPosts', () => {
it('应该成功获取我的帖子列表', async () => {
const mockResponse = {
code: 200,
rows: [
{
postId: 1,
title: '我的帖子',
author: 'currentUser',
status: '1'
}
],
total: 1
};
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.getMyPosts({ pageNum: 1, pageSize: 10 });
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/my-posts', {
method: 'GET',
params: { pageNum: 1, pageSize: 10 },
});
});
});
// 收藏列表测试
describe('getMyFavorites', () => {
it('应该成功获取我的收藏列表', async () => {
const mockResponse = {
code: 200,
rows: [
{
postId: 1,
title: '收藏的帖子',
author: 'otherUser'
}
],
total: 1
};
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.getMyFavorites({ pageNum: 1, pageSize: 10 });
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/my-favorites', {
method: 'GET',
params: { pageNum: 1, pageSize: 10 },
});
});
});
// 更新帖子测试
describe('updatePost', () => {
it('应该成功更新帖子', async () => {
const postData: API.Post.PostInfo = {
postId: 1,
title: '更新的标题',
content: '更新的内容',
author: 'testuser',
views: 0,
comments: 0,
favorites: 0,
likes: 0,
tags: 'tag1,tag2',
publishTime: new Date().toISOString(),
status: '1'
};
const mockResponse = { code: 200, msg: '更新成功', data: null };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.updatePost(postData);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/update', {
method: 'PUT',
data: postData,
});
});
});
// 删除帖子测试
describe('deletePost', () => {
it('应该成功删除帖子', async () => {
const mockResponse = { code: 200, msg: '删除成功' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.deletePost(1);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/delete/1', {
method: 'DELETE',
});
});
});
// 标签相关测试
describe('tag operations', () => {
it('应该成功获取热门标签', async () => {
const mockResponse = {
code: 200,
data: [
{ tagId: 1, tagName: '日剧', postCount: 10 },
{ tagId: 2, tagName: '电影', postCount: 8 }
]
};
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.getHotTags();
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/tags/hot', {
method: 'GET',
});
});
it('应该成功获取可用标签', async () => {
const mockResponse = {
code: 200,
data: [
{ tagId: 1, tagName: '日剧', tagColor: 'blue' },
{ tagId: 2, tagName: '电影', tagColor: 'green' }
]
};
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.getAvailableTags();
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/tags/available', {
method: 'GET',
});
});
it('应该成功根据标签获取帖子', async () => {
const mockResponse = {
code: 200,
rows: [{ postId: 1, title: '日剧帖子' }],
total: 1
};
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.getPostsByTag(1);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/bytag/1', {
method: 'GET',
});
});
});
// 图片上传测试
describe('image operations', () => {
it('应该成功上传图片', async () => {
const mockResponse = {
code: 200,
data: {
url: '/images/123456_test.jpg',
filename: '123456_test.jpg',
originalName: 'test.jpg',
size: '1024'
}
};
(request as jest.Mock).mockResolvedValue(mockResponse);
const formData = new FormData();
formData.append('file', new Blob(['test'], { type: 'image/jpeg' }));
const result = await postService.uploadImage(formData);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/upload', {
method: 'POST',
data: formData,
});
});
it('应该成功删除图片', async () => {
const mockResponse = { code: 200, msg: '删除成功' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.deleteImage('test.jpg');
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/upload', {
method: 'DELETE',
params: { filename: 'test.jpg' },
});
});
});
// 推广相关测试
describe('promotion operations', () => {
it('应该成功获取推广帖子', async () => {
const mockResponse = {
code: 200,
data: [
{
postId: 1,
title: '推广帖子',
promotionPlanId: 1
}
]
};
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.getPromotionPosts();
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/promotion', {
method: 'GET',
});
});
it('应该成功获取推广计划', async () => {
const mockResponse = {
code: 200,
data: [
{
id: 1,
name: '首页推荐',
description: '帖子显示在首页推荐位置',
price: 50.00,
duration: 7
}
]
};
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.getPromotionPlans();
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/promotion-plans', {
method: 'GET',
});
});
it('应该成功创建支付记录', async () => {
const mockResponse = {
code: 200,
data: {
paymentId: 1,
postId: 1,
planId: 1,
amount: 50.00,
paymentStatus: 'pending'
}
};
(request as jest.Mock).mockResolvedValue(mockResponse);
const paymentData = {
postId: 1,
planId: 1,
amount: 50.00
};
const result = await postService.createPayment(paymentData);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/payment', {
method: 'POST',
data: paymentData,
});
});
it('应该成功获取推广状态', async () => {
const mockResponse = {
code: 200,
data: {
hasPromotion: true,
promotionPlanId: 1
}
};
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.getPromotionStatus(1);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/promotion-status/1', {
method: 'GET',
});
});
it('应该成功确认支付', async () => {
const mockResponse = { code: 200, msg: '支付成功' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.confirmPayment(1);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/payment/confirm/1', {
method: 'POST',
});
});
it('应该成功取消支付', async () => {
const mockResponse = { code: 200, msg: '支付已取消' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.cancelPayment(1);
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/payment/cancel/1', {
method: 'POST',
});
});
});
// 新推广支付流程测试
describe('new promotion payment flow', () => {
it('应该成功执行新推广流程:发布帖子 -> 创建支付 -> 确认支付', async () => {
// 1. 先发布帖子
const publishResponse = {
code: 200,
data: { postId: 123, message: '帖子发布成功' }
};
(request as jest.Mock).mockResolvedValueOnce(publishResponse);
const postData = {
title: '推广帖子标题',
content: '推广帖子内容',
summary: '推广帖子摘要',
tags: 'tag1,tag2'
};
const publishResult = await postService.publishPost(postData);
expect(publishResult).toEqual(publishResponse);
// 2. 创建支付记录(使用真实的帖子ID)
const paymentResponse = {
code: 200,
data: {
paymentId: 1,
postId: 123, // 真实的帖子ID
planId: 1,
amount: 50.00,
paymentStatus: 'pending'
}
};
(request as jest.Mock).mockResolvedValueOnce(paymentResponse);
const paymentData = {
postId: 123, // 使用发布帖子返回的ID
planId: 1,
amount: 50.00
};
const paymentResult = await postService.createPayment(paymentData);
expect(paymentResult).toEqual(paymentResponse);
// 3. 确认支付
const confirmResponse = { code: 200, msg: '支付成功,推广已生效' };
(request as jest.Mock).mockResolvedValueOnce(confirmResponse);
const confirmResult = await postService.confirmPayment(1);
expect(confirmResult).toEqual(confirmResponse);
// 验证API调用顺序和参数
expect(request).toHaveBeenCalledTimes(3);
expect(request).toHaveBeenNthCalledWith(1, '/api/post-center/publish', {
method: 'POST',
data: postData,
});
expect(request).toHaveBeenNthCalledWith(2, '/api/post-center/payment', {
method: 'POST',
data: paymentData,
});
expect(request).toHaveBeenNthCalledWith(3, '/api/post-center/payment/confirm/1', {
method: 'POST',
});
});
it('应该处理支付失败后重新尝试支付的场景', async () => {
// 第一次支付失败,第二次应该复用已创建的帖子
const paymentData = {
postId: 123, // 复用已创建的帖子ID
planId: 1,
amount: 50.00
};
// 第一次支付失败
const failedPaymentResponse = { code: 400, msg: '支付处理失败' };
(request as jest.Mock).mockResolvedValueOnce(failedPaymentResponse);
let result = await postService.createPayment(paymentData);
expect(result).toEqual(failedPaymentResponse);
// 第二次支付成功
const successPaymentResponse = {
code: 200,
data: {
paymentId: 2,
postId: 123,
planId: 1,
amount: 50.00,
paymentStatus: 'pending'
}
};
(request as jest.Mock).mockResolvedValueOnce(successPaymentResponse);
result = await postService.createPayment(paymentData);
expect(result).toEqual(successPaymentResponse);
// 验证使用的是同一个帖子ID
expect(request).toHaveBeenCalledTimes(2);
expect(request).toHaveBeenNthCalledWith(1, '/api/post-center/payment', {
method: 'POST',
data: paymentData,
});
expect(request).toHaveBeenNthCalledWith(2, '/api/post-center/payment', {
method: 'POST',
data: paymentData,
});
});
it('应该成功删除取消发布的草稿帖子', async () => {
const deleteResponse = { code: 200, msg: '草稿帖子删除成功' };
(request as jest.Mock).mockResolvedValue(deleteResponse);
const result = await postService.deletePost(123);
expect(result).toEqual(deleteResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/delete/123', {
method: 'DELETE',
});
});
it('应该处理发布帖子成功但创建支付失败的情况', async () => {
// 1. 发布帖子成功
const publishResponse = {
code: 200,
data: { postId: 123, message: '帖子发布成功' }
};
(request as jest.Mock).mockResolvedValueOnce(publishResponse);
const postData = {
title: '推广帖子标题',
content: '推广帖子内容',
summary: '推广帖子摘要',
tags: 'tag1,tag2'
};
await postService.publishPost(postData);
// 2. 创建支付失败
const paymentResponse = { code: 400, msg: '该帖子已购买推广服务' };
(request as jest.Mock).mockResolvedValueOnce(paymentResponse);
const paymentData = {
postId: 123,
planId: 1,
amount: 50.00
};
const paymentResult = await postService.createPayment(paymentData);
expect(paymentResult).toEqual(paymentResponse);
});
it('应该处理发布帖子失败的情况', async () => {
const publishResponse = { code: 400, msg: '帖子标题不能为空' };
(request as jest.Mock).mockResolvedValue(publishResponse);
const postData = {
title: '',
content: '内容',
summary: '摘要',
tags: 'tag1'
};
const result = await postService.publishPost(postData);
expect(result).toEqual(publishResponse);
});
it('应该处理支付确认失败的情况', async () => {
const confirmResponse = { code: 400, msg: '支付记录中的帖子ID无效' };
(request as jest.Mock).mockResolvedValue(confirmResponse);
const result = await postService.confirmPayment(1);
expect(result).toEqual(confirmResponse);
});
it('应该成功取消支付并返回发布页面', async () => {
const cancelResponse = { code: 200, msg: '支付已取消' };
(request as jest.Mock).mockResolvedValue(cancelResponse);
const result = await postService.cancelPayment(1);
expect(result).toEqual(cancelResponse);
});
it('应该处理重复购买推广的情况', async () => {
const paymentResponse = { code: 400, msg: '该帖子已购买推广服务' };
(request as jest.Mock).mockResolvedValue(paymentResponse);
const paymentData = {
postId: 123,
planId: 1,
amount: 50.00
};
const result = await postService.createPayment(paymentData);
expect(result).toEqual(paymentResponse);
});
});
// 举报相关测试
describe('report operations', () => {
it('应该成功举报帖子', async () => {
const mockResponse = { code: 200, msg: '举报提交成功' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.reportPost(1, '内容不当');
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post-center/report/1', {
method: 'POST',
data: { reason: '内容不当' },
});
});
});
// 管理员功能测试
describe('admin operations', () => {
it('应该成功获取待审核帖子', async () => {
const mockResponse = {
code: 200,
rows: [
{
postId: 1,
title: '待审核帖子',
status: '0'
}
],
total: 1
};
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.getReviewPosts({ status: '0' });
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post/review/list', {
method: 'GET',
params: { status: '0' },
});
});
it('应该成功审核帖子', async () => {
const mockResponse = { code: 200, msg: '审核成功' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.reviewPost(1, 'approve', '内容合规');
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post/review/1', {
method: 'PUT',
data: { action: 'approve', reason: '内容合规' },
});
});
it('应该成功下架帖子', async () => {
const mockResponse = { code: 200, msg: '下架成功' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.takeDownPost(1, '违规内容');
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post/takedown/1', {
method: 'PUT',
data: { reason: '违规内容' },
});
});
it('应该成功获取举报列表', async () => {
const mockResponse = {
code: 200,
rows: [
{
reportId: 1,
postId: 1,
reportReason: '内容不当',
status: '0'
}
],
total: 1
};
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.getReportList({});
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post/report/list', {
method: 'GET',
params: {},
});
});
it('应该成功处理举报', async () => {
const mockResponse = { code: 200, msg: '举报处理成功' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.handleReport(1, 'approve', 1, '举报属实');
expect(result).toEqual(mockResponse);
expect(request).toHaveBeenCalledWith('/api/post/report/handle/1', {
method: 'PUT',
data: { action: 'approve', postId: 1, reason: '举报属实' },
});
});
});
// 错误处理测试
describe('error handling', () => {
it('应该处理网络错误', async () => {
const error = new Error('Network Error');
(request as jest.Mock).mockRejectedValue(error);
await expect(postService.getPostList({})).rejects.toThrow('Network Error');
});
it('应该处理服务器错误响应', async () => {
const mockResponse = { code: 500, msg: '服务器内部错误' };
(request as jest.Mock).mockResolvedValue(mockResponse);
const result = await postService.getPostList({});
expect(result).toEqual(mockResponse);
});
});
});