import { beforeEach, describe, expect, it, vi } from 'vitest'; import type { ICommentRepository } from '../../../domain/repositories/comment.repository.interface.js'; import type { IIssueRepository } from '../../../../issue/domain/repositories/issue.repository.interface.js'; import { IssueNotFoundException } from '../../../../issue/domain/exceptions/issue-not-found.exception.js'; import { ListCommentsUseCase } from './list-comments.use-case.js'; import { ListCommentsQuery } from './list-comments.query.js'; import { buildComment, buildIssue, mockAuthorExpander, mockCommentRepository, mockIssueRepository } from '../test-helpers.js'; describe('ListCommentsUseCase', () => { let commentRepository: ICommentRepository; let issueRepository: IIssueRepository; let useCase: ListCommentsUseCase; beforeEach(() => { commentRepository = mockCommentRepository(); issueRepository = mockIssueRepository(); useCase = new ListCommentsUseCase(commentRepository, issueRepository, mockAuthorExpander()); }); it('forwards pagination params and returns the next cursor', async () => { vi.mocked(issueRepository.findById).mockResolvedValue(buildIssue()); vi.mocked(commentRepository.findByIssue).mockResolvedValue({ list: [buildComment({ id: 'comment-2' })], nextCursor: 'comment-2', }); const result = await useCase.execute(new ListCommentsQuery(1, 'user-1', 1, 'comment-1')); expect(commentRepository.findByIssue).toHaveBeenCalledWith({ issueId: 1, limit: 1, cursor: 'comment-1' }); expect(result.list.map((comment) => comment.id)).toEqual(['comment-2']); expect(result.nextCursor).toBe('comment-2'); }); it('throws IssueNotFoundException when the issue is not visible to the user', async () => { vi.mocked(issueRepository.findById).mockResolvedValue(null); await expect(useCase.execute(new ListCommentsQuery(1, 'user-2', 50))).rejects.toThrow(IssueNotFoundException); expect(commentRepository.findByIssue).not.toHaveBeenCalled(); }); });