@@ -9,6 +9,11 @@ import { useCallDetailStore } from '@/stores/calls/detail-store';
99jest . mock ( 'react-i18next' ) ;
1010jest . mock ( '@/lib/auth' ) ;
1111jest . mock ( '@/stores/calls/detail-store' ) ;
12+ jest . mock ( '@/hooks/use-analytics' , ( ) => ( {
13+ useAnalytics : ( ) => ( {
14+ trackEvent : jest . fn ( ) ,
15+ } ) ,
16+ } ) ) ;
1217
1318// Mock navigation
1419jest . mock ( '@react-navigation/native' , ( ) => ( {
@@ -25,10 +30,13 @@ jest.mock('nativewind', () => ({
2530} ) ) ;
2631
2732// Mock lucide-react-native icons
28- jest . mock ( 'lucide-react-native' , ( ) => ( {
29- SearchIcon : 'SearchIcon' ,
30- X : 'X' ,
31- } ) ) ;
33+ jest . mock ( 'lucide-react-native' , ( ) => {
34+ const { View } = require ( 'react-native' ) ;
35+ return {
36+ SearchIcon : ( props : any ) => < View testID = "search-icon" { ...props } /> ,
37+ X : ( props : any ) => < View testID = "x-icon" { ...props } /> ,
38+ } ;
39+ } ) ;
3240
3341// Mock Loading component
3442jest . mock ( '../../common/loading' , ( ) => ( {
@@ -58,6 +66,10 @@ jest.mock('react-native-keyboard-controller', () => ({
5866 const { View } = require ( 'react-native' ) ;
5967 return < View testID = "keyboard-aware-scroll-view" > { children } </ View > ;
6068 } ,
69+ KeyboardStickyView : ( { children } : any ) => {
70+ const { View } = require ( 'react-native' ) ;
71+ return < View testID = "keyboard-sticky-view" > { children } </ View > ;
72+ } ,
6173} ) ) ;
6274
6375// Mock react-native-gesture-handler
@@ -94,10 +106,86 @@ jest.mock('@gorhom/bottom-sheet', () => {
94106 } ;
95107} ) ;
96108
97- // Mock lucide-react-native icons
98- jest . mock ( 'lucide-react-native' , ( ) => ( {
99- SearchIcon : 'SearchIcon' ,
100- X : 'X' ,
109+ // Mock UI components
110+ jest . mock ( '../../ui/box' , ( ) => ( {
111+ Box : ( { children, ...props } : any ) => {
112+ const { View } = require ( 'react-native' ) ;
113+ return < View { ...props } > { children } </ View > ;
114+ } ,
115+ } ) ) ;
116+
117+ jest . mock ( '../../ui/button' , ( ) => ( {
118+ Button : ( { children, onPress, disabled, isDisabled, ...props } : any ) => {
119+ const { TouchableOpacity } = require ( 'react-native' ) ;
120+ const isButtonDisabled = disabled || isDisabled ;
121+ return (
122+ < TouchableOpacity
123+ onPress = { isButtonDisabled ? undefined : onPress }
124+ disabled = { isButtonDisabled }
125+ { ...props }
126+ >
127+ { children }
128+ </ TouchableOpacity >
129+ ) ;
130+ } ,
131+ ButtonText : ( { children, ...props } : any ) => {
132+ const { Text } = require ( 'react-native' ) ;
133+ return < Text { ...props } > { children } </ Text > ;
134+ } ,
135+ } ) ) ;
136+
137+ jest . mock ( '../../ui/heading' , ( ) => ( {
138+ Heading : ( { children, ...props } : any ) => {
139+ const { Text } = require ( 'react-native' ) ;
140+ return < Text { ...props } > { children } </ Text > ;
141+ } ,
142+ } ) ) ;
143+
144+ jest . mock ( '../../ui/hstack' , ( ) => ( {
145+ HStack : ( { children, ...props } : any ) => {
146+ const { View } = require ( 'react-native' ) ;
147+ return < View { ...props } > { children } </ View > ;
148+ } ,
149+ } ) ) ;
150+
151+ jest . mock ( '../../ui/vstack' , ( ) => ( {
152+ VStack : ( { children, ...props } : any ) => {
153+ const { View } = require ( 'react-native' ) ;
154+ return < View { ...props } > { children } </ View > ;
155+ } ,
156+ } ) ) ;
157+
158+ jest . mock ( '../../ui/text' , ( ) => ( {
159+ Text : ( { children, ...props } : any ) => {
160+ const { Text : RNText } = require ( 'react-native' ) ;
161+ return < RNText { ...props } > { children } </ RNText > ;
162+ } ,
163+ } ) ) ;
164+
165+ jest . mock ( '../../ui/input' , ( ) => ( {
166+ Input : ( { children, ...props } : any ) => {
167+ const { View } = require ( 'react-native' ) ;
168+ return < View { ...props } > { children } </ View > ;
169+ } ,
170+ InputField : ( { placeholder, value, onChangeText, ...props } : any ) => {
171+ const { TextInput } = require ( 'react-native' ) ;
172+ return < TextInput placeholder = { placeholder } value = { value } onChangeText = { onChangeText } { ...props } /> ;
173+ } ,
174+ InputSlot : ( { children, ...props } : any ) => {
175+ const { View } = require ( 'react-native' ) ;
176+ return < View { ...props } > { children } </ View > ;
177+ } ,
178+ } ) ) ;
179+
180+ jest . mock ( '../../ui/textarea' , ( ) => ( {
181+ Textarea : ( { children, ...props } : any ) => {
182+ const { View } = require ( 'react-native' ) ;
183+ return < View { ...props } > { children } </ View > ;
184+ } ,
185+ TextareaInput : ( { placeholder, value, onChangeText, ...props } : any ) => {
186+ const { TextInput } = require ( 'react-native' ) ;
187+ return < TextInput placeholder = { placeholder } value = { value } onChangeText = { onChangeText } { ...props } /> ;
188+ } ,
101189} ) ) ;
102190
103191const mockUseTranslation = useTranslation as jest . MockedFunction < typeof useTranslation > ;
@@ -146,6 +234,9 @@ describe('CallNotesModal', () => {
146234 'callNotes.searchPlaceholder' : 'Search notes...' ,
147235 'callNotes.addNotePlaceholder' : 'Add a note...' ,
148236 'callNotes.addNote' : 'Add Note' ,
237+ 'callNotes.noNotesFound' : 'No notes found' ,
238+ 'callNotes.addNoteLabel' : 'Add a note' ,
239+ 'common.cancel' : 'Cancel' ,
149240 } ;
150241 return translations [ key ] || key ;
151242 } ,
@@ -185,8 +276,8 @@ describe('CallNotesModal', () => {
185276 it ( 'renders correctly when closed' , ( ) => {
186277 const { queryByText } = render ( < CallNotesModal { ...mockProps } isOpen = { false } /> ) ;
187278
188- // Bottom sheet should still render but with index -1 ( closed)
189- expect ( queryByText ( 'Call Notes' ) ) . toBeTruthy ( ) ;
279+ // Component returns null when closed
280+ expect ( queryByText ( 'Call Notes' ) ) . toBeFalsy ( ) ;
190281 } ) ;
191282
192283 it ( 'handles search input correctly' , ( ) => {
0 commit comments