1import { vol } from 'memfs';
2
3import rnFixture from '../../plugins/__tests__/fixtures/react-native-project';
4import { readAndroidManifestAsync } from '../Manifest';
5import {
6  getApplicationIdAsync,
7  getPackage,
8  renameJniOnDiskForType,
9  renamePackageOnDiskForType,
10  setPackageInAndroidManifest,
11  setPackageInBuildGradle,
12} from '../Package';
13import { getAndroidManifestAsync } from '../Paths';
14
15jest.mock('fs');
16
17const EXAMPLE_BUILD_GRADLE = `
18  android {
19      compileSdkVersion rootProject.ext.compileSdkVersion
20      buildToolsVersion rootProject.ext.buildToolsVersion
21
22      namespace "com.helloworld"
23      defaultConfig {
24          applicationId "com.helloworld"
25          minSdkVersion rootProject.ext.minSdkVersion
26          targetSdkVersion rootProject.ext.targetSdkVersion
27          versionCode 1
28          versionName "1.0"
29      }
30  }
31  `;
32
33describe('package', () => {
34  afterAll(async () => {
35    vol.reset();
36  });
37  it(`returns null if no package is provided`, () => {
38    expect(getPackage({})).toBe(null);
39  });
40
41  it(`returns the package if provided`, () => {
42    expect(getPackage({ android: { package: 'com.example.xyz' } })).toBe('com.example.xyz');
43  });
44
45  it(`returns the applicationId defined in build.gradle`, () => {
46    const projectRoot = '/';
47    vol.fromJSON(rnFixture, projectRoot);
48
49    expect(getApplicationIdAsync(projectRoot)).resolves.toBe('com.helloworld');
50  });
51
52  it(`sets the applicationId in build.gradle if package is given`, () => {
53    expect(
54      setPackageInBuildGradle({ android: { package: 'my.new.app' } }, EXAMPLE_BUILD_GRADLE)
55    ).toMatch("applicationId 'my.new.app'");
56  });
57
58  it(`sets the namespace in build.gradle if package is given`, () => {
59    expect(
60      setPackageInBuildGradle({ android: { package: 'my.new.app' } }, EXAMPLE_BUILD_GRADLE)
61    ).toMatch("namespace 'my.new.app'");
62  });
63
64  it('adds package to android manifest', async () => {
65    const projectRoot = '/';
66    vol.fromJSON(rnFixture, projectRoot);
67
68    let androidManifestJson = await readAndroidManifestAsync(
69      await getAndroidManifestAsync(projectRoot)
70    );
71    androidManifestJson = await setPackageInAndroidManifest(
72      { android: { package: 'com.test.package' } },
73      androidManifestJson
74    );
75
76    expect(androidManifestJson.manifest.$.package).toMatch('com.test.package');
77  });
78});
79
80describe(renamePackageOnDiskForType, () => {
81  afterAll(async () => {
82    vol.reset();
83  });
84  it(`refactors a main project`, async () => {
85    const projectRoot = '/';
86    vol.fromJSON(rnFixture, projectRoot);
87
88    // Ensure the path that will be deleted exists before we
89    // delete it, this helps prevent the test from accidentally breaking.
90    const originalPath = '/android/app/src/main/java/com/helloworld/MainActivity.java';
91
92    expect(vol.toJSON()[originalPath]).toBeDefined();
93    await renamePackageOnDiskForType({
94      projectRoot,
95      type: 'main',
96      packageName: 'com.bacon.foobar',
97    });
98
99    const results = vol.toJSON();
100    // Ensure the file exists in the new location with the new package name
101    expect(results['/android/app/src/main/java/com/bacon/foobar/MainActivity.java']).toMatch(
102      /^package com.bacon.foobar;/
103    );
104    expect(results[originalPath]).toBeUndefined();
105    // Ensure the BUCK file is rewritten
106    // expect(results['/android/app/BUCK']).toMatch(/package = "com.bacon.foobar"/);
107  });
108  it(`refactors a debug project`, async () => {
109    const projectRoot = '/';
110    vol.fromJSON(rnFixture, projectRoot);
111    await renamePackageOnDiskForType({
112      projectRoot,
113      type: 'debug',
114      packageName: 'com.bacon.foobar',
115    });
116
117    const results = vol.toJSON();
118    expect(results['/android/app/src/debug/java/com/bacon/foobar/ReactNativeFlipper.java']).toMatch(
119      /package com.bacon.foobar;/
120    );
121  });
122});
123
124describe(renameJniOnDiskForType, () => {
125  afterAll(async () => {
126    vol.reset();
127  });
128  it(`refactors a main project`, async () => {
129    const projectRoot = '/';
130    vol.fromJSON(rnFixture, projectRoot);
131    await renameJniOnDiskForType({
132      projectRoot,
133      type: 'main',
134      packageName: 'com.bacon.foobar',
135    });
136
137    const results = vol.toJSON();
138    expect(
139      results['/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h']
140    ).toMatch(
141      /"Lcom\/bacon\/foobar\/newarchitecture\/modules\/MainApplicationTurboModuleManagerDelegate;";/
142    );
143  });
144});
145