import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { NoticeService } from './notice.service'; import { NoticeGateway } from './notice.gateway'; import { Notice, NoticeStatus, NoticeType } from './notice.entity'; describe('NoticeService', () => { let service: NoticeService; let repository: Repository; let gateway: NoticeGateway; const mockRepository = { create: jest.fn(), save: jest.fn(), find: jest.fn(), findOne: jest.fn(), count: jest.fn(), createQueryBuilder: jest.fn(), }; const mockGateway = { sendToUser: jest.fn(), broadcast: jest.fn(), }; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ NoticeService, { provide: getRepositoryToken(Notice), useValue: mockRepository, }, { provide: NoticeGateway, useValue: mockGateway, }, ], }).compile(); service = module.get(NoticeService); repository = module.get>(getRepositoryToken(Notice)); gateway = module.get(NoticeGateway); }); afterEach(() => { jest.clearAllMocks(); }); describe('create', () => { it('should create and send notice immediately when no scheduledAt', async () => { const createDto = { title: 'Test Notice', content: 'Test Content', userId: 1, }; const mockNotice = { id: 1, ...createDto, status: NoticeStatus.PENDING, type: NoticeType.SYSTEM, scheduledAt: null, }; mockRepository.create.mockReturnValue(mockNotice); mockRepository.save.mockResolvedValueOnce(mockNotice); mockRepository.save.mockResolvedValueOnce({ ...mockNotice, status: NoticeStatus.SENT, sentAt: new Date(), }); const result = await service.create(createDto); expect(mockRepository.create).toHaveBeenCalledWith({ ...createDto, scheduledAt: null, }); expect(mockRepository.save).toHaveBeenCalledTimes(2); expect(mockGateway.sendToUser).toHaveBeenCalledWith(1, { type: 'notice', data: mockNotice, }); }); it('should create scheduled notice without sending immediately', async () => { const scheduledAt = new Date(Date.now() + 3600000); // 1 hour later const createDto = { title: 'Scheduled Notice', content: 'Scheduled Content', scheduledAt: scheduledAt.toISOString(), }; const mockNotice = { id: 1, ...createDto, scheduledAt, status: NoticeStatus.PENDING, }; mockRepository.create.mockReturnValue(mockNotice); mockRepository.save.mockResolvedValue(mockNotice); const result = await service.create(createDto); expect(mockGateway.sendToUser).not.toHaveBeenCalled(); expect(mockGateway.broadcast).not.toHaveBeenCalled(); }); }); describe('sendSystemNotice', () => { it('should create and send system notice', async () => { const mockNotice = { id: 1, title: 'System Notice', content: 'System Content', type: NoticeType.SYSTEM, userId: 1, status: NoticeStatus.PENDING, }; mockRepository.create.mockReturnValue(mockNotice); mockRepository.save.mockResolvedValueOnce(mockNotice); mockRepository.save.mockResolvedValueOnce({ ...mockNotice, status: NoticeStatus.SENT, }); const result = await service.sendSystemNotice('System Notice', 'System Content', 1); expect(result.type).toBe(NoticeType.SYSTEM); expect(mockGateway.sendToUser).toHaveBeenCalled(); }); }); describe('sendBroadcast', () => { it('should create and send broadcast notice', async () => { const mockNotice = { id: 1, title: 'Broadcast Notice', content: 'Broadcast Content', type: NoticeType.BROADCAST, userId: null, status: NoticeStatus.PENDING, }; mockRepository.create.mockReturnValue(mockNotice); mockRepository.save.mockResolvedValueOnce(mockNotice); mockRepository.save.mockResolvedValueOnce({ ...mockNotice, status: NoticeStatus.SENT, }); const result = await service.sendBroadcast('Broadcast Notice', 'Broadcast Content'); expect(result.type).toBe(NoticeType.BROADCAST); expect(mockGateway.broadcast).toHaveBeenCalled(); }); }); describe('markAsRead', () => { it('should mark notice as read', async () => { const mockNotice = { id: 1, userId: 1, status: NoticeStatus.SENT, }; const updatedNotice = { ...mockNotice, status: NoticeStatus.READ, readAt: new Date(), }; mockRepository.findOne.mockResolvedValue(mockNotice); mockRepository.save.mockResolvedValue(updatedNotice); const result = await service.markAsRead(1, 1); expect(result.status).toBe(NoticeStatus.READ); expect(result.readAt).toBeDefined(); }); }); describe('getUserUnreadCount', () => { it('should return unread count for user', async () => { mockRepository.count.mockResolvedValue(5); const count = await service.getUserUnreadCount(1); expect(count).toBe(5); expect(mockRepository.count).toHaveBeenCalledWith({ where: [ { userId: 1, status: NoticeStatus.SENT }, { userId: null, status: NoticeStatus.SENT }, ], }); }); }); });