Mercurial
comparison hg-web/e2e/app_e2e_test.js @ 225:70de0c80d093 hg-web
[hg-web] Add side-by-side changeset diffs
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Sun, 02 Aug 2026 14:41:09 -0700 |
| parents | 3007ef5fc0ed |
| children | c5129452493e |
comparison
equal
deleted
inserted
replaced
| 224:3007ef5fc0ed | 225:70de0c80d093 |
|---|---|
| 71 path.join(root, 'README.md'), | 71 path.join(root, 'README.md'), |
| 72 '# Fixture Repository\n\n<script>window.__hgWebXss = true</script>\n', | 72 '# Fixture Repository\n\n<script>window.__hgWebXss = true</script>\n', |
| 73 ); | 73 ); |
| 74 fs.writeFileSync(path.join(root, 'docs', 'README.md'), '# Documentation\n\nNested README.\n'); | 74 fs.writeFileSync(path.join(root, 'docs', 'README.md'), '# Documentation\n\nNested README.\n'); |
| 75 fs.writeFileSync(path.join(root, 'src', 'main.c'), 'int main(void) { return 0; }\n'); | 75 fs.writeFileSync(path.join(root, 'src', 'main.c'), 'int main(void) { return 0; }\n'); |
| 76 fs.writeFileSync( | |
| 77 path.join(root, 'BUILD'), | |
| 78 'cc_library(\n name = "fixture",\n srcs = ["src/main.c"],\n)\n', | |
| 79 ); | |
| 76 fs.writeFileSync( | 80 fs.writeFileSync( |
| 77 path.join(root, 'pixel.png'), | 81 path.join(root, 'pixel.png'), |
| 78 Buffer.from( | 82 Buffer.from( |
| 79 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAusB9Wl2nWQAAAAASUVORK5CYII=', | 83 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAusB9Wl2nWQAAAAASUVORK5CYII=', |
| 80 'base64', | 84 'base64', |
| 86 fs.writeFileSync(path.join(root, 'archive.bin'), Buffer.from([0, 1, 2, 3])); | 90 fs.writeFileSync(path.join(root, 'archive.bin'), Buffer.from([0, 1, 2, 3])); |
| 87 run('hg', ['--repository', root, 'add'], options); | 91 run('hg', ['--repository', root, 'add'], options); |
| 88 run('hg', ['--repository', root, 'commit', '-u', 'Test User <[email protected]>', '-m', 'Initial fixture'], options); | 92 run('hg', ['--repository', root, 'commit', '-u', 'Test User <[email protected]>', '-m', 'Initial fixture'], options); |
| 89 const firstNode = run('hg', ['--repository', root, 'log', '-r', '.', '-T', '{node}'], options); | 93 const firstNode = run('hg', ['--repository', root, 'log', '-r', '.', '-T', '{node}'], options); |
| 90 | 94 |
| 91 fs.appendFileSync(path.join(root, 'README.md'), '\nSecond revision.\n'); | 95 fs.writeFileSync( |
| 96 path.join(root, 'README.md'), | |
| 97 '# Updated Fixture Repository\n\n<script>window.__hgWebXss = true</script>\n\nSecond revision.\n', | |
| 98 ); | |
| 92 fs.writeFileSync(path.join(root, 'new-file.txt'), 'new file\n'); | 99 fs.writeFileSync(path.join(root, 'new-file.txt'), 'new file\n'); |
| 93 run('hg', ['add', 'new-file.txt'], { ...options, cwd: root }); | 100 run('hg', ['add', 'new-file.txt'], { ...options, cwd: root }); |
| 94 run('hg', ['--repository', root, 'commit', '-u', 'Test User <[email protected]>', '-m', 'Update fixture'], options); | 101 run('hg', ['--repository', root, 'commit', '-u', 'Test User <[email protected]>', '-m', 'Update fixture'], options); |
| 95 const tipNode = run('hg', ['--repository', root, 'log', '-r', '.', '-T', '{node}'], options); | 102 const tipNode = run('hg', ['--repository', root, 'log', '-r', '.', '-T', '{node}'], options); |
| 96 return { firstNode, tipNode }; | 103 return { firstNode, tipNode }; |
| 280 }); | 287 }); |
| 281 | 288 |
| 282 await assertPageHasNoBrowserErrors(browser, '/directory', async page => { | 289 await assertPageHasNoBrowserErrors(browser, '/directory', async page => { |
| 283 await page.getByText('Repository Files').waitFor(); | 290 await page.getByText('Repository Files').waitFor(); |
| 284 await page.getByRole('link', { name: 'README.md' }).first().click(); | 291 await page.getByRole('link', { name: 'README.md' }).first().click(); |
| 285 await page.getByText('Fixture Repository').waitFor(); | 292 await page.getByText('Updated Fixture Repository').waitFor(); |
| 286 assert.equal(await page.evaluate(() => window.__hgWebXss), undefined); | 293 assert.equal(await page.evaluate(() => window.__hgWebXss), undefined); |
| 287 await page.keyboard.press('Escape'); | 294 await page.keyboard.press('Escape'); |
| 288 | 295 |
| 289 let delayedReadmeRequested = false; | 296 let delayedReadmeRequested = false; |
| 290 let markReadmeRequested; | 297 let markReadmeRequested; |
| 303 new Promise((_, reject) => { | 310 new Promise((_, reject) => { |
| 304 setTimeout(() => reject(new Error('Timed out waiting for delayed README request')), 5000); | 311 setTimeout(() => reject(new Error('Timed out waiting for delayed README request')), 5000); |
| 305 }), | 312 }), |
| 306 ]); | 313 ]); |
| 307 await page.getByRole('link', { name: 'root' }).click(); | 314 await page.getByRole('link', { name: 'root' }).click(); |
| 308 await page.getByText('Fixture Repository').waitFor(); | 315 await page.getByText('Updated Fixture Repository').waitFor(); |
| 309 await page.waitForTimeout(600); | 316 await page.waitForTimeout(600); |
| 310 assert.equal(await page.getByText('Documentation').count(), 0); | 317 assert.equal(await page.getByText('Documentation').count(), 0); |
| 311 assert.equal(delayedReadmeRequested, true); | 318 assert.equal(delayedReadmeRequested, true); |
| 312 | 319 |
| 313 await page.getByRole('link', { name: 'pixel.png' }).click(); | 320 await page.getByRole('link', { name: 'pixel.png' }).click(); |
| 323 }); | 330 }); |
| 324 assert.equal(await image.evaluate(element => element.naturalWidth), 1); | 331 assert.equal(await image.evaluate(element => element.naturalWidth), 1); |
| 325 await page.getByRole('dialog', { name: 'Preview pixel.png' }).waitFor(); | 332 await page.getByRole('dialog', { name: 'Preview pixel.png' }).waitFor(); |
| 326 await page.keyboard.press('Escape'); | 333 await page.keyboard.press('Escape'); |
| 327 | 334 |
| 335 await page.getByRole('link', { name: 'BUILD' }).click(); | |
| 336 const buildCode = page.locator('code.language-python'); | |
| 337 await buildCode.waitFor(); | |
| 338 await page.getByText('cc_library').waitFor(); | |
| 339 assert.match(await buildCode.textContent(), /name = "fixture"/); | |
| 340 await page.keyboard.press('Escape'); | |
| 341 | |
| 328 await page.getByRole('link', { name: 'src' }).click(); | 342 await page.getByRole('link', { name: 'src' }).click(); |
| 329 await page.getByRole('link', { name: 'main.c' }).click(); | 343 await page.getByRole('link', { name: 'main.c' }).click(); |
| 330 await page.getByText('int main(void)').waitFor(); | 344 await page.getByText('int main(void)').waitFor(); |
| 331 await page.keyboard.press('Escape'); | 345 await page.keyboard.press('Escape'); |
| 332 }); | 346 }); |
| 353 await assertPageHasNoBrowserErrors(browser, `/changeset/${tipNode}`, async page => { | 367 await assertPageHasNoBrowserErrors(browser, `/changeset/${tipNode}`, async page => { |
| 354 await page.getByRole('heading', { name: 'Update fixture' }).waitFor(); | 368 await page.getByRole('heading', { name: 'Update fixture' }).waitFor(); |
| 355 await page.locator('.changeset-files code').filter({ hasText: 'new-file.txt' }).waitFor(); | 369 await page.locator('.changeset-files code').filter({ hasText: 'new-file.txt' }).waitFor(); |
| 356 await page.getByText('added', { exact: true }).waitFor(); | 370 await page.getByText('added', { exact: true }).waitFor(); |
| 357 await page.getByRole('region', { name: 'Changeset diff' }).waitFor(); | 371 await page.getByRole('region', { name: 'Changeset diff' }).waitFor(); |
| 372 await page.locator('.diff-column-headings').getByText('Before').first().waitFor(); | |
| 373 await page.locator('.diff-column-headings').getByText('After').first().waitFor(); | |
| 374 await page.locator('.diff-left.diff-remove').filter({ hasText: '# Fixture Repository' }).waitFor(); | |
| 375 await page.locator('.diff-right.diff-add').filter({ hasText: '# Updated Fixture Repository' }).waitFor(); | |
| 376 assert.equal( | |
| 377 await page.locator('.diff-left.diff-context').filter({ hasText: '<script>' }).first().textContent(), | |
| 378 '<script>window.__hgWebXss = true</script>', | |
| 379 ); | |
| 358 assert.equal( | 380 assert.equal( |
| 359 await page.locator('.changeset-paper').evaluate( | 381 await page.locator('.changeset-paper').evaluate( |
| 360 element => getComputedStyle(element).backgroundImage, | 382 element => getComputedStyle(element).backgroundImage, |
| 361 ), | 383 ), |
| 362 'none', | 384 'none', |