文件
shanghaipeiwan/server/tests/review-comment.spec.ts

159 行
4.7 KiB
TypeScript

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

import { ReviewAndCommentService } from '../src/core/review/review.service';
import { OrderStatus } from '../src/core/order/order-state-machine';
describe('ReviewAndCommentService (TDD 订单评价打分与动态评论测试套件)', () => {
let service: ReviewAndCommentService;
beforeEach(() => {
service = new ReviewAndCommentService();
});
describe('1. 订单评价业务规则与越权拦截', () => {
it('已完成(COMPLETED)状态的订单成功提交 5 星好评与评价标签', () => {
const review = service.submitOrderReview({
orderId: 'ord_1001',
orderStatus: OrderStatus.COMPLETED,
expertId: 101,
userId: 2001,
userNickname: '电竞小王子',
rating: 5,
tags: ['技术强', '声音好听', '带飞吃鸡'],
content: '大神非常给力,连续吃鸡3把!'
});
expect(review.id).toBeDefined();
expect(review.rating).toBe(5);
expect(review.tags).toContain('带飞吃鸡');
expect(review.orderId).toBe('ord_1001');
});
it('非 COMPLETED 状态的订单(如服务中/待付款)尝试评价应被拒绝拦截', () => {
expect(() => {
service.submitOrderReview({
orderId: 'ord_1002',
orderStatus: OrderStatus.IN_SERVICE,
expertId: 101,
userId: 2001,
userNickname: '小李',
rating: 5,
});
}).toThrow('只有已完成(COMPLETED)状态的订单才允许提交服务评价');
});
it('评分小于 1 或大于 5 时应抛出参数校验异常', () => {
expect(() => {
service.submitOrderReview({
orderId: 'ord_1003',
orderStatus: OrderStatus.COMPLETED,
expertId: 101,
userId: 2001,
userNickname: '小李',
rating: 6,
});
}).toThrow('评分必须在 1 至 5 星之间');
expect(() => {
service.submitOrderReview({
orderId: 'ord_1004',
orderStatus: OrderStatus.COMPLETED,
expertId: 101,
userId: 2001,
userNickname: '小李',
rating: 0,
});
}).toThrow('评分必须在 1 至 5 星之间');
});
it('同一订单禁止重复提交评价(防刷评)', () => {
service.submitOrderReview({
orderId: 'ord_1005',
orderStatus: OrderStatus.COMPLETED,
expertId: 101,
userId: 2001,
userNickname: '小李',
rating: 5,
});
expect(() => {
service.submitOrderReview({
orderId: 'ord_1005',
orderStatus: OrderStatus.COMPLETED,
expertId: 101,
userId: 2001,
userNickname: '小李',
rating: 4,
});
}).toThrow('该订单已评价,不可重复提交评价');
});
it('大神新增多条评价后,动态综合平均评分计算准确', () => {
service.submitOrderReview({
orderId: 'ord_201',
orderStatus: OrderStatus.COMPLETED,
expertId: 102,
userId: 301,
userNickname: '玩家A',
rating: 5,
});
service.submitOrderReview({
orderId: 'ord_202',
orderStatus: OrderStatus.COMPLETED,
expertId: 102,
userId: 302,
userNickname: '玩家B',
rating: 4,
});
const avg = service.calculateExpertAverageRating(102);
expect(avg).toBe(4.5);
});
});
describe('2. 友圈动态互动评论区规则', () => {
it('成功发表动态互动评论并支持按动态聚合查询', () => {
const c1 = service.submitPostComment({
postId: 'post_001',
userId: 2001,
author: '三里屯吃货',
content: '我也在三里屯,求组队!'
});
const c2 = service.submitPostComment({
postId: 'post_001',
userId: 2002,
author: '火锅达人',
content: '晚上几点开饭?已加微。'
});
const list = service.getCommentsByPost('post_001');
expect(list.length).toBe(2);
expect(list[0].id).toBe(c1.id);
expect(list[1].id).toBe(c2.id);
});
it('空评论或纯空格评论应被拦截', () => {
expect(() => {
service.submitPostComment({
postId: 'post_001',
userId: 2001,
author: '张三',
content: ' '
});
}).toThrow('评论内容不能为空');
});
it('超长评论(超过500字)应被安全阻断', () => {
const longText = 'a'.repeat(501);
expect(() => {
service.submitPostComment({
postId: 'post_001',
userId: 2001,
author: '张三',
content: longText
});
}).toThrow('评论内容不能超过 500 个字符');
});
});
});