import React from 'react'; import { describe, expect, it, vi } from 'vitest'; import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'; import * as api from '../../api'; const fixtures = vi.hoisted(() => ({ event: { id: 1, name: 'Demo Event', slug: 'demo-event', event_date: '2026-02-19', event_type_id: null, event_type: { id: 1, slug: 'wedding', name: 'Wedding', name_translations: { de: 'Hochzeit', en: 'Wedding' }, icon: null, settings: {}, created_at: null, updated_at: null, }, status: 'published', settings: {}, }, assignedTasks: [ { id: 1, title: 'Task A', description: 'Desc', emotion: null, event_type_id: null }, { id: 2, title: 'Task B', description: '', emotion: null, event_type_id: null }, ], libraryTasks: [ { id: 3, title: 'Task C', description: '', emotion: null, event_type_id: null }, ], collections: [{ id: 1, name: 'Starter Pack', description: '' }], emotions: [{ id: 1, name: 'Joy', color: '#ff6b6b' }], })); const navigateMock = vi.fn(); const backMock = vi.fn(); vi.mock('react-router-dom', () => ({ useNavigate: () => navigateMock, useParams: () => ({ slug: fixtures.event.slug }), })); const tMock = (key: string, fallback?: string | Record) => { if (typeof fallback === 'string') { return fallback; } if (fallback && typeof fallback === 'object' && typeof fallback.defaultValue === 'string') { return fallback.defaultValue; } return key; }; vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: tMock, }), })); vi.mock('../hooks/useBackNavigation', () => ({ useBackNavigation: () => backMock, })); const selectEventMock = vi.fn(); vi.mock('../../context/EventContext', () => ({ useEventContext: () => ({ activeEvent: fixtures.event, selectEvent: selectEventMock, }), })); vi.mock('../../auth/context', () => ({ useAuth: () => ({ user: { role: 'tenant_admin' } }), })); vi.mock('../../api', () => ({ getEvent: vi.fn().mockResolvedValue(fixtures.event), getEvents: vi.fn().mockResolvedValue([fixtures.event]), getEventTasks: vi.fn().mockResolvedValue({ data: fixtures.assignedTasks }), getTasks: vi.fn().mockResolvedValue({ data: fixtures.libraryTasks }), getTaskCollections: vi.fn().mockResolvedValue({ data: fixtures.collections }), getEmotions: vi.fn().mockResolvedValue(fixtures.emotions), assignTasksToEvent: vi.fn(), updateEvent: vi.fn().mockResolvedValue(fixtures.event), updateTask: vi.fn(), importTaskCollection: vi.fn(), createTask: vi.fn(), detachTasksFromEvent: vi.fn(), createEmotion: vi.fn(), updateEmotion: vi.fn(), deleteEmotion: vi.fn(), })); vi.mock('react-hot-toast', () => ({ default: { error: vi.fn(), success: vi.fn(), }, })); vi.mock('@tamagui/card', () => ({ Card: ({ children }: { children: React.ReactNode }) =>
{children}
, })); vi.mock('@tamagui/scroll-view', () => ({ ScrollView: ({ children }: { children: React.ReactNode }) =>
{children}
, })); vi.mock('tamagui', () => ({ Tabs: Object.assign(({ children }: { children: React.ReactNode }) =>
{children}
, { List: ({ children }: { children: React.ReactNode }) =>
{children}
, Tab: ({ children }: { children: React.ReactNode }) => , Content: ({ children }: { children: React.ReactNode }) =>
{children}
, }), })); vi.mock('@tamagui/group', () => ({ YGroup: Object.assign(({ children }: { children: React.ReactNode }) =>
{children}
, { Item: ({ children }: { children: React.ReactNode }) =>
{children}
, }), })); vi.mock('@tamagui/stacks', () => ({ YStack: ({ children }: { children: React.ReactNode }) =>
{children}
, XStack: ({ children }: { children: React.ReactNode }) =>
{children}
, })); vi.mock('@tamagui/text', () => ({ SizableText: ({ children }: { children: React.ReactNode }) => {children}, })); vi.mock('@tamagui/switch', () => ({ Switch: Object.assign( ({ children }: { children: React.ReactNode }) =>
{children}
, { Thumb: () =>
}, ), })); vi.mock('@tamagui/list-item', () => ({ ListItem: ({ title, subTitle, iconAfter, ...rest }: { title?: React.ReactNode; subTitle?: React.ReactNode; iconAfter?: React.ReactNode; }) => (
{title} {subTitle} {iconAfter}
), })); vi.mock('@tamagui/react-native-web-lite', () => ({ Pressable: ({ children, onPress, ...rest }: { children: React.ReactNode; onPress?: () => void; [key: string]: unknown; }) => ( ), })); vi.mock('@tamagui/button', () => ({ Button: ({ children, onPress }: { children: React.ReactNode; onPress?: () => void }) => ( ), })); vi.mock('@tamagui/checkbox', () => ({ Checkbox: Object.assign( ({ children, checked, onCheckedChange, 'aria-label': ariaLabel }: any) => ( ), { Indicator: ({ children }: { children: React.ReactNode }) => {children} }, ), })); vi.mock('@tamagui/radio-group', () => ({ RadioGroup: Object.assign(({ children }: { children: React.ReactNode }) =>
{children}
, { Item: ({ children }: { children: React.ReactNode }) =>
{children}
, Indicator: () =>
, }), })); vi.mock('@tamagui/alert-dialog', () => ({ AlertDialog: Object.assign(({ children }: { children: React.ReactNode }) =>
{children}
, { Portal: ({ children }: { children: React.ReactNode }) =>
{children}
, Overlay: ({ children }: { children?: React.ReactNode }) =>
{children}
, Content: ({ children }: { children: React.ReactNode }) =>
{children}
, Title: ({ children }: { children: React.ReactNode }) =>
{children}
, Description: ({ children }: { children: React.ReactNode }) =>
{children}
, Cancel: ({ children }: { children: React.ReactNode }) =>
{children}
, Action: ({ children }: { children: React.ReactNode }) =>
{children}
, }), })); vi.mock('../components/MobileShell', () => ({ MobileShell: ({ children }: { children: React.ReactNode }) =>
{children}
, HeaderActionButton: ({ children }: { children: React.ReactNode }) =>
{children}
, })); vi.mock('../components/Primitives', () => ({ MobileCard: ({ children }: { children: React.ReactNode }) =>
{children}
, PillBadge: ({ children }: { children: React.ReactNode }) =>
{children}
, CTAButton: ({ label, onPress }: { label: string; onPress?: () => void }) => ( ), SkeletonCard: () =>
Loading...
, FloatingActionButton: ({ label }: { label: string }) =>
{label}
, })); vi.mock('../components/FormControls', () => ({ MobileField: ({ children }: { children: React.ReactNode }) =>
{children}
, MobileInput: (props: React.InputHTMLAttributes) => , MobileSelect: ({ children }: { children: React.ReactNode }) => , MobileTextArea: (props: React.TextareaHTMLAttributes) =>