1/* eslint-env jest */ 2import JsonFile from '@expo/json-file'; 3import execa from 'execa'; 4import fs from 'fs-extra'; 5import klawSync from 'klaw-sync'; 6import path from 'path'; 7 8import { execute, projectRoot, getLoadedModulesAsync, setupTestProjectAsync, bin } from './utils'; 9 10const originalForceColor = process.env.FORCE_COLOR; 11const originalCI = process.env.CI; 12 13beforeAll(async () => { 14 await fs.mkdir(projectRoot, { recursive: true }); 15 process.env.FORCE_COLOR = '0'; 16 process.env.CI = '1'; 17}); 18 19afterAll(() => { 20 process.env.FORCE_COLOR = originalForceColor; 21 process.env.CI = originalCI; 22}); 23 24it('loads expected modules by default', async () => { 25 const modules = await getLoadedModulesAsync(`require('../../build/src/export').expoExport`); 26 expect(modules).toStrictEqual([ 27 '../node_modules/ansi-styles/index.js', 28 '../node_modules/arg/index.js', 29 '../node_modules/chalk/source/index.js', 30 '../node_modules/chalk/source/util.js', 31 '../node_modules/has-flag/index.js', 32 '../node_modules/supports-color/index.js', 33 '@expo/cli/build/src/export/index.js', 34 '@expo/cli/build/src/log.js', 35 '@expo/cli/build/src/utils/args.js', 36 '@expo/cli/build/src/utils/errors.js', 37 ]); 38}); 39 40it('runs `npx expo export --help`', async () => { 41 const results = await execute('export', '--help'); 42 expect(results.stdout).toMatchInlineSnapshot(` 43 " 44 Info 45 Export the static files of the app for hosting it on a web server 46 47 Usage 48 $ npx expo export <dir> 49 50 Options 51 <dir> Directory of the Expo project. Default: Current working directory 52 --platform <all|android|ios> Platforms: android, ios, all. Default: all 53 --dev Configure static files for developing locally using a non-https server 54 --output-dir <dir> The directory to export the static files to. Default: dist 55 --max-workers <number> Maximum number of tasks to allow the bundler to spawn 56 --dump-assetmap Dump the asset map for further processing 57 --dump-sourcemap Dump the source map for debugging the JS bundle 58 -c, --clear Clear the bundler cache 59 -h, --help Usage info 60 " 61 `); 62}); 63 64it( 65 'runs `npx expo export`', 66 async () => { 67 const projectRoot = await setupTestProjectAsync('basic-export', 'with-assets'); 68 // `npx expo export` 69 await execa('node', [bin, 'export', '--dump-sourcemap', '--dump-assetmap'], { 70 cwd: projectRoot, 71 }); 72 73 const outputDir = path.join(projectRoot, 'dist'); 74 // List output files with sizes for snapshotting. 75 // This is to make sure that any changes to the output are intentional. 76 // Posix path formatting is used to make paths the same across OSes. 77 const files = klawSync(outputDir) 78 .map((entry) => { 79 if (entry.path.includes('node_modules') || !entry.stats.isFile()) { 80 return null; 81 } 82 return path.posix.relative(outputDir, entry.path); 83 }) 84 .filter(Boolean); 85 86 const metadata = await JsonFile.readAsync(path.resolve(outputDir, 'metadata.json')); 87 88 expect(metadata).toEqual({ 89 bundler: 'metro', 90 fileMetadata: { 91 android: { 92 assets: [ 93 { 94 ext: 'png', 95 path: 'assets/fb960eb5e4eb49ec8786c7f6c4a57ce2', 96 }, 97 { 98 ext: 'png', 99 path: 'assets/9ce7db807e4147e00df372d053c154c2', 100 }, 101 { 102 ext: 'ttf', 103 path: 'assets/3858f62230ac3c915f300c664312c63f', 104 }, 105 ], 106 bundle: expect.stringMatching(/bundles\/android-.*\.js/), 107 }, 108 ios: { 109 assets: [ 110 { 111 ext: 'png', 112 path: 'assets/fb960eb5e4eb49ec8786c7f6c4a57ce2', 113 }, 114 { 115 ext: 'png', 116 path: 'assets/9ce7db807e4147e00df372d053c154c2', 117 }, 118 { 119 ext: 'ttf', 120 path: 'assets/2f334f6c7ca5b2a504bdf8acdee104f3', 121 }, 122 ], 123 bundle: expect.stringMatching(/bundles\/ios-.*\.js/), 124 }, 125 }, 126 version: 0, 127 }); 128 129 const assetmap = await JsonFile.readAsync(path.resolve(outputDir, 'assetmap.json')); 130 expect(assetmap).toEqual({ 131 '2f334f6c7ca5b2a504bdf8acdee104f3': { 132 __packager_asset: true, 133 fileHashes: ['2f334f6c7ca5b2a504bdf8acdee104f3'], 134 fileSystemLocation: expect.stringMatching(/\/.*\/basic-export\/assets/), 135 files: [expect.stringMatching(/\/.*\/basic-export\/assets\/font\.ios\.ttf/)], 136 hash: '2f334f6c7ca5b2a504bdf8acdee104f3', 137 httpServerLocation: '/assets/assets', 138 name: 'font', 139 scales: [1], 140 type: 'ttf', 141 }, 142 143 '3858f62230ac3c915f300c664312c63f': { 144 __packager_asset: true, 145 fileHashes: ['3858f62230ac3c915f300c664312c63f'], 146 fileSystemLocation: expect.stringMatching(/\/.*\/basic-export\/assets/), 147 files: [expect.stringMatching(/\/.*\/basic-export\/assets\/font\.ttf/)], 148 hash: '3858f62230ac3c915f300c664312c63f', 149 httpServerLocation: '/assets/assets', 150 name: 'font', 151 scales: [1], 152 type: 'ttf', 153 }, 154 d48d481475a80809fcf9253a765193d1: { 155 __packager_asset: true, 156 fileHashes: ['fb960eb5e4eb49ec8786c7f6c4a57ce2', '9ce7db807e4147e00df372d053c154c2'], 157 fileSystemLocation: expect.stringMatching(/\/.*\/basic-export\/assets/), 158 files: [ 159 expect.stringMatching(/\/.*\/basic-export\/assets\/icon\.png/), 160 expect.stringMatching(/\/.*\/basic-export\/assets\/icon@2x\.png/), 161 ], 162 hash: 'd48d481475a80809fcf9253a765193d1', 163 height: 1, 164 httpServerLocation: '/assets/assets', 165 name: 'icon', 166 scales: [1, 2], 167 type: 'png', 168 width: 1, 169 }, 170 }); 171 172 // If this changes then everything else probably changed as well. 173 expect(files).toEqual([ 174 'assetmap.json', 175 'assets/2f334f6c7ca5b2a504bdf8acdee104f3', 176 'assets/3858f62230ac3c915f300c664312c63f', 177 'assets/9ce7db807e4147e00df372d053c154c2', 178 'assets/fb960eb5e4eb49ec8786c7f6c4a57ce2', 179 expect.stringMatching(/bundles\/android-[\w\d]+\.js/), 180 expect.stringMatching(/bundles\/android-[\w\d]+\.map/), 181 expect.stringMatching(/bundles\/ios-[\w\d]+\.js/), 182 expect.stringMatching(/bundles\/ios-[\w\d]+\.map/), 183 'debug.html', 184 'metadata.json', 185 ]); 186 }, 187 // Could take 45s depending on how fast npm installs 188 120 * 1000 189); 190