This commit is contained in:
2025-12-16 21:05:01 +01:00
parent f61e3a4e5a
commit 7532c7ed6d
207 changed files with 7861 additions and 2606 deletions

View File

@@ -1,11 +1,14 @@
import { describe, it, expect, beforeEach } from 'vitest';
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
import { JoinLeagueUseCase } from '@core/racing/application/use-cases/JoinLeagueUseCase';
import type { ILeagueMembershipRepository } from '@core/racing/domain/repositories/ILeagueMembershipRepository';
import type { Logger } from '@core/shared/application';
import { LeagueMembership } from '@core/racing/domain/entities/LeagueMembership';
import type { JoinRequest } from '@core/racing/domain/entities/LeagueMembership';
class InMemoryLeagueMembershipRepository implements ILeagueMembershipRepository {
private memberships: LeagueMembership[] = [];
private joinRequests: JoinRequest[] = [];
async getMembership(leagueId: string, driverId: string): Promise<LeagueMembership | null> {
return (
@@ -15,23 +18,15 @@ class InMemoryLeagueMembershipRepository implements ILeagueMembershipRepository
);
}
async getActiveMembershipForDriver(driverId: string): Promise<LeagueMembership | null> {
return (
this.memberships.find(
(m) => m.driverId === driverId && m.status === 'active',
) || null
);
}
async getLeagueMembers(leagueId: string): Promise<LeagueMembership[]> {
return this.memberships.filter(
(m) => m.leagueId === leagueId && m.status === 'active',
);
}
async getTeamMembers(leagueId: string): Promise<LeagueMembership[]> {
return this.memberships.filter(
(m) => m.leagueId === leagueId && m.status === 'active',
async getJoinRequests(leagueId: string): Promise<JoinRequest[]> {
return this.joinRequests.filter(
(r) => r.leagueId === leagueId,
);
}
@@ -55,16 +50,15 @@ class InMemoryLeagueMembershipRepository implements ILeagueMembershipRepository
);
}
async getJoinRequests(): Promise<never> {
throw new Error('Not implemented for this test');
async saveJoinRequest(request: JoinRequest): Promise<JoinRequest> {
this.joinRequests.push(request);
return request;
}
async saveJoinRequest(): Promise<never> {
throw new Error('Not implemented for this test');
}
async removeJoinRequest(): Promise<never> {
throw new Error('Not implemented for this test');
async removeJoinRequest(requestId: string): Promise<void> {
this.joinRequests = this.joinRequests.filter(
(r) => r.id !== requestId,
);
}
seedMembership(membership: LeagueMembership): void {
@@ -80,28 +74,43 @@ describe('Membership use-cases', () => {
describe('JoinLeagueUseCase', () => {
let repository: InMemoryLeagueMembershipRepository;
let useCase: JoinLeagueUseCase;
let logger: {
debug: Mock;
info: Mock;
warn: Mock;
error: Mock;
};
beforeEach(() => {
repository = new InMemoryLeagueMembershipRepository();
useCase = new JoinLeagueUseCase(repository);
logger = {
debug: vi.fn(),
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
};
useCase = new JoinLeagueUseCase(
repository as unknown as ILeagueMembershipRepository,
logger as unknown as Logger,
);
});
it('creates an active member when driver has no membership', async () => {
const leagueId = 'league-1';
const driverId = 'driver-1';
await useCase.execute({ leagueId, driverId });
const result = await useCase.execute({ leagueId, driverId });
const membership = await repository.getMembership(leagueId, driverId);
expect(membership).not.toBeNull();
expect(membership?.leagueId).toBe(leagueId);
expect(membership?.driverId).toBe(driverId);
expect(membership?.role as MembershipRole).toBe('member');
expect(membership?.status as MembershipStatus).toBe('active');
expect(membership?.joinedAt).toBeInstanceOf(Date);
expect(result.isOk()).toBe(true);
const membership = result.unwrap();
expect(membership.leagueId).toBe(leagueId);
expect(membership.driverId).toBe(driverId);
expect(membership.role).toBe('member');
expect(membership.status).toBe('active');
expect(membership.joinedAt).toBeInstanceOf(Date);
});
it('throws when driver already has membership for league', async () => {
it('returns error when driver already has membership for league', async () => {
const leagueId = 'league-1';
const driverId = 'driver-1';
@@ -113,9 +122,13 @@ describe('Membership use-cases', () => {
joinedAt: new Date('2024-01-01'),
}));
await expect(
useCase.execute({ leagueId, driverId }),
).rejects.toThrow('Already a member or have a pending request');
const result = await useCase.execute({ leagueId, driverId });
expect(result.isErr()).toBe(true);
expect(result.unwrapErr()).toEqual({
code: 'ALREADY_MEMBER',
details: { message: 'Already a member or have a pending request' },
});
});
});
});