337 lines
8.4 KiB
JavaScript
337 lines
8.4 KiB
JavaScript
// Mock react-native-css-interop FIRST to avoid appearance listener issues
|
|
jest.mock('react-native-css-interop', () => ({
|
|
__esModule: true,
|
|
}))
|
|
|
|
// Import extend-expect for jest matchers
|
|
import '@testing-library/react-native/extend-expect'
|
|
|
|
// Mock global Appearance for react-native-css-interop
|
|
global.Appearance = {
|
|
getColorScheme: jest.fn(() => 'light'),
|
|
addChangeListener: jest.fn(() => ({ remove: jest.fn() })),
|
|
removeChangeListener: jest.fn(),
|
|
}
|
|
|
|
// Initialize globals for react-native-reanimated
|
|
global._tagToJSPropNamesMapping = {}
|
|
global._WORKLET = false
|
|
global._ReanimatedModule = {}
|
|
|
|
// Mock react-native modules
|
|
// Note: NativeAnimatedHelper may not be needed in newer React Native versions
|
|
// jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper')
|
|
|
|
// Mock expo modules
|
|
jest.mock('expo-constants', () => ({
|
|
default: {},
|
|
Constants: {},
|
|
}))
|
|
|
|
jest.mock('expo-modules-core', () => ({
|
|
EventEmitter: class MockEventEmitter {},
|
|
requireNativeViewManager: jest.fn(() => ({})),
|
|
requireOptionalNativeModule: jest.fn(() => ({})),
|
|
requireNativeModule: jest.fn(() => ({})),
|
|
}))
|
|
|
|
// Mock expo-asset
|
|
jest.mock('expo-asset', () => ({
|
|
AssetModule: {},
|
|
Asset: class MockAsset {
|
|
static fromModule = jest.fn(() => ({ localUri: '' }))
|
|
static fromURI = jest.fn(() => ({ localUri: '' }))
|
|
},
|
|
}))
|
|
|
|
// Mock expo-image
|
|
jest.mock('expo-image', () => ({
|
|
Image: 'Image',
|
|
}))
|
|
|
|
// Mock expo-linear-gradient
|
|
jest.mock('expo-linear-gradient', () => ({
|
|
LinearGradient: 'LinearGradient',
|
|
}))
|
|
|
|
// Mock expo-blur
|
|
jest.mock('expo-blur', () => ({
|
|
BlurView: 'BlurView',
|
|
}))
|
|
|
|
// Mock @expo/vector-icons
|
|
jest.mock('@expo/vector-icons', () => {
|
|
const mockIonicons = function mockIonicons(props) {
|
|
return null
|
|
}
|
|
return {
|
|
Ionicons: mockIonicons,
|
|
MaterialIcons: mockIonicons,
|
|
FontAwesome: mockIonicons,
|
|
Feather: mockIonicons,
|
|
}
|
|
})
|
|
|
|
// Mock react-native-safe-area-context
|
|
jest.mock('react-native-safe-area-context', () => ({
|
|
useSafeAreaInsets: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
|
|
SafeAreaProvider: ({ children }: any) => children,
|
|
SafeAreaView: 'SafeAreaView',
|
|
}))
|
|
|
|
// Mock react-native-gesture-handler
|
|
jest.mock('react-native-gesture-handler', () => {
|
|
const mockReact = require('react')
|
|
const mockRN = require('react-native')
|
|
|
|
// Mock Swipeable component that renders children and right actions
|
|
const MockSwipeable = mockReact.forwardRef(({ children, renderRightActions, testID, enabled, ...props }, ref) => {
|
|
return mockReact.createElement(mockRN.View, { testID, ref, ...props }, [
|
|
children,
|
|
renderRightActions && renderRightActions(),
|
|
])
|
|
})
|
|
MockSwipeable.displayName = 'Swipeable'
|
|
|
|
return {
|
|
GestureDetector: mockRN.View,
|
|
Gesture: {
|
|
Tap: () => ({}),
|
|
Pan: () => ({}),
|
|
LongPress: () => ({}),
|
|
Pinch: () => ({}),
|
|
Rotation: () => ({}),
|
|
Fling: () => ({}),
|
|
NativeViewGesture: () => ({}),
|
|
ForceTouch: () => ({}),
|
|
ManualGesture: () => ({}),
|
|
},
|
|
GestureHandlerRootView: mockRN.View,
|
|
RawButton: mockRN.View,
|
|
BaseButton: mockRN.View,
|
|
RectButton: mockRN.View,
|
|
BorderlessButton: mockRN.View,
|
|
Swipeable: MockSwipeable,
|
|
State: {},
|
|
Directions: {},
|
|
}
|
|
})
|
|
|
|
jest.mock('expo-linking', () => ({
|
|
createURL: (url) => url,
|
|
parse: (url) => ({ path: url }),
|
|
}))
|
|
|
|
jest.mock('expo-secure-store', () => ({
|
|
getItemAsync: jest.fn(),
|
|
setItemAsync: jest.fn(),
|
|
deleteItemAsync: jest.fn(),
|
|
}))
|
|
|
|
jest.mock('expo-font', () => ({
|
|
useFonts: () => [true, null],
|
|
}))
|
|
|
|
jest.mock('expo-splash-screen', () => ({
|
|
preventAutoHideAsync: jest.fn(),
|
|
hideAsync: jest.fn(),
|
|
}))
|
|
|
|
// Mock react-native-reanimated
|
|
jest.mock('react-native-reanimated', () => ({
|
|
__esModule: true,
|
|
default: {
|
|
createAnimatedComponent: (Component) => Component,
|
|
call: () => {},
|
|
},
|
|
useSharedValue: (v) => ({ value: v }),
|
|
useAnimatedStyle: (fn) => fn(),
|
|
withTiming: (v) => v,
|
|
withSpring: (v) => v,
|
|
withDecay: (v) => v,
|
|
withRepeat: (v) => v,
|
|
withSequence: (...args) => args[0],
|
|
Easing: {
|
|
linear: (v) => v,
|
|
ease: (v) => v,
|
|
quad: (v) => v,
|
|
cubic: (v) => v,
|
|
},
|
|
runOnJS: (fn) => fn,
|
|
runOnUI: (fn) => fn,
|
|
}))
|
|
|
|
// Mock react-native-screens
|
|
jest.mock('react-native-screens', () => ({
|
|
FullWindowOverlay: 'FullWindowOverlay',
|
|
enableScreens: jest.fn(),
|
|
}))
|
|
|
|
// Mock nativewind
|
|
jest.mock('nativewind', () => ({
|
|
styled: jest.fn(),
|
|
}))
|
|
|
|
// Mock @react-navigation/native
|
|
jest.mock('@react-navigation/native', () => ({
|
|
useNavigation: () => ({
|
|
navigate: jest.fn(),
|
|
goBack: jest.fn(),
|
|
reset: jest.fn(),
|
|
}),
|
|
useRoute: () => ({
|
|
params: {},
|
|
}),
|
|
NavigationContainer: ({ children }) => children,
|
|
}))
|
|
|
|
// Mock expo-router
|
|
jest.mock('expo-router', () => ({
|
|
useRouter: () => ({
|
|
push: jest.fn(),
|
|
replace: jest.fn(),
|
|
back: jest.fn(),
|
|
}),
|
|
useLocalSearchParams: () => ({}),
|
|
useSegments: () => [],
|
|
usePathname: () => '/',
|
|
}))
|
|
|
|
// Global mock for console methods to reduce noise in tests
|
|
global.console = {
|
|
...console,
|
|
error: jest.fn(),
|
|
warn: jest.fn(),
|
|
log: jest.fn(),
|
|
}
|
|
|
|
// Mock @repo/core and @repo/sdk
|
|
jest.mock('@repo/core', () => ({
|
|
root: {
|
|
get: jest.fn(),
|
|
},
|
|
}))
|
|
|
|
jest.mock('@repo/sdk', () => ({
|
|
CategoryController: class MockCategoryController {},
|
|
}))
|
|
|
|
// Note: The second react-native mock has been removed to avoid circular dependency issues
|
|
// The first mock at the top of this file handles all necessary react-native mocking
|
|
|
|
// Mock DevMenu module
|
|
jest.mock('react-native/src/private/devsupport/devmenu/DevMenu', () => ({
|
|
default: {},
|
|
}))
|
|
|
|
// Mock SettingsManager module
|
|
jest.mock('react-native/src/private/specs_DEPRECATED/modules/NativeSettingsManager', () => ({
|
|
default: {
|
|
getConstants: () => ({}),
|
|
},
|
|
}))
|
|
|
|
// Mock lib/auth to avoid TypeScript compilation errors
|
|
jest.mock('@/lib/auth', () => ({
|
|
OWNER_ID: 'test-owner-id',
|
|
}))
|
|
|
|
// Mock components
|
|
jest.mock('@/components/icon', () => ({
|
|
DownArrowIcon: () => null,
|
|
PointsIcon: () => null,
|
|
SearchIcon: () => null,
|
|
LeftArrowIcon: () => null,
|
|
UploadIcon: () => null,
|
|
WhitePointsIcon: () => null,
|
|
RightArrowIcon: () => null,
|
|
}))
|
|
|
|
// Mock UI components that have complex dependencies
|
|
jest.mock('@/components/ui/Text', () => {
|
|
const mockReact = require('react')
|
|
const mockRN = require('react-native')
|
|
const Text = mockReact.forwardRef(({ children, ...props }, ref) => (
|
|
mockReact.createElement(mockRN.Text, { ref, ...props }, children)
|
|
))
|
|
Text.displayName = 'Text'
|
|
return {
|
|
__esModule: true,
|
|
default: Text,
|
|
}
|
|
})
|
|
|
|
jest.mock('@/components/ui/Block', () => {
|
|
const mockReact = require('react')
|
|
const mockRN = require('react-native')
|
|
const Block = mockReact.forwardRef(({ children, onClick, ...props }, ref) => {
|
|
if (onClick) {
|
|
return mockReact.createElement(mockRN.Pressable, { ref, onPress: onClick, ...props }, children)
|
|
}
|
|
return mockReact.createElement(mockRN.View, { ref, ...props }, children)
|
|
})
|
|
Block.displayName = 'Block'
|
|
return {
|
|
__esModule: true,
|
|
default: Block,
|
|
}
|
|
})
|
|
|
|
jest.mock('@/components/ui/button', () => {
|
|
const mockReact = require('react')
|
|
const mockRN = require('react-native')
|
|
return {
|
|
Button: mockReact.forwardRef(({ children, onPress, disabled, ...props }, ref) => (
|
|
mockReact.createElement(mockRN.Pressable, { ref, onPress, disabled, ...props }, children)
|
|
)),
|
|
}
|
|
})
|
|
|
|
jest.mock('@/components/skeleton/HomeSkeleton', () => ({
|
|
HomeSkeleton: () => null,
|
|
}))
|
|
|
|
// Mock drawer components
|
|
jest.mock('@/components/drawer/UploadReferenceImageDrawer', () => ({
|
|
default: () => null,
|
|
}))
|
|
|
|
// Mock SearchResultsGrid
|
|
jest.mock('@/components/SearchResultsGrid', () => ({
|
|
default: () => null,
|
|
}))
|
|
|
|
// Mock FlashList to actually render items
|
|
jest.mock('@shopify/flash-list', () => {
|
|
const { View } = require('react-native')
|
|
return {
|
|
FlashList: ({ data, renderItem }) => {
|
|
return data.map((item, index) => renderItem({ item, index }))
|
|
},
|
|
}
|
|
})
|
|
|
|
// Mock @gorhom/bottom-sheet
|
|
jest.mock('@gorhom/bottom-sheet', () => {
|
|
const { View } = require('react-native')
|
|
return {
|
|
BottomSheet: View,
|
|
BottomSheetView: View,
|
|
BottomSheetModal: View,
|
|
BottomSheetModalProvider: ({ children }) => children,
|
|
BottomSheetScrollView: ({ children }) => children,
|
|
useBottomSheet: () => ({
|
|
snapTo: jest.fn(),
|
|
expand: jest.fn(),
|
|
collapse: jest.fn(),
|
|
close: jest.fn(),
|
|
}),
|
|
useBottomSheetModal: () => ({
|
|
present: jest.fn(),
|
|
dismiss: jest.fn(),
|
|
}),
|
|
useBottomSheetSpringConfigs: jest.fn(() => ({})),
|
|
useBottomSheetTimingConfigs: jest.fn(() => ({})),
|
|
}
|
|
})
|