import React from 'react'; import { act, cleanup, render, screen, waitFor } from '@testing-library/react'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { LivePackRadar } from '../components/group-rides/live-pack-radar'; import { GroupRidesManagement } from '../components/group-rides/group-rides-management'; const streams = vi.hoisted(() => ({ listeners: new Map void; error: (error: unknown) => void; stop: ReturnType }>() })); vi.mock('../lib/firebase-client', () => ({ firestore: {}, firebaseAuth: {} })); vi.mock('firebase/app', () => ({ getApps: () => [{ name: 'motorsignal-local-qa' }], initializeApp: vi.fn() })); vi.mock('firebase/auth', () => ({ getAuth: () => ({}), connectAuthEmulator: vi.fn(), signInWithEmailAndPassword: vi.fn(), signOut: vi.fn() })); vi.mock('firebase/firestore', () => ({ getFirestore: () => ({}), connectFirestoreEmulator: vi.fn(), collection: (_db: unknown, ...path: string[]) => path.join('/'), where: () => ({}), query: (path: string) => `query:${path}`, getDoc: async () => { throw Object.assign(new Error('permission-denied'), { code: 'permission-denied' }); }, doc: (_db: unknown, ...path: string[]) => path.join('/'), onSnapshot: (path: string, next: (snapshot: unknown) => void, error: (error: unknown) => void) => { const stop = vi.fn(); streams.listeners.set(path, { next, error, stop }); return stop; }, })); const ride = { id: 'ride', title: 'Isolated Ride', meetingPoint: 'QA Rally', participantCount: 2 } as any; const snapshot = (data: unknown) => ({ exists: () => true, data: () => data }); const rideData = { organizerUid: 'owner', accessUids: ['owner', 'member'] }; function load() { const view = render(); act(() => streams.listeners.get('group_rides/ride')!.next(snapshot(rideData))); act(() => streams.listeners.get('group_rides/ride/live_presence/owner')!.next(snapshot({ latitude: 34.5, longitude: -83.9, speedMph: 40, updatedAt: new Date().toISOString(), sharingEnabled: true }))); expect(screen.getByTestId('telemetry-card-ApexLeader')).toBeDefined(); return view; } beforeEach(() => { streams.listeners.clear(); window.history.replaceState({}, '', '/'); }); afterEach(cleanup); describe('radar stops exposing cached telemetry when access ends', () => { it('clears cached cards and stops presence listeners when membership is revoked', () => { load(); const presence = streams.listeners.get('group_rides/ride/live_presence/owner')!; act(() => streams.listeners.get('group_rides/ride')!.next(snapshot({ organizerUid: 'owner', accessUids: ['owner'] }))); expect(screen.getByTestId('telemetry-access-barrier')).toBeDefined(); expect(screen.queryByTestId('telemetry-card-ApexLeader')).toBeNull(); expect(presence.stop).toHaveBeenCalledOnce(); act(() => presence.next(snapshot({ latitude: 34.5, longitude: -83.9, updatedAt: new Date().toISOString() }))); expect(screen.queryByTestId('telemetry-card-ApexLeader')).toBeNull(); }); it('clears cached cards and stops listeners after a denied presence snapshot', () => { load(); const presence = streams.listeners.get('group_rides/ride/live_presence/owner')!; act(() => presence.error({ code: 'permission-denied', message: 'permission-denied' })); expect(screen.getByTestId('telemetry-access-barrier')).toBeDefined(); expect(screen.queryByTestId('telemetry-card-ApexLeader')).toBeNull(); expect(presence.stop).toHaveBeenCalledOnce(); }); it('unsubscribes ride and presence streams when leaving the radar tab', () => { const view = load(); view.unmount(); for (const listener of streams.listeners.values()) expect(listener.stop).toHaveBeenCalledOnce(); }); it('shows a telemetry error and clears cached cards when the ride disappears', () => { load(); const presence = streams.listeners.get('group_rides/ride/live_presence/owner')!; act(() => streams.listeners.get('group_rides/ride')!.next({ exists: () => false })); expect(screen.queryByTestId('telemetry-card-ApexLeader')).toBeNull(); expect(screen.getByTestId('presence-error-state').textContent).toContain('no longer available'); expect(presence.stop).toHaveBeenCalledOnce(); }); it('shows an error instead of an empty pack on unavailable presence streams', () => { load(); act(() => streams.listeners.get('group_rides/ride/live_presence/owner')!.error({ code: 'unavailable', message: 'unavailable' })); expect(screen.queryByTestId('telemetry-card-ApexLeader')).toBeNull(); expect(screen.getByTestId('presence-error-state')).toBeDefined(); expect(screen.queryByTestId('empty-pack-state')).toBeNull(); }); it('keeps an inaccessible selected ride in real radar mode instead of displaying a demo', async () => { window.history.replaceState({}, '', '/group-rides?tab=radar&rideId=removed-ride'); render(); await act(async () => { await Promise.resolve(); }); act(() => streams.listeners.get('group_rides/removed-ride')?.error({ code: 'permission-denied', message: 'permission-denied' })); await waitFor(() => expect(screen.getByTestId('telemetry-access-barrier')).toBeDefined()); expect(screen.queryByTestId('showcase-simulation-pill')).toBeNull(); }); });