146 lines
4.4 KiB
TypeScript
146 lines
4.4 KiB
TypeScript
import React from 'react';
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { render, screen, waitFor } from '@testing-library/react';
|
|
import '@testing-library/jest-dom';
|
|
|
|
import ProtestReviewPage from './page';
|
|
|
|
// Mock useEffectiveDriverId
|
|
vi.mock('@/hooks/useEffectiveDriverId', () => ({
|
|
useEffectiveDriverId: () => 'driver-1',
|
|
}));
|
|
|
|
// Mocks for Next.js navigation
|
|
const mockPush = vi.fn();
|
|
|
|
vi.mock('next/navigation', () => ({
|
|
useRouter: () => ({
|
|
push: mockPush,
|
|
}),
|
|
useParams: () => ({ id: 'league-1', protestId: 'protest-1' }),
|
|
}));
|
|
|
|
// Mock effective driver id hook
|
|
vi.mock('@/hooks/useEffectiveDriverId', () => ({
|
|
useEffectiveDriverId: () => 'driver-1',
|
|
}));
|
|
|
|
const mockGetProtestDetailViewModel = vi.fn();
|
|
const mockFetchLeagueMemberships = vi.fn();
|
|
const mockGetMembership = vi.fn();
|
|
|
|
// Mock useLeagueAdminStatus hook
|
|
vi.mock('@/hooks/league/useLeagueAdminStatus', () => ({
|
|
useLeagueAdminStatus: (leagueId: string, driverId: string) => ({
|
|
data: mockGetMembership.mock.results[0]?.value ?
|
|
(mockGetMembership.mock.results[0].value.role === 'admin' || mockGetMembership.mock.results[0].value.role === 'owner') : false,
|
|
isLoading: false,
|
|
isError: false,
|
|
isSuccess: true,
|
|
refetch: vi.fn(),
|
|
}),
|
|
}));
|
|
|
|
// Mock useProtestDetail hook
|
|
vi.mock('@/hooks/league/useProtestDetail', () => ({
|
|
useProtestDetail: (leagueId: string, protestId: string, enabled: boolean = true) => ({
|
|
data: mockGetProtestDetailViewModel.mock.results[0]?.value || null,
|
|
isLoading: false,
|
|
isError: false,
|
|
isSuccess: !!mockGetProtestDetailViewModel.mock.results[0]?.value,
|
|
refetch: vi.fn(),
|
|
retry: vi.fn(),
|
|
}),
|
|
}));
|
|
|
|
// Mock useInject for protest service
|
|
vi.mock('@/lib/di/hooks/useInject', () => ({
|
|
useInject: (token: symbol) => {
|
|
if (token.toString().includes('PROTEST_SERVICE_TOKEN')) {
|
|
return {
|
|
applyPenalty: vi.fn(),
|
|
requestDefense: vi.fn(),
|
|
};
|
|
}
|
|
return {};
|
|
},
|
|
}));
|
|
|
|
// Mock the static LeagueMembershipService for LeagueRoleUtility
|
|
vi.mock('@/lib/services/leagues/LeagueMembershipService', () => ({
|
|
LeagueMembershipService: {
|
|
getMembership: mockGetMembership,
|
|
fetchLeagueMemberships: mockFetchLeagueMemberships,
|
|
setLeagueMemberships: vi.fn(),
|
|
clearLeagueMemberships: vi.fn(),
|
|
getCachedMembershipsIterator: vi.fn(() => [][Symbol.iterator]()),
|
|
getAllMembershipsForDriver: vi.fn(() => []),
|
|
getLeagueMembers: vi.fn(() => []),
|
|
},
|
|
}));
|
|
|
|
const mockIsLeagueAdminOrHigherRole = vi.fn();
|
|
|
|
vi.mock('@/lib/utilities/LeagueRoleUtility', () => ({
|
|
LeagueRoleUtility: {
|
|
isLeagueAdminOrHigherRole: (...args: unknown[]) => mockIsLeagueAdminOrHigherRole(...args),
|
|
},
|
|
}));
|
|
|
|
describe('ProtestReviewPage', () => {
|
|
beforeEach(() => {
|
|
mockPush.mockReset();
|
|
mockGetProtestDetailViewModel.mockReset();
|
|
mockFetchLeagueMemberships.mockReset();
|
|
mockGetMembership.mockReset();
|
|
mockIsLeagueAdminOrHigherRole.mockReset();
|
|
|
|
// Set up default mock implementations
|
|
mockFetchLeagueMemberships.mockResolvedValue(undefined);
|
|
mockGetMembership.mockReturnValue({ role: 'admin' });
|
|
mockIsLeagueAdminOrHigherRole.mockReturnValue(true);
|
|
});
|
|
|
|
it('loads protest detail via LeagueStewardingService view model method', async () => {
|
|
mockGetProtestDetailViewModel.mockResolvedValue({
|
|
protest: {
|
|
id: 'protest-1',
|
|
raceId: 'race-1',
|
|
protestingDriverId: 'driver-1',
|
|
accusedDriverId: 'driver-2',
|
|
description: 'desc',
|
|
submittedAt: '2023-10-01T10:00:00Z',
|
|
status: 'pending',
|
|
incident: { lap: 1 },
|
|
},
|
|
race: {
|
|
id: 'race-1',
|
|
name: 'Test Race',
|
|
formattedDate: '10/1/2023',
|
|
},
|
|
protestingDriver: { id: 'driver-1', name: 'Driver 1' },
|
|
accusedDriver: { id: 'driver-2', name: 'Driver 2' },
|
|
penaltyTypes: [
|
|
{
|
|
type: 'time_penalty',
|
|
label: 'Time Penalty',
|
|
description: 'Add seconds to race result',
|
|
requiresValue: true,
|
|
valueLabel: 'seconds',
|
|
defaultValue: 5,
|
|
},
|
|
],
|
|
defaultReasons: { upheld: 'Upheld reason', dismissed: 'Dismissed reason' },
|
|
initialPenaltyType: 'time_penalty',
|
|
initialPenaltyValue: 5,
|
|
});
|
|
|
|
render(<ProtestReviewPage />);
|
|
|
|
await waitFor(() => {
|
|
expect(mockGetProtestDetailViewModel).toHaveBeenCalledWith('league-1', 'protest-1');
|
|
});
|
|
|
|
expect(await screen.findByText('Protest Review')).toBeInTheDocument();
|
|
});
|
|
}); |