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