1import Constants, { ExecutionEnvironment } from 'expo-constants';
2
3import { extractExpoPathFromURL } from '../extractPathFromURL';
4
5describe(extractExpoPathFromURL, () => {
6  const originalExecutionEnv = Constants.executionEnvironment;
7
8  afterEach(() => {
9    Constants.executionEnvironment = originalExecutionEnv;
10  });
11
12  for (const [name, exenv] of [
13    ['Expo Go', ExecutionEnvironment.StoreClient],
14    ['Bare', ExecutionEnvironment.Bare],
15  ] as const) {
16    describe(name, () => {
17      test.each<string>([
18        'scheme://expo-development-client/?url=http%3A%2F%2Flocalhost%3A8081%2Fexample%2Fpath',
19        'scheme://expo-development-client/?url=http://acme.com/foo/bar?query=param',
20        'scheme://expo-development-client/?url=acme://foo/bar?query=param&query2=param2',
21        'app.bacon.expo://expo-development-client',
22        'exp://127.0.0.1:19000/',
23        'exp://127.0.0.1:19000/--/test/path?query=param',
24        'exp://127.0.0.1:19000/--/test/path?shouldBeEscaped=x%252By%2540xxx.com',
25        'exp://127.0.0.1:19000/x?y=x%252By%2540xxx.com',
26        'exp://127.0.0.1:19000?query=param',
27        'exp://u.expo.dev/update/123abc',
28        'exp://u.expo.dev/update/123abc/--/test/path?query=param',
29        'exp://u.expo.dev/update/123abc/efg',
30        'exp://exp.host/@test/test',
31        'exp://exp.host/@test/test/--/test/path?query=param',
32        'exp://exp.host/@test/test/--/test/path',
33        'exp://exp.host/@test/test/--/test/path/--/foobar',
34        'https://example.com/test/path?query=param',
35        'https://example.com/test/path',
36        'https://example.com:8000/test/path',
37        'https://example.com:8000/test/path+with+plus',
38        'https://example.com/test/path?query=do+not+escape',
39        'https://example.com/test/path?missingQueryValue=',
40        'custom:///?shouldBeEscaped=x%252By%2540xxx.com',
41        'custom:///test/path?foo=bar',
42        'custom:///',
43        'custom://',
44        'custom://?hello=bar',
45        'invalid',
46      ])(`parses %p`, (url) => {
47        Constants.executionEnvironment = exenv;
48
49        const res = extractExpoPathFromURL(url);
50        expect(res).toMatchSnapshot();
51
52        if (exenv === ExecutionEnvironment.StoreClient) {
53          // Ensure the Expo Go handling never breaks
54          expect(res).not.toMatch(/^--\//);
55        }
56      });
57    });
58  }
59  it(`decodes query params in bare`, () => {
60    Constants.executionEnvironment = ExecutionEnvironment.Bare;
61    expect(extractExpoPathFromURL(`custom:///?x=%20%2B%2F`)).toEqual('?x= +/');
62  });
63  it(`decodes query params in Expo Go`, () => {
64    Constants.executionEnvironment = ExecutionEnvironment.StoreClient;
65    expect(extractExpoPathFromURL(`custom:///?x=%20%2B%2F`)).toEqual('?x= +/');
66    expect(extractExpoPathFromURL(`exp://127.0.0.1:19000/--/test/path?x=%20%2B%2F`)).toEqual(
67      'test/path?x= +/'
68    );
69    expect(extractExpoPathFromURL(`exp://x?y=%20%2B%2F`)).toEqual('?y= +/');
70  });
71
72  it(`only handles Expo Go URLs in Expo Go`, () => {
73    Constants.executionEnvironment = ExecutionEnvironment.Bare;
74
75    const res = extractExpoPathFromURL('exp://127.0.0.1:19000/--/test');
76    // This should look mostly broken, but it's the best we can do
77    // when someone uses this format outside of Expo Go.
78    expect(res).toEqual('127.0.0.1:19000/--/test');
79  });
80});
81