v0.8.0 cad1d13

web-access-smoke.cjs RawHistoryFolder

1// Isolated profile only: rotates access and disconnects all browser views.
2const { chromium } = require(process.env.PLAYWRIGHT_MODULE || 'playwright');
3const { execFileSync } = require('node:child_process');
4const assert = require('node:assert/strict');
5(async () => {
6  if (!process.env.VEV_BINARY || !process.env.VEV_ENV) throw new Error('VEV_BINARY and isolated VEV_ENV are required');
7  const link = flag => execFileSync(process.env.VEV_BINARY, [flag], { encoding: 'utf8' }).match(/http:\/\/127\.0\.0\.1:8778\/#token=[A-Za-z0-9_-]+/)[0];
8  const first = link('--web-daemon');
9  assert.equal(link('--web-daemon'), first);
10  const browser = await chromium.launch({ executablePath: process.env.CHROMIUM_PATH });
11  try {
12    const page = await browser.newPage();
13    await page.goto(first);
14    await page.waitForFunction(() => document.querySelector('#status').textContent === 'Connected');
15    await page.waitForFunction(() => Number(document.querySelector('#view-count').textContent) >= 1);
16    const initial = Number(await page.locator('#view-count').textContent());
17    assert.equal(await page.locator('#view-description').textContent(), `Connected browser terminal views: ${initial}`);
18    const button = page.locator('#palette');
19    const normal = await button.evaluate(node => ({ color: getComputedStyle(node).color, background: getComputedStyle(node).backgroundColor, border: getComputedStyle(node).borderTopWidth }));
20    await button.hover();
21    const hover = await button.evaluate(node => ({ color: getComputedStyle(node).color, background: getComputedStyle(node).backgroundColor }));
22    assert.equal(normal.border, '0px');
23    assert.equal(hover.background, normal.background);
24    assert.notEqual(hover.color, normal.color);
25    const other = await browser.newPage();
26    await other.goto(first);
27    await other.waitForFunction(() => document.querySelector('#status').textContent === 'Connected');
28    await page.waitForFunction(n => Number(document.querySelector('#view-count').textContent) === n + 1, initial);
29    assert.equal(await page.locator('#connection').getAttribute('data-state'), 'connected');
30    await other.close();
31    await page.waitForFunction(n => Number(document.querySelector('#view-count').textContent) === n, initial);
32    const next = link('--web-renew-token');
33    assert.notEqual(next, first);
34    await page.waitForFunction(() => document.querySelector('#status').textContent.startsWith('Disconnected'));
35    const oldStatus = await page.evaluate(async () => (await fetch('/health')).status);
36    assert.equal(oldStatus, 401);
37    assert.equal(await page.locator('#view-description').textContent(), 'Connected browser terminal views: unknown');
38    await page.locator('#reconnect').click();
39    await page.waitForFunction(() => document.querySelector('#status').textContent === 'Authentication required');
40    assert.equal(await page.locator('#help').isVisible(), true);
41    assert.equal(await page.locator('#reconnect').isVisible(), false);
42    const revoked = await browser.newPage();
43    await revoked.goto(first);
44    await revoked.waitForFunction(() => document.querySelector('#status').textContent === 'Authentication required');
45    await revoked.goto(next);
46    await revoked.waitForFunction(() => document.querySelector('#status').textContent === 'Connected');
47    assert.equal(await revoked.locator('#help').isVisible(), false);
48    await revoked.close();
49    await page.goto(next);
50    await page.waitForFunction(() => document.querySelector('#status').textContent === 'Connected');
51    console.log('Web access smoke passed: stable live token, view count, rotation, cookie revocation, reconnect.');
52  } finally { await browser.close(); }
53})().catch(error => { console.error(error); process.exitCode = 1; });

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close