feat(terminal): add forced redraw resize

This commit is contained in:
Teigen
2026-06-17 23:41:47 +08:00
parent b374121c18
commit 2c81bbc08b
10 changed files with 82 additions and 28 deletions
+14 -2
View File
@@ -369,7 +369,7 @@ describe('session-routes', () => {
expect(res.statusCode).toBe(200);
const body = JSON.parse(res.body);
expect(body.success).toBe(true);
expect(harness.ctx._session.resize).toHaveBeenCalledWith(120, 40);
expect(harness.ctx._session.resize).toHaveBeenCalledWith(120, 40, { viewportType: undefined, force: undefined });
});
it('passes viewport type through for resize arbitration', async () => {
@@ -381,7 +381,19 @@ describe('session-routes', () => {
expect(res.statusCode).toBe(200);
const body = JSON.parse(res.body);
expect(body.success).toBe(true);
expect(harness.ctx._session.resize).toHaveBeenCalledWith(48, 28, { viewportType: 'mobile' });
expect(harness.ctx._session.resize).toHaveBeenCalledWith(48, 28, { viewportType: 'mobile', force: undefined });
});
it('passes force resize through for redraw requests', async () => {
const res = await harness.app.inject({
method: 'POST',
url: `/api/sessions/${harness.ctx._sessionId}/resize`,
payload: { cols: 120, rows: 40, force: true },
});
expect(res.statusCode).toBe(200);
const body = JSON.parse(res.body);
expect(body.success).toBe(true);
expect(harness.ctx._session.resize).toHaveBeenCalledWith(120, 40, { viewportType: undefined, force: true });
});
it('rejects cols exceeding max (500)', async () => {
+19 -4
View File
@@ -285,7 +285,7 @@ describe('ws-routes', () => {
ws.send(JSON.stringify({ t: 'z', c: 120, r: 40 }));
await vi.waitFor(() => {
expect(session.resize).toHaveBeenCalledWith(120, 40);
expect(session.resize).toHaveBeenCalledWith(120, 40, { viewportType: undefined, force: false });
});
} finally {
ws.close();
@@ -300,7 +300,22 @@ describe('ws-routes', () => {
ws.send(JSON.stringify({ t: 'z', c: 48, r: 28, v: 'mobile' }));
await vi.waitFor(() => {
expect(session.resize).toHaveBeenCalledWith(48, 28, { viewportType: 'mobile' });
expect(session.resize).toHaveBeenCalledWith(48, 28, { viewportType: 'mobile', force: false });
});
} finally {
ws.close();
}
});
it('passes force resize through for redraw requests', async () => {
const ws = await connectWs('/ws/sessions/ws-test-session/terminal');
try {
const session = ctx._session;
ws.send(JSON.stringify({ t: 'z', c: 120, r: 40, f: true }));
await vi.waitFor(() => {
expect(session.resize).toHaveBeenCalledWith(120, 40, { viewportType: undefined, force: true });
});
} finally {
ws.close();
@@ -342,7 +357,7 @@ describe('ws-routes', () => {
ws.send(JSON.stringify({ t: 'z', c: 1, r: 1 }));
await vi.waitFor(() => {
expect(session.resize).toHaveBeenCalledWith(1, 1);
expect(session.resize).toHaveBeenCalledWith(1, 1, { viewportType: undefined, force: false });
});
} finally {
ws.close();
@@ -357,7 +372,7 @@ describe('ws-routes', () => {
ws.send(JSON.stringify({ t: 'z', c: 500, r: 200 }));
await vi.waitFor(() => {
expect(session.resize).toHaveBeenCalledWith(500, 200);
expect(session.resize).toHaveBeenCalledWith(500, 200, { viewportType: undefined, force: false });
});
} finally {
ws.close();
+9
View File
@@ -113,6 +113,15 @@ describe('Session resize arbitration', () => {
expect(resize).toHaveBeenCalledWith(100, 30);
});
it('applies forced resizes even when the dimensions did not change', () => {
const session = new Session({ workingDir: '/tmp', mode: 'shell' });
const resize = attachFakePty(session, 120, 40);
session.resize(120, 40, { force: true });
expect(resize).toHaveBeenCalledWith(120, 40);
});
describe('idle-desktop override (whoever is active wins)', () => {
afterEach(() => {
vi.useRealTimers();