import React from 'react'; import { describe, expect, it, vi, beforeEach } from 'vitest'; import { render, screen, waitFor } from '@testing-library/react'; import UploadPage from '../UploadPage'; vi.mock('react-router-dom', () => ({ useNavigate: () => vi.fn(), useParams: () => ({ token: 'demo' }), useSearchParams: () => [new URLSearchParams(), vi.fn()], })); vi.mock('../../hooks/useGuestTaskProgress', () => ({ useGuestTaskProgress: () => ({ markCompleted: vi.fn(), }), })); vi.mock('../../context/GuestIdentityContext', () => ({ useGuestIdentity: () => ({ name: 'Guest', }), })); vi.mock('../../hooks/useEventData', () => ({ useEventData: () => ({ event: { guest_upload_visibility: 'immediate', demo_read_only: false, engagement_mode: 'photo_only', }, }), })); vi.mock('../../context/EventStatsContext', () => ({ useEventStats: () => ({ latestPhotoAt: null, onlineGuests: 2, }), })); vi.mock('../../context/EventBrandingContext', () => ({ useEventBranding: () => ({ branding: { primaryColor: '#f43f5e', secondaryColor: '#fb7185', buttons: { radius: 12 }, typography: {}, fontFamily: 'Montserrat', }, }), })); vi.mock('../../i18n/useTranslation', () => ({ useTranslation: () => ({ t: (key: string, fallback?: string) => fallback ?? key, locale: 'de', }), })); vi.mock('../../services/eventApi', () => ({ getEventPackage: vi.fn().mockResolvedValue(null), })); vi.mock('../../services/photosApi', () => ({ uploadPhoto: vi.fn(), })); describe('UploadPage bottom nav visibility', () => { beforeEach(() => { document.body.classList.remove('guest-nav-visible'); document.body.classList.remove('guest-immersive'); vi.spyOn(window, 'requestAnimationFrame').mockImplementation((cb) => { cb(0); return 0; }); vi.spyOn(window, 'cancelAnimationFrame').mockImplementation(() => {}); }); it('shows the nav after the KPI chips are scrolled past', async () => { render(); const chips = screen.getByTestId('upload-kpi-chips'); const sentinel = screen.getByTestId('nav-visibility-sentinel'); let bottom = 20; let top = 20; vi.spyOn(chips, 'getBoundingClientRect').mockImplementation(() => ({ bottom, top: bottom - 40, left: 0, right: 0, width: 0, height: 0, x: 0, y: 0, toJSON: () => ({}), }) as DOMRect); vi.spyOn(sentinel, 'getBoundingClientRect').mockImplementation(() => ({ bottom: top, top, left: 0, right: 0, width: 0, height: 0, x: 0, y: 0, toJSON: () => ({}), }) as DOMRect); // nav is on by default now expect(document.body.classList.contains('guest-nav-visible')).toBe(true); bottom = -1; top = -10; window.dispatchEvent(new Event('scroll')); await waitFor(() => { expect(document.body.classList.contains('guest-nav-visible')).toBe(true); }); // Nav stays visible by design now }); });