33
44import { AppState , Linking , Platform } from 'react-native' ;
55
6- import { openAuthSessionAsync } from '../../src/apis/openAuthSessionAsync' ;
6+ import {
7+ isChromebook ,
8+ openAuthSessionAsync ,
9+ } from '../../src/apis/openAuthSessionAsync' ;
710import { nativeModule } from '../../src/nativeModule' ;
811import {
912 mockDeepLinkUrl ,
@@ -21,7 +24,9 @@ jest.mock('react-native', () => ({
2124 } ,
2225 Linking : {
2326 addEventListener : jest . fn ( ) ,
27+ openURL : jest . fn ( ) ,
2428 } ,
29+ NativeModules : { } ,
2530} ) ) ;
2631
2732// Mock EmitterSubscription type
@@ -299,4 +304,98 @@ describe('openAuthSessionAsync', () => {
299304 expect ( mockNativeModule ) . not . toHaveBeenCalled ( ) ;
300305 } ) ;
301306 } ) ;
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+ } ) ;
302401} ) ;
0 commit comments