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