/* eslint-env jest */
import JsonFile from '@expo/json-file';
import assert from 'assert';
import execa from 'execa';
import fs from 'fs-extra';
import klawSync from 'klaw-sync';
import path from 'path';
import { execute, projectRoot, getLoadedModulesAsync, setupTestProjectAsync, bin } 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';
});
afterAll(() => {
process.env.FORCE_COLOR = originalForceColor;
process.env.CI = originalCI;
});
it('loads expected modules by default', async () => {
const modules = await getLoadedModulesAsync(
`require('../../build/src/export/web').expoExportWeb`
);
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/web/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:web --help`', async () => {
const results = await execute('export:web', '--help');
expect(results.stdout).toMatchInlineSnapshot(`
"
Info
Export the static files of the web app for hosting on a web server
Usage
$ npx expo export:web
Options
Directory of the Expo project. Default: Current working directory
--dev Bundle in development mode
-c, --clear Clear the bundler cache
-h, --help Usage info
"
`);
});
it(
'runs `npx expo export:web`',
async () => {
const projectRoot = await setupTestProjectAsync('basic-export-web', 'with-web');
// `npx expo export:web`
await execa('node', [bin, 'export:web'], {
cwd: projectRoot,
});
const outputDir = path.join(projectRoot, 'web-build');
// 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 assetsManifest = await JsonFile.readAsync(path.resolve(outputDir, 'asset-manifest.json'));
expect(assetsManifest.entrypoints).toEqual([
expect.stringMatching(/static\/js\/\d+\.[a-z\d]+\.js/),
expect.stringMatching(/static\/js\/main\.[a-z\d]+\.js/),
]);
const knownFiles = [
['main.js', expect.stringMatching(/static\/js\/main\.[a-z\d]+\.js/)],
['index.html', '/index.html'],
['manifest.json', '/manifest.json'],
['serve.json', '/serve.json'],
];
assert(assetsManifest.files);
console.log(assetsManifest.files);
for (const [key, value] of knownFiles) {
const files = assetsManifest.files as Record;
expect(files[key]).toEqual(value);
delete files[key];
}
for (const [key, value] of Object.entries(assetsManifest?.files ?? {})) {
expect(key).toMatch(/(static\/js\/)?(\d+|main)\.[a-z\d]+\.js(\.LICENSE\.txt|\.map)?/);
expect(value).toMatch(/(static\/js\/)?(\d+|main)\.[a-z\d]+\.js(\.LICENSE\.txt|\.map)?/);
}
expect(await JsonFile.readAsync(path.resolve(outputDir, 'manifest.json'))).toEqual({
display: 'standalone',
lang: 'en',
name: 'basic-export-web',
prefer_related_applications: true,
related_applications: [
{
id: 'com.example.minimal',
platform: 'itunes',
},
{
id: 'com.example.minimal',
platform: 'play',
url: 'http://play.google.com/store/apps/details?id=com.example.minimal',
},
],
short_name: 'basic-export-web',
start_url: '/?utm_source=web_app_manifest',
});
expect(await JsonFile.readAsync(path.resolve(outputDir, 'serve.json'))).toEqual({
headers: [
{
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable',
},
],
source: 'static/**/*.js',
},
],
});
// If this changes then everything else probably changed as well.
expect(files).toEqual([
'asset-manifest.json',
'index.html',
'manifest.json',
'serve.json',
expect.stringMatching(/static\/js\/\d+\.[a-z\d]+\.js/),
expect.stringMatching(/static\/js\/\d+\.[a-z\d]+\.js\.LICENSE\.txt/),
expect.stringMatching(/static\/js\/\d+\.[a-z\d]+\.js\.map/),
expect.stringMatching(/static\/js\/main\.[a-z\d]+\.js/),
expect.stringMatching(/static\/js\/main\.[a-z\d]+\.js\.map/),
]);
},
// Could take 45s depending on how fast npm installs
120 * 1000
);