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