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