Files
learnharness/tests/keyboard-toggle-sidebar.test.ts
T
amosblomqvist d5c4c3bf9f ui: the chat comeback — side-based authorship, restored quotes, tucked whys
Blockquotes: the callout override had displaced Streamdown's own styled
blockquote component, so plain quotes rendered as bare unstyled text
since that commit. The pass-through branch now restores Streamdown's
verbatim classes (border-l-4, muted italic).

Explanations tucked for ALL questions (owner): the prediction's Why /
Hide-why toggle is universal — every quiz answered card sits its
explanation behind the same collapsed button. Same pattern, one law.

The thinking row's rhythm: my-1 -> my-3. The 4px margin hugged the
options on non-graded answered cards (owner report); 12px matches the
card's mt-2/mt-3 spacing grammar everywhere the row renders.

Side-based authorship (owner round, 2026-10-07): the document shape
blurred user into agent — three left-rail idioms (user text, user
thinking, quoted prose) collided once quotes rendered. User rows go
RIGHT: 'You' messages and practice thinking cards hug the right edge at
85% width with the rail mirrored (border-r), text still reading
left-to-right. In-card thinking (inside the answered card, the agent's
context) stays left. Transcript thinking rows arrive EXPANDED — the
thinking was clearly sent. Cmd+T (toggle-user-thinking, chat scope,
cheat-sheet row) sets every user-thinking row to one state via a module
store: explicit sets stomp individual toggles, late mounts honor the
last set (the state initializer reads the store, so static render
reflects it too).
2026-10-08 02:29:05 +03:00

57 lines
2.3 KiB
TypeScript

import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
actionForBinding,
bindingForAction,
formatBinding,
kbdEventForAction,
} from "../src/core/keyboard.ts";
import { kbdEventForAction as kbdEventForActionFromUi } from "../components/keyboard-shortcuts.tsx";
/**
* The ⌘B sidebar bug interlude (owner, 2026-09-25): ⌘B did nothing because
* the sidebar listened on the pre-convention "lh:toggle-sidebar" while the
* dispatcher sent "lh:kbd-toggle-sidebar". The fix is structural — both
* sides compose the event name through the ONE helper — and these pins
* hold the chain together: the registry maps the keypress to the action,
* the helper spells the event, and the UI dispatcher imports the same
* helper (not its own copy).
*/
describe("kbdEventForAction — the one spelling for action events", () => {
it("dispatch and listen names are the helper's output", () => {
assert.equal(kbdEventForAction("toggle-sidebar"), "lh:kbd-toggle-sidebar");
assert.equal(kbdEventForAction("sessions-search"), "lh:kbd-sessions-search");
});
it("the dispatcher imports the same helper (no second spelling exists)", () => {
assert.equal(kbdEventForActionFromUi, kbdEventForAction);
});
});
describe("the ⌘B chain — keypress → binding → action → event", () => {
it("mod+t is the toggle-user-thinking action (owner round, 2026-10-07)", () => {
assert.equal(actionForBinding("mod+t"), "toggle-user-thinking");
assert.equal(bindingForAction("toggle-user-thinking"), "mod+t");
assert.equal(kbdEventForAction("toggle-user-thinking"), "lh:kbd-toggle-user-thinking");
});
it("mod+b is the toggle-sidebar action", () => {
assert.equal(actionForBinding("mod+b"), "toggle-sidebar");
assert.equal(bindingForAction("toggle-sidebar"), "mod+b");
assert.equal(formatBinding("mod+b"), "⌘B");
});
it("the event the chain ends in is the one the sidebar answers on", () => {
const action = actionForBinding("mod+b");
assert.equal(action, "toggle-sidebar");
assert.equal(kbdEventForAction(action), "lh:kbd-toggle-sidebar");
});
});
describe("the thinking pill suffix — ⇧⇥ via the registry", () => {
it("shift+tab formats as ⇧⇥ and maps to cycle-thinking", () => {
assert.equal(actionForBinding("shift+tab"), "cycle-thinking");
assert.equal(formatBinding("shift+tab"), "⇧⇥");
});
});