1import { Platform } from 'react-native'; 2import { Linking } from 'expo'; 3 4import * as WebBrowser from 'expo-web-browser'; 5import Constants from 'expo-constants'; 6 7import { waitFor } from './helpers'; 8 9const validHttpUrl = 'http://expo.io/'; 10const validHttpsUrl = 'https://expo.io/'; 11const validExpUrl = 'exp://expo.io/@community/native-component-list'; 12const redirectingBackendUrl = 'https://backend-xxswjknyfi.now.sh/?linkingUri='; 13 14export const name = 'Linking'; 15 16export function test(t) { 17 t.describe('Linking', () => { 18 t.describe('canOpenUrl', () => { 19 t.it('can open exp:// URLs', async () => { 20 t.expect(await Linking.canOpenURL(validExpUrl)).toBe(true); 21 }); 22 23 t.it('can open its own URLs', async () => { 24 t.expect(await Linking.canOpenURL(Constants.linkingUri)).toBe(true); 25 }); 26 27 t.it('can open http:// URLs', async () => { 28 t.expect(await Linking.canOpenURL(validHttpUrl)).toBe(true); 29 }); 30 31 t.it('can open https:// URLs', async () => { 32 t.expect(await Linking.canOpenURL(validHttpsUrl)).toBe(true); 33 }); 34 }); 35 36 t.describe('addListener', () => { 37 let previousInterval = 0; 38 t.beforeAll(() => { 39 previousInterval = t.jasmine.DEFAULT_TIMEOUT_INTERVAL; 40 t.jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; 41 }); 42 t.afterAll(() => { 43 t.jasmine.DEFAULT_TIMEOUT_INTERVAL = previousInterval; 44 }); 45 46 if (Platform.OS === 'android') { 47 // We can't run this test on iOS since iOS it fails with an exception 48 // "The specified URL has an unsupported scheme. Only HTTP and HTTPS URLs are supported." 49 t.it('listener gets called with a proper URL when opened from a web modal', async () => { 50 let handlerCalled = false; 51 const testUrl = Linking.makeUrl('++message=hello'); 52 const handler = ({ url }) => { 53 t.expect(url).toEqual(testUrl); 54 handlerCalled = true; 55 }; 56 Linking.addEventListener('url', handler); 57 await WebBrowser.openBrowserAsync(testUrl); 58 t.expect(handlerCalled).toBe(true); 59 Linking.removeListener('url', handler); 60 }); 61 62 // We can't run this test on iOS since iOS asks "whether to open this link in Expo" 63 // and we can't programmatically tap "Open". 64 t.it('listener gets called with a proper URL when opened from a web browser', async () => { 65 let handlerCalled = false; 66 const handler = ({ url }) => { 67 t.expect(url).toEqual(Linking.makeUrl('++message=Redirected automatically by timer')); 68 handlerCalled = true; 69 }; 70 Linking.addEventListener('url', handler); 71 await Linking.openURL(`${redirectingBackendUrl}${Linking.makeUrl('++')}`); 72 await waitFor(8000); 73 t.expect(handlerCalled).toBe(true); 74 Linking.removeListener('url', handler); 75 }); 76 } 77 78 t.it('listener gets called with a proper URL when opened from a web modal', async () => { 79 let handlerCalled = false; 80 const handler = ({ url }) => { 81 t.expect(url).toEqual(Linking.makeUrl('++message=Redirected automatically by timer')); 82 handlerCalled = true; 83 if (Platform.OS === 'ios') WebBrowser.dismissBrowser(); 84 }; 85 Linking.addEventListener('url', handler); 86 await WebBrowser.openBrowserAsync(`${redirectingBackendUrl}${Linking.makeUrl('++')}`); 87 await waitFor(1000); 88 t.expect(handlerCalled).toBe(true); 89 Linking.removeListener('url', handler); 90 }); 91 92 t.it('listener gets called with a proper URL when opened with Linking.openURL', async () => { 93 let handlerCalled = false; 94 const handler = ({ url }) => { 95 handlerCalled = true; 96 }; 97 Linking.addEventListener('url', handler); 98 await Linking.openURL(Linking.makeUrl('++')); 99 await waitFor(500); 100 t.expect(handlerCalled).toBe(true); 101 Linking.removeListener('url', handler); 102 }); 103 104 t.it('listener parses out deep link information correctly', async () => { 105 let handlerCalled = false; 106 const handler = ({ url }) => { 107 let { path, queryParams } = Linking.parse(url); 108 // ignore +'s on the front of path, 109 // since there may be one or two depending on how test-suite is being served 110 t.expect(path.replace(/\+/g, '')).toEqual('test/path'); 111 t.expect(queryParams.query).toEqual('param'); 112 handlerCalled = true; 113 }; 114 Linking.addEventListener('url', handler); 115 await Linking.openURL(Linking.makeUrl('++test/path?query=param')); 116 await waitFor(500); 117 t.expect(handlerCalled).toBe(true); 118 Linking.removeListener('url', handler); 119 }); 120 }); 121 }); 122} 123