1/* eslint-env jest */
2import execa from 'execa';
3import fs from 'fs-extra';
4import klawSync from 'klaw-sync';
5import path from 'path';
6
7import { execute, projectRoot, getLoadedModulesAsync, bin } from './utils';
8
9const originalForceColor = process.env.FORCE_COLOR;
10const originalCI = process.env.CI;
11
12beforeAll(async () => {
13  await fs.mkdir(projectRoot, { recursive: true });
14  process.env.FORCE_COLOR = '0';
15  process.env.CI = '1';
16  process.env._EXPO_E2E_USE_PATH_ALIASES = '1';
17});
18
19afterAll(() => {
20  process.env.FORCE_COLOR = originalForceColor;
21  process.env.CI = originalCI;
22  delete process.env._EXPO_E2E_USE_PATH_ALIASES;
23});
24
25it('loads expected modules by default', async () => {
26  const modules = await getLoadedModulesAsync(
27    `require('../../build/src/export/embed').expoExportEmbed`
28  );
29  expect(modules).toStrictEqual([
30    '../node_modules/ansi-styles/index.js',
31    '../node_modules/arg/index.js',
32    '../node_modules/chalk/source/index.js',
33    '../node_modules/chalk/source/util.js',
34    '../node_modules/has-flag/index.js',
35    '../node_modules/supports-color/index.js',
36    '@expo/cli/build/src/export/embed/index.js',
37    '@expo/cli/build/src/log.js',
38    '@expo/cli/build/src/utils/args.js',
39  ]);
40});
41
42it('runs `npx expo export:embed --help`', async () => {
43  const results = await execute('export:embed', '--help');
44  expect(results.stdout).toMatchInlineSnapshot(`
45    "
46      Info
47        (Internal) Export the JavaScript bundle during a native build script for embedding in a native binary
48
49      Usage
50        $ npx expo export:embed <dir>
51
52      Options
53        <dir>                                  Directory of the Expo project. Default: Current working directory
54        --entry-file <path>                    Path to the root JS file, either absolute or relative to JS root
55        --platform <string>                    Either "ios" or "android" (default: "ios")
56        --transformer <string>                 Specify a custom transformer to be used
57        --dev [boolean]                        If false, warnings are disabled and the bundle is minified (default: true)
58        --minify [boolean]                     Allows overriding whether bundle is minified. This defaults to false if dev is true, and true if dev is false. Disabling minification can be useful for speeding up production builds for testing purposes.
59        --bundle-output <string>               File name where to store the resulting bundle, ex. /tmp/groups.bundle
60        --bundle-encoding <string>             Encoding the bundle should be written in (https://nodejs.org/api/buffer.html#buffer_buffer). (default: "utf8")
61        --max-workers <number>                 Specifies the maximum number of workers the worker-pool will spawn for transforming files. This defaults to the number of the cores available on your machine.
62        --sourcemap-output <string>            File name where to store the sourcemap file for resulting bundle, ex. /tmp/groups.map
63        --sourcemap-sources-root <string>      Path to make sourcemap's sources entries relative to, ex. /root/dir
64        --sourcemap-use-absolute-path          Report SourceMapURL using its full path
65        --assets-dest <string>                 Directory name where to store assets referenced in the bundle
66        --asset-catalog-dest <string>          Directory to create an iOS Asset Catalog for images
67        --unstable-transform-profile <string>  Experimental, transform JS for a specific JS engine. Currently supported: hermes, hermes-canary, default
68        --reset-cache                          Removes cached files
69        -v, --verbose                          Enables debug logging
70        --config <string>                      Path to the CLI configuration file
71        --read-global-cache                    Try to fetch transformed JS code from the global cache, if configured.
72        -h, --help                             Usage info
73    "
74  `);
75});
76
77function ensureTesterReady(fixtureName: string): string {
78  const root = path.join(__dirname, '../../../../../apps/router-e2e');
79  // Clear metro cache for the env var to be updated
80  // await fs.remove(path.join(root, "node_modules/.cache/metro"));
81
82  // @ts-ignore
83  process.env.E2E_ROUTER_SRC = fixtureName;
84
85  return root;
86}
87
88it(
89  'runs `npx expo export:embed`',
90  async () => {
91    const projectRoot = ensureTesterReady('static-rendering');
92    const output = 'dist-export-embed';
93    await fs.remove(path.join(projectRoot, output));
94    await fs.ensureDir(path.join(projectRoot, output));
95
96    await execa(
97      'node',
98      [
99        bin,
100        'export:embed',
101        '--entry-file',
102        path.join(projectRoot, './index.js'),
103        '--bundle-output',
104        `./${output}/output.js`,
105        '--assets-dest',
106        output,
107        '--platform',
108        'ios',
109        '--dev',
110        'false',
111      ],
112      {
113        cwd: projectRoot,
114        env: {
115          NODE_ENV: 'production',
116          EXPO_USE_STATIC: 'static',
117          E2E_ROUTER_SRC: 'static-rendering',
118          E2E_ROUTER_ASYNC: 'development',
119        },
120      }
121    );
122
123    const outputDir = path.join(projectRoot, 'dist-export-embed');
124    // List output files with sizes for snapshotting.
125    // This is to make sure that any changes to the output are intentional.
126    // Posix path formatting is used to make paths the same across OSes.
127    const files = klawSync(outputDir)
128      .map((entry) => {
129        if (entry.path.includes('node_modules') || !entry.stats.isFile()) {
130          return null;
131        }
132        return path.posix.relative(outputDir, entry.path);
133      })
134      .filter(Boolean);
135
136    // If this changes then everything else probably changed as well.
137    expect(files).toEqual([
138      'assets/__e2e__/static-rendering/sweet.ttf',
139      'assets/__packages/expo-router/assets/error.png',
140      'assets/__packages/expo-router/assets/file.png',
141      'assets/__packages/expo-router/assets/forward.png',
142      'assets/__packages/expo-router/assets/pkg.png',
143      'assets/assets/icon.png',
144      'output.js',
145    ]);
146  },
147  // Could take 45s depending on how fast npm installs
148  120 * 1000
149);
150