1082815dcSEvan Baconimport plist from '@expo/plist';
2082815dcSEvan Baconimport * as fs from 'fs';
3082815dcSEvan Baconimport { vol } from 'memfs';
4082815dcSEvan Baconimport * as path from 'path';
5082815dcSEvan Bacon
6*ed3bd27bSEvan Baconimport rnFixture from '../../plugins/__tests__/fixtures/react-native-project';
7082815dcSEvan Baconimport {
8082815dcSEvan Bacon  ensureApplicationTargetEntitlementsFileConfigured,
9082815dcSEvan Bacon  getEntitlementsPath,
10082815dcSEvan Bacon} from '../Entitlements';
11082815dcSEvan Bacon
12082815dcSEvan Baconconst fsReal = jest.requireActual('fs') as typeof fs;
13082815dcSEvan Bacon
14082815dcSEvan Baconjest.mock('fs');
15082815dcSEvan Bacon
16082815dcSEvan Baconconst exampleEntitlements = `<?xml version="0.0" encoding="UTF-8"?>
17082815dcSEvan Bacon<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
18082815dcSEvan Bacon<plist version="1.0">
19082815dcSEvan Bacon<dict>
20082815dcSEvan Bacon	<key>special</key>
21082815dcSEvan Bacon	<true/>
22082815dcSEvan Bacon</dict>
23082815dcSEvan Bacon</plist>`;
24082815dcSEvan Bacon
25082815dcSEvan Bacondescribe(ensureApplicationTargetEntitlementsFileConfigured, () => {
26082815dcSEvan Bacon  const projectRoot = '/app';
27082815dcSEvan Bacon
28082815dcSEvan Bacon  afterEach(() => {
29082815dcSEvan Bacon    vol.reset();
30082815dcSEvan Bacon  });
31082815dcSEvan Bacon
32082815dcSEvan Bacon  it('creates a new entitlements file when none exists', async () => {
33*ed3bd27bSEvan Bacon    vol.fromJSON(rnFixture, projectRoot);
34082815dcSEvan Bacon    const entitlementsPathBefore = getEntitlementsPath(projectRoot);
35082815dcSEvan Bacon    ensureApplicationTargetEntitlementsFileConfigured(projectRoot);
36082815dcSEvan Bacon    const entitlementsPath = getEntitlementsPath(projectRoot);
37082815dcSEvan Bacon    expect(entitlementsPathBefore).toBeNull();
38*ed3bd27bSEvan Bacon    expect(entitlementsPath).toBe('/app/ios/HelloWorld/HelloWorld.entitlements');
39082815dcSEvan Bacon
40082815dcSEvan Bacon    // New file has the contents of the old entitlements file
41*ed3bd27bSEvan Bacon    const data = plist.parse(await fs.promises.readFile(entitlementsPath!, 'utf8'));
42082815dcSEvan Bacon    expect(data).toStrictEqual({
43082815dcSEvan Bacon      // No entitlements enabled by default
44082815dcSEvan Bacon    });
45082815dcSEvan Bacon  });
46082815dcSEvan Bacon
47082815dcSEvan Bacon  it('creates a new entitlements file if file in XCBuildConfiguration does not exists', async () => {
48082815dcSEvan Bacon    vol.fromJSON(
49082815dcSEvan Bacon      {
50082815dcSEvan Bacon        'ios/testproject.xcodeproj/project.pbxproj': fsReal.readFileSync(
51082815dcSEvan Bacon          path.join(__dirname, 'fixtures/project-with-entitlements.pbxproj'),
52082815dcSEvan Bacon          'utf-8'
53082815dcSEvan Bacon        ),
54082815dcSEvan Bacon        'ios/testproject/AppDelegate.m': '',
55082815dcSEvan Bacon      },
56082815dcSEvan Bacon      projectRoot
57082815dcSEvan Bacon    );
58082815dcSEvan Bacon    ensureApplicationTargetEntitlementsFileConfigured(projectRoot);
59082815dcSEvan Bacon    const entitlementsPath = getEntitlementsPath(projectRoot);
60082815dcSEvan Bacon    expect(entitlementsPath).toBe('/app/ios/testproject/testproject.entitlements');
61082815dcSEvan Bacon
62082815dcSEvan Bacon    // New file has the contents of the old entitlements file
63082815dcSEvan Bacon    const data = plist.parse(await fs.promises.readFile(entitlementsPath, 'utf8'));
64082815dcSEvan Bacon    expect(data).toStrictEqual({});
65082815dcSEvan Bacon  });
66082815dcSEvan Bacon
67082815dcSEvan Bacon  it('does not create any entitlements files if it already exists', async () => {
68082815dcSEvan Bacon    vol.fromJSON(
69082815dcSEvan Bacon      {
70082815dcSEvan Bacon        'ios/testproject.xcodeproj/project.pbxproj': fsReal.readFileSync(
71082815dcSEvan Bacon          path.join(__dirname, 'fixtures/project-with-entitlements.pbxproj'),
72082815dcSEvan Bacon          'utf-8'
73082815dcSEvan Bacon        ),
74082815dcSEvan Bacon        'ios/testapp/example.entitlements': exampleEntitlements,
75082815dcSEvan Bacon        'ios/testproject/AppDelegate.m': '',
76082815dcSEvan Bacon      },
77082815dcSEvan Bacon      projectRoot
78082815dcSEvan Bacon    );
79082815dcSEvan Bacon    ensureApplicationTargetEntitlementsFileConfigured(projectRoot);
80082815dcSEvan Bacon    const entitlementsPath = getEntitlementsPath(projectRoot);
81082815dcSEvan Bacon    expect(entitlementsPath).toBe('/app/ios/testapp/example.entitlements');
82082815dcSEvan Bacon
83082815dcSEvan Bacon    // New file has the contents of the old entitlements file
84082815dcSEvan Bacon    const data = plist.parse(await fs.promises.readFile(entitlementsPath, 'utf8'));
85082815dcSEvan Bacon    expect(data).toStrictEqual({ special: true });
86082815dcSEvan Bacon
87082815dcSEvan Bacon    // entitlement file in default location does not exist
88082815dcSEvan Bacon    expect(fs.existsSync('/app/ios/testproject/testproject.entitlements')).toBe(false);
89082815dcSEvan Bacon  });
90082815dcSEvan Bacon});
91082815dcSEvan Bacon
92082815dcSEvan Bacondescribe(getEntitlementsPath, () => {
93082815dcSEvan Bacon  const projectRoot = '/app';
94082815dcSEvan Bacon
95082815dcSEvan Bacon  afterEach(() => {
96082815dcSEvan Bacon    vol.reset();
97082815dcSEvan Bacon  });
98082815dcSEvan Bacon
99082815dcSEvan Bacon  it('returns null if CODE_SIGN_ENTITLEMENTS is not specified', async () => {
100082815dcSEvan Bacon    vol.fromJSON(
101082815dcSEvan Bacon      {
102*ed3bd27bSEvan Bacon        'ios/testproject.xcodeproj/project.pbxproj':
103*ed3bd27bSEvan Bacon          rnFixture['ios/HelloWorld.xcodeproj/project.pbxproj'],
104082815dcSEvan Bacon        'ios/testproject/AppDelegate.m': '',
105082815dcSEvan Bacon      },
106082815dcSEvan Bacon      projectRoot
107082815dcSEvan Bacon    );
108082815dcSEvan Bacon
109082815dcSEvan Bacon    const entitlementsPath = getEntitlementsPath(projectRoot);
110082815dcSEvan Bacon    expect(entitlementsPath).toBeNull();
111082815dcSEvan Bacon  });
112082815dcSEvan Bacon  it('returns path if CODE_SIGN_ENTITLEMENTS is specified and file exists', async () => {
113082815dcSEvan Bacon    vol.fromJSON(
114082815dcSEvan Bacon      {
115082815dcSEvan Bacon        'ios/testproject.xcodeproj/project.pbxproj': fsReal.readFileSync(
116082815dcSEvan Bacon          path.join(__dirname, 'fixtures/project-with-entitlements.pbxproj'),
117082815dcSEvan Bacon          'utf-8'
118082815dcSEvan Bacon        ),
119082815dcSEvan Bacon        'ios/testapp/example.entitlements': exampleEntitlements,
120082815dcSEvan Bacon        'ios/testproject/AppDelegate.m': '',
121082815dcSEvan Bacon      },
122082815dcSEvan Bacon      projectRoot
123082815dcSEvan Bacon    );
124082815dcSEvan Bacon
125082815dcSEvan Bacon    const entitlementsPath = getEntitlementsPath(projectRoot);
126082815dcSEvan Bacon    expect(entitlementsPath).toBe('/app/ios/testapp/example.entitlements');
127082815dcSEvan Bacon  });
128082815dcSEvan Bacon});
129