import { describe, it, expect, beforeEach, vi, type Mock } from 'vitest'; import { GetLeagueAdminPermissionsUseCase, type GetLeagueAdminPermissionsInput, type GetLeagueAdminPermissionsResult, type GetLeagueAdminPermissionsErrorCode, } from './GetLeagueAdminPermissionsUseCase'; import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository'; import type { ILeagueMembershipRepository } from '../../domain/repositories/ILeagueMembershipRepository'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import type { Logger } from '@core/shared/application'; describe('GetLeagueAdminPermissionsUseCase', () => { let mockLeagueRepo: ILeagueRepository; let mockMembershipRepo: ILeagueMembershipRepository; let mockFindById: Mock; let mockGetMembership: Mock; const logger: Logger = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn(), }; beforeEach(() => { mockFindById = vi.fn(); mockGetMembership = vi.fn(); mockLeagueRepo = { findById: mockFindById, findAll: vi.fn(), create: vi.fn(), update: vi.fn(), delete: vi.fn(), exists: vi.fn(), findByOwnerId: vi.fn(), searchByName: vi.fn(), } as ILeagueRepository; mockMembershipRepo = { getMembership: mockGetMembership, getMembershipsForDriver: vi.fn(), saveMembership: vi.fn(), removeMembership: vi.fn(), getJoinRequests: vi.fn(), saveJoinRequest: vi.fn(), removeJoinRequest: vi.fn(), countByLeagueId: vi.fn(), getLeagueMembers: vi.fn(), } as ILeagueMembershipRepository; }); const createUseCase = () => new GetLeagueAdminPermissionsUseCase(mockLeagueRepo, mockMembershipRepo, logger); const input: GetLeagueAdminPermissionsInput = { leagueId: 'league1', performerDriverId: 'driver1', }; it('returns LEAGUE_NOT_FOUND when league does not exist and does not call output', async () => { mockFindById.mockResolvedValue(null); const useCase = createUseCase(); const result = await useCase.execute(input); expect(result.isErr()).toBe(true); const err = result.unwrapErr() as ApplicationErrorCode; expect(err.code).toBe('LEAGUE_NOT_FOUND'); expect(err.details.message).toBe('League not found'); }); it('returns USER_NOT_MEMBER when membership is missing and does not call output', async () => { mockFindById.mockResolvedValue({ id: 'league1' }); mockGetMembership.mockResolvedValue(null); const useCase = createUseCase(); const result = await useCase.execute(input); expect(result.isErr()).toBe(true); const err = result.unwrapErr() as ApplicationErrorCode; expect(err.code).toBe('USER_NOT_MEMBER'); expect(err.details.message).toBe('User is not a member of this league'); }); it('returns USER_NOT_MEMBER when membership is not active and does not call output', async () => { mockFindById.mockResolvedValue({ id: 'league1' }); mockGetMembership.mockResolvedValue({ status: 'inactive', role: 'admin' }); const useCase = createUseCase(); const result = await useCase.execute(input); expect(result.isErr()).toBe(true); const err = result.unwrapErr() as ApplicationErrorCode; expect(err.code).toBe('USER_NOT_MEMBER'); expect(err.details.message).toBe('User is not a member of this league'); }); it('returns USER_NOT_MEMBER when role is member and does not call output', async () => { mockFindById.mockResolvedValue({ id: 'league1' }); mockGetMembership.mockResolvedValue({ status: 'active', role: 'member' }); const useCase = createUseCase(); const result = await useCase.execute(input); expect(result.isErr()).toBe(true); const err = result.unwrapErr() as ApplicationErrorCode; expect(err.code).toBe('USER_NOT_MEMBER'); expect(err.details.message).toBe('User is not a member of this league'); }); it('returns admin permissions for admin role and calls output once', async () => { const league = { id: 'league1' } as unknown as { id: string }; mockFindById.mockResolvedValue(league); mockGetMembership.mockResolvedValue({ status: 'active', role: 'admin' }); const useCase = createUseCase(); const result = await useCase.execute(input); expect(result.isOk()).toBe(true); expect(result.unwrap()).toBeUndefined(); const presented = expect(presented.league).toBe(league); expect(presented.permissions).toEqual({ canManageSchedule: true, canManageMembers: true, canManageSponsorships: true, canManageScoring: true, }); }); it('returns admin permissions for owner role and calls output once', async () => { const league = { id: 'league1' } as unknown as { id: string }; mockFindById.mockResolvedValue(league); mockGetMembership.mockResolvedValue({ status: 'active', role: 'owner' }); const useCase = createUseCase(); const result = await useCase.execute(input); expect(result.isOk()).toBe(true); expect(result.unwrap()).toBeUndefined(); const presented = expect(presented.league).toBe(league); expect(presented.permissions).toEqual({ canManageSchedule: true, canManageMembers: true, canManageSponsorships: true, canManageScoring: true, }); }); it('wraps repository errors in REPOSITORY_ERROR and does not call output', async () => { const error = new Error('repo failed'); mockFindById.mockRejectedValue(error); const useCase = createUseCase(); const result = await useCase.execute(input); expect(result.isErr()).toBe(true); const err = result.unwrapErr() as ApplicationErrorCode; expect(err.code).toBe('REPOSITORY_ERROR'); expect(err.details.message).toBe('repo failed'); }); });