1/* eslint-env jest */ 2import execa from 'execa'; 3import fs from 'fs-extra'; 4import klawSync from 'klaw-sync'; 5import path from 'path'; 6 7import { runExportSideEffects } from './export-side-effects'; 8import { bin, getPageHtml, getRouterE2ERoot } from '../utils'; 9 10runExportSideEffects(); 11 12describe('static-rendering with a custom base path', () => { 13 const projectRoot = getRouterE2ERoot(); 14 const outputName = 'dist-static-rendering-asset-prefix'; 15 const outputDir = path.join(projectRoot, outputName); 16 17 beforeAll( 18 async () => { 19 const basePath = '/one/two'; 20 process.env.EXPO_E2E_BASE_PATH = basePath; 21 await execa('node', [bin, 'export', '-p', 'web', '--clear', '--output-dir', outputName], { 22 cwd: projectRoot, 23 env: { 24 NODE_ENV: 'production', 25 EXPO_E2E_BASE_PATH: basePath, 26 EXPO_USE_STATIC: 'static', 27 E2E_ROUTER_SRC: 'static-rendering', 28 E2E_ROUTER_ASYNC: 'development', 29 }, 30 }); 31 }, 32 // Could take 45s depending on how fast the bundler resolves 33 560 * 1000 34 ); 35 36 it( 37 'has expected files', 38 async () => { 39 // List output files with sizes for snapshotting. 40 // This is to make sure that any changes to the output are intentional. 41 // Posix path formatting is used to make paths the same across OSes. 42 const files = klawSync(outputDir) 43 .map((entry) => { 44 if (entry.path.includes('node_modules') || !entry.stats.isFile()) { 45 return null; 46 } 47 return path.posix.relative(outputDir, entry.path); 48 }) 49 .filter(Boolean); 50 51 expect( 52 files.find((file) => file?.match(/\_expo\/static\/js\/web\/index-.*\.js/)) 53 ).toBeDefined(); 54 55 // The wrapper should not be included as a route. 56 expect(files).not.toContain('+html.html'); 57 expect(files).not.toContain('_layout.html'); 58 59 // Injected by framework 60 expect(files).toContain('_sitemap.html'); 61 expect(files).toContain('[...404].html'); 62 63 // Normal routes 64 expect(files).toContain('about.html'); 65 expect(files).toContain('index.html'); 66 expect(files).toContain('styled.html'); 67 expect(files).toContain('links.html'); 68 69 // generateStaticParams values 70 expect(files).toContain('[post].html'); 71 expect(files).toContain('welcome-to-the-universe.html'); 72 expect(files).toContain('other.html'); 73 }, 74 5 * 1000 75 ); 76 77 it( 78 'writes assets with prefix', 79 async () => { 80 const indexHtml = await getPageHtml(outputDir, 'index.html'); 81 82 const jsFiles = indexHtml.querySelectorAll('script').map((script) => script.attributes.src); 83 expect(jsFiles).toEqual([ 84 expect.stringMatching(/\/one\/two\/_expo\/static\/js\/web\/index-.*\.js/), 85 ]); 86 87 const links = indexHtml.querySelectorAll('html > head > link').filter((link) => { 88 // Fonts are tested elsewhere 89 return link.attributes.as !== 'font'; 90 }); 91 92 const cssFiles = links.map((link) => link.attributes.href); 93 94 cssFiles.forEach((src) => { 95 // Linked to the expected static location 96 expect(src).toMatch(/^\/one\/two\/_expo\/static\/css\/.*\.css$/); 97 }); 98 99 const fontLinks = indexHtml.querySelectorAll('html > head > link[as="font"]'); 100 101 const fontFiles = fontLinks.map((link) => link.attributes.href); 102 103 fontFiles.forEach((src) => { 104 // Linked to the expected static location 105 expect(src).toMatch(/^\/one\/two\/assets\/.*\.ttf/); 106 }); 107 108 for (const file of [...cssFiles, ...jsFiles]) { 109 expect( 110 fs.existsSync( 111 path.join( 112 outputDir, 113 // If we strip the asset prefix, the file should exist. 114 file.replace(/^\/one\/two/, '') 115 ) 116 ) 117 ).toBe(true); 118 } 119 }, 120 5 * 1000 121 ); 122 123 it( 124 'supports usePathname in +html files', 125 async () => { 126 const page = await fs.readFile(path.join(outputDir, 'index.html'), 'utf8'); 127 128 expect(page).toContain('<meta name="custom-value" content="value"/>'); 129 130 // Root element 131 expect(page).toContain('<div id="root">'); 132 133 expect( 134 (await getPageHtml(outputDir, 'about.html')).querySelector( 135 'html > head > meta[name="expo-e2e-pathname"]' 136 )?.attributes.content 137 ).toBe('/about'); 138 139 expect( 140 (await getPageHtml(outputDir, 'index.html')).querySelector( 141 'html > head > meta[name="expo-e2e-pathname"]' 142 )?.attributes.content 143 ).toBe('/'); 144 145 expect( 146 (await getPageHtml(outputDir, 'welcome-to-the-universe.html')).querySelector( 147 'html > head > meta[name="expo-e2e-pathname"]' 148 )?.attributes.content 149 ).toBe('/welcome-to-the-universe'); 150 }, 151 5 * 1000 152 ); 153 154 it( 155 'supports basePath in Links', 156 async () => { 157 expect( 158 (await getPageHtml(outputDir, 'links.html')).querySelector( 159 'body > #root a[data-testid="links-one"]' 160 )?.attributes.href 161 ).toBe('/one/two/about'); 162 }, 163 5 * 1000 164 ); 165}); 166