3
3
4
4
import { AppState , Linking , Platform } from 'react-native' ;
5
5
6
- import { openAuthSessionAsync } from '../../src/apis/openAuthSessionAsync' ;
6
+ import {
7
+ isChromebook ,
8
+ openAuthSessionAsync ,
9
+ } from '../../src/apis/openAuthSessionAsync' ;
7
10
import { nativeModule } from '../../src/nativeModule' ;
8
11
import {
9
12
mockDeepLinkUrl ,
@@ -21,7 +24,9 @@ jest.mock('react-native', () => ({
21
24
} ,
22
25
Linking : {
23
26
addEventListener : jest . fn ( ) ,
27
+ openURL : jest . fn ( ) ,
24
28
} ,
29
+ NativeModules : { } ,
25
30
} ) ) ;
26
31
27
32
// Mock EmitterSubscription type
@@ -299,4 +304,98 @@ describe('openAuthSessionAsync', () => {
299
304
expect ( mockNativeModule ) . not . toHaveBeenCalled ( ) ;
300
305
} ) ;
301
306
} ) ;
307
+
308
+ describe ( 'isChromebook' , ( ) => {
309
+ it ( 'returns false by default' , async ( ) => {
310
+ const result = await isChromebook ( ) ;
311
+ expect ( result ) . toBe ( false ) ;
312
+ } ) ;
313
+
314
+ it ( 'returns true when NativeModules.ChromeOS.isChromeOS returns true' , async ( ) => {
315
+ const mockReactNative = require ( 'react-native' ) ;
316
+ mockReactNative . NativeModules . ChromeOS = {
317
+ isChromeOS : jest . fn ( ) . mockResolvedValue ( true ) ,
318
+ } ;
319
+
320
+ const result = await isChromebook ( ) ;
321
+ expect ( result ) . toBe ( true ) ;
322
+
323
+ // Clean up
324
+ delete mockReactNative . NativeModules . ChromeOS ;
325
+ } ) ;
326
+ } ) ;
327
+
328
+ describe ( 'ChromeOS flow' , ( ) => {
329
+ beforeEach ( ( ) => {
330
+ mockPlatform . OS = 'android' ;
331
+ mockAppState . currentState = 'active' ;
332
+ } ) ;
333
+
334
+ it ( 'uses ChromeOS flow when isChromebook returns true' , async ( ) => {
335
+ const mockAppStateListener = { ...mockEmitterSubscription } ;
336
+ const mockLinkingListener = { ...mockEmitterSubscription } ;
337
+
338
+ // Mock isChromebook to return true
339
+ const mockReactNative = require ( 'react-native' ) ;
340
+ mockReactNative . NativeModules . ChromeOS = {
341
+ isChromeOS : jest . fn ( ) . mockResolvedValue ( true ) ,
342
+ } ;
343
+
344
+ mockAppState . addEventListener . mockReturnValue ( mockAppStateListener ) ;
345
+ mockLinking . addEventListener . mockReturnValue ( mockLinkingListener ) ;
346
+ mockLinking . openURL . mockResolvedValue ( undefined ) ;
347
+
348
+ // Mock redirect URL received
349
+ mockLinking . addEventListener . mockImplementation (
350
+ ( _event : any , callback : any ) => {
351
+ setTimeout ( ( ) => {
352
+ callback ( { url : mockReturnUrl } ) ;
353
+ } , 0 ) ;
354
+
355
+ return mockLinkingListener ;
356
+ } ,
357
+ ) ;
358
+
359
+ const result = await openAuthSessionAsync ( mockUrl , mockRedirectUrls ) ;
360
+
361
+ expect ( mockLinking . openURL ) . toHaveBeenCalledWith ( mockUrl ) ;
362
+ expect ( mockLinking . openURL ) . toHaveBeenCalledWith ( mockReturnUrl ) ;
363
+ expect ( result ) . toBe ( mockReturnUrl ) ;
364
+
365
+ // Clean up
366
+ delete mockReactNative . NativeModules . ChromeOS ;
367
+ } ) ;
368
+
369
+ it ( 'handles isChromebook error and falls back to Android' , async ( ) => {
370
+ const mockAppStateListener = { ...mockEmitterSubscription } ;
371
+ const mockLinkingListener = { ...mockEmitterSubscription } ;
372
+
373
+ // Mock isChromebook to throw error
374
+ const mockReactNative = require ( 'react-native' ) ;
375
+ mockReactNative . NativeModules . ChromeOS = {
376
+ isChromeOS : jest . fn ( ) . mockRejectedValue ( new Error ( 'Detection failed' ) ) ,
377
+ } ;
378
+
379
+ mockAppState . currentState = 'background' ;
380
+ mockAppState . addEventListener . mockReturnValue ( mockAppStateListener ) ;
381
+ mockLinking . addEventListener . mockReturnValue ( mockLinkingListener ) ;
382
+ mockNativeModule . mockResolvedValue ( undefined ) ;
383
+
384
+ mockAppState . addEventListener . mockImplementation ( ( event , callback ) => {
385
+ setTimeout ( ( ) => {
386
+ callback ( 'active' ) ;
387
+ } , 0 ) ;
388
+
389
+ return mockAppStateListener ;
390
+ } ) ;
391
+
392
+ const result = await openAuthSessionAsync ( mockUrl , mockRedirectUrls ) ;
393
+
394
+ expect ( mockNativeModule ) . toHaveBeenCalledWith ( mockUrl ) ;
395
+ expect ( result ) . toBeNull ( ) ;
396
+
397
+ // Clean up
398
+ delete mockReactNative . NativeModules . ChromeOS ;
399
+ } ) ;
400
+ } ) ;
302
401
} ) ;
0 commit comments