code quality
Some checks failed
CI / lint-typecheck (pull_request) Failing after 12s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
Some checks failed
CI / lint-typecheck (pull_request) Failing after 12s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
/**
|
||||
* Application Use Case Tests: CloseAdminVoteSessionUseCase
|
||||
*
|
||||
*
|
||||
* Tests for closing admin vote sessions and generating rating events
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { describe, it, expect, vi, beforeEach, Mock } from 'vitest';
|
||||
import { CloseAdminVoteSessionUseCase } from './CloseAdminVoteSessionUseCase';
|
||||
import { RatingEventFactory } from '../../domain/services/RatingEventFactory';
|
||||
import { RatingSnapshotCalculator } from '../../domain/services/RatingSnapshotCalculator';
|
||||
import { AdminVoteSessionRepository } from '../../domain/repositories/AdminVoteSessionRepository';
|
||||
import { RatingEventRepository } from '../../domain/repositories/RatingEventRepository';
|
||||
import { UserRatingRepository } from '../../domain/repositories/UserRatingRepository';
|
||||
import { AdminVoteSession, AdminVoteOutcome } from '../../domain/entities/AdminVoteSession';
|
||||
|
||||
// Mock repositories
|
||||
const createMockRepositories = () => ({
|
||||
@@ -51,14 +55,14 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
beforeEach(() => {
|
||||
mockRepositories = createMockRepositories();
|
||||
useCase = new CloseAdminVoteSessionUseCase(
|
||||
mockRepositories.adminVoteSessionRepository,
|
||||
mockRepositories.ratingEventRepository,
|
||||
mockRepositories.userRatingRepository
|
||||
mockRepositories.adminVoteSessionRepository as unknown as AdminVoteSessionRepository,
|
||||
mockRepositories.ratingEventRepository as unknown as RatingEventRepository,
|
||||
mockRepositories.userRatingRepository as unknown as UserRatingRepository
|
||||
);
|
||||
vi.clearAllMocks();
|
||||
// Default mock for RatingEventFactory.createFromVote to return an empty array
|
||||
// to avoid "events is not iterable" error in tests that don't explicitly mock it
|
||||
(RatingEventFactory.createFromVote as any).mockReturnValue([]);
|
||||
(RatingEventFactory.createFromVote as unknown as Mock).mockReturnValue([]);
|
||||
});
|
||||
|
||||
describe('Input validation', () => {
|
||||
@@ -84,7 +88,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
it('should accept valid input', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -144,7 +157,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
it('should find session by ID when provided', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -186,7 +208,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
describe('Admin ownership validation', () => {
|
||||
it('should reject when admin does not own the session', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'different-admin',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -227,7 +258,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
it('should accept when admin owns the session', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -269,7 +309,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
describe('Session closure validation', () => {
|
||||
it('should reject when session is already closed', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -310,7 +359,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
it('should accept when session is not closed', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -352,7 +410,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
describe('Voting window validation', () => {
|
||||
it('should reject when trying to close outside voting window', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -388,7 +455,7 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
constructor() {
|
||||
super('2026-02-02');
|
||||
}
|
||||
} as any;
|
||||
} as unknown as typeof Date;
|
||||
|
||||
const result = await useCase.execute({
|
||||
voteSessionId: 'session-123',
|
||||
@@ -404,7 +471,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
it('should accept when trying to close within voting window', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -440,7 +516,7 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
constructor() {
|
||||
super('2026-01-15T12:00:00');
|
||||
}
|
||||
} as any;
|
||||
} as unknown as typeof Date;
|
||||
|
||||
const result = await useCase.execute({
|
||||
voteSessionId: 'session-123',
|
||||
@@ -457,7 +533,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
describe('Session closure', () => {
|
||||
it('should call close method on session', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -497,7 +582,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
it('should save closed session', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -537,7 +631,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
it('should return outcome in success response', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -585,7 +688,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
describe('Rating event creation', () => {
|
||||
it('should create rating events when outcome is positive', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -616,7 +728,7 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
mockRepositories.adminVoteSessionRepository.findById.mockResolvedValue(mockSession);
|
||||
|
||||
const mockEvent = { id: 'event-123' };
|
||||
(RatingEventFactory.createFromVote as any).mockReturnValue([mockEvent]);
|
||||
(RatingEventFactory.createFromVote as unknown as Mock).mockReturnValue([mockEvent]);
|
||||
|
||||
await useCase.execute({
|
||||
voteSessionId: 'session-123',
|
||||
@@ -635,7 +747,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
it('should create rating events when outcome is negative', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -666,7 +787,7 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
mockRepositories.adminVoteSessionRepository.findById.mockResolvedValue(mockSession);
|
||||
|
||||
const mockEvent = { id: 'event-123' };
|
||||
(RatingEventFactory.createFromVote as any).mockReturnValue([mockEvent]);
|
||||
(RatingEventFactory.createFromVote as unknown as Mock).mockReturnValue([mockEvent]);
|
||||
|
||||
await useCase.execute({
|
||||
voteSessionId: 'session-123',
|
||||
@@ -685,7 +806,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
it('should not create rating events when outcome is tie', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -726,7 +856,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
it('should save created rating events', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -758,7 +897,7 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
const mockEvent1 = { id: 'event-123' };
|
||||
const mockEvent2 = { id: 'event-124' };
|
||||
(RatingEventFactory.createFromVote as any).mockReturnValue([mockEvent1, mockEvent2]);
|
||||
(RatingEventFactory.createFromVote as unknown as Mock).mockReturnValue([mockEvent1, mockEvent2]);
|
||||
|
||||
await useCase.execute({
|
||||
voteSessionId: 'session-123',
|
||||
@@ -772,7 +911,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
it('should return eventsCreated count', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -804,7 +952,7 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
const mockEvent1 = { id: 'event-123' };
|
||||
const mockEvent2 = { id: 'event-124' };
|
||||
(RatingEventFactory.createFromVote as any).mockReturnValue([mockEvent1, mockEvent2]);
|
||||
(RatingEventFactory.createFromVote as unknown as Mock).mockReturnValue([mockEvent1, mockEvent2]);
|
||||
|
||||
const result = await useCase.execute({
|
||||
voteSessionId: 'session-123',
|
||||
@@ -818,7 +966,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
describe('Snapshot recalculation', () => {
|
||||
it('should recalculate snapshot when events are created', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -849,13 +1006,13 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
mockRepositories.adminVoteSessionRepository.findById.mockResolvedValue(mockSession);
|
||||
|
||||
const mockEvent = { id: 'event-123' };
|
||||
(RatingEventFactory.createFromVote as any).mockReturnValue([mockEvent]);
|
||||
(RatingEventFactory.createFromVote as unknown as Mock).mockReturnValue([mockEvent]);
|
||||
|
||||
const mockAllEvents = [{ id: 'event-1' }, { id: 'event-2' }];
|
||||
mockRepositories.ratingEventRepository.getAllByUserId.mockResolvedValue(mockAllEvents);
|
||||
|
||||
const mockSnapshot = { userId: 'admin-123', overallReputation: 75 };
|
||||
(RatingSnapshotCalculator.calculate as any).mockReturnValue(mockSnapshot);
|
||||
(RatingSnapshotCalculator.calculate as unknown as Mock).mockReturnValue(mockSnapshot);
|
||||
|
||||
await useCase.execute({
|
||||
voteSessionId: 'session-123',
|
||||
@@ -869,7 +1026,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
it('should not recalculate snapshot when no events are created (tie)', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -937,7 +1103,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
|
||||
it('should handle save errors gracefully', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
@@ -981,7 +1156,16 @@ describe('CloseAdminVoteSessionUseCase', () => {
|
||||
describe('Return values', () => {
|
||||
it('should return voteSessionId in success response', async () => {
|
||||
const futureDate = new Date('2026-02-01');
|
||||
const mockSession: any = {
|
||||
const mockSession: {
|
||||
id: string;
|
||||
adminId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
_closed: boolean;
|
||||
_outcome?: AdminVoteOutcome;
|
||||
close: Mock;
|
||||
closed: boolean;
|
||||
} = {
|
||||
id: 'session-123',
|
||||
adminId: 'admin-123',
|
||||
startDate: new Date('2026-01-01'),
|
||||
|
||||
Reference in New Issue
Block a user