chore: 代码风格统一和项目文档添加
主要变更: 1. 代码风格统一 - 统一使用双引号替代单引号 - 保持项目代码风格一致性 - 涵盖所有模块、配置、实体和服务文件 2. 项目文档 - 新增 SECURITY_FIXES_SUMMARY.md - 安全修复总结文档 - 新增 项目问题评估报告.md - 项目问题评估文档 3. 包含修改的文件类别 - 配置文件:app, database, jwt, redis, cache, performance - 实体文件:所有 TypeORM 实体 - 模块文件:所有业务模块 - 公共模块:guards, decorators, interceptors, filters, utils - 测试文件:单元测试和 E2E 测试 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,40 +1,40 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BlacklistService } from './blacklist.service';
|
||||
import { Blacklist } from '../../entities/blacklist.entity';
|
||||
import { User } from '../../entities/user.entity';
|
||||
import { GroupMember } from '../../entities/group-member.entity';
|
||||
import { BlacklistStatus } from '../../common/enums';
|
||||
import { NotFoundException, ForbiddenException } from '@nestjs/common';
|
||||
import { Test, TestingModule } from "@nestjs/testing";
|
||||
import { getRepositoryToken } from "@nestjs/typeorm";
|
||||
import { Repository } from "typeorm";
|
||||
import { BlacklistService } from "./blacklist.service";
|
||||
import { Blacklist } from "../../entities/blacklist.entity";
|
||||
import { User } from "../../entities/user.entity";
|
||||
import { GroupMember } from "../../entities/group-member.entity";
|
||||
import { BlacklistStatus } from "../../common/enums";
|
||||
import { NotFoundException, ForbiddenException } from "@nestjs/common";
|
||||
|
||||
describe('BlacklistService', () => {
|
||||
describe("BlacklistService", () => {
|
||||
let service: BlacklistService;
|
||||
let blacklistRepository: Repository<Blacklist>;
|
||||
let userRepository: Repository<User>;
|
||||
let groupMemberRepository: Repository<GroupMember>;
|
||||
|
||||
const mockBlacklist = {
|
||||
id: 'blacklist-1',
|
||||
reporterId: 'user-1',
|
||||
targetGameId: 'game-123',
|
||||
targetNickname: '违规玩家',
|
||||
reason: '恶意行为',
|
||||
proofImages: ['image1.jpg'],
|
||||
id: "blacklist-1",
|
||||
reporterId: "user-1",
|
||||
targetGameId: "game-123",
|
||||
targetNickname: "违规玩家",
|
||||
reason: "恶意行为",
|
||||
proofImages: ["image1.jpg"],
|
||||
status: BlacklistStatus.PENDING,
|
||||
createdAt: new Date(),
|
||||
};
|
||||
|
||||
const mockUser = {
|
||||
id: 'user-1',
|
||||
username: '举报人',
|
||||
id: "user-1",
|
||||
username: "举报人",
|
||||
isMember: true,
|
||||
};
|
||||
|
||||
const mockGroupMember = {
|
||||
id: 'member-1',
|
||||
userId: 'user-1',
|
||||
groupId: 'group-1',
|
||||
id: "member-1",
|
||||
userId: "user-1",
|
||||
groupId: "group-1",
|
||||
};
|
||||
|
||||
const mockQueryBuilder = {
|
||||
@@ -76,43 +76,53 @@ describe('BlacklistService', () => {
|
||||
}).compile();
|
||||
|
||||
service = module.get<BlacklistService>(BlacklistService);
|
||||
blacklistRepository = module.get<Repository<Blacklist>>(getRepositoryToken(Blacklist));
|
||||
blacklistRepository = module.get<Repository<Blacklist>>(
|
||||
getRepositoryToken(Blacklist),
|
||||
);
|
||||
userRepository = module.get<Repository<User>>(getRepositoryToken(User));
|
||||
groupMemberRepository = module.get<Repository<GroupMember>>(getRepositoryToken(GroupMember));
|
||||
groupMemberRepository = module.get<Repository<GroupMember>>(
|
||||
getRepositoryToken(GroupMember),
|
||||
);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
it("should be defined", () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
|
||||
describe('create', () => {
|
||||
it('应该成功创建黑名单举报', async () => {
|
||||
describe("create", () => {
|
||||
it("应该成功创建黑名单举报", async () => {
|
||||
const createDto = {
|
||||
targetGameId: 'game-123',
|
||||
targetNickname: '违规玩家',
|
||||
reason: '恶意行为',
|
||||
proofImages: ['image1.jpg'],
|
||||
targetGameId: "game-123",
|
||||
targetNickname: "违规玩家",
|
||||
reason: "恶意行为",
|
||||
proofImages: ["image1.jpg"],
|
||||
};
|
||||
|
||||
jest.spyOn(userRepository, 'findOne').mockResolvedValue(mockUser as any);
|
||||
jest.spyOn(blacklistRepository, 'create').mockReturnValue(mockBlacklist as any);
|
||||
jest.spyOn(blacklistRepository, 'save').mockResolvedValue(mockBlacklist as any);
|
||||
jest.spyOn(blacklistRepository, 'findOne').mockResolvedValue(mockBlacklist as any);
|
||||
jest.spyOn(userRepository, "findOne").mockResolvedValue(mockUser as any);
|
||||
jest
|
||||
.spyOn(blacklistRepository, "create")
|
||||
.mockReturnValue(mockBlacklist as any);
|
||||
jest
|
||||
.spyOn(blacklistRepository, "save")
|
||||
.mockResolvedValue(mockBlacklist as any);
|
||||
jest
|
||||
.spyOn(blacklistRepository, "findOne")
|
||||
.mockResolvedValue(mockBlacklist as any);
|
||||
|
||||
const result = await service.create('user-1', createDto);
|
||||
const result = await service.create("user-1", createDto);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(blacklistRepository.create).toHaveBeenCalledWith({
|
||||
...createDto,
|
||||
reporterId: 'user-1',
|
||||
reporterId: "user-1",
|
||||
status: BlacklistStatus.PENDING,
|
||||
});
|
||||
expect(blacklistRepository.save).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('findAll', () => {
|
||||
it('应该返回黑名单列表', async () => {
|
||||
describe("findAll", () => {
|
||||
it("应该返回黑名单列表", async () => {
|
||||
const query = { status: BlacklistStatus.APPROVED };
|
||||
mockQueryBuilder.getMany.mockResolvedValue([mockBlacklist]);
|
||||
|
||||
@@ -122,151 +132,170 @@ describe('BlacklistService', () => {
|
||||
expect(blacklistRepository.createQueryBuilder).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('应该支持按状态筛选', async () => {
|
||||
it("应该支持按状态筛选", async () => {
|
||||
const query = { status: BlacklistStatus.PENDING };
|
||||
|
||||
|
||||
mockQueryBuilder.getMany.mockResolvedValue([mockBlacklist]);
|
||||
|
||||
await service.findAll(query);
|
||||
|
||||
expect(mockQueryBuilder.andWhere).toHaveBeenCalledWith(
|
||||
'blacklist.status = :status',
|
||||
{ status: BlacklistStatus.PENDING }
|
||||
"blacklist.status = :status",
|
||||
{ status: BlacklistStatus.PENDING },
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findOne', () => {
|
||||
it('应该返回单个黑名单记录', async () => {
|
||||
jest.spyOn(blacklistRepository, 'findOne').mockResolvedValue(mockBlacklist as any);
|
||||
describe("findOne", () => {
|
||||
it("应该返回单个黑名单记录", async () => {
|
||||
jest
|
||||
.spyOn(blacklistRepository, "findOne")
|
||||
.mockResolvedValue(mockBlacklist as any);
|
||||
|
||||
const result = await service.findOne('blacklist-1');
|
||||
const result = await service.findOne("blacklist-1");
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result.id).toBe('blacklist-1');
|
||||
expect(result.id).toBe("blacklist-1");
|
||||
});
|
||||
|
||||
it('记录不存在时应该抛出异常', async () => {
|
||||
jest.spyOn(blacklistRepository, 'findOne').mockResolvedValue(null);
|
||||
it("记录不存在时应该抛出异常", async () => {
|
||||
jest.spyOn(blacklistRepository, "findOne").mockResolvedValue(null);
|
||||
|
||||
await expect(service.findOne('non-existent')).rejects.toThrow(NotFoundException);
|
||||
await expect(service.findOne("non-existent")).rejects.toThrow(
|
||||
NotFoundException,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('review', () => {
|
||||
it('应该成功审核黑名单(会员权限)', async () => {
|
||||
describe("review", () => {
|
||||
it("应该成功审核黑名单(会员权限)", async () => {
|
||||
const reviewDto = {
|
||||
status: BlacklistStatus.APPROVED,
|
||||
reviewNote: '确认违规',
|
||||
reviewNote: "确认违规",
|
||||
};
|
||||
|
||||
const updatedBlacklist = {
|
||||
...mockBlacklist,
|
||||
...reviewDto,
|
||||
reviewerId: 'user-1',
|
||||
reviewerId: "user-1",
|
||||
};
|
||||
|
||||
jest.spyOn(userRepository, 'findOne').mockResolvedValue(mockUser as any);
|
||||
jest.spyOn(blacklistRepository, 'findOne')
|
||||
jest.spyOn(userRepository, "findOne").mockResolvedValue(mockUser as any);
|
||||
jest
|
||||
.spyOn(blacklistRepository, "findOne")
|
||||
.mockResolvedValueOnce(mockBlacklist as any) // First call in review method
|
||||
.mockResolvedValueOnce(updatedBlacklist as any); // Second call in findOne at the end
|
||||
jest.spyOn(blacklistRepository, 'save').mockResolvedValue(updatedBlacklist as any);
|
||||
jest
|
||||
.spyOn(blacklistRepository, "save")
|
||||
.mockResolvedValue(updatedBlacklist as any);
|
||||
|
||||
const result = await service.review('user-1', 'blacklist-1', reviewDto);
|
||||
const result = await service.review("user-1", "blacklist-1", reviewDto);
|
||||
|
||||
expect(result.status).toBe(BlacklistStatus.APPROVED);
|
||||
expect(blacklistRepository.save).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('非会员审核时应该抛出异常', async () => {
|
||||
it("非会员审核时应该抛出异常", async () => {
|
||||
const reviewDto = {
|
||||
status: BlacklistStatus.APPROVED,
|
||||
};
|
||||
|
||||
jest.spyOn(userRepository, 'findOne').mockResolvedValue({
|
||||
jest.spyOn(userRepository, "findOne").mockResolvedValue({
|
||||
...mockUser,
|
||||
isMember: false,
|
||||
} as any);
|
||||
|
||||
await expect(service.review('user-1', 'blacklist-1', reviewDto)).rejects.toThrow(ForbiddenException);
|
||||
await expect(
|
||||
service.review("user-1", "blacklist-1", reviewDto),
|
||||
).rejects.toThrow(ForbiddenException);
|
||||
});
|
||||
|
||||
it('用户不存在时应该抛出异常', async () => {
|
||||
it("用户不存在时应该抛出异常", async () => {
|
||||
const reviewDto = {
|
||||
status: BlacklistStatus.APPROVED,
|
||||
};
|
||||
|
||||
jest.spyOn(userRepository, 'findOne').mockResolvedValue(null);
|
||||
jest.spyOn(userRepository, "findOne").mockResolvedValue(null);
|
||||
|
||||
await expect(service.review('user-1', 'blacklist-1', reviewDto)).rejects.toThrow(ForbiddenException);
|
||||
await expect(
|
||||
service.review("user-1", "blacklist-1", reviewDto),
|
||||
).rejects.toThrow(ForbiddenException);
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkBlacklist', () => {
|
||||
it('应该正确检查玩家是否在黑名单', async () => {
|
||||
jest.spyOn(blacklistRepository, 'findOne').mockResolvedValue({
|
||||
describe("checkBlacklist", () => {
|
||||
it("应该正确检查玩家是否在黑名单", async () => {
|
||||
jest.spyOn(blacklistRepository, "findOne").mockResolvedValue({
|
||||
...mockBlacklist,
|
||||
status: BlacklistStatus.APPROVED,
|
||||
} as any);
|
||||
|
||||
const result = await service.checkBlacklist('game-123');
|
||||
const result = await service.checkBlacklist("game-123");
|
||||
|
||||
expect(result.isBlacklisted).toBe(true);
|
||||
expect(result.blacklist).toBeDefined();
|
||||
expect(blacklistRepository.findOne).toHaveBeenCalledWith({
|
||||
where: {
|
||||
targetGameId: 'game-123',
|
||||
targetGameId: "game-123",
|
||||
status: BlacklistStatus.APPROVED,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('玩家不在黑名单时应该返回false', async () => {
|
||||
jest.spyOn(blacklistRepository, 'findOne').mockResolvedValue(null);
|
||||
it("玩家不在黑名单时应该返回false", async () => {
|
||||
jest.spyOn(blacklistRepository, "findOne").mockResolvedValue(null);
|
||||
|
||||
const result = await service.checkBlacklist('game-123');
|
||||
const result = await service.checkBlacklist("game-123");
|
||||
|
||||
expect(result.isBlacklisted).toBe(false);
|
||||
expect(result.blacklist).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('remove', () => {
|
||||
it('举报人应该可以删除自己的举报', async () => {
|
||||
jest.spyOn(blacklistRepository, 'findOne').mockResolvedValue(mockBlacklist as any);
|
||||
jest.spyOn(userRepository, 'findOne').mockResolvedValue(mockUser as any);
|
||||
jest.spyOn(blacklistRepository, 'remove').mockResolvedValue(mockBlacklist as any);
|
||||
describe("remove", () => {
|
||||
it("举报人应该可以删除自己的举报", async () => {
|
||||
jest
|
||||
.spyOn(blacklistRepository, "findOne")
|
||||
.mockResolvedValue(mockBlacklist as any);
|
||||
jest.spyOn(userRepository, "findOne").mockResolvedValue(mockUser as any);
|
||||
jest
|
||||
.spyOn(blacklistRepository, "remove")
|
||||
.mockResolvedValue(mockBlacklist as any);
|
||||
|
||||
const result = await service.remove('user-1', 'blacklist-1');
|
||||
const result = await service.remove("user-1", "blacklist-1");
|
||||
|
||||
expect(result.message).toBe('删除成功');
|
||||
expect(result.message).toBe("删除成功");
|
||||
expect(blacklistRepository.remove).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('会员应该可以删除任何举报', async () => {
|
||||
jest.spyOn(blacklistRepository, 'findOne').mockResolvedValue({
|
||||
it("会员应该可以删除任何举报", async () => {
|
||||
jest.spyOn(blacklistRepository, "findOne").mockResolvedValue({
|
||||
...mockBlacklist,
|
||||
reporterId: 'other-user',
|
||||
reporterId: "other-user",
|
||||
} as any);
|
||||
jest.spyOn(userRepository, 'findOne').mockResolvedValue(mockUser as any);
|
||||
jest.spyOn(blacklistRepository, 'remove').mockResolvedValue(mockBlacklist as any);
|
||||
jest.spyOn(userRepository, "findOne").mockResolvedValue(mockUser as any);
|
||||
jest
|
||||
.spyOn(blacklistRepository, "remove")
|
||||
.mockResolvedValue(mockBlacklist as any);
|
||||
|
||||
const result = await service.remove('user-1', 'blacklist-1');
|
||||
const result = await service.remove("user-1", "blacklist-1");
|
||||
|
||||
expect(result.message).toBe('删除成功');
|
||||
expect(result.message).toBe("删除成功");
|
||||
});
|
||||
|
||||
it('非举报人且非会员删除时应该抛出异常', async () => {
|
||||
jest.spyOn(blacklistRepository, 'findOne').mockResolvedValue({
|
||||
it("非举报人且非会员删除时应该抛出异常", async () => {
|
||||
jest.spyOn(blacklistRepository, "findOne").mockResolvedValue({
|
||||
...mockBlacklist,
|
||||
reporterId: 'other-user',
|
||||
reporterId: "other-user",
|
||||
} as any);
|
||||
jest.spyOn(userRepository, 'findOne').mockResolvedValue({
|
||||
jest.spyOn(userRepository, "findOne").mockResolvedValue({
|
||||
...mockUser,
|
||||
isMember: false,
|
||||
} as any);
|
||||
|
||||
await expect(service.remove('user-1', 'blacklist-1')).rejects.toThrow(ForbiddenException);
|
||||
await expect(service.remove("user-1", "blacklist-1")).rejects.toThrow(
|
||||
ForbiddenException,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user