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 --dev Configure static files for developing locally using a non-https server 53 --output-dir <dir> The directory to export the static files to. Default: dist 54 --max-workers <number> Maximum number of tasks to allow the bundler to spawn 55 --dump-assetmap Dump the asset map for further processing 56 --dump-sourcemap Dump the source map for debugging the JS bundle 57 -p, --platform <platform> Options: android, ios, web, all. Default: all 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 web: { 126 assets: [ 127 { 128 ext: 'png', 129 path: 'assets/fb960eb5e4eb49ec8786c7f6c4a57ce2', 130 }, 131 { 132 ext: 'png', 133 path: 'assets/9ce7db807e4147e00df372d053c154c2', 134 }, 135 { 136 ext: 'ttf', 137 path: 'assets/3858f62230ac3c915f300c664312c63f', 138 }, 139 ], 140 bundle: expect.stringMatching(/bundles\/web-.*\.js/), 141 }, 142 }, 143 version: 0, 144 }); 145 146 const assetmap = await JsonFile.readAsync(path.resolve(outputDir, 'assetmap.json')); 147 expect(assetmap).toEqual({ 148 '2f334f6c7ca5b2a504bdf8acdee104f3': { 149 __packager_asset: true, 150 fileHashes: ['2f334f6c7ca5b2a504bdf8acdee104f3'], 151 fileSystemLocation: expect.stringMatching(/\/.*\/basic-export\/assets/), 152 files: [expect.stringMatching(/\/.*\/basic-export\/assets\/font\.ios\.ttf/)], 153 hash: '2f334f6c7ca5b2a504bdf8acdee104f3', 154 httpServerLocation: '/assets/assets', 155 name: 'font', 156 scales: [1], 157 type: 'ttf', 158 }, 159 160 '3858f62230ac3c915f300c664312c63f': { 161 __packager_asset: true, 162 fileHashes: ['3858f62230ac3c915f300c664312c63f'], 163 fileSystemLocation: expect.stringMatching(/\/.*\/basic-export\/assets/), 164 files: [expect.stringMatching(/\/.*\/basic-export\/assets\/font\.ttf/)], 165 hash: '3858f62230ac3c915f300c664312c63f', 166 httpServerLocation: '/assets/assets', 167 name: 'font', 168 scales: [1], 169 type: 'ttf', 170 }, 171 d48d481475a80809fcf9253a765193d1: { 172 __packager_asset: true, 173 fileHashes: ['fb960eb5e4eb49ec8786c7f6c4a57ce2', '9ce7db807e4147e00df372d053c154c2'], 174 fileSystemLocation: expect.stringMatching(/\/.*\/basic-export\/assets/), 175 files: [ 176 expect.stringMatching(/\/.*\/basic-export\/assets\/icon\.png/), 177 expect.stringMatching(/\/.*\/basic-export\/assets\/icon@2x\.png/), 178 ], 179 hash: 'd48d481475a80809fcf9253a765193d1', 180 height: 1, 181 httpServerLocation: '/assets/assets', 182 name: 'icon', 183 scales: [1, 2], 184 type: 'png', 185 width: 1, 186 }, 187 }); 188 189 // If this changes then everything else probably changed as well. 190 expect(files).toEqual([ 191 'assetmap.json', 192 'assets/2f334f6c7ca5b2a504bdf8acdee104f3', 193 'assets/3858f62230ac3c915f300c664312c63f', 194 'assets/9ce7db807e4147e00df372d053c154c2', 195 'assets/assets/font.ttf', 196 'assets/assets/icon.png', 197 'assets/assets/icon@2x.png', 198 199 'assets/fb960eb5e4eb49ec8786c7f6c4a57ce2', 200 expect.stringMatching(/bundles\/android-[\w\d]+\.js/), 201 expect.stringMatching(/bundles\/android-[\w\d]+\.map/), 202 expect.stringMatching(/bundles\/ios-[\w\d]+\.js/), 203 expect.stringMatching(/bundles\/ios-[\w\d]+\.map/), 204 expect.stringMatching(/bundles\/web-[\w\d]+\.js/), 205 expect.stringMatching(/bundles\/web-[\w\d]+\.map/), 206 'debug.html', 207 'drawable-mdpi/assets_icon.png', 208 'drawable-xhdpi/assets_icon.png', 209 'favicon.ico', 210 'index.html', 211 'metadata.json', 212 'raw/assets_font.ttf', 213 ]); 214 }, 215 // Could take 45s depending on how fast npm installs 216 120 * 1000 217); 218