1import { resolve } from 'path';
2
3import rnFixture from '../../plugins/__tests__/fixtures/react-native-project';
4import * as XML from '../../utils/XML';
5import {
6  addMetaDataItemToMainApplication,
7  addUsesLibraryItemToMainApplication,
8  AndroidManifest,
9  ensureToolsAvailable,
10  findMetaDataItem,
11  findUsesLibraryItem,
12  getMainActivity,
13  getMainApplication,
14  getRunnableActivity,
15  prefixAndroidKeys,
16  readAndroidManifestAsync,
17  removeMetaDataItemFromMainApplication,
18  removeUsesLibraryItemFromMainApplication,
19} from '../Manifest';
20
21async function getFixtureManifestAsync() {
22  return (await XML.parseXMLAsync(
23    rnFixture['android/app/src/main/AndroidManifest.xml']
24  )) as AndroidManifest;
25}
26
27describe(getMainActivity, () => {
28  it(`works`, async () => {
29    const manifest = await getFixtureManifestAsync();
30    const activity = getMainActivity(manifest)!;
31    expect(activity.$).toBeDefined();
32    expect(Array.isArray(activity['intent-filter'])).toBe(true);
33  });
34  it(`returns null`, async () => {
35    const activity = getMainActivity({} as any);
36    expect(activity).toBe(null);
37  });
38});
39describe(getRunnableActivity, () => {
40  it(`works`, async () => {
41    const sampleManifestPath = resolve(
42      __dirname,
43      'fixtures/complex-react-native-AndroidManifest.xml'
44    );
45    const manifest = await readAndroidManifestAsync(sampleManifestPath);
46    const activity = getRunnableActivity(manifest)!;
47    expect(activity.$).toBeDefined();
48    expect(activity.$['android:name']).toBe('.CustomNamed');
49    expect(Array.isArray(activity['intent-filter'])).toBe(true);
50  });
51});
52describe(getMainApplication, () => {
53  it(`works`, async () => {
54    const manifest = await getFixtureManifestAsync();
55    const app = getMainApplication(manifest)!;
56    expect(app.$).toBeDefined();
57    expect(app.activity).toBeDefined();
58  });
59  it(`returns null`, async () => {
60    const app = getMainApplication({} as any);
61    expect(app).toBe(null);
62  });
63  it(`matches against fully qualified MainApplications`, async () => {
64    const manifest = await getFixtureManifestAsync();
65    const app = getMainApplication(manifest)!;
66    app.$['android:name'] = 'dev.expo.go.MainApplication';
67    expect(getMainApplication(manifest)).toBeDefined();
68  });
69});
70describe(addMetaDataItemToMainApplication, () => {
71  it(`adds then removes meta-data item`, async () => {
72    const manifest = await getFixtureManifestAsync();
73    const app = getMainApplication(manifest)!;
74    addMetaDataItemToMainApplication(app, 'bacon', 'pancake');
75    expect(findMetaDataItem(app, 'bacon')).toBe(2);
76    removeMetaDataItemFromMainApplication(app, 'bacon');
77    expect(findMetaDataItem(app, 'bacon')).toBe(-1);
78  });
79});
80describe(addUsesLibraryItemToMainApplication, () => {
81  it(`adds then removes uses-library item`, async () => {
82    const manifest = await getFixtureManifestAsync();
83    const app = getMainApplication(manifest)!;
84    addUsesLibraryItemToMainApplication(app, { name: 'bacon', required: true });
85    expect(findUsesLibraryItem(app, 'bacon')).toBe(0);
86    removeUsesLibraryItemFromMainApplication(app, 'bacon');
87    expect(findUsesLibraryItem(app, 'bacon')).toBe(-1);
88  });
89});
90describe(prefixAndroidKeys, () => {
91  it(`adds android: prefix to all keys in an object`, () => {
92    expect(prefixAndroidKeys({ bacon: 'pancake', required: true })).toStrictEqual({
93      'android:bacon': 'pancake',
94      'android:required': true,
95    });
96  });
97});
98
99describe(ensureToolsAvailable, () => {
100  it(`ensures tools are available`, async () => {
101    const manifest = await getFixtureManifestAsync();
102    expect(XML.format(manifest)).not.toMatch(/xmlns:tools="http:\/\/schemas\.android\.com\/tools"/);
103
104    const firstFewLines = XML.format(ensureToolsAvailable(manifest))
105      .split('\n')
106      .splice(0, 1)
107      .join('\n');
108    expect(firstFewLines).toMatchInlineSnapshot(
109      `"<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">"`
110    );
111    expect(firstFewLines).toMatch(/xmlns:tools="http:\/\/schemas\.android\.com\/tools"/);
112
113    // ensure idempotent
114    const firstFewLines2 = XML.format(ensureToolsAvailable(manifest))
115      .split('\n')
116      .splice(0, 1)
117      .join('\n');
118    expect(firstFewLines2).toEqual(firstFewLines);
119    expect(firstFewLines2).toEqual(firstFewLines);
120  });
121});
122