88 lines
3.6 KiB
TypeScript
88 lines
3.6 KiB
TypeScript
import { describe, expect, it } from "bun:test";
|
|
import {
|
|
collectTerminalState,
|
|
formatTerminalState,
|
|
type TerminalStateInfo,
|
|
} from "@oh-my-pi/pi-coding-agent/debug/terminal-info";
|
|
import { TERMINAL } from "@oh-my-pi/pi-tui";
|
|
|
|
const sample: TerminalStateInfo = {
|
|
detectedId: "kitty",
|
|
columns: 120,
|
|
rows: 40,
|
|
cellWidthPx: 9,
|
|
cellHeightPx: 18,
|
|
trueColor: true,
|
|
imageProtocol: "Kitty graphics",
|
|
notifyProtocol: "OSC 99 (kitty desktop notifications)",
|
|
osc99Confirmed: true,
|
|
hyperlinks: false,
|
|
deccara: true,
|
|
screenToScrollback: true,
|
|
synchronizedOutput: false,
|
|
multiplexer: null,
|
|
env: { TERM: "xterm-kitty", TERM_PROGRAM: undefined, TERM_PROGRAM_VERSION: undefined, COLORTERM: "truecolor" },
|
|
};
|
|
|
|
describe("formatTerminalState", () => {
|
|
it("surfaces the negotiated subprotocols and their on/off state", () => {
|
|
const out = formatTerminalState(sample);
|
|
expect(out).toContain("Detected: kitty");
|
|
expect(out).toContain("Graphics: Kitty graphics");
|
|
expect(out).toContain("Notify: OSC 99 (kitty desktop notifications) · confirmed via DA");
|
|
expect(out).toContain("Hyperlinks: no (OSC 8)");
|
|
expect(out).toContain("True color: yes (24-bit SGR)");
|
|
expect(out).toContain("DECCARA: yes (rectangular-SGR background fills)");
|
|
expect(out).toContain("Sync output: no (DEC 2026)");
|
|
});
|
|
|
|
it("reports geometry, cell size, and the scrollback strategy", () => {
|
|
const out = formatTerminalState(sample);
|
|
expect(out).toContain("120x40 cells · cell 9x18px");
|
|
// supportsScreenToScrollback -> the non-destructive CSI 22 J clear.
|
|
expect(out).toContain("Screen->history clear: CSI 22 J");
|
|
});
|
|
|
|
it("renders the redraw fallback when screen-to-scrollback is unsupported", () => {
|
|
const out = formatTerminalState({ ...sample, screenToScrollback: false });
|
|
expect(out).toContain("Screen->history clear: CSI 2 J (redraw)");
|
|
});
|
|
|
|
it("drops the OSC-99-confirmed marker when the terminal never answered the probe", () => {
|
|
const out = formatTerminalState({ ...sample, osc99Confirmed: false });
|
|
expect(out).toContain("Notify: OSC 99 (kitty desktop notifications)");
|
|
expect(out).not.toContain("confirmed via DA");
|
|
});
|
|
|
|
it("shows 'none' for no multiplexer and '(unset)' for absent detection vars", () => {
|
|
const out = formatTerminalState(sample);
|
|
expect(out).toContain("Multiplexer: none");
|
|
expect(out).toContain("TERM: xterm-kitty");
|
|
expect(out).toContain("COLORTERM: truecolor");
|
|
expect(out).toContain("TERM_PROGRAM: (unset)");
|
|
});
|
|
|
|
it("names the multiplexer when one wraps the session", () => {
|
|
expect(formatTerminalState({ ...sample, multiplexer: "tmux" })).toContain("Multiplexer: tmux");
|
|
});
|
|
});
|
|
|
|
describe("collectTerminalState", () => {
|
|
it("passes live geometry through and maps protocols to human-readable names (never raw escapes)", () => {
|
|
const info = collectTerminalState({ columns: 88, rows: 25, synchronizedOutput: true });
|
|
expect(info.columns).toBe(88);
|
|
expect(info.rows).toBe(25);
|
|
expect(info.synchronizedOutput).toBe(true);
|
|
// The graphics/notify subprotocols are surfaced as readable labels, not the
|
|
// enum's underlying escape sequences (\x1b_G, \x1b]99;;, …).
|
|
expect(info.imageProtocol).not.toContain("\x1b");
|
|
expect(info.notifyProtocol).not.toContain("\x1b");
|
|
expect(info.imageProtocol.length).toBeGreaterThan(0);
|
|
expect(info.notifyProtocol.length).toBeGreaterThan(0);
|
|
// Capability booleans mirror the resolved TERMINAL singleton.
|
|
expect(info.deccara).toBe(TERMINAL.deccara);
|
|
expect(info.hyperlinks).toBe(TERMINAL.hyperlinks);
|
|
expect(info.trueColor).toBe(TERMINAL.trueColor);
|
|
});
|
|
});
|