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