1082815dcSEvan Baconimport { resolve } from 'path';
2082815dcSEvan Bacon
3*ed3bd27bSEvan Baconimport rnFixture from '../../plugins/__tests__/fixtures/react-native-project';
4*ed3bd27bSEvan Baconimport * as XML from '../../utils/XML';
5*ed3bd27bSEvan Baconimport { AndroidManifest, getMainActivity, readAndroidManifestAsync } from '../Manifest';
6082815dcSEvan Baconimport {
7082815dcSEvan Bacon  appendScheme,
8082815dcSEvan Bacon  ensureManifestHasValidIntentFilter,
9082815dcSEvan Bacon  getScheme,
10082815dcSEvan Bacon  getSchemesFromManifest,
11082815dcSEvan Bacon  hasScheme,
12082815dcSEvan Bacon  removeScheme,
13082815dcSEvan Bacon  setScheme,
14082815dcSEvan Bacon} from '../Scheme';
15082815dcSEvan Bacon
16*ed3bd27bSEvan Baconasync function getFixtureManifestAsync() {
17*ed3bd27bSEvan Bacon  return (await XML.parseXMLAsync(
18*ed3bd27bSEvan Bacon    rnFixture['android/app/src/main/AndroidManifest.xml']
19*ed3bd27bSEvan Bacon  )) as AndroidManifest;
20*ed3bd27bSEvan Bacon}
21*ed3bd27bSEvan Bacon
22082815dcSEvan Baconconst fixturesPath = resolve(__dirname, 'fixtures');
23082815dcSEvan Baconconst sampleManifestWithHostPath = resolve(
24082815dcSEvan Bacon  fixturesPath,
25082815dcSEvan Bacon  'react-native-AndroidManifest-with-host.xml'
26082815dcSEvan Bacon);
27082815dcSEvan Bacon
28082815dcSEvan Bacondescribe('scheme', () => {
29082815dcSEvan Bacon  it(`returns empty array if no scheme is provided`, () => {
30082815dcSEvan Bacon    expect(getScheme({})).toStrictEqual([]);
31082815dcSEvan Bacon  });
32082815dcSEvan Bacon
33082815dcSEvan Bacon  it(`returns the scheme if provided`, () => {
34082815dcSEvan Bacon    expect(getScheme({ scheme: 'myapp' })).toStrictEqual(['myapp']);
35082815dcSEvan Bacon    expect(getScheme({ scheme: ['other', 'myapp'] })).toStrictEqual(['other', 'myapp']);
36082815dcSEvan Bacon    expect(
37082815dcSEvan Bacon      getScheme({
38*ed3bd27bSEvan Bacon        scheme: [
39*ed3bd27bSEvan Bacon          'other',
40*ed3bd27bSEvan Bacon          'myapp',
41*ed3bd27bSEvan Bacon          // @ts-expect-error
42*ed3bd27bSEvan Bacon          null,
43*ed3bd27bSEvan Bacon        ],
44082815dcSEvan Bacon      })
45082815dcSEvan Bacon    ).toStrictEqual(['other', 'myapp']);
46082815dcSEvan Bacon  });
47082815dcSEvan Bacon
48082815dcSEvan Bacon  it('does not add scheme if none provided', async () => {
49*ed3bd27bSEvan Bacon    let androidManifestJson = await getFixtureManifestAsync();
50082815dcSEvan Bacon    androidManifestJson = await setScheme({}, androidManifestJson);
51082815dcSEvan Bacon
52082815dcSEvan Bacon    expect(androidManifestJson).toEqual(androidManifestJson);
53082815dcSEvan Bacon  });
54082815dcSEvan Bacon
55082815dcSEvan Bacon  it('adds scheme to android manifest', async () => {
56*ed3bd27bSEvan Bacon    let androidManifestJson = await getFixtureManifestAsync();
57082815dcSEvan Bacon    androidManifestJson = await setScheme(
58082815dcSEvan Bacon      {
59082815dcSEvan Bacon        scheme: 'myapp',
60082815dcSEvan Bacon        android: {
61082815dcSEvan Bacon          // @ts-ignore
62082815dcSEvan Bacon          scheme: ['android-only'],
63082815dcSEvan Bacon          package: 'com.demo.value',
64082815dcSEvan Bacon        },
65082815dcSEvan Bacon        ios: { scheme: 'ios-only' },
66082815dcSEvan Bacon      },
67082815dcSEvan Bacon      androidManifestJson
68082815dcSEvan Bacon    );
69082815dcSEvan Bacon
70082815dcSEvan Bacon    const mainActivity = getMainActivity(androidManifestJson);
71*ed3bd27bSEvan Bacon    const intentFilters = mainActivity!['intent-filter']!;
72082815dcSEvan Bacon
73*ed3bd27bSEvan Bacon    const schemeIntent: string[] = [];
74082815dcSEvan Bacon
75082815dcSEvan Bacon    for (const intent of intentFilters) {
76082815dcSEvan Bacon      if ('data' in intent) {
77*ed3bd27bSEvan Bacon        for (const dataFilter of intent.data!) {
78082815dcSEvan Bacon          const possibleScheme = dataFilter.$['android:scheme'];
79082815dcSEvan Bacon          if (possibleScheme) {
80082815dcSEvan Bacon            schemeIntent.push(possibleScheme);
81082815dcSEvan Bacon          }
82082815dcSEvan Bacon        }
83082815dcSEvan Bacon      }
84082815dcSEvan Bacon    }
85082815dcSEvan Bacon
86082815dcSEvan Bacon    expect(schemeIntent).toStrictEqual(['myapp', 'android-only', 'com.demo.value']);
87082815dcSEvan Bacon  });
88082815dcSEvan Bacon});
89082815dcSEvan Bacon
90082815dcSEvan Baconfunction removeSingleTaskFromActivities(manifest) {
91082815dcSEvan Bacon  for (const application of manifest.manifest.application) {
92082815dcSEvan Bacon    for (const activity of application.activity) {
93082815dcSEvan Bacon      if (activity.$['android:launchMode'] === 'singleTask') {
94082815dcSEvan Bacon        delete activity.$['android:launchMode'];
95082815dcSEvan Bacon      }
96082815dcSEvan Bacon    }
97082815dcSEvan Bacon  }
98082815dcSEvan Bacon
99082815dcSEvan Bacon  return manifest;
100082815dcSEvan Bacon}
101082815dcSEvan Bacon
102082815dcSEvan Bacondescribe('Schemes', () => {
103082815dcSEvan Bacon  it(`ensure manifest has valid intent filter added`, async () => {
104*ed3bd27bSEvan Bacon    const manifest = await getFixtureManifestAsync();
105082815dcSEvan Bacon    const manifestHasValidIntentFilter = ensureManifestHasValidIntentFilter(manifest);
106082815dcSEvan Bacon    expect(manifestHasValidIntentFilter).toBe(true);
107082815dcSEvan Bacon  });
108082815dcSEvan Bacon
109082815dcSEvan Bacon  it(`detect if no singleTask Activity exists`, async () => {
110*ed3bd27bSEvan Bacon    const manifest = await getFixtureManifestAsync();
111082815dcSEvan Bacon    removeSingleTaskFromActivities(manifest);
112082815dcSEvan Bacon
113082815dcSEvan Bacon    expect(ensureManifestHasValidIntentFilter(manifest)).toBe(false);
114082815dcSEvan Bacon  });
115082815dcSEvan Bacon
116082815dcSEvan Bacon  it(`adds and removes a new scheme`, async () => {
117*ed3bd27bSEvan Bacon    const manifest = await getFixtureManifestAsync();
118082815dcSEvan Bacon    ensureManifestHasValidIntentFilter(manifest);
119082815dcSEvan Bacon
120082815dcSEvan Bacon    const modifiedManifest = appendScheme('myapp.test', manifest);
121082815dcSEvan Bacon    const schemes = getSchemesFromManifest(modifiedManifest);
122082815dcSEvan Bacon    expect(schemes).toContain('myapp.test');
123082815dcSEvan Bacon    const removedManifest = removeScheme('myapp.test', manifest);
124082815dcSEvan Bacon    expect(getSchemesFromManifest(removedManifest)).not.toContain('myapp.test');
125082815dcSEvan Bacon  });
126082815dcSEvan Bacon
127082815dcSEvan Bacon  it(`get all schemes for the host`, async () => {
128082815dcSEvan Bacon    const manifest = await readAndroidManifestAsync(sampleManifestWithHostPath);
129082815dcSEvan Bacon    ensureManifestHasValidIntentFilter(manifest);
130082815dcSEvan Bacon    expect(hasScheme('longestschemewiththehost', manifest)).toBe(true);
131082815dcSEvan Bacon
132082815dcSEvan Bacon    const modifiedManifest = appendScheme('myapp.test', manifest);
133082815dcSEvan Bacon    let schemes = getSchemesFromManifest(modifiedManifest, 'any-host');
134082815dcSEvan Bacon    expect(schemes).toContain('myapp.test');
135082815dcSEvan Bacon    expect(schemes).not.toContain('longestschemewiththehost');
136082815dcSEvan Bacon
137082815dcSEvan Bacon    schemes = getSchemesFromManifest(modifiedManifest, 'expo-development-client');
138082815dcSEvan Bacon    expect(schemes).toContain('myapp.test');
139082815dcSEvan Bacon    expect(schemes).toContain('longestschemewiththehost');
140082815dcSEvan Bacon  });
141082815dcSEvan Bacon
142082815dcSEvan Bacon  it(`detect when a duplicate might be added`, async () => {
143*ed3bd27bSEvan Bacon    const manifest = await getFixtureManifestAsync();
144082815dcSEvan Bacon    ensureManifestHasValidIntentFilter(manifest);
145082815dcSEvan Bacon
146082815dcSEvan Bacon    const modifiedManifest = appendScheme('myapp.test', manifest);
147082815dcSEvan Bacon    expect(hasScheme('myapp.test', modifiedManifest)).toBe(true);
148082815dcSEvan Bacon  });
149082815dcSEvan Bacon
150082815dcSEvan Bacon  it(`detect a non-existent scheme`, async () => {
151*ed3bd27bSEvan Bacon    const manifest = await getFixtureManifestAsync();
152082815dcSEvan Bacon
153082815dcSEvan Bacon    expect(hasScheme('myapp.test', manifest)).toBe(false);
154082815dcSEvan Bacon  });
155082815dcSEvan Bacon});
156