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