1dfe12d45SEvan Bacon/* eslint-env jest */
2dfe12d45SEvan Baconimport execa from 'execa';
3*87669a95SMark Lawlorimport { constants as fsConstants } from 'fs';
4dfe12d45SEvan Baconimport fs from 'fs-extra';
5dfe12d45SEvan Baconimport klawSync from 'klaw-sync';
6dfe12d45SEvan Baconimport path from 'path';
7dfe12d45SEvan Bacon
8dfe12d45SEvan Baconimport { execute, projectRoot, getLoadedModulesAsync, setupTestProjectAsync, bin } from './utils';
9dfe12d45SEvan Bacon
10dfe12d45SEvan Baconconst originalForceColor = process.env.FORCE_COLOR;
11dfe12d45SEvan Baconconst originalCI = process.env.CI;
12*87669a95SMark Lawlorconst originalUseTypedRoutes = process.env._EXPO_E2E_USE_TYPED_ROUTES;
13*87669a95SMark Lawlor
14*87669a95SMark Lawlorconst generatedFiles = ['tsconfig.json', 'expo-env.d.ts', '.expo/types/router.d.ts', '.gitignore'];
15dfe12d45SEvan Bacon
16dfe12d45SEvan BaconbeforeAll(async () => {
17dfe12d45SEvan Bacon  await fs.mkdir(projectRoot, { recursive: true });
18dfe12d45SEvan Bacon  process.env.FORCE_COLOR = '0';
19dfe12d45SEvan Bacon  process.env.CI = '1';
20*87669a95SMark Lawlor  process.env._EXPO_E2E_USE_TYPED_ROUTES = '1';
21dfe12d45SEvan Bacon});
22dfe12d45SEvan Bacon
23*87669a95SMark LawlorafterAll(async () => {
24dfe12d45SEvan Bacon  process.env.FORCE_COLOR = originalForceColor;
25dfe12d45SEvan Bacon  process.env.CI = originalCI;
26*87669a95SMark Lawlor  process.env._EXPO_E2E_USE_TYPED_ROUTES = originalUseTypedRoutes;
27*87669a95SMark Lawlor
28*87669a95SMark Lawlor  // Remove the generated files
29*87669a95SMark Lawlor  await Promise.all(
30*87669a95SMark Lawlor    generatedFiles.map((file) =>
31*87669a95SMark Lawlor      fs.promises.rm(path.join(projectRoot, file), { recursive: true, force: true })
32*87669a95SMark Lawlor    )
33*87669a95SMark Lawlor  );
34dfe12d45SEvan Bacon});
35dfe12d45SEvan Bacon
36dfe12d45SEvan Baconit('loads expected modules by default', async () => {
37dfe12d45SEvan Bacon  const modules = await getLoadedModulesAsync(`require('../../build/src/customize').expoCustomize`);
38dfe12d45SEvan Bacon  expect(modules).toStrictEqual([
394067174dSWill Schurman    '../node_modules/ansi-styles/index.js',
40dfe12d45SEvan Bacon    '../node_modules/arg/index.js',
41dfe12d45SEvan Bacon    '../node_modules/chalk/source/index.js',
42dfe12d45SEvan Bacon    '../node_modules/chalk/source/util.js',
43dfe12d45SEvan Bacon    '../node_modules/has-flag/index.js',
44dfe12d45SEvan Bacon    '../node_modules/supports-color/index.js',
45dfe12d45SEvan Bacon    '@expo/cli/build/src/customize/index.js',
46dfe12d45SEvan Bacon    '@expo/cli/build/src/log.js',
47dfe12d45SEvan Bacon    '@expo/cli/build/src/utils/args.js',
48dfe12d45SEvan Bacon  ]);
49dfe12d45SEvan Bacon});
50dfe12d45SEvan Bacon
51dfe12d45SEvan Baconit('runs `npx expo customize --help`', async () => {
52dfe12d45SEvan Bacon  const results = await execute('customize', '--help');
53dfe12d45SEvan Bacon  expect(results.stdout).toMatchInlineSnapshot(`
54dfe12d45SEvan Bacon    "
55dfe12d45SEvan Bacon      Info
56dfe12d45SEvan Bacon        Generate static project files
57dfe12d45SEvan Bacon
58dfe12d45SEvan Bacon      Usage
59dfe12d45SEvan Bacon        $ npx expo customize [files...] -- [options]
60dfe12d45SEvan Bacon
61dfe12d45SEvan Bacon      Options
62dfe12d45SEvan Bacon        [files...]  List of files to generate
63dfe12d45SEvan Bacon        [options]   Options to pass to the install command
64dfe12d45SEvan Bacon        -h, --help  Usage info
65dfe12d45SEvan Bacon    "
66dfe12d45SEvan Bacon  `);
67dfe12d45SEvan Bacon});
68dfe12d45SEvan Bacon
69dfe12d45SEvan Baconit(
70dfe12d45SEvan Bacon  'runs `npx expo customize`',
71dfe12d45SEvan Bacon  async () => {
72dfe12d45SEvan Bacon    const projectRoot = await setupTestProjectAsync('basic-customize', 'with-blank');
73dfe12d45SEvan Bacon    // `npx expo customize index.html serve.json babel.config.js`
74dfe12d45SEvan Bacon    await execa('node', [bin, 'customize', 'web/index.html', 'web/serve.json', 'babel.config.js'], {
75dfe12d45SEvan Bacon      cwd: projectRoot,
76dfe12d45SEvan Bacon    });
77dfe12d45SEvan Bacon
78dfe12d45SEvan Bacon    const files = klawSync(projectRoot)
79dfe12d45SEvan Bacon      .map((entry) => {
80dfe12d45SEvan Bacon        if (entry.path.includes('node_modules') || !entry.stats.isFile()) {
81dfe12d45SEvan Bacon          return null;
82dfe12d45SEvan Bacon        }
83dfe12d45SEvan Bacon        return path.posix.relative(projectRoot, entry.path);
84dfe12d45SEvan Bacon      })
85dfe12d45SEvan Bacon      .filter(Boolean);
86dfe12d45SEvan Bacon
87dfe12d45SEvan Bacon    expect(files).toEqual([
88dfe12d45SEvan Bacon      'App.js',
89dfe12d45SEvan Bacon      'app.json',
90dfe12d45SEvan Bacon      'babel.config.js',
91dfe12d45SEvan Bacon      'package.json',
92dfe12d45SEvan Bacon      'web/index.html',
93dfe12d45SEvan Bacon      'web/serve.json',
94dfe12d45SEvan Bacon      'yarn.lock',
95dfe12d45SEvan Bacon    ]);
96dfe12d45SEvan Bacon  },
97dfe12d45SEvan Bacon  // Could take 45s depending on how fast npm installs
98dfe12d45SEvan Bacon  120 * 1000
99dfe12d45SEvan Bacon);
100*87669a95SMark Lawlor
101*87669a95SMark Lawlorit(
102*87669a95SMark Lawlor  'runs `npx expo customize tsconfig.json`',
103*87669a95SMark Lawlor  async () => {
104*87669a95SMark Lawlor    const projectRoot = await setupTestProjectAsync('expo-typescript', 'with-router', '48.0.0');
105*87669a95SMark Lawlor
106*87669a95SMark Lawlor    // `npx expo typescript
107*87669a95SMark Lawlor    await execa('node', [bin, 'customize', 'tsconfig.json'], {
108*87669a95SMark Lawlor      cwd: projectRoot,
109*87669a95SMark Lawlor      // env: { NODE_OPTIONS: '--inspect-brk' },
110*87669a95SMark Lawlor    });
111*87669a95SMark Lawlor
112*87669a95SMark Lawlor    // Expect them to exist with correct access controls
113*87669a95SMark Lawlor    for (const file of generatedFiles) {
114*87669a95SMark Lawlor      await expect(
115*87669a95SMark Lawlor        fs.promises.access(path.join(projectRoot, file), fsConstants.F_OK)
116*87669a95SMark Lawlor      ).resolves.toBeUndefined();
117*87669a95SMark Lawlor    }
118*87669a95SMark Lawlor  },
119*87669a95SMark Lawlor  // Could take 45s depending on how fast npm installs
120*87669a95SMark Lawlor  120 * 1000
121*87669a95SMark Lawlor);
122*87669a95SMark Lawlor
123*87669a95SMark Lawlorit(
124*87669a95SMark Lawlor  'runs `npx expo customize tsconfig.json` on a partially setup project',
125*87669a95SMark Lawlor  async () => {
126*87669a95SMark Lawlor    const projectRoot = await setupTestProjectAsync('expo-typescript', 'with-router', '48.0.0');
127*87669a95SMark Lawlor
128*87669a95SMark Lawlor    const existingTsConfig = {
129*87669a95SMark Lawlor      extends: 'custom-package',
130*87669a95SMark Lawlor      compilerOptions: {
131*87669a95SMark Lawlor        strict: true,
132*87669a95SMark Lawlor      },
133*87669a95SMark Lawlor      customOption: true,
134*87669a95SMark Lawlor      include: ['custom'],
135*87669a95SMark Lawlor    };
136*87669a95SMark Lawlor
137*87669a95SMark Lawlor    // Write a tsconfig with partial data
138*87669a95SMark Lawlor    await fs.promises.writeFile(
139*87669a95SMark Lawlor      path.join(projectRoot, 'tsconfig.json'),
140*87669a95SMark Lawlor      JSON.stringify(existingTsConfig)
141*87669a95SMark Lawlor    );
142*87669a95SMark Lawlor
143*87669a95SMark Lawlor    // `npx expo typescript
144*87669a95SMark Lawlor    const a = await execa('node', [bin, 'customize', 'tsconfig.json'], {
145*87669a95SMark Lawlor      cwd: projectRoot,
146*87669a95SMark Lawlor    });
147*87669a95SMark Lawlor
148*87669a95SMark Lawlor    const newTsconfig = await fs.promises.readFile(
149*87669a95SMark Lawlor      path.join(projectRoot, 'tsconfig.json'),
150*87669a95SMark Lawlor      'utf-8'
151*87669a95SMark Lawlor    );
152*87669a95SMark Lawlor
153*87669a95SMark Lawlor    expect(JSON.parse(newTsconfig)).toEqual({
154*87669a95SMark Lawlor      ...existingTsConfig,
155*87669a95SMark Lawlor      include: ['custom', '.expo/types/**/*.ts', 'expo-env.d.ts'],
156*87669a95SMark Lawlor    });
157*87669a95SMark Lawlor  },
158*87669a95SMark Lawlor  // Could take 45s depending on how fast npm installs
159*87669a95SMark Lawlor  120 * 1000
160*87669a95SMark Lawlor);
161