1import Constants, { ExecutionEnvironment } from 'expo-constants';
2import { Platform } from 'react-native';
3
4import { collectManifestSchemes, resolveScheme } from '../Schemes';
5
6describe(collectManifestSchemes, () => {
7  const consoleWarn = console.warn;
8  const manifest = Constants.__rawManifest_TEST;
9  const executionEnvironment = Constants.executionEnvironment;
10
11  afterEach(() => {
12    console.warn = consoleWarn;
13    Constants.executionEnvironment = executionEnvironment;
14    Constants.__rawManifest_TEST = manifest;
15  });
16
17  beforeEach(() => {
18    console.warn = jest.fn();
19    Constants.executionEnvironment = ExecutionEnvironment.StoreClient;
20    Constants.__rawManifest_TEST = {
21      ...manifest,
22      scheme: 'demo',
23    };
24  });
25
26  it(`collects none`, () => {
27    Constants.__rawManifest_TEST = {
28      ...manifest,
29      scheme: undefined,
30    };
31    expect(collectManifestSchemes()).toStrictEqual([]);
32  });
33  it(`collects default`, () => {
34    Constants.__rawManifest_TEST = {
35      ...manifest,
36      scheme: 'demo',
37    };
38    expect(collectManifestSchemes()).toStrictEqual(['demo']);
39  });
40  it(`collects all`, () => {
41    Constants.__rawManifest_TEST = {
42      ...manifest,
43      // @ts-ignore An array of strings is a secret feature until we drop turtle v1
44      scheme: ['scheme.1', 'scheme.2'],
45      detach: {
46        scheme: 'detach.scheme.1',
47      },
48      ios: {
49        // @ts-ignore An array of strings is a secret feature until we drop turtle v1
50        scheme: ['ios.scheme.1', null],
51        bundleIdentifier: 'ios.bundleIdentifier',
52      },
53      android: {
54        // @ts-ignore An array of strings is a secret feature until we drop turtle v1
55        scheme: ['android.scheme.1'],
56        package: 'android.package',
57      },
58    };
59
60    expect(collectManifestSchemes()).toStrictEqual(
61      Platform.select({
62        ios: ['scheme.1', 'scheme.2', 'detach.scheme.1', 'ios.scheme.1'],
63        android: ['scheme.1', 'scheme.2', 'detach.scheme.1', 'android.scheme.1'],
64      })
65    );
66  });
67});
68
69describe(resolveScheme, () => {
70  const consoleWarn = console.warn;
71  const manifest = Constants.__rawManifest_TEST;
72  const executionEnvironment = Constants.executionEnvironment;
73
74  afterEach(() => {
75    console.warn = consoleWarn;
76    Constants.executionEnvironment = executionEnvironment;
77    Constants.__rawManifest_TEST = manifest;
78  });
79
80  beforeEach(() => {
81    console.warn = jest.fn();
82    Constants.executionEnvironment = ExecutionEnvironment.StoreClient;
83    Constants.__rawManifest_TEST = {
84      ...Constants.__rawManifest_TEST,
85      scheme: 'demo',
86    };
87  });
88
89  it(`collects default in client`, () => {
90    Constants.executionEnvironment = ExecutionEnvironment.StoreClient;
91    Constants.__rawManifest_TEST = {
92      ...Constants.__rawManifest_TEST,
93      scheme: undefined,
94    };
95    expect(resolveScheme({})).toStrictEqual('exp');
96    expect(console.warn).toBeCalled();
97  });
98
99  it(`allows for compliant alternative in client`, () => {
100    Constants.executionEnvironment = ExecutionEnvironment.StoreClient;
101    Constants.__rawManifest_TEST = {
102      ...Constants.__rawManifest_TEST,
103      scheme: 'unused',
104    };
105    expect(resolveScheme({ scheme: 'exps' })).toStrictEqual('exps');
106  });
107
108  it(`silently rejects non-compliant alternative in client`, () => {
109    Constants.executionEnvironment = ExecutionEnvironment.StoreClient;
110    Constants.__rawManifest_TEST = {
111      ...Constants.__rawManifest_TEST,
112      scheme: 'unused',
113    };
114    expect(resolveScheme({ scheme: 'foobar' })).toStrictEqual('exp');
115  });
116
117  //
118
119  it(`uses property over manifest in bare`, () => {
120    Constants.executionEnvironment = ExecutionEnvironment.Bare;
121    Constants.__rawManifest_TEST = {
122      ...Constants.__rawManifest_TEST,
123      scheme: 'unused',
124    };
125    expect(resolveScheme({ scheme: 'foobar' })).toStrictEqual('foobar');
126  });
127  it(`uses manifest when property is missing in bare`, () => {
128    Constants.executionEnvironment = ExecutionEnvironment.Bare;
129    Constants.__rawManifest_TEST = {
130      ...Constants.__rawManifest_TEST,
131      scheme: 'foobar',
132    };
133    expect(resolveScheme({})).toStrictEqual('foobar');
134  });
135  it(`warns when multiple schemes are defined in bare`, () => {
136    Constants.executionEnvironment = ExecutionEnvironment.Bare;
137    Constants.__rawManifest_TEST = {
138      ...Constants.__rawManifest_TEST,
139      // @ts-ignore An array of strings is a secret feature until we drop turtle v1
140      scheme: ['foobar', 'beta'],
141    };
142    expect(resolveScheme({})).toStrictEqual('foobar');
143    expect(console.warn).toBeCalled();
144  });
145  it(`warns no scheme is defined in but the app id is in bare`, () => {
146    Constants.executionEnvironment = ExecutionEnvironment.Bare;
147    Constants.__rawManifest_TEST = {
148      ...Constants.__rawManifest_TEST,
149      scheme: undefined,
150      ios: { bundleIdentifier: 'bundleIdentifier' },
151      android: { package: 'package' },
152    };
153    expect(resolveScheme({})).toStrictEqual(
154      Platform.select({
155        ios: 'bundleIdentifier',
156        android: 'package',
157      })
158    );
159    expect(console.warn).toBeCalled();
160  });
161  it(`throws when no scheme is provided in bare`, () => {
162    Constants.executionEnvironment = ExecutionEnvironment.Bare;
163    Constants.__rawManifest_TEST = {
164      ...Constants.__rawManifest_TEST,
165      scheme: undefined,
166    };
167
168    expect(() => resolveScheme({})).toThrow();
169  });
170  it(`throws when no manifest is linked in bare`, () => {
171    Constants.executionEnvironment = ExecutionEnvironment.Bare;
172    // @ts-ignore: invalid manifest for test
173    Constants.__rawManifest_TEST = {};
174    expect(() => resolveScheme({})).toThrow('expo-constants manifest');
175  });
176});
177