test apps api
This commit is contained in:
@@ -1,107 +1,531 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { TeamService } from './TeamService';
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import type { Logger } from '@core/shared/application/Logger';
|
||||
import { Result } from '@core/shared/application/Result';
|
||||
import { GetAllTeamsUseCase } from '@core/racing/application/use-cases/GetAllTeamsUseCase';
|
||||
import { GetTeamDetailsUseCase } from '@core/racing/application/use-cases/GetTeamDetailsUseCase';
|
||||
import { GetTeamMembersUseCase } from '@core/racing/application/use-cases/GetTeamMembersUseCase';
|
||||
import { GetTeamJoinRequestsUseCase } from '@core/racing/application/use-cases/GetTeamJoinRequestsUseCase';
|
||||
import { CreateTeamUseCase } from '@core/racing/application/use-cases/CreateTeamUseCase';
|
||||
import { UpdateTeamUseCase } from '@core/racing/application/use-cases/UpdateTeamUseCase';
|
||||
import { GetDriverTeamUseCase } from '@core/racing/application/use-cases/GetDriverTeamUseCase';
|
||||
import { GetTeamMembershipUseCase } from '@core/racing/application/use-cases/GetTeamMembershipUseCase';
|
||||
import type { CreateTeamInputDTO } from './dtos/CreateTeamInputDTO';
|
||||
import type { UpdateTeamInputDTO } from './dtos/UpdateTeamInputDTO';
|
||||
import { TeamService } from './TeamService';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import { AllTeamsPresenter } from './presenters/AllTeamsPresenter';
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import { DriverTeamPresenter } from './presenters/DriverTeamPresenter';
|
||||
import { DriverTeamViewModel } from './dtos/TeamDto';
|
||||
type ValueObjectStub = { props: string; toString(): string };
|
||||
|
||||
type TeamEntityStub = {
|
||||
id: string;
|
||||
name: ValueObjectStub;
|
||||
tag: ValueObjectStub;
|
||||
description: ValueObjectStub;
|
||||
ownerId: ValueObjectStub;
|
||||
leagues: ValueObjectStub[];
|
||||
createdAt: { toDate(): Date };
|
||||
update: Mock;
|
||||
};
|
||||
|
||||
describe('TeamService', () => {
|
||||
let service: TeamService;
|
||||
let getAllTeamsUseCase: ReturnType<typeof vi.mocked<GetAllTeamsUseCase>>;
|
||||
let getDriverTeamUseCase: ReturnType<typeof vi.mocked<GetDriverTeamUseCase>>;
|
||||
const makeValueObject = (value: string): ValueObjectStub => ({
|
||||
props: value,
|
||||
toString() {
|
||||
return value;
|
||||
},
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
const mockGetAllTeamsUseCase = {
|
||||
execute: vi.fn(),
|
||||
const makeTeam = (overrides?: Partial<Omit<TeamEntityStub, 'update'>>): TeamEntityStub => {
|
||||
const base: Omit<TeamEntityStub, 'update'> = {
|
||||
id: 'team-1',
|
||||
name: makeValueObject('Team One'),
|
||||
tag: makeValueObject('T1'),
|
||||
description: makeValueObject('Desc'),
|
||||
ownerId: makeValueObject('owner-1'),
|
||||
leagues: [makeValueObject('league-1')],
|
||||
createdAt: { toDate: () => new Date('2023-01-01T00:00:00.000Z') },
|
||||
};
|
||||
const mockGetDriverTeamUseCase = {
|
||||
execute: vi.fn(),
|
||||
|
||||
const team: TeamEntityStub = {
|
||||
...base,
|
||||
...overrides,
|
||||
update: vi.fn((updates: Partial<{ name: string; tag: string; description: string }>) => {
|
||||
const next: Partial<Omit<TeamEntityStub, 'update'>> = {
|
||||
...(overrides ?? {}),
|
||||
...(updates.name !== undefined ? { name: makeValueObject(updates.name) } : {}),
|
||||
...(updates.tag !== undefined ? { tag: makeValueObject(updates.tag) } : {}),
|
||||
...(updates.description !== undefined ? { description: makeValueObject(updates.description) } : {}),
|
||||
};
|
||||
|
||||
return makeTeam(next);
|
||||
}),
|
||||
};
|
||||
const mockLogger = {
|
||||
|
||||
return team;
|
||||
};
|
||||
|
||||
let teamRepository: {
|
||||
findAll: Mock;
|
||||
findById: Mock;
|
||||
create: Mock;
|
||||
update: Mock;
|
||||
};
|
||||
let membershipRepository: {
|
||||
countByTeamId: Mock;
|
||||
getActiveMembershipForDriver: Mock;
|
||||
getMembership: Mock;
|
||||
getTeamMembers: Mock;
|
||||
getJoinRequests: Mock;
|
||||
saveMembership: Mock;
|
||||
};
|
||||
let driverRepository: {
|
||||
findById: Mock;
|
||||
};
|
||||
let logger: Logger;
|
||||
let service: TeamService;
|
||||
|
||||
beforeEach(() => {
|
||||
teamRepository = {
|
||||
findAll: vi.fn(),
|
||||
findById: vi.fn(),
|
||||
create: vi.fn(),
|
||||
update: vi.fn(),
|
||||
};
|
||||
|
||||
membershipRepository = {
|
||||
countByTeamId: vi.fn(),
|
||||
getActiveMembershipForDriver: vi.fn(),
|
||||
getMembership: vi.fn(),
|
||||
getTeamMembers: vi.fn(),
|
||||
getJoinRequests: vi.fn(),
|
||||
saveMembership: vi.fn(),
|
||||
};
|
||||
|
||||
driverRepository = {
|
||||
findById: vi.fn(),
|
||||
};
|
||||
|
||||
logger = {
|
||||
debug: vi.fn(),
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
} as unknown as Logger;
|
||||
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
TeamService,
|
||||
service = new TeamService(teamRepository as unknown as never, membershipRepository as unknown as never, driverRepository as unknown as never, logger);
|
||||
});
|
||||
|
||||
it('getAll returns teams and totalCount on success', async () => {
|
||||
teamRepository.findAll.mockResolvedValue([makeTeam()]);
|
||||
membershipRepository.countByTeamId.mockResolvedValue(3);
|
||||
|
||||
await expect(service.getAll()).resolves.toEqual({
|
||||
teams: [
|
||||
{
|
||||
provide: GetAllTeamsUseCase,
|
||||
useValue: mockGetAllTeamsUseCase,
|
||||
},
|
||||
{
|
||||
provide: GetDriverTeamUseCase,
|
||||
useValue: mockGetDriverTeamUseCase,
|
||||
},
|
||||
{
|
||||
provide: 'Logger',
|
||||
useValue: mockLogger,
|
||||
id: 'team-1',
|
||||
name: 'Team One',
|
||||
tag: 'T1',
|
||||
description: 'Desc',
|
||||
memberCount: 3,
|
||||
leagues: ['league-1'],
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get<TeamService>(TeamService);
|
||||
getAllTeamsUseCase = module.get(GetAllTeamsUseCase);
|
||||
getDriverTeamUseCase = module.get(GetDriverTeamUseCase);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
|
||||
describe('getAll', () => {
|
||||
it('should call use case and return result', async () => {
|
||||
const mockResult = { isOk: () => true, value: { teams: [], totalCount: 0 } };
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
getAllTeamsUseCase.execute.mockResolvedValue(mockResult as any);
|
||||
|
||||
const mockPresenter = {
|
||||
present: vi.fn(),
|
||||
getViewModel: vi.fn().mockReturnValue({ teams: [], totalCount: 0 }),
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(AllTeamsPresenter as any) = vi.fn().mockImplementation(() => mockPresenter);
|
||||
|
||||
const result = await service.getAll();
|
||||
|
||||
expect(getAllTeamsUseCase.execute).toHaveBeenCalled();
|
||||
expect(result).toEqual({ teams: [], totalCount: 0 });
|
||||
totalCount: 1,
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDriverTeam', () => {
|
||||
it('should call use case and return result', async () => {
|
||||
const mockResult = { isOk: () => true, value: {} };
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
getDriverTeamUseCase.execute.mockResolvedValue(mockResult as any);
|
||||
it('getAll returns empty list when use case error message is empty (covers fallback)', async () => {
|
||||
const executeSpy = vi
|
||||
.spyOn(GetAllTeamsUseCase.prototype, 'execute')
|
||||
.mockResolvedValueOnce(Result.err({ code: 'REPOSITORY_ERROR', details: { message: '' } }));
|
||||
|
||||
const mockPresenter = {
|
||||
present: vi.fn(),
|
||||
getViewModel: vi.fn().mockReturnValue({} as DriverTeamViewModel),
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(DriverTeamPresenter as any) = vi.fn().mockImplementation(() => mockPresenter);
|
||||
await expect(service.getAll()).resolves.toEqual({ teams: [], totalCount: 0 });
|
||||
|
||||
const result = await service.getDriverTeam('driver1');
|
||||
executeSpy.mockRestore();
|
||||
});
|
||||
|
||||
expect(getDriverTeamUseCase.execute).toHaveBeenCalledWith({ driverId: 'driver1' });
|
||||
expect(result).toEqual({});
|
||||
it('getAll returns empty list when repository throws', async () => {
|
||||
teamRepository.findAll.mockRejectedValue(new Error('boom'));
|
||||
await expect(service.getAll()).resolves.toEqual({ teams: [], totalCount: 0 });
|
||||
});
|
||||
|
||||
it('getDetails returns DTO on success', async () => {
|
||||
teamRepository.findById.mockResolvedValue(makeTeam());
|
||||
membershipRepository.getMembership.mockResolvedValue({
|
||||
teamId: 'team-1',
|
||||
driverId: 'driver-1',
|
||||
role: 'driver',
|
||||
status: 'active',
|
||||
joinedAt: new Date('2023-02-01T00:00:00.000Z'),
|
||||
});
|
||||
|
||||
it('should return null on error', async () => {
|
||||
const mockResult = { isErr: () => true, error: {} };
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
getDriverTeamUseCase.execute.mockResolvedValue(mockResult as any);
|
||||
|
||||
const result = await service.getDriverTeam('driver1');
|
||||
|
||||
expect(result).toBeNull();
|
||||
await expect(service.getDetails('team-1', 'driver-1')).resolves.toEqual({
|
||||
team: {
|
||||
id: 'team-1',
|
||||
name: 'Team One',
|
||||
tag: 'T1',
|
||||
description: 'Desc',
|
||||
ownerId: 'owner-1',
|
||||
leagues: ['league-1'],
|
||||
createdAt: '2023-01-01T00:00:00.000Z',
|
||||
},
|
||||
membership: {
|
||||
role: 'member',
|
||||
joinedAt: '2023-02-01T00:00:00.000Z',
|
||||
isActive: true,
|
||||
},
|
||||
canManage: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('getDetails passes empty driverId when userId missing', async () => {
|
||||
const executeSpy = vi
|
||||
.spyOn(GetTeamDetailsUseCase.prototype, 'execute')
|
||||
.mockImplementationOnce(async (input) => {
|
||||
expect(input).toEqual({ teamId: 'team-1', driverId: '' });
|
||||
return Result.err({ code: 'REPOSITORY_ERROR', details: { message: '' } });
|
||||
});
|
||||
|
||||
await expect(service.getDetails('team-1')).resolves.toBeNull();
|
||||
|
||||
executeSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('getDetails returns null on TEAM_NOT_FOUND', async () => {
|
||||
teamRepository.findById.mockResolvedValue(null);
|
||||
await expect(service.getDetails('team-1', 'driver-1')).resolves.toBeNull();
|
||||
});
|
||||
|
||||
it('getMembers returns DTO on success (filters missing drivers)', async () => {
|
||||
teamRepository.findById.mockResolvedValue(makeTeam());
|
||||
membershipRepository.getTeamMembers.mockResolvedValue([
|
||||
{
|
||||
teamId: 'team-1',
|
||||
driverId: 'd1',
|
||||
role: 'driver',
|
||||
status: 'active',
|
||||
joinedAt: new Date('2023-02-01T00:00:00.000Z'),
|
||||
},
|
||||
{
|
||||
teamId: 'team-1',
|
||||
driverId: 'd2',
|
||||
role: 'owner',
|
||||
status: 'active',
|
||||
joinedAt: new Date('2023-02-02T00:00:00.000Z'),
|
||||
},
|
||||
]);
|
||||
|
||||
driverRepository.findById.mockImplementation(async (id: string) => {
|
||||
if (id === 'd1') return { id: 'd1', name: makeValueObject('Driver One') };
|
||||
return null;
|
||||
});
|
||||
|
||||
await expect(service.getMembers('team-1')).resolves.toEqual({
|
||||
members: [
|
||||
{
|
||||
driverId: 'd1',
|
||||
driverName: 'Driver One',
|
||||
role: 'member',
|
||||
joinedAt: '2023-02-01T00:00:00.000Z',
|
||||
isActive: true,
|
||||
avatarUrl: '',
|
||||
},
|
||||
],
|
||||
totalCount: 1,
|
||||
ownerCount: 1,
|
||||
managerCount: 0,
|
||||
memberCount: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it('getMembers returns empty DTO on error', async () => {
|
||||
teamRepository.findById.mockResolvedValue(null);
|
||||
|
||||
await expect(service.getMembers('team-1')).resolves.toEqual({
|
||||
members: [],
|
||||
totalCount: 0,
|
||||
ownerCount: 0,
|
||||
managerCount: 0,
|
||||
memberCount: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('getMembers returns empty DTO when use case error message is empty (covers fallback)', async () => {
|
||||
const executeSpy = vi
|
||||
.spyOn(GetTeamMembersUseCase.prototype, 'execute')
|
||||
.mockResolvedValueOnce(Result.err({ code: 'REPOSITORY_ERROR', details: { message: '' } }));
|
||||
|
||||
await expect(service.getMembers('team-1')).resolves.toEqual({
|
||||
members: [],
|
||||
totalCount: 0,
|
||||
ownerCount: 0,
|
||||
managerCount: 0,
|
||||
memberCount: 0,
|
||||
});
|
||||
|
||||
executeSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('getJoinRequests returns DTO on success', async () => {
|
||||
teamRepository.findById.mockResolvedValue(makeTeam());
|
||||
membershipRepository.getJoinRequests.mockResolvedValue([
|
||||
{
|
||||
id: 'jr1',
|
||||
teamId: 'team-1',
|
||||
driverId: 'd1',
|
||||
requestedAt: new Date('2023-02-03T00:00:00.000Z'),
|
||||
},
|
||||
]);
|
||||
driverRepository.findById.mockResolvedValue({ id: 'd1', name: makeValueObject('Driver One') });
|
||||
|
||||
await expect(service.getJoinRequests('team-1')).resolves.toEqual({
|
||||
requests: [
|
||||
{
|
||||
requestId: 'jr1',
|
||||
driverId: 'd1',
|
||||
driverName: 'Driver One',
|
||||
teamId: 'team-1',
|
||||
status: 'pending',
|
||||
requestedAt: '2023-02-03T00:00:00.000Z',
|
||||
avatarUrl: '',
|
||||
},
|
||||
],
|
||||
pendingCount: 1,
|
||||
totalCount: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it('getJoinRequests returns empty DTO on error', async () => {
|
||||
teamRepository.findById.mockResolvedValue(null);
|
||||
|
||||
await expect(service.getJoinRequests('team-1')).resolves.toEqual({
|
||||
requests: [],
|
||||
pendingCount: 0,
|
||||
totalCount: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('getJoinRequests returns empty DTO when use case error message is empty (covers fallback)', async () => {
|
||||
const executeSpy = vi
|
||||
.spyOn(GetTeamJoinRequestsUseCase.prototype, 'execute')
|
||||
.mockResolvedValueOnce(Result.err({ code: 'REPOSITORY_ERROR', details: { message: '' } }));
|
||||
|
||||
await expect(service.getJoinRequests('team-1')).resolves.toEqual({
|
||||
requests: [],
|
||||
pendingCount: 0,
|
||||
totalCount: 0,
|
||||
});
|
||||
|
||||
executeSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('create returns success on success', async () => {
|
||||
membershipRepository.getActiveMembershipForDriver.mockResolvedValue(null);
|
||||
teamRepository.create.mockImplementation(async (team: unknown) => team);
|
||||
|
||||
const input: CreateTeamInputDTO = { name: 'N', tag: 'T', description: 'D' };
|
||||
|
||||
await expect(service.create(input, 'owner-1')).resolves.toEqual({
|
||||
id: expect.any(String),
|
||||
success: true,
|
||||
});
|
||||
expect(membershipRepository.saveMembership).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('create returns failure DTO on error', async () => {
|
||||
membershipRepository.getActiveMembershipForDriver.mockResolvedValue({ teamId: 'team-1' });
|
||||
|
||||
const input: CreateTeamInputDTO = { name: 'N', tag: 'T' };
|
||||
|
||||
await expect(service.create(input, 'owner-1')).resolves.toEqual({
|
||||
id: '',
|
||||
success: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('create uses empty description and ownerId when missing', async () => {
|
||||
const executeSpy = vi
|
||||
.spyOn(CreateTeamUseCase.prototype, 'execute')
|
||||
.mockImplementationOnce(async (command) => {
|
||||
expect(command).toMatchObject({ description: '', ownerId: '' });
|
||||
return Result.err({ code: 'REPOSITORY_ERROR', details: { message: '' } });
|
||||
});
|
||||
|
||||
const input: CreateTeamInputDTO = { name: 'N', tag: 'T' };
|
||||
|
||||
await expect(service.create(input)).resolves.toEqual({ id: '', success: false });
|
||||
|
||||
executeSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('update returns success on success', async () => {
|
||||
membershipRepository.getMembership.mockResolvedValue({ role: 'owner' });
|
||||
teamRepository.findById.mockResolvedValue(makeTeam());
|
||||
teamRepository.update.mockResolvedValue(undefined);
|
||||
|
||||
const input: UpdateTeamInputDTO = { name: 'New Name' };
|
||||
|
||||
await expect(service.update('team-1', input, 'owner-1')).resolves.toEqual({ success: true });
|
||||
|
||||
expect(teamRepository.update).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('update returns failure DTO on error', async () => {
|
||||
membershipRepository.getMembership.mockResolvedValue(null);
|
||||
|
||||
const input: UpdateTeamInputDTO = { name: 'New Name' };
|
||||
|
||||
await expect(service.update('team-1', input, 'owner-1')).resolves.toEqual({ success: false });
|
||||
});
|
||||
|
||||
it('update uses empty updatedBy when userId missing', async () => {
|
||||
const executeSpy = vi
|
||||
.spyOn(UpdateTeamUseCase.prototype, 'execute')
|
||||
.mockImplementationOnce(async (command) => {
|
||||
expect(command.updatedBy).toBe('');
|
||||
return Result.err({ code: 'REPOSITORY_ERROR', details: { message: '' } });
|
||||
});
|
||||
|
||||
const input: UpdateTeamInputDTO = { name: 'New Name' };
|
||||
|
||||
await expect(service.update('team-1', input)).resolves.toEqual({ success: false });
|
||||
|
||||
executeSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('update includes name when provided', async () => {
|
||||
const executeSpy = vi
|
||||
.spyOn(UpdateTeamUseCase.prototype, 'execute')
|
||||
.mockImplementationOnce(async (command) => {
|
||||
expect(command.updates).toEqual({ name: 'New Name' });
|
||||
return Result.err({ code: 'REPOSITORY_ERROR', details: { message: '' } });
|
||||
});
|
||||
|
||||
const input: UpdateTeamInputDTO = { name: 'New Name' };
|
||||
|
||||
await expect(service.update('team-1', input, 'owner-1')).resolves.toEqual({ success: false });
|
||||
|
||||
executeSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('update includes tag when provided', async () => {
|
||||
const executeSpy = vi
|
||||
.spyOn(UpdateTeamUseCase.prototype, 'execute')
|
||||
.mockImplementationOnce(async (command) => {
|
||||
expect(command.updates).toEqual({ tag: 'NEW' });
|
||||
return Result.err({ code: 'REPOSITORY_ERROR', details: { message: '' } });
|
||||
});
|
||||
|
||||
const input: UpdateTeamInputDTO = { tag: 'NEW' };
|
||||
|
||||
await expect(service.update('team-1', input, 'owner-1')).resolves.toEqual({ success: false });
|
||||
|
||||
executeSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('update includes description when provided', async () => {
|
||||
const executeSpy = vi
|
||||
.spyOn(UpdateTeamUseCase.prototype, 'execute')
|
||||
.mockImplementationOnce(async (command) => {
|
||||
expect(command.updates).toEqual({ description: 'D' });
|
||||
return Result.err({ code: 'REPOSITORY_ERROR', details: { message: '' } });
|
||||
});
|
||||
|
||||
const input: UpdateTeamInputDTO = { description: 'D' };
|
||||
|
||||
await expect(service.update('team-1', input, 'owner-1')).resolves.toEqual({ success: false });
|
||||
|
||||
executeSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('update includes no updates when no fields are provided', async () => {
|
||||
const executeSpy = vi
|
||||
.spyOn(UpdateTeamUseCase.prototype, 'execute')
|
||||
.mockImplementationOnce(async (command) => {
|
||||
expect(command.updates).toEqual({});
|
||||
return Result.err({ code: 'REPOSITORY_ERROR', details: { message: '' } });
|
||||
});
|
||||
|
||||
const input: UpdateTeamInputDTO = {};
|
||||
|
||||
await expect(service.update('team-1', input, 'owner-1')).resolves.toEqual({ success: false });
|
||||
|
||||
executeSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('getDriverTeam returns driver team DTO on success', async () => {
|
||||
membershipRepository.getActiveMembershipForDriver.mockResolvedValue({
|
||||
teamId: 'team-1',
|
||||
role: 'driver',
|
||||
status: 'active',
|
||||
joinedAt: new Date('2023-02-01T00:00:00.000Z'),
|
||||
});
|
||||
teamRepository.findById.mockResolvedValue(makeTeam());
|
||||
|
||||
await expect(service.getDriverTeam('driver-1')).resolves.toEqual({
|
||||
team: {
|
||||
id: 'team-1',
|
||||
name: 'Team One',
|
||||
tag: 'T1',
|
||||
description: 'Desc',
|
||||
ownerId: 'owner-1',
|
||||
leagues: ['league-1'],
|
||||
createdAt: '2023-01-01T00:00:00.000Z',
|
||||
},
|
||||
membership: {
|
||||
role: 'member',
|
||||
joinedAt: '2023-02-01T00:00:00.000Z',
|
||||
isActive: true,
|
||||
},
|
||||
isOwner: false,
|
||||
canManage: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('getDriverTeam returns null when membership is missing', async () => {
|
||||
membershipRepository.getActiveMembershipForDriver.mockResolvedValue(null);
|
||||
|
||||
await expect(service.getDriverTeam('driver-1')).resolves.toBeNull();
|
||||
expect(teamRepository.findById).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('getDriverTeam returns null when use case error message is empty (covers fallback)', async () => {
|
||||
const executeSpy = vi
|
||||
.spyOn(GetDriverTeamUseCase.prototype, 'execute')
|
||||
.mockResolvedValueOnce(Result.err({ code: 'REPOSITORY_ERROR', details: { message: '' } }));
|
||||
|
||||
await expect(service.getDriverTeam('driver-1')).resolves.toBeNull();
|
||||
|
||||
executeSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('getMembership returns presenter model on success', async () => {
|
||||
membershipRepository.getMembership.mockResolvedValue({
|
||||
teamId: 'team-1',
|
||||
driverId: 'd1',
|
||||
role: 'driver',
|
||||
status: 'active',
|
||||
joinedAt: new Date('2023-02-01T00:00:00.000Z'),
|
||||
});
|
||||
|
||||
await expect(service.getMembership('team-1', 'd1')).resolves.toEqual({
|
||||
role: 'member',
|
||||
joinedAt: '2023-02-01T00:00:00.000Z',
|
||||
isActive: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('getMembership returns null when missing', async () => {
|
||||
membershipRepository.getMembership.mockResolvedValue(null);
|
||||
await expect(service.getMembership('team-1', 'd1')).resolves.toBeNull();
|
||||
});
|
||||
|
||||
it('getMembership returns null when use case error message is empty (covers fallback)', async () => {
|
||||
const executeSpy = vi
|
||||
.spyOn(GetTeamMembershipUseCase.prototype, 'execute')
|
||||
.mockResolvedValueOnce(Result.err({ code: 'REPOSITORY_ERROR', details: { message: '' } }));
|
||||
|
||||
await expect(service.getMembership('team-1', 'd1')).resolves.toBeNull();
|
||||
|
||||
executeSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user