/* eslint-env jest */ import JsonFile from '@expo/json-file'; import execa from 'execa'; import fs from 'fs-extra'; import klawSync from 'klaw-sync'; import path from 'path'; import { execute, projectRoot, getLoadedModulesAsync, setupTestProjectAsync, bin, ensurePortFreeAsync, } from './utils'; const originalForceColor = process.env.FORCE_COLOR; const originalCI = process.env.CI; beforeAll(async () => { await fs.mkdir(projectRoot, { recursive: true }); process.env.FORCE_COLOR = '0'; process.env.CI = '1'; process.env._EXPO_E2E_USE_PATH_ALIASES = '1'; delete process.env.EXPO_WEB_OUTPUT_MODE; }); afterAll(() => { process.env.FORCE_COLOR = originalForceColor; process.env.CI = originalCI; delete process.env._EXPO_E2E_USE_PATH_ALIASES; }); it('loads expected modules by default', async () => { const modules = await getLoadedModulesAsync(`require('../../build/src/export').expoExport`); expect(modules).toStrictEqual([ '../node_modules/ansi-styles/index.js', '../node_modules/arg/index.js', '../node_modules/chalk/source/index.js', '../node_modules/chalk/source/util.js', '../node_modules/has-flag/index.js', '../node_modules/supports-color/index.js', '@expo/cli/build/src/export/index.js', '@expo/cli/build/src/log.js', '@expo/cli/build/src/utils/args.js', '@expo/cli/build/src/utils/errors.js', ]); }); it('runs `npx expo export --help`', async () => { const results = await execute('export', '--help'); expect(results.stdout).toMatchInlineSnapshot(` " Info Export the static files of the app for hosting it on a web server Usage $ npx expo export Options Directory of the Expo project. Default: Current working directory --dev Configure static files for developing locally using a non-https server --output-dir The directory to export the static files to. Default: dist --max-workers Maximum number of tasks to allow the bundler to spawn --dump-assetmap Dump the asset map for further processing --dump-sourcemap Dump the source map for debugging the JS bundle -p, --platform Options: android, ios, web, all. Default: all --no-minify Prevent minifying source -c, --clear Clear the bundler cache -h, --help Usage info " `); }); describe('server', () => { beforeEach(() => ensurePortFreeAsync(8081)); it( 'runs `npx expo export`', async () => { const projectRoot = await setupTestProjectAsync('basic-export', 'with-assets'); // `npx expo export` await execa('node', [bin, 'export', '--dump-sourcemap', '--dump-assetmap'], { cwd: projectRoot, }); const outputDir = path.join(projectRoot, 'dist'); // List output files with sizes for snapshotting. // This is to make sure that any changes to the output are intentional. // Posix path formatting is used to make paths the same across OSes. const files = klawSync(outputDir) .map((entry) => { if (entry.path.includes('node_modules') || !entry.stats.isFile()) { return null; } return path.posix.relative(outputDir, entry.path); }) .filter(Boolean); const metadata = await JsonFile.readAsync(path.resolve(outputDir, 'metadata.json')); expect(metadata).toEqual({ bundler: 'metro', fileMetadata: { android: { assets: [ { ext: 'png', path: 'assets/fb960eb5e4eb49ec8786c7f6c4a57ce2', }, { ext: 'png', path: 'assets/9ce7db807e4147e00df372d053c154c2', }, { ext: 'ttf', path: 'assets/3858f62230ac3c915f300c664312c63f', }, ], bundle: expect.stringMatching(/bundles\/android-.*\.hbc/), }, ios: { assets: [ { ext: 'png', path: 'assets/fb960eb5e4eb49ec8786c7f6c4a57ce2', }, { ext: 'png', path: 'assets/9ce7db807e4147e00df372d053c154c2', }, { ext: 'ttf', path: 'assets/2f334f6c7ca5b2a504bdf8acdee104f3', }, ], bundle: expect.stringMatching(/bundles\/ios-.*\.hbc/), }, }, version: 0, }); const assetmap = await JsonFile.readAsync(path.resolve(outputDir, 'assetmap.json')); expect(assetmap).toEqual({ '2f334f6c7ca5b2a504bdf8acdee104f3': { __packager_asset: true, fileHashes: ['2f334f6c7ca5b2a504bdf8acdee104f3'], fileSystemLocation: expect.stringMatching(/\/.*\/basic-export\/assets/), files: [expect.stringMatching(/\/.*\/basic-export\/assets\/font\.ios\.ttf/)], hash: '2f334f6c7ca5b2a504bdf8acdee104f3', httpServerLocation: '/assets/assets', name: 'font', scales: [1], type: 'ttf', }, '3858f62230ac3c915f300c664312c63f': { __packager_asset: true, fileHashes: ['3858f62230ac3c915f300c664312c63f'], fileSystemLocation: expect.stringMatching(/\/.*\/basic-export\/assets/), files: [expect.stringMatching(/\/.*\/basic-export\/assets\/font\.ttf/)], hash: '3858f62230ac3c915f300c664312c63f', httpServerLocation: '/assets/assets', name: 'font', scales: [1], type: 'ttf', }, d48d481475a80809fcf9253a765193d1: { __packager_asset: true, fileHashes: ['fb960eb5e4eb49ec8786c7f6c4a57ce2', '9ce7db807e4147e00df372d053c154c2'], fileSystemLocation: expect.stringMatching(/\/.*\/basic-export\/assets/), files: [ expect.stringMatching(/\/.*\/basic-export\/assets\/icon\.png/), expect.stringMatching(/\/.*\/basic-export\/assets\/icon@2x\.png/), ], hash: 'd48d481475a80809fcf9253a765193d1', height: 1, httpServerLocation: '/assets/assets', name: 'icon', scales: [1, 2], type: 'png', width: 1, }, }); // If this changes then everything else probably changed as well. expect(files).toEqual([ 'assetmap.json', 'assets/2f334f6c7ca5b2a504bdf8acdee104f3', 'assets/3858f62230ac3c915f300c664312c63f', 'assets/9ce7db807e4147e00df372d053c154c2', 'assets/assets/font.ttf', 'assets/assets/icon.png', 'assets/assets/icon@2x.png', 'assets/fb960eb5e4eb49ec8786c7f6c4a57ce2', expect.stringMatching(/bundles\/android-[\w\d]+\.hbc/), expect.stringMatching(/bundles\/android-[\w\d]+\.map/), expect.stringMatching(/bundles\/ios-[\w\d]+\.hbc/), expect.stringMatching(/bundles\/ios-[\w\d]+\.map/), expect.stringMatching(/bundles\/web-[\w\d]+\.js/), expect.stringMatching(/bundles\/web-[\w\d]+\.map/), 'debug.html', 'favicon.ico', 'index.html', 'metadata.json', ]); }, // Could take 45s depending on how fast npm installs 120 * 1000 ); });