pi-mono/packages/tui/test/settings-list.test.ts
Petr Houška 3bae85274a fix(tui,coding-agent): handle selection page keys in all scrolling lists
tui.select.pageUp/pageDown were configurable but ignored by SelectList,
SettingsList, editor autocomplete, and most coding-agent selectors. In
fullscreen mode, the default PageUp/PageDown also scrolled the transcript
instead of reaching the focused list.

- add getSelectPageIndex() and handle page keys in SelectList, SettingsList,
  editor autocomplete, and the model, scoped models, auth, user message,
  settings submenu, llama search, and /mcp selectors
- add Component.capturesViewportInput: a focused component that sets it
  receives fullscreen viewport keys instead of the transcript, as a focused
  overlay already does
- let page keys move an open autocomplete menu before app actions, so a
  remapped Ctrl+V pages the menu instead of pasting an image

closes #7629

Co-authored-by: muyiyr <940955635@qq.com>
2026-10-28 19:05:21 +01:00

80 lines
2.1 KiB
TypeScript

import assert from "node:assert";
import { describe, it } from "node:test";
import { SettingsList, type SettingsListTheme } from "../src/components/settings-list.ts";
const testTheme: SettingsListTheme = {
label: (text) => text,
value: (text) => text,
description: (text) => text,
cursor: "> ",
hint: (text) => text,
};
const items = [
{
id: "tui-mode",
label: "TUI mode",
currentValue: "regular",
values: ["regular", "fullscreen"],
},
];
describe("SettingsList", () => {
it("includes spaces in an active search instead of changing the selected setting", () => {
const changes: Array<{ id: string; value: string }> = [];
const list = new SettingsList(
items.map((item) => ({ ...item })),
10,
testTheme,
(id, value) => changes.push({ id, value }),
() => {},
{ enableSearch: true },
);
for (const character of "TUI mode") list.handleInput(character);
assert.deepStrictEqual(changes, []);
assert.match(list.render(80)[0] ?? "", /TUI mode/);
list.handleInput("\r");
assert.deepStrictEqual(changes, [{ id: "tui-mode", value: "fullscreen" }]);
});
it("keeps Space as a change shortcut before a search query is entered", () => {
const changes: Array<{ id: string; value: string }> = [];
const list = new SettingsList(
items.map((item) => ({ ...item })),
10,
testTheme,
(id, value) => changes.push({ id, value }),
() => {},
{ enableSearch: true },
);
list.handleInput(" ");
assert.deepStrictEqual(changes, [{ id: "tui-mode", value: "fullscreen" }]);
});
it("moves by one visible page with selection page keys (#7629)", () => {
const list = new SettingsList(
Array.from({ length: 12 }, (_, index) => ({
id: `setting-${index}`,
label: `Setting ${index}`,
currentValue: String(index),
})),
5,
testTheme,
() => {},
() => {},
);
list.handleInput("\x1b[6~");
assert.match(list.render(80).join("\n"), /> Setting 5/);
list.handleInput("\x1b[6~");
list.handleInput("\x1b[6~");
assert.match(list.render(80).join("\n"), /> Setting 11/);
list.handleInput("\x1b[5~");
assert.match(list.render(80).join("\n"), /> Setting 6/);
});
});