202 lines
6.1 KiB
TypeScript
202 lines
6.1 KiB
TypeScript
import { describe, it, expect, beforeEach, vi, type Mock } from 'vitest';
|
|
import {
|
|
GetTeamMembersUseCase,
|
|
type GetTeamMembersInput,
|
|
type GetTeamMembersResult,
|
|
type GetTeamMembersErrorCode,
|
|
} from './GetTeamMembersUseCase';
|
|
import { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository';
|
|
import { IDriverRepository } from '../../domain/repositories/IDriverRepository';
|
|
import { ITeamRepository } from '../../domain/repositories/ITeamRepository';
|
|
import { Driver } from '../../domain/entities/Driver';
|
|
import { Team } from '../../domain/entities/Team';
|
|
import type { Logger } from '@core/shared/application';
|
|
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
|
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
|
|
|
describe('GetTeamMembersUseCase', () => {
|
|
let useCase: GetTeamMembersUseCase;
|
|
let membershipRepository: {
|
|
getTeamMembers: Mock;
|
|
};
|
|
let driverRepository: {
|
|
findById: Mock;
|
|
};
|
|
let teamRepository: {
|
|
findById: Mock;
|
|
};
|
|
let logger: {
|
|
debug: Mock;
|
|
info: Mock;
|
|
warn: Mock;
|
|
error: Mock;
|
|
};
|
|
let output: UseCaseOutputPort<GetTeamMembersResult> & { present: Mock };
|
|
|
|
beforeEach(() => {
|
|
membershipRepository = {
|
|
getTeamMembers: vi.fn(),
|
|
};
|
|
driverRepository = {
|
|
findById: vi.fn(),
|
|
};
|
|
teamRepository = {
|
|
findById: vi.fn(),
|
|
};
|
|
logger = {
|
|
debug: vi.fn(),
|
|
info: vi.fn(),
|
|
warn: vi.fn(),
|
|
error: vi.fn(),
|
|
};
|
|
output = {
|
|
present: vi.fn(),
|
|
} as unknown as UseCaseOutputPort<GetTeamMembersResult> & { present: Mock };
|
|
|
|
useCase = new GetTeamMembersUseCase(
|
|
membershipRepository as unknown as ITeamMembershipRepository,
|
|
driverRepository as unknown as IDriverRepository,
|
|
teamRepository as unknown as ITeamRepository,
|
|
logger as unknown as Logger,
|
|
output,
|
|
);
|
|
});
|
|
|
|
it('should return team members with driver entities', async () => {
|
|
const team = Team.create({
|
|
id: 'team-1',
|
|
name: 'Team Name',
|
|
tag: 'TAG',
|
|
description: 'Description',
|
|
ownerId: 'driver-1',
|
|
leagues: [],
|
|
});
|
|
|
|
const input: GetTeamMembersInput = { teamId: team.id };
|
|
|
|
const memberships = [
|
|
{ teamId: team.id, driverId: 'driver-1', role: 'owner' as const, status: 'active' as const, joinedAt: new Date() },
|
|
{ teamId: team.id, driverId: 'driver-2', role: 'driver' as const, status: 'active' as const, joinedAt: new Date() },
|
|
];
|
|
|
|
const driver1 = Driver.create({
|
|
id: 'driver-1',
|
|
iracingId: '123',
|
|
name: 'Driver 1',
|
|
country: 'US',
|
|
});
|
|
|
|
const driver2 = Driver.create({
|
|
id: 'driver-2',
|
|
iracingId: '456',
|
|
name: 'Driver 2',
|
|
country: 'UK',
|
|
});
|
|
|
|
teamRepository.findById.mockResolvedValue(team);
|
|
membershipRepository.getTeamMembers.mockResolvedValue(memberships);
|
|
driverRepository.findById.mockImplementation((id: string) => {
|
|
if (id === 'driver-1') return Promise.resolve(driver1);
|
|
if (id === 'driver-2') return Promise.resolve(driver2);
|
|
return Promise.resolve(null);
|
|
});
|
|
|
|
const result = await useCase.execute(input);
|
|
|
|
expect(result.isOk()).toBe(true);
|
|
expect(result.unwrap()).toBeUndefined();
|
|
|
|
expect(output.present).toHaveBeenCalledTimes(1);
|
|
const presented = output.present.mock.calls[0]?.[0] as GetTeamMembersResult;
|
|
|
|
expect(presented.team).toBe(team);
|
|
expect(presented.members).toHaveLength(2);
|
|
expect(presented.members[0]).toEqual({ membership: memberships[0], driver: driver1 });
|
|
expect(presented.members[1]).toEqual({ membership: memberships[1], driver: driver2 });
|
|
});
|
|
|
|
it('should handle driver not found', async () => {
|
|
const team = Team.create({
|
|
id: 'team-1',
|
|
name: 'Team Name',
|
|
tag: 'TAG',
|
|
description: 'Description',
|
|
ownerId: 'driver-1',
|
|
leagues: [],
|
|
});
|
|
|
|
const input: GetTeamMembersInput = { teamId: team.id };
|
|
|
|
const memberships = [
|
|
{ teamId: team.id, driverId: 'driver-1', role: 'owner' as const, status: 'active' as const, joinedAt: new Date() },
|
|
];
|
|
|
|
teamRepository.findById.mockResolvedValue(team);
|
|
membershipRepository.getTeamMembers.mockResolvedValue(memberships);
|
|
driverRepository.findById.mockResolvedValue(null);
|
|
|
|
const result = await useCase.execute(input);
|
|
|
|
expect(result.isOk()).toBe(true);
|
|
expect(result.unwrap()).toBeUndefined();
|
|
|
|
expect(output.present).toHaveBeenCalledTimes(1);
|
|
const presented = output.present.mock.calls[0]?.[0] as GetTeamMembersResult;
|
|
|
|
expect(presented.team).toBe(team);
|
|
expect(presented.members).toEqual([
|
|
{ membership: memberships[0], driver: null },
|
|
]);
|
|
});
|
|
|
|
it('should return TEAM_NOT_FOUND when team does not exist', async () => {
|
|
const input: GetTeamMembersInput = { teamId: 'missing-team' };
|
|
|
|
teamRepository.findById.mockResolvedValue(null);
|
|
|
|
const result = await useCase.execute(input);
|
|
|
|
expect(result.isErr()).toBe(true);
|
|
|
|
const error = result.unwrapErr() as ApplicationErrorCode<
|
|
GetTeamMembersErrorCode,
|
|
{ message: string }
|
|
>;
|
|
|
|
expect(error.code).toBe('TEAM_NOT_FOUND');
|
|
expect(error.details.message).toBe('Team not found');
|
|
expect(output.present).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should return REPOSITORY_ERROR when repository throws', async () => {
|
|
const team = Team.create({
|
|
id: 'team-1',
|
|
name: 'Team Name',
|
|
tag: 'TAG',
|
|
description: 'Description',
|
|
ownerId: 'driver-1',
|
|
leagues: [],
|
|
});
|
|
|
|
const input: GetTeamMembersInput = { teamId: team.id };
|
|
|
|
const error = new Error('Repository failure');
|
|
|
|
teamRepository.findById.mockResolvedValue(team);
|
|
membershipRepository.getTeamMembers.mockRejectedValue(error);
|
|
|
|
const result = await useCase.execute(input);
|
|
|
|
expect(result.isErr()).toBe(true);
|
|
|
|
const err = result.unwrapErr() as ApplicationErrorCode<
|
|
GetTeamMembersErrorCode,
|
|
{ message: string }
|
|
>;
|
|
|
|
expect(err.code).toBe('REPOSITORY_ERROR');
|
|
expect(err.details.message).toBe('Repository failure');
|
|
expect(output.present).not.toHaveBeenCalled();
|
|
});
|
|
});
|