@@ -17,23 +17,56 @@ jest.mock('../src/NativeAppsFlyerRPC', () => ({
1717 } ,
1818} ) ) ;
1919
20- // Mock NativeEventEmitter
21- jest . mock ( 'react-native' , ( ) => ( {
22- Platform : {
23- OS : 'ios' ,
24- } ,
25- NativeEventEmitter : jest . fn ( ) . mockImplementation ( ( ) => ( {
26- addListener : jest . fn ( ( eventName , callback ) => ( {
27- remove : jest . fn ( ) ,
20+ // Mock react-native with TurboModuleRegistry and NativeModules
21+ jest . mock ( 'react-native' , ( ) => {
22+ const mockModule = {
23+ executeJson : jest . fn ( ) ,
24+ addListener : jest . fn ( ) ,
25+ removeListeners : jest . fn ( ) ,
26+ } ;
27+
28+ return {
29+ Platform : {
30+ OS : 'ios' ,
31+ } ,
32+ NativeEventEmitter : jest . fn ( ) . mockImplementation ( ( ) => ( {
33+ addListener : jest . fn ( ( eventName , callback ) => ( {
34+ remove : jest . fn ( ) ,
35+ } ) ) ,
2836 } ) ) ,
29- } ) ) ,
30- } ) ) ;
37+ TurboModuleRegistry : {
38+ get : jest . fn ( ( name ) => {
39+ if ( name === 'RNAppsFlyerRPC' ) {
40+ return mockModule ;
41+ }
42+ return null ;
43+ } ) ,
44+ } ,
45+ NativeModules : {
46+ RNAppsFlyerRPC : mockModule ,
47+ } ,
48+ } ;
49+ } ) ;
3150
3251import NativeAppsFlyerRPC from '../src/NativeAppsFlyerRPC' ;
52+ import { NativeModules , TurboModuleRegistry } from 'react-native' ;
3353
3454describe ( 'AppsFlyerRPC' , ( ) => {
55+ // Get the mock native module for setting up expectations
56+ const getMockNativeModule = ( ) => {
57+ return TurboModuleRegistry . get ( 'RNAppsFlyerRPC' ) || NativeModules . RNAppsFlyerRPC ;
58+ } ;
59+
3560 beforeEach ( ( ) => {
3661 jest . clearAllMocks ( ) ;
62+ // Reset the mock module's executeJson to return a default success response
63+ const mockModule = getMockNativeModule ( ) ;
64+ if ( mockModule ) {
65+ mockModule . executeJson . mockResolvedValue ( JSON . stringify ( {
66+ id : 'test-123' ,
67+ result : { success : true } ,
68+ } ) ) ;
69+ }
3770 } ) ;
3871
3972 describe ( 'Singleton Pattern' , ( ) => {
@@ -50,22 +83,24 @@ describe('AppsFlyerRPC', () => {
5083
5184 describe ( 'RPC Request/Response Handling' , ( ) => {
5285 it ( 'should execute RPC request successfully' , async ( ) => {
86+ const mockModule = getMockNativeModule ( ) ;
5387 const mockResponse = JSON . stringify ( {
5488 id : 'test-123' ,
5589 result : { success : true , message : 'OK' } ,
5690 } ) ;
57- NativeAppsFlyerRPC . executeJson . mockResolvedValue ( mockResponse ) ;
91+ mockModule . executeJson . mockResolvedValue ( mockResponse ) ;
5892
5993 const result = await AppsFlyerRPC . instance . initialize ( {
6094 devKey : 'test-key' ,
6195 appId : 'id123' ,
6296 } ) ;
6397
64- expect ( NativeAppsFlyerRPC . executeJson ) . toHaveBeenCalled ( ) ;
98+ expect ( mockModule . executeJson ) . toHaveBeenCalled ( ) ;
6599 expect ( result ) . toBeUndefined ( ) ; // initialize returns void
66100 } ) ;
67101
68102 it ( 'should handle RPC error response' , async ( ) => {
103+ const mockModule = getMockNativeModule ( ) ;
69104 const mockErrorResponse = JSON . stringify ( {
70105 id : 'test-123' ,
71106 error : {
@@ -74,7 +109,7 @@ describe('AppsFlyerRPC', () => {
74109 details : null ,
75110 } ,
76111 } ) ;
77- NativeAppsFlyerRPC . executeJson . mockResolvedValue ( mockErrorResponse ) ;
112+ mockModule . executeJson . mockResolvedValue ( mockErrorResponse ) ;
78113
79114 await expect (
80115 AppsFlyerRPC . instance . initialize ( {
@@ -85,15 +120,17 @@ describe('AppsFlyerRPC', () => {
85120 } ) ;
86121
87122 it ( 'should throw error for null response' , async ( ) => {
88- NativeAppsFlyerRPC . executeJson . mockResolvedValue ( null ) ;
123+ const mockModule = getMockNativeModule ( ) ;
124+ mockModule . executeJson . mockResolvedValue ( null ) ;
89125
90126 await expect (
91127 AppsFlyerRPC . instance . setDebug ( true )
92- ) . rejects . toThrow ( 'Null response from native' ) ;
128+ ) . rejects . toThrow ( 'Empty response from native' ) ;
93129 } ) ;
94130
95131 it ( 'should throw error for invalid JSON response' , async ( ) => {
96- NativeAppsFlyerRPC . executeJson . mockResolvedValue ( 'invalid json' ) ;
132+ const mockModule = getMockNativeModule ( ) ;
133+ mockModule . executeJson . mockResolvedValue ( 'invalid json' ) ;
97134
98135 await expect (
99136 AppsFlyerRPC . instance . setDebug ( true )
@@ -121,30 +158,32 @@ describe('AppsFlyerRPC', () => {
121158
122159 describe ( 'API Methods' , ( ) => {
123160 beforeEach ( ( ) => {
161+ const mockModule = getMockNativeModule ( ) ;
124162 const mockSuccessResponse = JSON . stringify ( {
125163 id : 'test-123' ,
126164 result : { success : true } ,
127165 } ) ;
128- NativeAppsFlyerRPC . executeJson . mockResolvedValue ( mockSuccessResponse ) ;
166+ mockModule . executeJson . mockResolvedValue ( mockSuccessResponse ) ;
129167 } ) ;
130168
131169 describe ( 'initialize' , ( ) => {
132170 it ( 'should call setPluginInfo and init' , async ( ) => {
171+ const mockModule = getMockNativeModule ( ) ;
133172 await AppsFlyerRPC . instance . initialize ( {
134173 devKey : 'test-key' ,
135174 appId : 'id123' ,
136175 } ) ;
137176
138- expect ( NativeAppsFlyerRPC . executeJson ) . toHaveBeenCalledTimes ( 2 ) ;
177+ expect ( mockModule . executeJson ) . toHaveBeenCalledTimes ( 2 ) ;
139178
140179 // First call: setPluginInfo
141- const firstCall = NativeAppsFlyerRPC . executeJson . mock . calls [ 0 ] [ 0 ] ;
180+ const firstCall = mockModule . executeJson . mock . calls [ 0 ] [ 0 ] ;
142181 const firstRequest = JSON . parse ( firstCall ) ;
143182 expect ( firstRequest . method ) . toBe ( 'setPluginInfo' ) ;
144183 expect ( firstRequest . params . plugin ) . toBe ( 'react_native' ) ;
145184
146185 // Second call: init
147- const secondCall = NativeAppsFlyerRPC . executeJson . mock . calls [ 1 ] [ 0 ] ;
186+ const secondCall = mockModule . executeJson . mock . calls [ 1 ] [ 0 ] ;
148187 const secondRequest = JSON . parse ( secondCall ) ;
149188 expect ( secondRequest . method ) . toBe ( 'init' ) ;
150189 expect ( secondRequest . params . devKey ) . toBe ( 'test-key' ) ;
@@ -154,9 +193,10 @@ describe('AppsFlyerRPC', () => {
154193
155194 describe ( 'setDebug' , ( ) => {
156195 it ( 'should call isDebug RPC method' , async ( ) => {
196+ const mockModule = getMockNativeModule ( ) ;
157197 await AppsFlyerRPC . instance . setDebug ( true ) ;
158198
159- const call = NativeAppsFlyerRPC . executeJson . mock . calls [ 0 ] [ 0 ] ;
199+ const call = mockModule . executeJson . mock . calls [ 0 ] [ 0 ] ;
160200 const request = JSON . parse ( call ) ;
161201 expect ( request . method ) . toBe ( 'isDebug' ) ;
162202 expect ( request . params . isDebug ) . toBe ( true ) ;
@@ -165,52 +205,57 @@ describe('AppsFlyerRPC', () => {
165205
166206 describe ( 'waitForATT' , ( ) => {
167207 it ( 'should call waitForATT with default timeout' , async ( ) => {
208+ const mockModule = getMockNativeModule ( ) ;
168209 await AppsFlyerRPC . instance . waitForATT ( ) ;
169210
170- const call = NativeAppsFlyerRPC . executeJson . mock . calls [ 0 ] [ 0 ] ;
211+ const call = mockModule . executeJson . mock . calls [ 0 ] [ 0 ] ;
171212 const request = JSON . parse ( call ) ;
172213 expect ( request . method ) . toBe ( 'waitForATT' ) ;
173214 expect ( request . params . timeout ) . toBe ( 60 ) ;
174215 } ) ;
175216
176217 it ( 'should call waitForATT with custom timeout' , async ( ) => {
218+ const mockModule = getMockNativeModule ( ) ;
177219 await AppsFlyerRPC . instance . waitForATT ( { timeout : 30 } ) ;
178220
179- const call = NativeAppsFlyerRPC . executeJson . mock . calls [ 0 ] [ 0 ] ;
221+ const call = mockModule . executeJson . mock . calls [ 0 ] [ 0 ] ;
180222 const request = JSON . parse ( call ) ;
181223 expect ( request . params . timeout ) . toBe ( 30 ) ;
182224 } ) ;
183225 } ) ;
184226
185227 describe ( 'start' , ( ) => {
186228 it ( 'should call start without awaitResponse' , async ( ) => {
229+ const mockModule = getMockNativeModule ( ) ;
187230 await AppsFlyerRPC . instance . start ( ) ;
188231
189- const call = NativeAppsFlyerRPC . executeJson . mock . calls [ 0 ] [ 0 ] ;
232+ const call = mockModule . executeJson . mock . calls [ 0 ] [ 0 ] ;
190233 const request = JSON . parse ( call ) ;
191234 expect ( request . method ) . toBe ( 'start' ) ;
192235 expect ( request . params . awaitResponse ) . toBeUndefined ( ) ;
193236 } ) ;
194237
195238 it ( 'should call start with awaitResponse' , async ( ) => {
239+ const mockModule = getMockNativeModule ( ) ;
196240 const mockResponse = JSON . stringify ( {
197241 id : 'test-123' ,
198242 result : { data : { attribution : 'data' } } ,
199243 } ) ;
200- NativeAppsFlyerRPC . executeJson . mockResolvedValue ( mockResponse ) ;
244+ mockModule . executeJson . mockResolvedValue ( mockResponse ) ;
201245
202246 const result = await AppsFlyerRPC . instance . start ( { awaitResponse : true } ) ;
203247
204- const call = NativeAppsFlyerRPC . executeJson . mock . calls [ 0 ] [ 0 ] ;
248+ const call = mockModule . executeJson . mock . calls [ 0 ] [ 0 ] ;
205249 const request = JSON . parse ( call ) ;
206250 expect ( request . params . awaitResponse ) . toBe ( true ) ;
207251 expect ( result ) . toEqual ( { attribution : 'data' } ) ;
208252 } ) ;
209253
210254 it ( 'startWithCallback should call start with awaitResponse' , async ( ) => {
255+ const mockModule = getMockNativeModule ( ) ;
211256 await AppsFlyerRPC . instance . startWithCallback ( ) ;
212257
213- const call = NativeAppsFlyerRPC . executeJson . mock . calls [ 0 ] [ 0 ] ;
258+ const call = mockModule . executeJson . mock . calls [ 0 ] [ 0 ] ;
214259 const request = JSON . parse ( call ) ;
215260 expect ( request . method ) . toBe ( 'start' ) ;
216261 expect ( request . params . awaitResponse ) . toBe ( true ) ;
@@ -219,31 +264,34 @@ describe('AppsFlyerRPC', () => {
219264
220265 describe ( 'logEvent' , ( ) => {
221266 it ( 'should log event without values' , async ( ) => {
267+ const mockModule = getMockNativeModule ( ) ;
222268 await AppsFlyerRPC . instance . logEvent ( 'test_event' ) ;
223269
224- const call = NativeAppsFlyerRPC . executeJson . mock . calls [ 0 ] [ 0 ] ;
270+ const call = mockModule . executeJson . mock . calls [ 0 ] [ 0 ] ;
225271 const request = JSON . parse ( call ) ;
226272 expect ( request . method ) . toBe ( 'logEvent' ) ;
227273 expect ( request . params . eventName ) . toBe ( 'test_event' ) ;
228274 expect ( request . params . eventValues ) . toBeUndefined ( ) ;
229275 } ) ;
230276
231277 it ( 'should log event with values' , async ( ) => {
278+ const mockModule = getMockNativeModule ( ) ;
232279 await AppsFlyerRPC . instance . logEvent ( 'test_event' , {
233280 eventValues : { key : 'value' } ,
234281 } ) ;
235282
236- const call = NativeAppsFlyerRPC . executeJson . mock . calls [ 0 ] [ 0 ] ;
283+ const call = mockModule . executeJson . mock . calls [ 0 ] [ 0 ] ;
237284 const request = JSON . parse ( call ) ;
238285 expect ( request . params . eventValues ) . toEqual ( { key : 'value' } ) ;
239286 } ) ;
240287
241288 it ( 'should log event with awaitResponse' , async ( ) => {
289+ const mockModule = getMockNativeModule ( ) ;
242290 const mockResponse = JSON . stringify ( {
243291 id : 'test-123' ,
244292 result : { data : { statusCode : 200 } } ,
245293 } ) ;
246- NativeAppsFlyerRPC . executeJson . mockResolvedValue ( mockResponse ) ;
294+ mockModule . executeJson . mockResolvedValue ( mockResponse ) ;
247295
248296 const result = await AppsFlyerRPC . instance . logEvent ( 'test_event' , {
249297 eventValues : { key : 'value' } ,
@@ -256,21 +304,23 @@ describe('AppsFlyerRPC', () => {
256304 } ) ;
257305
258306 it ( 'logEventWithCallback should call logEvent with awaitResponse' , async ( ) => {
307+ const mockModule = getMockNativeModule ( ) ;
259308 await AppsFlyerRPC . instance . logEventWithCallback ( 'test_event' , {
260309 eventValues : { key : 'value' } ,
261310 } ) ;
262311
263- const call = NativeAppsFlyerRPC . executeJson . mock . calls [ 0 ] [ 0 ] ;
312+ const call = mockModule . executeJson . mock . calls [ 0 ] [ 0 ] ;
264313 const request = JSON . parse ( call ) ;
265314 expect ( request . params . awaitResponse ) . toBe ( true ) ;
266315 } ) ;
267316 } ) ;
268317
269318 describe ( 'registerConversionListener' , ( ) => {
270319 it ( 'should call registerConversionListener' , async ( ) => {
320+ const mockModule = getMockNativeModule ( ) ;
271321 await AppsFlyerRPC . instance . registerConversionListener ( ) ;
272322
273- const call = NativeAppsFlyerRPC . executeJson . mock . calls [ 0 ] [ 0 ] ;
323+ const call = mockModule . executeJson . mock . calls [ 0 ] [ 0 ] ;
274324 const request = JSON . parse ( call ) ;
275325 expect ( request . method ) . toBe ( 'registerConversionListener' ) ;
276326 expect ( request . params ) . toEqual ( { } ) ;
@@ -279,9 +329,10 @@ describe('AppsFlyerRPC', () => {
279329
280330 describe ( 'registerDeepLinkListener' , ( ) => {
281331 it ( 'should call registerDeeplinkListener' , async ( ) => {
332+ const mockModule = getMockNativeModule ( ) ;
282333 await AppsFlyerRPC . instance . registerDeepLinkListener ( ) ;
283334
284- const call = NativeAppsFlyerRPC . executeJson . mock . calls [ 0 ] [ 0 ] ;
335+ const call = mockModule . executeJson . mock . calls [ 0 ] [ 0 ] ;
285336 const request = JSON . parse ( call ) ;
286337 expect ( request . method ) . toBe ( 'registerDeeplinkListener' ) ;
287338 expect ( request . params ) . toEqual ( { } ) ;
@@ -319,15 +370,34 @@ describe('AppsFlyerRPC', () => {
319370 } ) ;
320371
321372 describe ( 'Platform Support' , ( ) => {
322- it ( 'should throw error on Android' , async ( ) => {
373+ it ( 'should work on both iOS and Android' , async ( ) => {
374+ // Test iOS
375+ Platform . OS = 'ios' ;
376+ const mockModule = getMockNativeModule ( ) ;
377+ const mockResponse = JSON . stringify ( {
378+ id : 'test-123' ,
379+ result : { success : true } ,
380+ } ) ;
381+ mockModule . executeJson . mockResolvedValue ( mockResponse ) ;
382+
383+ await AppsFlyerRPC . instance . initialize ( {
384+ devKey : 'test-key' ,
385+ appId : 'id123' ,
386+ } ) ;
387+
388+ expect ( mockModule . executeJson ) . toHaveBeenCalled ( ) ;
389+
390+ // Test Android
323391 Platform . OS = 'android' ;
392+ jest . clearAllMocks ( ) ;
393+ mockModule . executeJson . mockResolvedValue ( mockResponse ) ;
324394
325- await expect (
326- AppsFlyerRPC . instance . initialize ( {
327- devKey : 'test-key ' ,
328- appId : 'com.test.app' ,
329- } )
330- ) . rejects . toThrow ( 'RPC is currently only supported on iOS' ) ;
395+ await AppsFlyerRPC . instance . initialize ( {
396+ devKey : 'test-key' ,
397+ appId : 'com. test.app ' ,
398+ } ) ;
399+
400+ expect ( mockModule . executeJson ) . toHaveBeenCalled ( ) ;
331401
332402 Platform . OS = 'ios' ; // Reset
333403 } ) ;
0 commit comments