69 lines
3.7 KiB
JavaScript
69 lines
3.7 KiB
JavaScript
const assert = require('node:assert/strict');
|
|
const { chromium, expect } = require('@playwright/test');
|
|
|
|
(async () => {
|
|
const base = new URL(process.argv[2]);
|
|
const sessionId = process.argv[3];
|
|
assert.equal(base.hostname, '127.0.0.1');
|
|
assert.match(sessionId, /^s-[a-f0-9]{32}$/);
|
|
const browser = await chromium.launch({
|
|
executablePath: process.env.CHROMIUM_EXECUTABLE,
|
|
args: ['--no-sandbox', '--disable-dev-shm-usage'],
|
|
});
|
|
try {
|
|
const page = await browser.newPage();
|
|
const errors = [];
|
|
page.on('pageerror', error => errors.push(error.message));
|
|
await page.route('**/*', route => new URL(route.request().url()).origin === base.origin ? route.continue() : route.abort());
|
|
await page.addInitScript(() => {
|
|
const NativeWebSocket = window.WebSocket;
|
|
window.fixtureSockets = [];
|
|
window.WebSocket = class extends NativeWebSocket {
|
|
constructor(...args) { super(...args); window.fixtureSockets.push(this); }
|
|
};
|
|
});
|
|
const text = () => page.evaluate(() => {
|
|
const buffer = window.fixtureTerminal?.buffer.active;
|
|
return buffer ? Array.from({ length: buffer.length }, (_, i) => buffer.getLine(i)?.translateToString()).join('\n') : '';
|
|
});
|
|
for (const width of [1440, 390]) {
|
|
await page.setViewportSize({ width, height: 844 });
|
|
await page.goto(base.href);
|
|
await page.getByRole('button', { name: 'Open terminal', exact: true }).click();
|
|
await expect.poll(text).toContain('D09-LINE-0000');
|
|
await expect.poll(text).toContain('D09-LINE-0099');
|
|
await expect(page.getByRole('combobox', { name: 'Terminal session' })).toHaveValue(sessionId);
|
|
await page.locator('.xterm-helper-textarea').focus();
|
|
// No contiguous expected marker in the echoed command: prove execution.
|
|
await page.keyboard.type(`printf 'NATIVE-%s-INPUT\\n' '${width}'`);
|
|
await page.keyboard.press('Enter');
|
|
await expect.poll(text).toContain(`NATIVE-${width}-INPUT`);
|
|
const before = await page.evaluate(() => window.fixtureSockets.length);
|
|
await page.evaluate(() => window.fixtureSockets.at(-1).close());
|
|
await expect.poll(() => page.evaluate(() => window.fixtureSockets.length), { timeout: 8000 }).toBe(before + 1);
|
|
await expect.poll(() => page.evaluate(() => window.fixtureSockets.at(-1).readyState)).toBe(1);
|
|
// A retained old buffer must not make a failed reconnect look successful.
|
|
await page.locator('.xterm-helper-textarea').focus();
|
|
await page.keyboard.type(`printf 'REJOIN-%s-DONE\\n' '${width}'`);
|
|
await page.keyboard.press('Enter');
|
|
await expect.poll(text).toContain(`REJOIN-${width}-DONE`);
|
|
assert.equal((await text()).split('D09-LINE-0000').length - 1, 1);
|
|
await page.evaluate(() => window.fixtureTerminal.scrollToTop());
|
|
await expect(page.locator('.xterm-rows')).toContainText('D09-LINE-0000');
|
|
await page.screenshot({ path: `/out/actual-terminal-history-${width}.png` });
|
|
await page.getByRole('button', { name: 'Close', exact: true }).click();
|
|
const sessions = await page.evaluate(async () => {
|
|
const response = await fetch('/api/terminal/sessions');
|
|
if (!response.ok) throw new Error(`session inventory failed: ${response.status}`);
|
|
return response.json();
|
|
});
|
|
assert.equal(sessions.length, 1, 'browser reconnect must not create another session');
|
|
assert.equal(sessions[0].id, sessionId);
|
|
}
|
|
assert.deepEqual(errors, []);
|
|
console.log('PASS real CLIPopup/xterm -> actual authenticated handler -> private tmux: typed command, history, same-session WebSocket reconnect and visible1440/390 history; synthetic owner bootstrap only');
|
|
} finally {
|
|
await browser.close();
|
|
}
|
|
})().catch(error => { console.error(error); process.exitCode = 1; });
|