Files
oh-my-pi/packages/tui/test/image-render.test.ts
T
HvC 28d9de74ce Implement Windows Sixel support and terminal capability checks (#241)
* windows sixel imp

* windows sixel imp, terminal capability check, pessimistic sixel selection

* fix codex suggestions

---------

Co-authored-by: Brit <lol@no.com>
2026-03-01 22:23:05 +01:00

141 lines
4.3 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it } from "bun:test";
import { Image } from "@oh-my-pi/pi-tui/components/image";
import {
type CellDimensions,
getCellDimensions,
ImageProtocol,
isWindowsTerminalPreviewSixelSupported,
renderImage,
setCellDimensions,
TERMINAL,
} from "@oh-my-pi/pi-tui/terminal-capabilities";
type MutableTerminalInfo = {
imageProtocol: ImageProtocol | null;
};
const terminal = TERMINAL as unknown as MutableTerminalInfo;
const BASE64_DUMMY = "AA==";
const SQUARE_DIMENSIONS = { widthPx: 100, heightPx: 100 };
const BASE64_ONE_PIXEL_PNG =
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVR4nGNgAAAAAgABSK+kcQAAAABJRU5ErkJggg==";
function parseKittyParam(sequence: string, key: "c" | "r"): number | null {
const match = sequence.match(new RegExp(`${key}=(\\d+)`));
if (!match) return null;
return Number.parseInt(match[1], 10);
}
function parseITermWidth(sequence: string): string | null {
const match = sequence.match(/width=([^;:]+)/);
return match?.[1] ?? null;
}
describe("terminal image rendering", () => {
const originalProtocol = TERMINAL.imageProtocol;
let originalCellDims: CellDimensions;
beforeEach(() => {
originalCellDims = { ...getCellDimensions() };
setCellDimensions({ widthPx: 10, heightPx: 10 });
terminal.imageProtocol = null;
});
afterEach(() => {
setCellDimensions(originalCellDims);
terminal.imageProtocol = originalProtocol;
});
it("fits Kitty images within max width and max height while preserving aspect ratio", () => {
terminal.imageProtocol = ImageProtocol.Kitty;
const result = renderImage(BASE64_DUMMY, SQUARE_DIMENSIONS, {
maxWidthCells: 10,
maxHeightCells: 2,
});
expect(result).not.toBeNull();
expect(result?.rows).toBe(2);
expect(parseKittyParam(result?.sequence ?? "", "c")).toBe(2);
expect(parseKittyParam(result?.sequence ?? "", "r")).toBe(2);
});
it("uses intrinsic image size when no bounds are provided", () => {
terminal.imageProtocol = ImageProtocol.Kitty;
const result = renderImage(BASE64_DUMMY, SQUARE_DIMENSIONS);
expect(result).not.toBeNull();
expect(result?.rows).toBe(10);
expect(parseKittyParam(result?.sequence ?? "", "c")).toBe(10);
expect(parseKittyParam(result?.sequence ?? "", "r")).toBe(10);
});
it("reduces iTerm2 width when max height is the limiting bound", () => {
terminal.imageProtocol = ImageProtocol.Iterm2;
const result = renderImage(BASE64_DUMMY, SQUARE_DIMENSIONS, {
maxWidthCells: 10,
maxHeightCells: 2,
});
expect(result).not.toBeNull();
expect(result?.rows).toBe(2);
expect(parseITermWidth(result?.sequence ?? "")).toBe("2");
expect(result?.sequence).toContain("height=auto");
});
it("encodes SIXEL output when protocol is SIXEL", () => {
terminal.imageProtocol = ImageProtocol.Sixel;
const result = renderImage(BASE64_ONE_PIXEL_PNG, SQUARE_DIMENSIONS, {
maxWidthCells: 10,
maxHeightCells: 2,
});
expect(result).not.toBeNull();
expect(result?.rows).toBe(2);
expect(result?.sequence.startsWith("\x1bP")).toBe(true);
});
it("Image component forwards maxHeightCells to terminal rendering", () => {
terminal.imageProtocol = ImageProtocol.Kitty;
const image = new Image(
BASE64_DUMMY,
"image/png",
{ fallbackColor: text => text },
{ maxWidthCells: 10, maxHeightCells: 2 },
SQUARE_DIMENSIONS,
);
const lines = image.render(20);
expect(lines).toHaveLength(2);
expect(lines[1]).toContain("\x1b[1A");
expect(lines[1]).toContain("c=2");
expect(lines[1]).toContain("r=2");
});
});
describe("Windows Terminal Preview SIXEL detection", () => {
it("requires Windows platform, WT session, and known version 1.22+", () => {
expect(
isWindowsTerminalPreviewSixelSupported(
{ WT_SESSION: "1", TERM_PROGRAM: "Windows_Terminal", TERM_PROGRAM_VERSION: "1.22.2362.0" },
"win32",
),
).toBe(true);
expect(
isWindowsTerminalPreviewSixelSupported(
{ WT_SESSION: "1", TERM_PROGRAM: "Windows_Terminal", TERM_PROGRAM_VERSION: "1.21.0.0" },
"win32",
),
).toBe(false);
expect(
isWindowsTerminalPreviewSixelSupported({ WT_SESSION: "1", TERM_PROGRAM: "Windows_Terminal" }, "win32"),
).toBe(false);
expect(
isWindowsTerminalPreviewSixelSupported(
{ WT_SESSION: "1", TERM_PROGRAM: "Windows_Terminal", TERM_PROGRAM_VERSION: "1.22.2362.0" },
"linux",
),
).toBe(false);
});
});