1import { vol } from 'memfs';
2import path from 'path';
3
4import {
5  writeAssetMapAsync,
6  writeBundlesAsync,
7  writeDebugHtmlAsync,
8  writeSourceMapsAsync,
9} from '../writeContents';
10
11describe(writeDebugHtmlAsync, () => {
12  afterEach(() => {
13    vol.reset();
14  });
15
16  it(`creates a debug html file`, async () => {
17    const projectRoot = '/';
18    await writeDebugHtmlAsync({
19      outputDir: projectRoot,
20      fileNames: { ios: 'index.ios.js', android: 'index.android.js', windows: 'index.windows.js' },
21    });
22    expect(vol.readFileSync(path.join(projectRoot, 'debug.html'), 'utf8')).toMatchSnapshot();
23  });
24});
25
26describe(writeBundlesAsync, () => {
27  afterEach(() => {
28    vol.reset();
29  });
30  it(`writes JS bundles to disk`, async () => {
31    const projectRoot = '/';
32
33    const contents = `var foo = true;`;
34    const results = await writeBundlesAsync({
35      outputDir: projectRoot,
36      bundles: {
37        ios: {
38          code: contents,
39        },
40        android: {
41          code: contents,
42        },
43      },
44    });
45
46    expect(results.fileNames.android).toBeDefined();
47
48    expect(results.fileNames.ios).toBe('ios-4fe3891dcaca43901bd8797db78405e4.js');
49    expect(results.hashes).toStrictEqual({
50      ios: expect.any(String),
51      android: expect.any(String),
52    });
53    expect(vol.readFileSync(path.join(projectRoot, results.fileNames.ios), 'utf8')).toBe(contents);
54  });
55  it(`writes hbc bundles to disk`, async () => {
56    const projectRoot = '/';
57    const contents = Uint8Array.from([1, 2, 3]);
58    const results = await writeBundlesAsync({
59      outputDir: projectRoot,
60      bundles: {
61        ios: {
62          // this overwrites js code if present
63          hermesBytecodeBundle: contents,
64          code: 'var foo = true;',
65        },
66      },
67    });
68
69    expect(results.fileNames.ios).toBe('ios-5289df737df57326fcdd22597afb1fac.js');
70    expect(results.hashes).toStrictEqual({
71      ios: expect.any(String),
72    });
73    expect(vol.readFileSync(path.join(projectRoot, results.fileNames.ios))).toBeDefined();
74  });
75});
76
77describe(writeAssetMapAsync, () => {
78  afterEach(() => {
79    vol.reset();
80  });
81  it(`writes asset map to disk`, async () => {
82    const projectRoot = '/';
83
84    const results = await writeAssetMapAsync({
85      outputDir: projectRoot,
86      assets: [{ hash: 'alpha' }, { hash: 'beta' }] as any,
87    });
88
89    expect(results).toStrictEqual({
90      alpha: { hash: 'alpha' },
91      beta: { hash: 'beta' },
92    });
93
94    expect(
95      JSON.parse(vol.readFileSync(path.join(projectRoot, 'assetmap.json'), 'utf8') as string)
96    ).toBeDefined();
97  });
98});
99
100describe(writeSourceMapsAsync, () => {
101  afterEach(() => {
102    vol.reset();
103  });
104
105  it(`writes source maps to disk`, async () => {
106    const projectRoot = '/';
107
108    // User wrote this
109    const contents = `var foo = true;\ninvalid-source-map-comment`;
110
111    // Metro made this
112    const bundles = {
113      ios: {
114        code: contents,
115        map: 'ios_map',
116      },
117      android: {
118        code: contents,
119        map: 'android_map',
120      },
121    };
122
123    // Expo persists the code and returns info
124    const jsResults = await writeBundlesAsync({
125      outputDir: projectRoot,
126      bundles,
127    });
128
129    // Expo also modifies the source maps and persists
130    const results = await writeSourceMapsAsync({
131      outputDir: projectRoot,
132      hashes: jsResults.hashes,
133      fileNames: jsResults.fileNames,
134      bundles,
135    });
136
137    for (const item of results) {
138      expect(vol.readFileSync(path.join(projectRoot, item.fileName), 'utf8')).toBe(item.map);
139      expect(
140        vol.readFileSync(path.join(projectRoot, `${item.platform}-${item.hash}.js`), 'utf8')
141      ).toMatch(/\/\/# sourceMappingURL=/);
142      // // Removed by `removeOriginalSourceMappingUrl`
143      // expect(
144      //   vol.readFileSync(path.join(projectRoot, `${item.platform}-${item.hash}.js`), 'utf8')
145      // ).not.toMatch(/invalid-source-map-comment/);
146    }
147  });
148});
149