89 lines
3.2 KiB
TypeScript
89 lines
3.2 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import type { IIssueRepository } from '../../../domain/repositories/issue.repository.interface.js';
|
|
import { Issue } from '../../../domain/entities/issue.entity.js';
|
|
import { InvalidCalendarRangeException } from '../../../domain/exceptions/invalid-calendar-range.exception.js';
|
|
import { ListCalendarIssuesUseCase } from './list-calendar-issues.use-case.js';
|
|
import { ListCalendarIssuesQuery } from './list-calendar-issues.query.js';
|
|
import type { IssueUserExpanderService } from '../../services/issue-user-expander.service.js';
|
|
import type { IssueWithUsersDto } from '../../dto/issue-with-users.dto.js';
|
|
|
|
const FROM = new Date('2026-09-28T00:00:00+03:00');
|
|
const TO = new Date('2026-11-09T00:00:00+03:00');
|
|
|
|
const buildIssue = (id: number) =>
|
|
Issue.reconstitute({
|
|
id,
|
|
key: `ISSUE-${id}`,
|
|
title: `Issue ${id}`,
|
|
content: null,
|
|
status: 'OPEN',
|
|
priority: 0,
|
|
assignee: null,
|
|
reporter: 'user-1',
|
|
projectId: 'project-1',
|
|
dueDate: new Date('2026-10-15T12:00:00Z'),
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
});
|
|
|
|
describe('ListCalendarIssuesUseCase', () => {
|
|
let repository: IIssueRepository;
|
|
let issueUserExpander: IssueUserExpanderService;
|
|
let useCase: ListCalendarIssuesUseCase;
|
|
|
|
beforeEach(() => {
|
|
repository = {
|
|
findById: vi.fn(),
|
|
findByCKey: vi.fn(),
|
|
findAll: vi.fn(),
|
|
findByDueDateRange: vi.fn(),
|
|
countByStatus: vi.fn(),
|
|
create: vi.fn(),
|
|
update: vi.fn(),
|
|
delete: vi.fn(),
|
|
};
|
|
issueUserExpander = {
|
|
expandAll: vi.fn(async (issues: Issue[]) => issues.map((issue) => ({ id: issue.id }) as IssueWithUsersDto)),
|
|
} as unknown as IssueUserExpanderService;
|
|
useCase = new ListCalendarIssuesUseCase(repository, issueUserExpander);
|
|
});
|
|
|
|
it('forwards the range and filters, asking for one issue more than the limit', async () => {
|
|
vi.mocked(repository.findByDueDateRange).mockResolvedValue([buildIssue(1), buildIssue(2)]);
|
|
|
|
const result = await useCase.execute(
|
|
new ListCalendarIssuesQuery('user-1', FROM, TO, 'project-1', ['OPEN'], 'user-2'),
|
|
);
|
|
|
|
expect(repository.findByDueDateRange).toHaveBeenCalledWith({
|
|
from: FROM,
|
|
to: TO,
|
|
limit: ListCalendarIssuesUseCase.MAX_ISSUES + 1,
|
|
userId: 'user-1',
|
|
projectId: 'project-1',
|
|
status: ['OPEN'],
|
|
assigneeId: 'user-2',
|
|
});
|
|
expect(result).toEqual({ list: [{ id: 1 }, { id: 2 }], truncated: false });
|
|
});
|
|
|
|
it('cuts the list to the limit and marks it as truncated', async () => {
|
|
const issues = Array.from({ length: ListCalendarIssuesUseCase.MAX_ISSUES + 1 }, (_, index) =>
|
|
buildIssue(index + 1),
|
|
);
|
|
vi.mocked(repository.findByDueDateRange).mockResolvedValue(issues);
|
|
|
|
const result = await useCase.execute(new ListCalendarIssuesQuery('user-1', FROM, TO));
|
|
|
|
expect(result.truncated).toBe(true);
|
|
expect(result.list).toHaveLength(ListCalendarIssuesUseCase.MAX_ISSUES);
|
|
});
|
|
|
|
it('rejects an invalid range without querying the repository', async () => {
|
|
await expect(useCase.execute(new ListCalendarIssuesQuery('user-1', TO, FROM))).rejects.toThrow(
|
|
InvalidCalendarRangeException,
|
|
);
|
|
expect(repository.findByDueDateRange).not.toHaveBeenCalled();
|
|
});
|
|
});
|