wip
This commit is contained in:
125
tests/unit/racing-application/MembershipUseCases.test.ts
Normal file
125
tests/unit/racing-application/MembershipUseCases.test.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
|
||||
import { JoinLeagueUseCase } from '@gridpilot/racing/application/use-cases/JoinLeagueUseCase';
|
||||
import type { ILeagueMembershipRepository } from '@gridpilot/racing/domain/repositories/ILeagueMembershipRepository';
|
||||
import type {
|
||||
LeagueMembership,
|
||||
MembershipRole,
|
||||
MembershipStatus,
|
||||
} from '@gridpilot/racing/domain/entities/LeagueMembership';
|
||||
|
||||
class InMemoryLeagueMembershipRepository implements ILeagueMembershipRepository {
|
||||
private memberships: LeagueMembership[] = [];
|
||||
|
||||
async getMembership(leagueId: string, driverId: string): Promise<LeagueMembership | null> {
|
||||
return (
|
||||
this.memberships.find(
|
||||
(m) => m.leagueId === leagueId && m.driverId === driverId,
|
||||
) || null
|
||||
);
|
||||
}
|
||||
|
||||
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 saveMembership(membership: LeagueMembership): Promise<LeagueMembership> {
|
||||
const existingIndex = this.memberships.findIndex(
|
||||
(m) => m.leagueId === membership.leagueId && m.driverId === membership.driverId,
|
||||
);
|
||||
|
||||
if (existingIndex >= 0) {
|
||||
this.memberships[existingIndex] = membership;
|
||||
} else {
|
||||
this.memberships.push(membership);
|
||||
}
|
||||
|
||||
return membership;
|
||||
}
|
||||
|
||||
async removeMembership(leagueId: string, driverId: string): Promise<void> {
|
||||
this.memberships = this.memberships.filter(
|
||||
(m) => !(m.leagueId === leagueId && m.driverId === driverId),
|
||||
);
|
||||
}
|
||||
|
||||
async getJoinRequests(): Promise<never> {
|
||||
throw new Error('Not implemented for this test');
|
||||
}
|
||||
|
||||
async saveJoinRequest(): Promise<never> {
|
||||
throw new Error('Not implemented for this test');
|
||||
}
|
||||
|
||||
async removeJoinRequest(): Promise<never> {
|
||||
throw new Error('Not implemented for this test');
|
||||
}
|
||||
|
||||
seedMembership(membership: LeagueMembership): void {
|
||||
this.memberships.push(membership);
|
||||
}
|
||||
|
||||
getAllMemberships(): LeagueMembership[] {
|
||||
return [...this.memberships];
|
||||
}
|
||||
}
|
||||
|
||||
describe('Membership use-cases', () => {
|
||||
describe('JoinLeagueUseCase', () => {
|
||||
let repository: InMemoryLeagueMembershipRepository;
|
||||
let useCase: JoinLeagueUseCase;
|
||||
|
||||
beforeEach(() => {
|
||||
repository = new InMemoryLeagueMembershipRepository();
|
||||
useCase = new JoinLeagueUseCase(repository);
|
||||
});
|
||||
|
||||
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 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);
|
||||
});
|
||||
|
||||
it('throws when driver already has membership for league', async () => {
|
||||
const leagueId = 'league-1';
|
||||
const driverId = 'driver-1';
|
||||
|
||||
repository.seedMembership({
|
||||
leagueId,
|
||||
driverId,
|
||||
role: 'member',
|
||||
status: 'active',
|
||||
joinedAt: new Date('2024-01-01'),
|
||||
});
|
||||
|
||||
await expect(
|
||||
useCase.execute({ leagueId, driverId }),
|
||||
).rejects.toThrow('Already a member or have a pending request');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,503 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
|
||||
import type { IRaceRegistrationRepository } from '@gridpilot/racing/domain/repositories/IRaceRegistrationRepository';
|
||||
import type { ILeagueMembershipRepository } from '@gridpilot/racing/domain/repositories/ILeagueMembershipRepository';
|
||||
import type { ITeamRepository } from '@gridpilot/racing/domain/repositories/ITeamRepository';
|
||||
import type { ITeamMembershipRepository } from '@gridpilot/racing/domain/repositories/ITeamMembershipRepository';
|
||||
import type { RaceRegistration } from '@gridpilot/racing/domain/entities/RaceRegistration';
|
||||
import type {
|
||||
LeagueMembership,
|
||||
MembershipStatus,
|
||||
} from '@gridpilot/racing/domain/entities/LeagueMembership';
|
||||
import type {
|
||||
Team,
|
||||
TeamMembership,
|
||||
TeamMembershipStatus,
|
||||
TeamRole,
|
||||
TeamJoinRequest,
|
||||
} from '@gridpilot/racing/domain/entities/Team';
|
||||
|
||||
import { RegisterForRaceUseCase } from '@gridpilot/racing/application/use-cases/RegisterForRaceUseCase';
|
||||
import { WithdrawFromRaceUseCase } from '@gridpilot/racing/application/use-cases/WithdrawFromRaceUseCase';
|
||||
import {
|
||||
IsDriverRegisteredForRaceQuery,
|
||||
GetRaceRegistrationsQuery,
|
||||
} from '@gridpilot/racing/application/use-cases/RaceRegistrationQueries';
|
||||
|
||||
import {
|
||||
CreateTeamUseCase,
|
||||
JoinTeamUseCase,
|
||||
LeaveTeamUseCase,
|
||||
ApproveTeamJoinRequestUseCase,
|
||||
RejectTeamJoinRequestUseCase,
|
||||
UpdateTeamUseCase,
|
||||
GetAllTeamsQuery,
|
||||
GetTeamDetailsQuery,
|
||||
GetTeamMembersQuery,
|
||||
GetTeamJoinRequestsQuery,
|
||||
GetDriverTeamQuery,
|
||||
} from '@gridpilot/racing/application/use-cases/TeamUseCases';
|
||||
|
||||
/**
|
||||
* Simple in-memory fakes mirroring current alpha behavior.
|
||||
*/
|
||||
|
||||
class InMemoryRaceRegistrationRepository implements IRaceRegistrationRepository {
|
||||
private registrations = new Map<string, Set<string>>(); // raceId -> driverIds
|
||||
|
||||
async isRegistered(raceId: string, driverId: string): Promise<boolean> {
|
||||
const set = this.registrations.get(raceId);
|
||||
return set ? set.has(driverId) : false;
|
||||
}
|
||||
|
||||
async getRegisteredDrivers(raceId: string): Promise<string[]> {
|
||||
const set = this.registrations.get(raceId);
|
||||
return set ? Array.from(set) : [];
|
||||
}
|
||||
|
||||
async getRegistrationCount(raceId: string): Promise<number> {
|
||||
const set = this.registrations.get(raceId);
|
||||
return set ? set.size : 0;
|
||||
}
|
||||
|
||||
async register(registration: RaceRegistration): Promise<void> {
|
||||
if (!this.registrations.has(registration.raceId)) {
|
||||
this.registrations.set(registration.raceId, new Set());
|
||||
}
|
||||
this.registrations.get(registration.raceId)!.add(registration.driverId);
|
||||
}
|
||||
|
||||
async withdraw(raceId: string, driverId: string): Promise<void> {
|
||||
const set = this.registrations.get(raceId);
|
||||
if (!set || !set.has(driverId)) {
|
||||
throw new Error('Not registered for this race');
|
||||
}
|
||||
set.delete(driverId);
|
||||
if (set.size === 0) {
|
||||
this.registrations.delete(raceId);
|
||||
}
|
||||
}
|
||||
|
||||
async getDriverRegistrations(driverId: string): Promise<string[]> {
|
||||
const result: string[] = [];
|
||||
for (const [raceId, set] of this.registrations.entries()) {
|
||||
if (set.has(driverId)) {
|
||||
result.push(raceId);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async clearRaceRegistrations(raceId: string): Promise<void> {
|
||||
this.registrations.delete(raceId);
|
||||
}
|
||||
}
|
||||
|
||||
class InMemoryLeagueMembershipRepositoryForRegistrations implements ILeagueMembershipRepository {
|
||||
private memberships: LeagueMembership[] = [];
|
||||
|
||||
async getMembership(leagueId: string, driverId: string): Promise<LeagueMembership | null> {
|
||||
return (
|
||||
this.memberships.find(
|
||||
(m) => m.leagueId === leagueId && m.driverId === driverId,
|
||||
) || null
|
||||
);
|
||||
}
|
||||
|
||||
async getLeagueMembers(leagueId: string): Promise<LeagueMembership[]> {
|
||||
return this.memberships.filter(
|
||||
(m) => m.leagueId === leagueId && m.status === 'active',
|
||||
);
|
||||
}
|
||||
|
||||
async getJoinRequests(): Promise<never> {
|
||||
throw new Error('Not needed for registration tests');
|
||||
}
|
||||
|
||||
async saveMembership(membership: LeagueMembership): Promise<LeagueMembership> {
|
||||
this.memberships.push(membership);
|
||||
return membership;
|
||||
}
|
||||
|
||||
async removeMembership(): Promise<void> {
|
||||
throw new Error('Not needed for registration tests');
|
||||
}
|
||||
|
||||
async saveJoinRequest(): Promise<never> {
|
||||
throw new Error('Not needed for registration tests');
|
||||
}
|
||||
|
||||
async removeJoinRequest(): Promise<never> {
|
||||
throw new Error('Not needed for registration tests');
|
||||
}
|
||||
|
||||
seedActiveMembership(leagueId: string, driverId: string): void {
|
||||
this.memberships.push({
|
||||
leagueId,
|
||||
driverId,
|
||||
role: 'member',
|
||||
status: 'active' as MembershipStatus,
|
||||
joinedAt: new Date('2024-01-01'),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class InMemoryTeamRepository implements ITeamRepository {
|
||||
private teams: Team[] = [];
|
||||
|
||||
async findById(id: string): Promise<Team | null> {
|
||||
return this.teams.find((t) => t.id === id) || null;
|
||||
}
|
||||
|
||||
async findAll(): Promise<Team[]> {
|
||||
return [...this.teams];
|
||||
}
|
||||
|
||||
async findByLeagueId(leagueId: string): Promise<Team[]> {
|
||||
return this.teams.filter((t) => t.leagues.includes(leagueId));
|
||||
}
|
||||
|
||||
async create(team: Team): Promise<Team> {
|
||||
this.teams.push(team);
|
||||
return team;
|
||||
}
|
||||
|
||||
async update(team: Team): Promise<Team> {
|
||||
const index = this.teams.findIndex((t) => t.id === team.id);
|
||||
if (index >= 0) {
|
||||
this.teams[index] = team;
|
||||
} else {
|
||||
this.teams.push(team);
|
||||
}
|
||||
return team;
|
||||
}
|
||||
|
||||
async delete(id: string): Promise<void> {
|
||||
this.teams = this.teams.filter((t) => t.id !== id);
|
||||
}
|
||||
|
||||
async exists(id: string): Promise<boolean> {
|
||||
return this.teams.some((t) => t.id === id);
|
||||
}
|
||||
|
||||
seedTeam(team: Team): void {
|
||||
this.teams.push(team);
|
||||
}
|
||||
}
|
||||
|
||||
class InMemoryTeamMembershipRepository implements ITeamMembershipRepository {
|
||||
private memberships: TeamMembership[] = [];
|
||||
private joinRequests: TeamJoinRequest[] = [];
|
||||
|
||||
async getMembership(teamId: string, driverId: string): Promise<TeamMembership | null> {
|
||||
return (
|
||||
this.memberships.find(
|
||||
(m) => m.teamId === teamId && m.driverId === driverId,
|
||||
) || null
|
||||
);
|
||||
}
|
||||
|
||||
async getActiveMembershipForDriver(driverId: string): Promise<TeamMembership | null> {
|
||||
return (
|
||||
this.memberships.find(
|
||||
(m) => m.driverId === driverId && m.status === 'active',
|
||||
) || null
|
||||
);
|
||||
}
|
||||
|
||||
async getTeamMembers(teamId: string): Promise<TeamMembership[]> {
|
||||
return this.memberships.filter(
|
||||
(m) => m.teamId === teamId && m.status === 'active',
|
||||
);
|
||||
}
|
||||
|
||||
async saveMembership(membership: TeamMembership): Promise<TeamMembership> {
|
||||
const index = this.memberships.findIndex(
|
||||
(m) => m.teamId === membership.teamId && m.driverId === membership.driverId,
|
||||
);
|
||||
if (index >= 0) {
|
||||
this.memberships[index] = membership;
|
||||
} else {
|
||||
this.memberships.push(membership);
|
||||
}
|
||||
return membership;
|
||||
}
|
||||
|
||||
async removeMembership(teamId: string, driverId: string): Promise<void> {
|
||||
this.memberships = this.memberships.filter(
|
||||
(m) => !(m.teamId === teamId && m.driverId === driverId),
|
||||
);
|
||||
}
|
||||
|
||||
async getJoinRequests(teamId: string): Promise<TeamJoinRequest[]> {
|
||||
// For these tests we ignore teamId and return all,
|
||||
// allowing use-cases to look up by request ID only.
|
||||
return [...this.joinRequests];
|
||||
}
|
||||
|
||||
async saveJoinRequest(request: TeamJoinRequest): Promise<TeamJoinRequest> {
|
||||
const index = this.joinRequests.findIndex((r) => r.id === request.id);
|
||||
if (index >= 0) {
|
||||
this.joinRequests[index] = request;
|
||||
} else {
|
||||
this.joinRequests.push(request);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
async removeJoinRequest(requestId: string): Promise<void> {
|
||||
this.joinRequests = this.joinRequests.filter((r) => r.id !== requestId);
|
||||
}
|
||||
|
||||
seedMembership(membership: TeamMembership): void {
|
||||
this.memberships.push(membership);
|
||||
}
|
||||
|
||||
seedJoinRequest(request: TeamJoinRequest): void {
|
||||
this.joinRequests.push(request);
|
||||
}
|
||||
|
||||
getAllMemberships(): TeamMembership[] {
|
||||
return [...this.memberships];
|
||||
}
|
||||
|
||||
getAllJoinRequests(): TeamJoinRequest[] {
|
||||
return [...this.joinRequests];
|
||||
}
|
||||
}
|
||||
|
||||
describe('Racing application use-cases - registrations', () => {
|
||||
let registrationRepo: InMemoryRaceRegistrationRepository;
|
||||
let membershipRepo: InMemoryLeagueMembershipRepositoryForRegistrations;
|
||||
let registerForRace: RegisterForRaceUseCase;
|
||||
let withdrawFromRace: WithdrawFromRaceUseCase;
|
||||
let isDriverRegistered: IsDriverRegisteredForRaceQuery;
|
||||
let getRaceRegistrations: GetRaceRegistrationsQuery;
|
||||
|
||||
beforeEach(() => {
|
||||
registrationRepo = new InMemoryRaceRegistrationRepository();
|
||||
membershipRepo = new InMemoryLeagueMembershipRepositoryForRegistrations();
|
||||
|
||||
registerForRace = new RegisterForRaceUseCase(registrationRepo, membershipRepo);
|
||||
withdrawFromRace = new WithdrawFromRaceUseCase(registrationRepo);
|
||||
isDriverRegistered = new IsDriverRegisteredForRaceQuery(registrationRepo);
|
||||
getRaceRegistrations = new GetRaceRegistrationsQuery(registrationRepo);
|
||||
});
|
||||
|
||||
it('registers an active league member for a race and tracks registration', async () => {
|
||||
const raceId = 'race-1';
|
||||
const leagueId = 'league-1';
|
||||
const driverId = 'driver-1';
|
||||
|
||||
membershipRepo.seedActiveMembership(leagueId, driverId);
|
||||
|
||||
await registerForRace.execute({ raceId, leagueId, driverId });
|
||||
|
||||
expect(await isDriverRegistered.execute({ raceId, driverId })).toBe(true);
|
||||
|
||||
const registeredDrivers = await getRaceRegistrations.execute({ raceId });
|
||||
expect(registeredDrivers).toContain(driverId);
|
||||
});
|
||||
|
||||
it('throws when registering a non-member for a race', async () => {
|
||||
const raceId = 'race-1';
|
||||
const leagueId = 'league-1';
|
||||
const driverId = 'driver-1';
|
||||
|
||||
await expect(
|
||||
registerForRace.execute({ raceId, leagueId, driverId }),
|
||||
).rejects.toThrow('Must be an active league member to register for races');
|
||||
});
|
||||
|
||||
it('withdraws a registration and reflects state in queries', async () => {
|
||||
const raceId = 'race-1';
|
||||
const leagueId = 'league-1';
|
||||
const driverId = 'driver-1';
|
||||
|
||||
membershipRepo.seedActiveMembership(leagueId, driverId);
|
||||
await registerForRace.execute({ raceId, leagueId, driverId });
|
||||
|
||||
await withdrawFromRace.execute({ raceId, driverId });
|
||||
|
||||
expect(await isDriverRegistered.execute({ raceId, driverId })).toBe(false);
|
||||
expect(await getRaceRegistrations.execute({ raceId })).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Racing application use-cases - teams', () => {
|
||||
let teamRepo: InMemoryTeamRepository;
|
||||
let membershipRepo: InMemoryTeamMembershipRepository;
|
||||
|
||||
let createTeam: CreateTeamUseCase;
|
||||
let joinTeam: JoinTeamUseCase;
|
||||
let leaveTeam: LeaveTeamUseCase;
|
||||
let approveJoin: ApproveTeamJoinRequestUseCase;
|
||||
let rejectJoin: RejectTeamJoinRequestUseCase;
|
||||
let updateTeamUseCase: UpdateTeamUseCase;
|
||||
let getAllTeamsQuery: GetAllTeamsQuery;
|
||||
let getTeamDetailsQuery: GetTeamDetailsQuery;
|
||||
let getTeamMembersQuery: GetTeamMembersQuery;
|
||||
let getTeamJoinRequestsQuery: GetTeamJoinRequestsQuery;
|
||||
let getDriverTeamQuery: GetDriverTeamQuery;
|
||||
|
||||
beforeEach(() => {
|
||||
teamRepo = new InMemoryTeamRepository();
|
||||
membershipRepo = new InMemoryTeamMembershipRepository();
|
||||
|
||||
createTeam = new CreateTeamUseCase(teamRepo, membershipRepo);
|
||||
joinTeam = new JoinTeamUseCase(teamRepo, membershipRepo);
|
||||
leaveTeam = new LeaveTeamUseCase(membershipRepo);
|
||||
approveJoin = new ApproveTeamJoinRequestUseCase(membershipRepo);
|
||||
rejectJoin = new RejectTeamJoinRequestUseCase(membershipRepo);
|
||||
updateTeamUseCase = new UpdateTeamUseCase(teamRepo, membershipRepo);
|
||||
getAllTeamsQuery = new GetAllTeamsQuery(teamRepo);
|
||||
getTeamDetailsQuery = new GetTeamDetailsQuery(teamRepo, membershipRepo);
|
||||
getTeamMembersQuery = new GetTeamMembersQuery(membershipRepo);
|
||||
getTeamJoinRequestsQuery = new GetTeamJoinRequestsQuery(membershipRepo);
|
||||
getDriverTeamQuery = new GetDriverTeamQuery(teamRepo, membershipRepo);
|
||||
});
|
||||
|
||||
it('creates a team and assigns creator as active owner', async () => {
|
||||
const ownerId = 'driver-1';
|
||||
|
||||
const result = await createTeam.execute({
|
||||
name: 'Apex Racing',
|
||||
tag: 'APEX',
|
||||
description: 'Professional GT3 racing',
|
||||
ownerId,
|
||||
leagues: ['league-1'],
|
||||
});
|
||||
|
||||
expect(result.team.id).toBeDefined();
|
||||
expect(result.team.ownerId).toBe(ownerId);
|
||||
|
||||
const membership = await membershipRepo.getActiveMembershipForDriver(ownerId);
|
||||
expect(membership?.teamId).toBe(result.team.id);
|
||||
expect(membership?.role as TeamRole).toBe('owner');
|
||||
expect(membership?.status as TeamMembershipStatus).toBe('active');
|
||||
});
|
||||
|
||||
it('prevents driver from joining multiple teams and mirrors legacy error message', async () => {
|
||||
const ownerId = 'driver-1';
|
||||
const otherTeamId = 'team-2';
|
||||
|
||||
// Seed an existing active membership
|
||||
membershipRepo.seedMembership({
|
||||
teamId: otherTeamId,
|
||||
driverId: ownerId,
|
||||
role: 'driver',
|
||||
status: 'active',
|
||||
joinedAt: new Date('2024-02-01'),
|
||||
});
|
||||
|
||||
await expect(
|
||||
joinTeam.execute({ teamId: 'team-1', driverId: ownerId }),
|
||||
).rejects.toThrow('Driver already belongs to a team');
|
||||
});
|
||||
|
||||
it('approves a join request and moves it into active membership', async () => {
|
||||
const teamId = 'team-1';
|
||||
const driverId = 'driver-2';
|
||||
|
||||
const request: TeamJoinRequest = {
|
||||
id: 'req-1',
|
||||
teamId,
|
||||
driverId,
|
||||
requestedAt: new Date('2024-03-01'),
|
||||
message: 'Let me in',
|
||||
};
|
||||
membershipRepo.seedJoinRequest(request);
|
||||
|
||||
await approveJoin.execute({ requestId: request.id });
|
||||
|
||||
const membership = await membershipRepo.getMembership(teamId, driverId);
|
||||
expect(membership).not.toBeNull();
|
||||
expect(membership?.status as TeamMembershipStatus).toBe('active');
|
||||
|
||||
const remainingRequests = await membershipRepo.getJoinRequests(teamId);
|
||||
expect(remainingRequests.find((r) => r.id === request.id)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('rejects a join request and removes it', async () => {
|
||||
const teamId = 'team-1';
|
||||
const driverId = 'driver-2';
|
||||
|
||||
const request: TeamJoinRequest = {
|
||||
id: 'req-2',
|
||||
teamId,
|
||||
driverId,
|
||||
requestedAt: new Date('2024-03-02'),
|
||||
message: 'Please?',
|
||||
};
|
||||
membershipRepo.seedJoinRequest(request);
|
||||
|
||||
await rejectJoin.execute({ requestId: request.id });
|
||||
|
||||
const remainingRequests = await membershipRepo.getJoinRequests(teamId);
|
||||
expect(remainingRequests.find((r) => r.id === request.id)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('updates team details when performed by owner or manager and reflects in queries', async () => {
|
||||
const ownerId = 'driver-1';
|
||||
const created = await createTeam.execute({
|
||||
name: 'Original Name',
|
||||
tag: 'ORIG',
|
||||
description: 'Original description',
|
||||
ownerId,
|
||||
leagues: [],
|
||||
});
|
||||
|
||||
await updateTeamUseCase.execute({
|
||||
teamId: created.team.id,
|
||||
updates: { name: 'Updated Name', description: 'Updated description' },
|
||||
updatedBy: ownerId,
|
||||
});
|
||||
|
||||
const teamDetails = await getTeamDetailsQuery.execute({
|
||||
teamId: created.team.id,
|
||||
driverId: ownerId,
|
||||
});
|
||||
|
||||
expect(teamDetails.team.name).toBe('Updated Name');
|
||||
expect(teamDetails.team.description).toBe('Updated description');
|
||||
});
|
||||
|
||||
it('returns driver team via query matching legacy getDriverTeam behavior', async () => {
|
||||
const ownerId = 'driver-1';
|
||||
|
||||
const { team } = await createTeam.execute({
|
||||
name: 'Apex Racing',
|
||||
tag: 'APEX',
|
||||
description: 'Professional GT3 racing',
|
||||
ownerId,
|
||||
leagues: [],
|
||||
});
|
||||
|
||||
const result = await getDriverTeamQuery.execute({ driverId: ownerId });
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.team.id).toBe(team.id);
|
||||
expect(result?.membership.driverId).toBe(ownerId);
|
||||
});
|
||||
|
||||
it('lists all teams and members via queries after multiple operations', async () => {
|
||||
const ownerId = 'driver-1';
|
||||
const otherDriverId = 'driver-2';
|
||||
|
||||
const { team } = await createTeam.execute({
|
||||
name: 'Apex Racing',
|
||||
tag: 'APEX',
|
||||
description: 'Professional GT3 racing',
|
||||
ownerId,
|
||||
leagues: [],
|
||||
});
|
||||
|
||||
await joinTeam.execute({ teamId: team.id, driverId: otherDriverId });
|
||||
|
||||
const teams = await getAllTeamsQuery.execute();
|
||||
expect(teams.length).toBe(1);
|
||||
|
||||
const members = await getTeamMembersQuery.execute({ teamId: team.id });
|
||||
const memberIds = members.map((m) => m.driverId).sort();
|
||||
expect(memberIds).toEqual([ownerId, otherDriverId].sort());
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user