core tests
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { GetDriverRankingsUseCase, GetDriverRankingsUseCasePorts } from './GetDriverRankingsUseCase';
|
||||
import { ValidationError } from '../../../shared/errors/ValidationError';
|
||||
|
||||
describe('GetDriverRankingsUseCase', () => {
|
||||
let mockLeaderboardsRepository: any;
|
||||
let mockEventPublisher: any;
|
||||
let ports: GetDriverRankingsUseCasePorts;
|
||||
let useCase: GetDriverRankingsUseCase;
|
||||
|
||||
const mockDrivers = [
|
||||
{ id: '1', name: 'Alice', rating: 2000, raceCount: 10, teamId: 't1', teamName: 'Team A' },
|
||||
{ id: '2', name: 'Bob', rating: 1500, raceCount: 5, teamId: 't2', teamName: 'Team B' },
|
||||
{ id: '3', name: 'Charlie', rating: 1800, raceCount: 8 },
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
mockLeaderboardsRepository = {
|
||||
findAllDrivers: vi.fn().mockResolvedValue([...mockDrivers]),
|
||||
};
|
||||
mockEventPublisher = {
|
||||
publishDriverRankingsAccessed: vi.fn().mockResolvedValue(undefined),
|
||||
publishLeaderboardsError: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
ports = {
|
||||
leaderboardsRepository: mockLeaderboardsRepository,
|
||||
eventPublisher: mockEventPublisher,
|
||||
};
|
||||
useCase = new GetDriverRankingsUseCase(ports);
|
||||
});
|
||||
|
||||
it('should return all drivers sorted by rating DESC by default', async () => {
|
||||
const result = await useCase.execute();
|
||||
|
||||
expect(result.drivers).toHaveLength(3);
|
||||
expect(result.drivers[0].name).toBe('Alice');
|
||||
expect(result.drivers[1].name).toBe('Charlie');
|
||||
expect(result.drivers[2].name).toBe('Bob');
|
||||
expect(result.drivers[0].rank).toBe(1);
|
||||
expect(result.drivers[1].rank).toBe(2);
|
||||
expect(result.drivers[2].rank).toBe(3);
|
||||
expect(mockEventPublisher.publishDriverRankingsAccessed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should filter drivers by search term', async () => {
|
||||
const result = await useCase.execute({ search: 'ali' });
|
||||
|
||||
expect(result.drivers).toHaveLength(1);
|
||||
expect(result.drivers[0].name).toBe('Alice');
|
||||
});
|
||||
|
||||
it('should filter drivers by minRating', async () => {
|
||||
const result = await useCase.execute({ minRating: 1700 });
|
||||
|
||||
expect(result.drivers).toHaveLength(2);
|
||||
expect(result.drivers.map(d => d.name)).toContain('Alice');
|
||||
expect(result.drivers.map(d => d.name)).toContain('Charlie');
|
||||
});
|
||||
|
||||
it('should filter drivers by teamId', async () => {
|
||||
const result = await useCase.execute({ teamId: 't1' });
|
||||
|
||||
expect(result.drivers).toHaveLength(1);
|
||||
expect(result.drivers[0].name).toBe('Alice');
|
||||
});
|
||||
|
||||
it('should sort drivers by name ASC', async () => {
|
||||
const result = await useCase.execute({ sortBy: 'name', sortOrder: 'asc' });
|
||||
|
||||
expect(result.drivers[0].name).toBe('Alice');
|
||||
expect(result.drivers[1].name).toBe('Bob');
|
||||
expect(result.drivers[2].name).toBe('Charlie');
|
||||
});
|
||||
|
||||
it('should paginate results', async () => {
|
||||
const result = await useCase.execute({ page: 2, limit: 1 });
|
||||
|
||||
expect(result.drivers).toHaveLength(1);
|
||||
expect(result.drivers[0].name).toBe('Charlie'); // Alice (1), Charlie (2), Bob (3)
|
||||
expect(result.pagination.total).toBe(3);
|
||||
expect(result.pagination.totalPages).toBe(3);
|
||||
expect(result.pagination.page).toBe(2);
|
||||
});
|
||||
|
||||
it('should throw ValidationError for invalid page', async () => {
|
||||
await expect(useCase.execute({ page: 0 })).rejects.toThrow(ValidationError);
|
||||
expect(mockEventPublisher.publishLeaderboardsError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should throw ValidationError for invalid limit', async () => {
|
||||
await expect(useCase.execute({ limit: 0 })).rejects.toThrow(ValidationError);
|
||||
});
|
||||
|
||||
it('should throw ValidationError for invalid sortBy', async () => {
|
||||
await expect(useCase.execute({ sortBy: 'invalid' as any })).rejects.toThrow(ValidationError);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { GetGlobalLeaderboardsUseCase, GetGlobalLeaderboardsUseCasePorts } from './GetGlobalLeaderboardsUseCase';
|
||||
|
||||
describe('GetGlobalLeaderboardsUseCase', () => {
|
||||
let mockLeaderboardsRepository: any;
|
||||
let mockEventPublisher: any;
|
||||
let ports: GetGlobalLeaderboardsUseCasePorts;
|
||||
let useCase: GetGlobalLeaderboardsUseCase;
|
||||
|
||||
const mockDrivers = [
|
||||
{ id: 'd1', name: 'Alice', rating: 2000, raceCount: 10 },
|
||||
{ id: 'd2', name: 'Bob', rating: 1500, raceCount: 5 },
|
||||
];
|
||||
|
||||
const mockTeams = [
|
||||
{ id: 't1', name: 'Team A', rating: 2500, memberCount: 5, raceCount: 20 },
|
||||
{ id: 't2', name: 'Team B', rating: 2200, memberCount: 3, raceCount: 15 },
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
mockLeaderboardsRepository = {
|
||||
findAllDrivers: vi.fn().mockResolvedValue([...mockDrivers]),
|
||||
findAllTeams: vi.fn().mockResolvedValue([...mockTeams]),
|
||||
};
|
||||
mockEventPublisher = {
|
||||
publishGlobalLeaderboardsAccessed: vi.fn().mockResolvedValue(undefined),
|
||||
publishLeaderboardsError: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
ports = {
|
||||
leaderboardsRepository: mockLeaderboardsRepository,
|
||||
eventPublisher: mockEventPublisher,
|
||||
};
|
||||
useCase = new GetGlobalLeaderboardsUseCase(ports);
|
||||
});
|
||||
|
||||
it('should return top drivers and teams', async () => {
|
||||
const result = await useCase.execute();
|
||||
|
||||
expect(result.drivers).toHaveLength(2);
|
||||
expect(result.drivers[0].name).toBe('Alice');
|
||||
expect(result.drivers[1].name).toBe('Bob');
|
||||
|
||||
expect(result.teams).toHaveLength(2);
|
||||
expect(result.teams[0].name).toBe('Team A');
|
||||
expect(result.teams[1].name).toBe('Team B');
|
||||
|
||||
expect(mockEventPublisher.publishGlobalLeaderboardsAccessed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should respect driver and team limits', async () => {
|
||||
const result = await useCase.execute({ driverLimit: 1, teamLimit: 1 });
|
||||
|
||||
expect(result.drivers).toHaveLength(1);
|
||||
expect(result.drivers[0].name).toBe('Alice');
|
||||
expect(result.teams).toHaveLength(1);
|
||||
expect(result.teams[0].name).toBe('Team A');
|
||||
});
|
||||
|
||||
it('should handle errors and publish error event', async () => {
|
||||
mockLeaderboardsRepository.findAllDrivers.mockRejectedValue(new Error('Repo error'));
|
||||
|
||||
await expect(useCase.execute()).rejects.toThrow('Repo error');
|
||||
expect(mockEventPublisher.publishLeaderboardsError).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,82 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { GetTeamRankingsUseCase, GetTeamRankingsUseCasePorts } from './GetTeamRankingsUseCase';
|
||||
import { ValidationError } from '../../../shared/errors/ValidationError';
|
||||
|
||||
describe('GetTeamRankingsUseCase', () => {
|
||||
let mockLeaderboardsRepository: any;
|
||||
let mockEventPublisher: any;
|
||||
let ports: GetTeamRankingsUseCasePorts;
|
||||
let useCase: GetTeamRankingsUseCase;
|
||||
|
||||
const mockTeams = [
|
||||
{ id: 't1', name: 'Team A', rating: 2500, memberCount: 0, raceCount: 20 },
|
||||
{ id: 't2', name: 'Team B', rating: 2200, memberCount: 0, raceCount: 15 },
|
||||
];
|
||||
|
||||
const mockDrivers = [
|
||||
{ id: 'd1', name: 'Alice', rating: 2000, raceCount: 10, teamId: 't1', teamName: 'Team A' },
|
||||
{ id: 'd2', name: 'Bob', rating: 1500, raceCount: 5, teamId: 't1', teamName: 'Team A' },
|
||||
{ id: 'd3', name: 'Charlie', rating: 1800, raceCount: 8, teamId: 't2', teamName: 'Team B' },
|
||||
{ id: 'd4', name: 'David', rating: 1600, raceCount: 2, teamId: 't3', teamName: 'Discovered Team' },
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
mockLeaderboardsRepository = {
|
||||
findAllTeams: vi.fn().mockResolvedValue([...mockTeams]),
|
||||
findAllDrivers: vi.fn().mockResolvedValue([...mockDrivers]),
|
||||
};
|
||||
mockEventPublisher = {
|
||||
publishTeamRankingsAccessed: vi.fn().mockResolvedValue(undefined),
|
||||
publishLeaderboardsError: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
ports = {
|
||||
leaderboardsRepository: mockLeaderboardsRepository,
|
||||
eventPublisher: mockEventPublisher,
|
||||
};
|
||||
useCase = new GetTeamRankingsUseCase(ports);
|
||||
});
|
||||
|
||||
it('should return teams with aggregated member counts', async () => {
|
||||
const result = await useCase.execute();
|
||||
|
||||
expect(result.teams).toHaveLength(3); // Team A, Team B, and discovered Team t3
|
||||
|
||||
const teamA = result.teams.find(t => t.id === 't1');
|
||||
expect(teamA?.memberCount).toBe(2);
|
||||
|
||||
const teamB = result.teams.find(t => t.id === 't2');
|
||||
expect(teamB?.memberCount).toBe(1);
|
||||
|
||||
const teamDiscovered = result.teams.find(t => t.id === 't3');
|
||||
expect(teamDiscovered?.memberCount).toBe(1);
|
||||
expect(teamDiscovered?.name).toBe('Discovered Team');
|
||||
|
||||
expect(mockEventPublisher.publishTeamRankingsAccessed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should filter teams by search term', async () => {
|
||||
const result = await useCase.execute({ search: 'team a' });
|
||||
|
||||
expect(result.teams).toHaveLength(1);
|
||||
expect(result.teams[0].name).toBe('Team A');
|
||||
});
|
||||
|
||||
it('should filter teams by minMemberCount', async () => {
|
||||
const result = await useCase.execute({ minMemberCount: 2 });
|
||||
|
||||
expect(result.teams).toHaveLength(1);
|
||||
expect(result.teams[0].id).toBe('t1');
|
||||
});
|
||||
|
||||
it('should sort teams by rating DESC by default', async () => {
|
||||
const result = await useCase.execute();
|
||||
|
||||
expect(result.teams[0].id).toBe('t1'); // 2500
|
||||
expect(result.teams[1].id).toBe('t2'); // 2200
|
||||
expect(result.teams[2].id).toBe('t3'); // 0
|
||||
});
|
||||
|
||||
it('should throw ValidationError for invalid minMemberCount', async () => {
|
||||
await expect(useCase.execute({ minMemberCount: -1 })).rejects.toThrow(ValidationError);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user