import React from 'react'; import '@testing-library/jest-dom/vitest'; import { cleanup } from '@testing-library/react'; import { afterEach, vi } from 'vitest'; Object.defineProperty(globalThis, '__DEV__', { configurable: true, value: false, }); const createElement = (tag: string) => ({ children, onChangeText, onPress, value, ...props }: { children?: React.ReactNode; onChangeText?: (value: string) => void; onPress?: () => void; value?: string; [key: string]: unknown; }) => { const safeProps: Record = { ...props, className: typeof props.className === 'string' ? props.className : undefined, disabled: props.disabled as boolean | undefined, onChange: onChangeText ? (event: React.ChangeEvent) => onChangeText(event.currentTarget.value) : undefined, onClick: onPress, value, }; delete safeProps.keyboardType; delete safeProps.keyboardShouldPersistTaps; delete safeProps.placeholderTextColor; delete safeProps.secureTextEntry; delete safeProps.showsHorizontalScrollIndicator; delete safeProps.textAlignVertical; return React.createElement(tag, safeProps, children); }; const TextInput = ({ multiline, ...props }: { multiline?: boolean; [key: string]: unknown; }) => createElement(multiline ? 'textarea' : 'input')(props); const mocks = vi.hoisted(() => ({ alert: vi.fn(), useAction: vi.fn(() => vi.fn()), useMutation: vi.fn(() => vi.fn()), useQuery: vi.fn(() => undefined), })); vi.mock('react-native', () => ({ Alert: { alert: mocks.alert }, Linking: { openURL: vi.fn() }, Modal: ({ children, visible, }: { children?: React.ReactNode; visible?: boolean; }) => (visible ? React.createElement('div', {}, children) : null), Pressable: createElement('button'), Platform: { OS: 'web', select: (values: Record) => values.web ?? values.default, }, RefreshControl: createElement('div'), ScrollView: createElement('div'), Switch: createElement('input'), Text: createElement('span'), TextInput, TurboModuleRegistry: { get: vi.fn(() => undefined), getEnforcing: vi.fn(() => ({})), }, View: createElement('div'), })); vi.mock('expo-clipboard', () => ({ setStringAsync: vi.fn(), })); vi.mock('expo-haptics', () => ({ impactAsync: vi.fn(), notificationAsync: vi.fn(), selectionAsync: vi.fn(), })); vi.mock('react-native-safe-area-context', () => ({ SafeAreaView: createElement('div'), })); vi.mock('expo-router', () => ({ Link: ({ children }: { children?: React.ReactNode }) => children, Stack: { Screen: () => null, }, useLocalSearchParams: () => ({}), useRouter: () => ({ push: vi.fn(), replace: vi.fn(), }), })); vi.mock('convex/react', () => ({ useAction: mocks.useAction, useMutation: mocks.useMutation, useQuery: mocks.useQuery, })); vi.mock('@convex-dev/auth/react', () => ({ useAuthActions: () => ({ signIn: vi.fn(), signOut: vi.fn(), }), })); export const mockedAlert = mocks.alert; export const mockedUseAction = mocks.useAction; export const mockedUseMutation = mocks.useMutation; export const mockedUseQuery = mocks.useQuery; afterEach(() => { cleanup(); });