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