mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 02:29:33 +01:00
fix(terminal): review of the Codex menu wheel guard
This commit is contained in:
1 parent
9fa6d98c7c
commit
372df864b9
4 files changed
+62
-3
No files matched your search
@@ -115,6 +115,18 @@ describe('isCodexSelectionMenu on live captures', () => {
|
||||
expect(isMenu(name), name).toBe(false);
|
||||
});
|
||||
|
||||
it('still reads a narrow question whose option descriptions wrap over many rows', () => {
|
||||
// The selected option sat 16 rows up from the bottom at 36 columns; sentence-length descriptions on
|
||||
// a phone-width pane push it further, and an earlier row cap lost it (the menu was missed and the
|
||||
// wheel moved the selection again).
|
||||
const rows = fixture('question-w36.txt').split('\n');
|
||||
const at = rows.findIndex((row) => /^\s{0,2}› 1\./.test(row));
|
||||
expect(at).toBeGreaterThan(-1);
|
||||
rows.splice(at + 1, 0, ...Array.from({ length: 12 }, (_, i) => ` wrapped description row ${i + 1}`));
|
||||
const terminal = terminalShowing(rows.join('\n'), 60);
|
||||
expect(windowRef.CodemanTerminalInput.isCodexSelectionMenu(terminal)).toBe(true);
|
||||
});
|
||||
|
||||
it('is false for a terminal it cannot read', () => {
|
||||
expect(windowRef.CodemanTerminalInput.isCodexSelectionMenu(undefined)).toBe(false);
|
||||
expect(windowRef.CodemanTerminalInput.isCodexSelectionMenu({ rows: 10, buffer: { active: { baseY: 0 } } })).toBe(
|
||||
|
||||
@@ -843,6 +843,54 @@ describe("the dialog check reads the TILE's session, never the active tab's", ()
|
||||
});
|
||||
});
|
||||
|
||||
describe("a Codex selection menu on the tile's own screen", () => {
|
||||
const MENU = [
|
||||
' Implement this plan?',
|
||||
'',
|
||||
'› 1. Yes, implement this plan Switch to Default and start coding',
|
||||
' 2. Yes, clear context and implement Start a fresh thread (current context: 2% used)',
|
||||
' 3. No, stay in Plan mode Continue planning with the model',
|
||||
'',
|
||||
' enter select · esc back',
|
||||
];
|
||||
/** Puts `rows` on the bottom of the tile's 24-row screen, the way xterm's buffer answers getLine. */
|
||||
function showOnScreen(term: { rows: number; buffer: { active: Record<string, unknown> } }, rows: string[]) {
|
||||
const screen = [...Array(term.rows - rows.length).fill(''), ...rows];
|
||||
term.buffer.active.getLine = (y: number) => ({ translateToString: () => screen[y] ?? '' });
|
||||
}
|
||||
|
||||
it('consumes the wheel without paging, and pages again once the menu is gone', async () => {
|
||||
const app = makeApp({ other: { mode: 'claude' }, 's-tile': { mode: 'codex' } }, 'other');
|
||||
const { ws, term, mount } = await connectTile(app, { mode: 'codex' });
|
||||
showOnScreen(term, MENU);
|
||||
|
||||
for (const lines of [-18, 18, -18]) {
|
||||
const ev = wheelLines(lines);
|
||||
mount.fire('wheel', ev);
|
||||
// Consumed (xterm does not scroll the stale rows under the menu either), and no key was sent.
|
||||
expect(ev.preventDefault).toHaveBeenCalled();
|
||||
}
|
||||
expect(flushed(ws)).toEqual([]);
|
||||
|
||||
// Menu closed: the composer is back on screen and the same wheel pages the transcript.
|
||||
showOnScreen(term, ['› Ask Codex to do anything', '', ' GPT-6-Astra medium · ~/cases/x', ' ? for shortcuts']);
|
||||
mount.fire('wheel', wheelLines(-18));
|
||||
expect(flushed(ws)).toEqual([{ t: 'i', d: PAGE_UP }]);
|
||||
});
|
||||
|
||||
it("asks about THIS tile's terminal, not the active tab's", async () => {
|
||||
const app = makeApp({ other: { mode: 'codex' }, 's-tile': { mode: 'codex' } }, 'other');
|
||||
(app as App & { terminal: unknown }).terminal = {
|
||||
rows: 24,
|
||||
buffer: { active: { getLine: () => ({ translateToString: () => '' }) } },
|
||||
};
|
||||
const { ws, term, mount } = await connectTile(app, { mode: 'codex' });
|
||||
showOnScreen(term, MENU);
|
||||
mount.fire('wheel', wheelLines(-18));
|
||||
expect(flushed(ws)).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('rows the tile pushed above the screen itself are not history', () => {
|
||||
it('pages after a one-screen capture taken at a taller size (the first load)', async () => {
|
||||
serveCapture(lines(40), 40); // the PTY was 40 rows when it was captured
|
||||
|
||||
Reference in new issue
Block a user