Files
rustguac/tests/client-navigation.mjs
T
Dave Kempe 6175cda36a client: leaving an embedded session moves the whole tab
In a fullscreen-on-connect session the client runs in a frame on the
Connections tab, and every other page refuses to load in a frame. Home in
the Ctrl+Alt+Shift panel, reconnect and the disconnected overlay only
moved the frame, so the browser showed "cannot open this page" in place
of the session. Every navigation now goes through rgGo(), which moves the
whole tab when embedded, and Close session hands back to the launcher.
tests/client-navigation.mjs fails if anything navigates around it.
2026-10-17 13:56:05 +11:00

61 lines
2.4 KiB
JavaScript

#!/usr/bin/env node
/*
* Pins how client.html leaves a session (#257).
*
* A fullscreen-on-connect session runs the client in a same-origin frame on
* the Connections tab. Every other page refuses to load in a frame
* (frame-ancestors 'none'), so a navigation from inside the frame (Home in
* the Ctrl+Alt+Shift panel, reconnect, the disconnected overlay) that only
* moved the frame showed the browser's "cannot open this page" in place of
* the session. Every navigation must go through rgGo(), which moves the
* whole tab when embedded.
*
* Usage: node tests/client-navigation.mjs
*/
import { readFile } from 'node:fs/promises';
import { dirname, resolve, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import vm from 'node:vm';
import assert from 'node:assert/strict';
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const html = await readFile(join(root, 'static/client.html'), 'utf8');
function lift(name) {
const start = html.indexOf(`function ${name}(`);
assert.notEqual(start, -1, `${name}() must exist in client.html`);
let i = html.indexOf('{', start), depth = 0;
for (; i < html.length; i++) {
if (html[i] === '{') depth++;
else if (html[i] === '}' && --depth === 0) break;
}
return { start, end: i + 1, src: html.slice(start, i + 1) };
}
const go = lift('rgGo');
// 1. Nothing navigates except through rgGo.
const outside = html.slice(0, go.start) + html.slice(go.end);
for (const pattern of [/location\.href\s*=/, /location\.replace\(/, /location\.assign\(/]) {
assert.doesNotMatch(outside, pattern, `client.html must navigate through rgGo(), not ${pattern}`);
}
// 2. rgGo moves the whole tab when embedded, and only this page otherwise.
function run(embedded) {
const top = { location: { href: '/client/x' } };
const self = { location: { href: '/client/x' } };
const ctx = { embedded, window: { top, location: self.location } };
vm.createContext(ctx);
vm.runInContext(go.src, ctx);
ctx.rgGo('/connections.html');
return { top: top.location.href, self: self.location.href };
}
let r = run(true);
assert.equal(r.top, '/connections.html', 'embedded: the whole tab goes');
assert.equal(r.self, '/client/x', 'embedded: the frame itself is not navigated');
r = run(false);
assert.equal(r.self, '/connections.html', 'a normal tab navigates itself');
console.log('client-navigation: ok');