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