106 lines
3.0 KiB
TypeScript
106 lines
3.0 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';
|
|
|
|
// 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();
|
|
|
|
vi.mock('@/lib/services/ServiceProvider', () => ({
|
|
useServices: () => ({
|
|
leagueStewardingService: {
|
|
getProtestDetailViewModel: mockGetProtestDetailViewModel,
|
|
},
|
|
protestService: {
|
|
applyPenalty: vi.fn(),
|
|
requestDefense: vi.fn(),
|
|
},
|
|
leagueMembershipService: {
|
|
fetchLeagueMemberships: mockFetchLeagueMemberships,
|
|
getMembership: mockGetMembership,
|
|
},
|
|
}),
|
|
}));
|
|
|
|
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();
|
|
|
|
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();
|
|
});
|
|
}); |