- Create __mocks__/ with react-native, expo-router, expo-constants, expo-status-bar, react-native-mmkv, @testing-library/react-native - Update vitest.config.ts with resolve aliases for all native modules - Add AuthScreen smoke test (3 tests) - Add HomeScreen smoke test (2 tests) - Add @types/react-test-renderer dev dependency - Total: 32 passing tests (27 store + 5 component)
103 lines
2.8 KiB
TypeScript
103 lines
2.8 KiB
TypeScript
/**
|
|
* Minimal react-native mock for Vitest.
|
|
* Provides lightweight stubs for components and APIs used in the mobile app.
|
|
*/
|
|
import React from 'react';
|
|
|
|
function createMockComponent(name: string) {
|
|
const Component = (props: Record<string, unknown>) =>
|
|
React.createElement(name, props, props.children as React.ReactNode);
|
|
Component.displayName = name;
|
|
return Component;
|
|
}
|
|
|
|
export const View = createMockComponent('View');
|
|
export const Text = createMockComponent('Text');
|
|
export const TextInput = createMockComponent('TextInput');
|
|
export const Pressable = createMockComponent('Pressable');
|
|
export const ScrollView = createMockComponent('ScrollView');
|
|
export const Modal = createMockComponent('Modal');
|
|
export const Image = createMockComponent('Image');
|
|
export const FlatList = createMockComponent('FlatList');
|
|
export const TouchableOpacity = createMockComponent('TouchableOpacity');
|
|
export const SafeAreaView = createMockComponent('SafeAreaView');
|
|
export const ActivityIndicator = createMockComponent('ActivityIndicator');
|
|
export const Alert = {
|
|
alert: () => {},
|
|
};
|
|
|
|
export const StyleSheet = {
|
|
create: <T extends Record<string, unknown>>(styles: T): T => styles,
|
|
flatten: (style: unknown) => style,
|
|
hairlineWidth: 1,
|
|
};
|
|
|
|
export const Platform = {
|
|
OS: 'ios' as const,
|
|
Version: '17.0',
|
|
select: (specifics: Record<string, unknown>) => specifics.ios ?? specifics.default,
|
|
};
|
|
|
|
export const AppState = {
|
|
currentState: 'active',
|
|
addEventListener: (_type: string, _handler: unknown) => ({
|
|
remove: () => {},
|
|
}),
|
|
};
|
|
|
|
export const Dimensions = {
|
|
get: () => ({ width: 375, height: 812, scale: 2, fontScale: 1 }),
|
|
addEventListener: () => ({ remove: () => {} }),
|
|
};
|
|
|
|
export const Keyboard = {
|
|
dismiss: () => {},
|
|
addListener: () => ({ remove: () => {} }),
|
|
};
|
|
|
|
export const Linking = {
|
|
openURL: async () => {},
|
|
canOpenURL: async () => true,
|
|
getInitialURL: async () => null,
|
|
addEventListener: () => ({ remove: () => {} }),
|
|
};
|
|
|
|
export const Animated = {
|
|
View: createMockComponent('Animated.View'),
|
|
Text: createMockComponent('Animated.Text'),
|
|
Image: createMockComponent('Animated.Image'),
|
|
Value: class {
|
|
_value: number;
|
|
constructor(val: number) { this._value = val; }
|
|
setValue(val: number) { this._value = val; }
|
|
interpolate() { return this; }
|
|
},
|
|
timing: () => ({ start: (cb?: () => void) => cb?.() }),
|
|
spring: () => ({ start: (cb?: () => void) => cb?.() }),
|
|
parallel: () => ({ start: (cb?: () => void) => cb?.() }),
|
|
sequence: () => ({ start: (cb?: () => void) => cb?.() }),
|
|
event: () => () => {},
|
|
};
|
|
|
|
export default {
|
|
View,
|
|
Text,
|
|
TextInput,
|
|
Pressable,
|
|
ScrollView,
|
|
Modal,
|
|
Image,
|
|
FlatList,
|
|
TouchableOpacity,
|
|
SafeAreaView,
|
|
ActivityIndicator,
|
|
Alert,
|
|
StyleSheet,
|
|
Platform,
|
|
AppState,
|
|
Dimensions,
|
|
Keyboard,
|
|
Linking,
|
|
Animated,
|
|
};
|