comparison hg-web/e2e/app_e2e_test.js @ 249:c5129452493e

[deploy] Bundle Mercurial with hg-web Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Tue, 04 Aug 2026 04:16:45 -0700
parents 70de0c80d093
children
comparison
equal deleted inserted replaced
248:b8b6e726964a 249:c5129452493e
6 const { chromium } = require('playwright-core'); 6 const { chromium } = require('playwright-core');
7 7
8 const BASE_URL = 'http://127.0.0.1:6970'; 8 const BASE_URL = 'http://127.0.0.1:6970';
9 const RUNFILES = process.env.JS_BINARY__RUNFILES; 9 const RUNFILES = process.env.JS_BINARY__RUNFILES;
10 const WORKSPACE = process.env.JS_BINARY__WORKSPACE; 10 const WORKSPACE = process.env.JS_BINARY__WORKSPACE;
11 let hgCommand = 'hg';
11 12
12 function run(command, args, options = {}) { 13 function run(command, args, options = {}) {
13 const result = spawnSync(command, args, { 14 const result = spawnSync(command, args, {
14 encoding: 'utf8', 15 encoding: 'utf8',
15 ...options, 16 ...options,
62 throw new Error(`Timed out waiting for ${url}\n${logs.join('')}`); 63 throw new Error(`Timed out waiting for ${url}\n${logs.join('')}`);
63 } 64 }
64 65
65 function createFixtureRepository(root) { 66 function createFixtureRepository(root) {
66 const options = { env: mercurialEnvironment(root) }; 67 const options = { env: mercurialEnvironment(root) };
67 run('hg', ['init', root], options); 68 run(hgCommand, ['init', root], options);
68 fs.mkdirSync(path.join(root, 'docs'), { recursive: true }); 69 fs.mkdirSync(path.join(root, 'docs'), { recursive: true });
69 fs.mkdirSync(path.join(root, 'src'), { recursive: true }); 70 fs.mkdirSync(path.join(root, 'src'), { recursive: true });
70 fs.writeFileSync( 71 fs.writeFileSync(
71 path.join(root, 'README.md'), 72 path.join(root, 'README.md'),
72 '# Fixture Repository\n\n<script>window.__hgWebXss = true</script>\n', 73 '# Fixture Repository\n\n<script>window.__hgWebXss = true</script>\n',
86 ); 87 );
87 fs.writeFileSync(path.join(root, 'movie.mp4'), Buffer.from('00000018667479706d703432', 'hex')); 88 fs.writeFileSync(path.join(root, 'movie.mp4'), Buffer.from('00000018667479706d703432', 'hex'));
88 fs.writeFileSync(path.join(root, 'sound.mp3'), Buffer.from('ID3')); 89 fs.writeFileSync(path.join(root, 'sound.mp3'), Buffer.from('ID3'));
89 fs.writeFileSync(path.join(root, 'document.pdf'), Buffer.from('%PDF-1.4\n%%EOF\n')); 90 fs.writeFileSync(path.join(root, 'document.pdf'), Buffer.from('%PDF-1.4\n%%EOF\n'));
90 fs.writeFileSync(path.join(root, 'archive.bin'), Buffer.from([0, 1, 2, 3])); 91 fs.writeFileSync(path.join(root, 'archive.bin'), Buffer.from([0, 1, 2, 3]));
91 run('hg', ['--repository', root, 'add'], options); 92 run(hgCommand, ['--repository', root, 'add'], options);
92 run('hg', ['--repository', root, 'commit', '-u', 'Test User <[email protected]>', '-m', 'Initial fixture'], options); 93 run(hgCommand, ['--repository', root, 'commit', '-u', 'Test User <[email protected]>', '-m', 'Initial fixture'], options);
93 const firstNode = run('hg', ['--repository', root, 'log', '-r', '.', '-T', '{node}'], options); 94 const firstNode = run(hgCommand, ['--repository', root, 'log', '-r', '.', '-T', '{node}'], options);
94 95
95 fs.writeFileSync( 96 fs.writeFileSync(
96 path.join(root, 'README.md'), 97 path.join(root, 'README.md'),
97 '# Updated Fixture Repository\n\n<script>window.__hgWebXss = true</script>\n\nSecond revision.\n', 98 '# Updated Fixture Repository\n\n<script>window.__hgWebXss = true</script>\n\nSecond revision.\n',
98 ); 99 );
99 fs.writeFileSync(path.join(root, 'new-file.txt'), 'new file\n'); 100 fs.writeFileSync(path.join(root, 'new-file.txt'), 'new file\n');
100 run('hg', ['add', 'new-file.txt'], { ...options, cwd: root }); 101 run(hgCommand, ['add', 'new-file.txt'], { ...options, cwd: root });
101 run('hg', ['--repository', root, 'commit', '-u', 'Test User <[email protected]>', '-m', 'Update fixture'], options); 102 run(hgCommand, ['--repository', root, 'commit', '-u', 'Test User <[email protected]>', '-m', 'Update fixture'], options);
102 const tipNode = run('hg', ['--repository', root, 'log', '-r', '.', '-T', '{node}'], options); 103 const tipNode = run(hgCommand, ['--repository', root, 'log', '-r', '.', '-T', '{node}'], options);
103 return { firstNode, tipNode }; 104 return { firstNode, tipNode };
104 } 105 }
105 106
106 async function assertJson(pathname, status = 200) { 107 async function assertJson(pathname, status = 200) {
107 const response = await fetch(`${BASE_URL}${pathname}`); 108 const response = await fetch(`${BASE_URL}${pathname}`);
145 let hgServer; 146 let hgServer;
146 let appServer; 147 let appServer;
147 let browser; 148 let browser;
148 149
149 try { 150 try {
150 const { firstNode, tipNode } = createFixtureRepository(fixtureRoot);
151 const runfilesWorkspace = path.join(RUNFILES, WORKSPACE); 151 const runfilesWorkspace = path.join(RUNFILES, WORKSPACE);
152 const serverBinary = path.join(runfilesWorkspace, 'hg-web', 'hg_web_server'); 152 const serverBinary = path.join(runfilesWorkspace, 'hg-web', 'hg_web_server');
153 hgCommand = path.join(
154 runfilesWorkspace,
155 'third_party',
156 'mercurial',
157 'runtime',
158 'bin',
159 'hg',
160 );
153 const chromiumPath = path.resolve(process.env.CHROMIUM_PATH); 161 const chromiumPath = path.resolve(process.env.CHROMIUM_PATH);
154 162
155 assert.ok(fs.existsSync(serverBinary), `missing server binary: ${serverBinary}`); 163 assert.ok(fs.existsSync(serverBinary), `missing server binary: ${serverBinary}`);
164 assert.ok(fs.existsSync(hgCommand), `missing bundled Mercurial: ${hgCommand}`);
156 assert.ok(fs.existsSync(chromiumPath), `missing Chromium binary: ${chromiumPath}`); 165 assert.ok(fs.existsSync(chromiumPath), `missing Chromium binary: ${chromiumPath}`);
166 const { firstNode, tipNode } = createFixtureRepository(fixtureRoot);
157 167
158 hgServer = spawn( 168 hgServer = spawn(
159 'hg', 169 hgCommand,
160 [ 170 [
161 '--repository', fixtureRoot, 171 '--repository', fixtureRoot,
162 'serve', 172 'serve',
163 '--address', '127.0.0.1', 173 '--address', '127.0.0.1',
164 '--port', '4444', 174 '--port', '4444',
258 assert.equal(response.status, 400, `${pathname} rejects invalid input`); 268 assert.equal(response.status, 400, `${pathname} rejects invalid input`);
259 } 269 }
260 assert.equal((await fetch(`${BASE_URL}/missing-route`)).status, 404); 270 assert.equal((await fetch(`${BASE_URL}/missing-route`)).status, 404);
261 271
262 const identify = run( 272 const identify = run(
263 'hg', 273 hgCommand,
264 ['identify', `${BASE_URL}/repo`], 274 ['identify', `${BASE_URL}/repo`],
265 { env: mercurialEnvironment(fixtureRoot) }, 275 { env: mercurialEnvironment(fixtureRoot) },
266 ); 276 );
267 assert.match(identify, new RegExp(`^${tipNode.slice(0, 12)}`)); 277 assert.match(identify, new RegExp(`^${tipNode.slice(0, 12)}`));
268 278