feat(ui): add ask keymap help modal
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { visibleWidth } from "@mariozechner/pi-tui";
|
||||
import { ASK_HELP_CLOSE_HINT, ASK_KEYMAPS } from "../src/constants/keymaps.ts";
|
||||
import { AskHelpModal } from "../src/ui/help-modal.ts";
|
||||
|
||||
const noop = () => {
|
||||
// Test callback intentionally does nothing.
|
||||
};
|
||||
|
||||
function plainTheme() {
|
||||
return {
|
||||
fg(_color: string, text: string) {
|
||||
return text;
|
||||
},
|
||||
bg(_color: string, text: string) {
|
||||
return text;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test("help modal renders compactly on phone-width screens", () => {
|
||||
const modal = new AskHelpModal(plainTheme(), noop);
|
||||
const lines = modal.render(28);
|
||||
|
||||
assert(lines.length > ASK_KEYMAPS.length + 4);
|
||||
assert(lines.every((line) => visibleWidth(line) <= 28));
|
||||
assert(lines.join("\n").includes("@eko24ive/pi-ask"));
|
||||
assert(lines.slice(-3, -1).join(" ").includes("Esc, Ctrl+C, or ?"));
|
||||
assert(lines.includes("│ ? │"));
|
||||
assert(lines.includes("│ Show this menu │"));
|
||||
});
|
||||
|
||||
test("help modal keeps context rows on wider screens", () => {
|
||||
const modal = new AskHelpModal(plainTheme(), noop);
|
||||
const lines = modal.render(72);
|
||||
|
||||
assert(lines.length > ASK_KEYMAPS.length + 4);
|
||||
assert(lines.join("\n").includes("Main flow"));
|
||||
assert(lines.at(-2)?.includes(ASK_HELP_CLOSE_HINT));
|
||||
});
|
||||
|
||||
test("help modal closes from configured keyboard shortcuts", () => {
|
||||
for (const input of ["?", "\u001b", "\u0003"]) {
|
||||
let closed = 0;
|
||||
const modal = new AskHelpModal(plainTheme(), () => {
|
||||
closed += 1;
|
||||
});
|
||||
|
||||
modal.handleInput(input);
|
||||
|
||||
assert.equal(closed, 1);
|
||||
}
|
||||
});
|
||||
|
||||
test("help modal ignores enter and closes idempotently on dispose", () => {
|
||||
let closed = 0;
|
||||
const modal = new AskHelpModal(plainTheme(), () => {
|
||||
closed += 1;
|
||||
});
|
||||
|
||||
modal.handleInput("\r");
|
||||
assert.equal(closed, 0);
|
||||
|
||||
modal.dispose();
|
||||
modal.dispose();
|
||||
assert.equal(closed, 1);
|
||||
});
|
||||
@@ -164,6 +164,25 @@ test("ctrl+c dismisses the flow from both navigation and editing modes", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("question mark opens keymap help outside non-empty editors", () => {
|
||||
const navigation = createInitialState({
|
||||
questions: [
|
||||
{
|
||||
id: "q1",
|
||||
prompt: "Question?",
|
||||
options: [{ value: "a", label: "A" }],
|
||||
},
|
||||
],
|
||||
});
|
||||
const input = inputState();
|
||||
|
||||
assert.deepEqual(getInputCommand(navigation, "?"), { kind: "showHelp" });
|
||||
assert.deepEqual(getInputCommand(input, "?", ""), { kind: "showHelp" });
|
||||
assert.deepEqual(getInputCommand(input, "?", "x"), {
|
||||
kind: "delegateToEditor",
|
||||
});
|
||||
});
|
||||
|
||||
test("note shortcuts use n for option notes and Shift+N for question notes", () => {
|
||||
const navigation = createInitialState({
|
||||
questions: [
|
||||
|
||||
@@ -223,7 +223,7 @@ test("footer hints wrap into exact lines on narrow screens", () => {
|
||||
"Space toggle",
|
||||
"Enter continue",
|
||||
"N/Shift+N note",
|
||||
"Esc dismiss",
|
||||
"Esc dismiss · ? help",
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -250,6 +250,6 @@ test("footer keeps earlier hint chunk on the first wrapped line", () => {
|
||||
assert.deepEqual(lines.slice(-4, -1), [
|
||||
"Enter confirm",
|
||||
"N/Shift+N note",
|
||||
"Esc dismiss",
|
||||
"Esc dismiss · ? help",
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -74,6 +74,6 @@ test("renderEditorBlock reapplies background after editor reset sequences", () =
|
||||
});
|
||||
|
||||
test("editing footers do not advertise tab navigation", () => {
|
||||
assert.equal(renderFooterText("input"), " Enter submit · Esc close");
|
||||
assert.equal(renderFooterText("note"), " Enter save · Esc close");
|
||||
assert.equal(renderFooterText("input"), " Enter submit · Esc close · ? help");
|
||||
assert.equal(renderFooterText("note"), " Enter save · Esc close · ? help");
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { UI_DIMENSIONS } from "../src/constants/ui.ts";
|
||||
import { createInitialState } from "../src/state/create.ts";
|
||||
import {
|
||||
applyNumberShortcut,
|
||||
@@ -7,7 +8,6 @@ import {
|
||||
enterQuestionNoteMode,
|
||||
saveNote,
|
||||
} from "../src/state/transitions.ts";
|
||||
import { UI_DIMENSIONS } from "../src/ui/constants.ts";
|
||||
import { renderSubmitScreen } from "../src/ui/render-submit.ts";
|
||||
|
||||
function plainTheme() {
|
||||
|
||||
Reference in New Issue
Block a user