import { beforeEach, describe, expect, it, vi } from 'vitest'; import type { IIssueRepository } from '../../../../issue/domain/repositories/issue.repository.interface.js'; import { IssueNotFoundException } from '../../../../issue/domain/exceptions/issue-not-found.exception.js'; import { CommentEventsService, type CommentEvent } from '../../services/comment-events.service.js'; import { CommentApplicationMapper } from '../../mappers/comment-application.mapper.js'; import { WatchIssueCommentsUseCase } from './watch-issue-comments.use-case.js'; import { WatchIssueCommentsQuery } from './watch-issue-comments.query.js'; import { buildComment, buildIssue, mockIssueRepository } from '../test-helpers.js'; const dtoForIssue = (issueId: number) => CommentApplicationMapper.toDto(buildComment({ id: `comment-of-${issueId}`, issueId }), new Map()); describe('WatchIssueCommentsUseCase', () => { let issueRepository: IIssueRepository; let commentEventsService: CommentEventsService; let useCase: WatchIssueCommentsUseCase; beforeEach(() => { issueRepository = mockIssueRepository(); commentEventsService = new CommentEventsService(); useCase = new WatchIssueCommentsUseCase(issueRepository, commentEventsService); }); it('streams only events of the requested issue', async () => { vi.mocked(issueRepository.findById).mockResolvedValue(buildIssue()); const received: CommentEvent[] = []; const events$ = await useCase.execute(new WatchIssueCommentsQuery(1, 'user-1')); events$.subscribe((event) => received.push(event)); commentEventsService.emit('comment.created', dtoForIssue(1)); commentEventsService.emit('comment.created', dtoForIssue(2)); expect(received.map((event) => event.comment.id)).toEqual(['comment-of-1']); }); it('throws IssueNotFoundException when the issue is not visible to the user', async () => { vi.mocked(issueRepository.findById).mockResolvedValue(null); await expect(useCase.execute(new WatchIssueCommentsQuery(1, 'user-2'))).rejects.toThrow(IssueNotFoundException); }); });