mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-07 16:09:43 +02:00
test(split-pane): cover the blank-Pane-B and stale-width-Pane-A fixes
Real-browser regression coverage for the previous commit: - SplitTerminalPane connects onto an already-quiet session and shows its existing scrollback with no new output, proving the ?full=1 fetch (not a live echo) populated the pane. - openSplitPane() force-resizes Pane A synchronously as part of opening a split. - Dragging the divider force-resizes Pane A once, at drag end. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
3859506f9b
commit
1678386f50
@@ -91,4 +91,80 @@ describe('SplitTerminalPane in a real browser', () => {
|
||||
await fetch(`/api/sessions/${id}`, { method: 'DELETE' });
|
||||
}, sessionId);
|
||||
});
|
||||
|
||||
it('shows existing scrollback immediately on connect, before any new output', async () => {
|
||||
// Regression guard: connect() previously only opened the WS and waited for
|
||||
// live 'terminal' events (ws-routes.ts sends nothing on connect), so a pane
|
||||
// opened onto an already-quiet session stayed blank until either new output
|
||||
// arrived or a resize happened to trigger a tmux repaint. Writing a marker
|
||||
// and letting the echo settle BEFORE connect() proves the fetched buffer,
|
||||
// not a live echo, is what populates the pane.
|
||||
const sessionId = await page.evaluate(async () => {
|
||||
const res = await fetch('/api/sessions', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ workingDir: '/tmp', mode: 'shell' }),
|
||||
});
|
||||
const id = (await res.json()).data.session.id;
|
||||
await fetch(`/api/sessions/${id}/shell`, { method: 'POST' });
|
||||
// Write directly to the session (not through SplitTerminalPane, which
|
||||
// does not exist yet). Poll the real ?full=1 capture (same endpoint
|
||||
// connect() below will use) rather than a fixed delay — the shell's
|
||||
// own startup can race an early write and, on this box, a startup
|
||||
// script issues a `clear` that erases scrollback (modern ncurses
|
||||
// `clear` emits \x1b[3J) if the input lands before the shell is ready.
|
||||
await fetch(`/api/sessions/${id}/input`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ input: 'PRE_EXISTING_MARKER\r' }),
|
||||
});
|
||||
const deadline = Date.now() + 5000;
|
||||
for (;;) {
|
||||
const res2 = await fetch(`/api/sessions/${id}/terminal?full=1`);
|
||||
const buffer = (await res2.json())?.data?.terminalBuffer ?? '';
|
||||
if (buffer.includes('PRE_EXISTING_MARKER')) break;
|
||||
if (Date.now() > deadline) throw new Error('marker never landed in ?full=1 capture: ' + JSON.stringify(buffer));
|
||||
await new Promise((r) => setTimeout(r, 200));
|
||||
}
|
||||
return id;
|
||||
});
|
||||
|
||||
const hasMarker = await page.evaluate(async (id) => {
|
||||
const mount = document.createElement('div');
|
||||
mount.style.width = '400px';
|
||||
mount.style.height = '300px';
|
||||
document.body.appendChild(mount);
|
||||
|
||||
const pane = new (window as any).SplitTerminalPane(id, mount);
|
||||
await pane.connect();
|
||||
|
||||
// xterm's write() parses asynchronously (it queues data and processes it
|
||||
// on a later microtask/frame), so the fetched buffer connect() writes is
|
||||
// not necessarily in the rendered buffer the instant connect() resolves.
|
||||
// Poll rather than check once — no new input is sent here, so any pass
|
||||
// still comes from the ?full=1 fetch inside connect(), never a live echo.
|
||||
let found = false;
|
||||
const deadline = Date.now() + 3000;
|
||||
while (!found && Date.now() < deadline) {
|
||||
const buf = pane.terminal.buffer.active;
|
||||
for (let i = 0; i < buf.length; i++) {
|
||||
if (buf.getLine(i)?.translateToString(true).includes('PRE_EXISTING_MARKER')) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) await new Promise((r) => setTimeout(r, 50));
|
||||
}
|
||||
|
||||
pane.destroy();
|
||||
document.body.removeChild(mount);
|
||||
return found;
|
||||
}, sessionId);
|
||||
|
||||
expect(hasMarker).toBe(true);
|
||||
|
||||
await page.evaluate(async (id) => {
|
||||
await fetch(`/api/sessions/${id}`, { method: 'DELETE' });
|
||||
}, sessionId);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user