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( 26 `require('../../build/src/export/web').expoExportWeb` 27 ); 28 expect(modules).toStrictEqual([ 29 '../node_modules/ansi-styles/index.js', 30 '../node_modules/arg/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/web/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:web --help`', async () => { 43 const results = await execute('export:web', '--help'); 44 expect(results.stdout).toMatchInlineSnapshot(` 45 " 46 Info 47 Export the static files of the web app for hosting on a web server 48 49 Usage 50 $ npx expo export:web <dir> 51 52 Options 53 <dir> Directory of the Expo project. Default: Current working directory 54 --dev Bundle in development mode 55 -c, --clear Clear the bundler cache 56 -h, --help Usage info 57 " 58 `); 59}); 60 61it( 62 'runs `npx expo export:web`', 63 async () => { 64 const projectRoot = await setupTestProjectAsync('basic-export-web', 'with-web'); 65 // `npx expo export:web` 66 await execa('node', [bin, 'export:web'], { 67 cwd: projectRoot, 68 }); 69 70 const outputDir = path.join(projectRoot, 'web-build'); 71 // List output files with sizes for snapshotting. 72 // This is to make sure that any changes to the output are intentional. 73 // Posix path formatting is used to make paths the same across OSes. 74 const files = klawSync(outputDir) 75 .map((entry) => { 76 if (entry.path.includes('node_modules') || !entry.stats.isFile()) { 77 return null; 78 } 79 return path.posix.relative(outputDir, entry.path); 80 }) 81 .filter(Boolean); 82 83 expect(await JsonFile.readAsync(path.resolve(outputDir, 'asset-manifest.json'))).toEqual({ 84 entrypoints: [ 85 expect.stringMatching(/static\/js\/runtime~app\.[a-z\d]+\.js/), 86 expect.stringMatching(/static\/js\/\d\.[a-z\d]+\.chunk\.js/), 87 expect.stringMatching(/static\/js\/app\.[a-z\d]+\.chunk\.js/), 88 ], 89 files: { 90 'app.js': expect.stringMatching(/static\/js\/app\.[a-z\d]+\.chunk\.js/), 91 'app.js.map': expect.stringMatching(/static\/js\/app\.[a-z\d]+\.chunk\.js\.map/), 92 'index.html': '/index.html', 93 'manifest.json': '/manifest.json', 94 'runtime~app.js': expect.stringMatching(/static\/js\/runtime~app\.[a-z\d]+\.js/), 95 'runtime~app.js.map': expect.stringMatching(/static\/js\/runtime~app\.[a-z\d]+\.js\.map/), 96 'serve.json': '/serve.json', 97 'static/js/2.6566e185.chunk.js': expect.stringMatching( 98 /static\/js\/\d\.[a-z\d]+\.chunk\.js/ 99 ), 100 'static/js/2.6566e185.chunk.js.LICENSE.txt': expect.stringMatching( 101 /static\/js\/\d\.[a-z\d]+\.chunk\.js\.LICENSE\.txt/ 102 ), 103 'static/js/2.6566e185.chunk.js.map': expect.stringMatching( 104 /static\/js\/\d\.[a-z\d]+\.chunk\.js\.map/ 105 ), 106 }, 107 }); 108 expect(await JsonFile.readAsync(path.resolve(outputDir, 'manifest.json'))).toEqual({ 109 display: 'standalone', 110 lang: 'en', 111 name: 'basic-export-web', 112 prefer_related_applications: true, 113 related_applications: [ 114 { 115 id: 'com.example.minimal', 116 platform: 'itunes', 117 }, 118 { 119 id: 'com.example.minimal', 120 platform: 'play', 121 url: 'http://play.google.com/store/apps/details?id=com.example.minimal', 122 }, 123 ], 124 short_name: 'basic-export-web', 125 start_url: '/?utm_source=web_app_manifest', 126 }); 127 expect(await JsonFile.readAsync(path.resolve(outputDir, 'serve.json'))).toEqual({ 128 headers: [ 129 { 130 headers: [ 131 { 132 key: 'Cache-Control', 133 value: 'public, max-age=31536000, immutable', 134 }, 135 ], 136 source: 'static/**/*.js', 137 }, 138 ], 139 }); 140 141 // If this changes then everything else probably changed as well. 142 expect(files).toEqual([ 143 'asset-manifest.json', 144 'index.html', 145 'manifest.json', 146 'serve.json', 147 expect.stringMatching(/static\/js\/\d\.[a-z\d]+\.chunk\.js/), 148 expect.stringMatching(/static\/js\/\d\.[a-z\d]+\.chunk\.js\.LICENSE\.txt/), 149 expect.stringMatching(/static\/js\/\d\.[a-z\d]+\.chunk\.js\.map/), 150 expect.stringMatching(/static\/js\/app\.[a-z\d]+\.chunk\.js/), 151 expect.stringMatching(/static\/js\/app\.[a-z\d]+\.chunk\.js\.map/), 152 expect.stringMatching(/static\/js\/runtime~app\.[a-z\d]+\.js/), 153 expect.stringMatching(/static\/js\/runtime~app\.[a-z\d]+\.js\.map/), 154 ]); 155 }, 156 // Could take 45s depending on how fast npm installs 157 120 * 1000 158); 159