Files
gongxue-base/apps/server/src/notifications/notifications.service.spec.ts

62 lines
2.3 KiB
TypeScript

import { BadRequestException, NotFoundException } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { NotificationsService } from './notifications.service';
function createQueryBuilder() {
return {
where: jest.fn().mockReturnThis(),
orderBy: jest.fn().mockReturnThis(),
take: jest.fn().mockReturnThis(),
andWhere: jest.fn().mockReturnThis(),
getMany: jest.fn().mockResolvedValue([]),
};
}
describe('NotificationsService boundaries', () => {
it('rejects empty recipients and de-duplicates repeated recipients', async () => {
const repo = {
save: jest.fn().mockImplementation(async (rows) => rows),
};
const service = new NotificationsService(repo as never, { emit: jest.fn() } as never);
await expect(
service.create({ recipientIds: [], type: 'test', title: '标题' }),
).rejects.toBeInstanceOf(BadRequestException);
const saved = await service.create({ recipientIds: [1, 1, 2], type: 'test', title: '标题' });
expect(saved).toHaveLength(2);
expect(repo.save).toHaveBeenCalledWith([
expect.objectContaining({ recipientId: 1 }),
expect.objectContaining({ recipientId: 2 }),
]);
});
it('clamps service-level page size to protect callers outside the controller', async () => {
const qb = createQueryBuilder();
const service = new NotificationsService(
{ createQueryBuilder: jest.fn().mockReturnValue(qb) } as never,
new EventEmitter2(),
);
await service.findByUser(7, undefined, 1000);
expect(qb.take).toHaveBeenCalledWith(100);
});
it('does not allow marking another user notification as read', async () => {
const repo = { findOne: jest.fn().mockResolvedValue(null), update: jest.fn() };
const service = new NotificationsService(repo as never, new EventEmitter2());
await expect(service.markRead(3, 7)).rejects.toBeInstanceOf(NotFoundException);
expect(repo.update).not.toHaveBeenCalled();
});
it('treats marking an already-read notification as idempotent', async () => {
const repo = {
findOne: jest.fn().mockResolvedValue({ id: 3, recipientId: 7, isRead: true }),
update: jest.fn(),
};
const service = new NotificationsService(repo as never, new EventEmitter2());
await expect(service.markRead(3, 7)).resolves.toBeUndefined();
expect(repo.update).not.toHaveBeenCalled();
});
});