Files
fusion/packages/dashboard/app/utils/__tests__/terminalPreferences.test.ts
gsxdsm 11c4120705 FN-6659: keep xterm font metrics symbols-free
Keep terminal wide-glyph fallback out of xterm's measured font path while preserving Nerd Font symbols in DOM rendering.

- Split terminal font resolution into symbols-free xterm font families and scoped glyph fallback families.
- Apply the glyph fallback CSS variable to both TerminalModal and SessionTerminal surfaces.
- Update regression coverage and the documented mobile xterm wide-glyph recurrence analysis.

Files changed:
 .changeset/fn-6659-terminal-render.md              |  5 +++
 .../xterm-symbols-nerd-font-unicode-range.md       | 22 +++++++-----
 .../dashboard/app/__tests__/terminal-input.test.ts | 42 +++++++++++++---------
 .../dashboard/app/components/SessionTerminal.css   |  8 +++++
 .../dashboard/app/components/SessionTerminal.tsx   | 21 +++++++++--
 .../dashboard/app/components/TerminalModal.css     |  8 +++++
 .../dashboard/app/components/TerminalModal.tsx     | 13 ++++++-
 .../__tests__/SessionTerminal.mobile.test.tsx      |  6 ++--
 .../components/__tests__/SessionTerminal.test.tsx  | 14 ++++----
 .../components/__tests__/TerminalModal.test.tsx    |  9 +++--
 .../utils/__tests__/terminalPreferences.test.ts    |  2 +-
 .../dashboard/app/utils/terminalPreferences.ts     | 16 +++++----
 12 files changed, 117 insertions(+), 49 deletions(-)

Fusion-Task-Id: FN-6659

Fusion-Task-Lineage: e29a709d-9d9d-4a90-9616-8f08c41b126d
2026-06-18 15:59:34 -07:00

118 lines
3.4 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
import {
DEFAULT_TERMINAL_PREFERENCES,
LEGACY_TERMINAL_FONT_SIZE_KEY,
TERMINAL_PREFERENCES_KEY,
XTERM_FONT_FAMILY,
readTerminalPreferences,
waitForTerminalFontMetrics,
writeTerminalPreferences,
} from "../terminalPreferences";
describe("terminalPreferences", () => {
beforeEach(() => {
localStorage.clear();
});
it("returns defaults when storage is empty", () => {
expect(readTerminalPreferences()).toEqual(DEFAULT_TERMINAL_PREFERENCES);
});
it("falls back to defaults for corrupt JSON", () => {
localStorage.setItem(TERMINAL_PREFERENCES_KEY, "not-json");
expect(readTerminalPreferences()).toEqual(DEFAULT_TERMINAL_PREFERENCES);
});
it("clamps font size values", () => {
localStorage.setItem(
TERMINAL_PREFERENCES_KEY,
JSON.stringify({ ...DEFAULT_TERMINAL_PREFERENCES, fontSize: 99 }),
);
expect(readTerminalPreferences().fontSize).toBe(32);
localStorage.setItem(
TERMINAL_PREFERENCES_KEY,
JSON.stringify({ ...DEFAULT_TERMINAL_PREFERENCES, fontSize: 1 }),
);
expect(readTerminalPreferences().fontSize).toBe(8);
});
it("rejects unknown enum values to defaults", () => {
localStorage.setItem(
TERMINAL_PREFERENCES_KEY,
JSON.stringify({
fontFamily: "comic-sans",
fontSize: 16,
cursorStyle: "boxy",
cursorBlink: false,
renderer: "webgl-only",
}),
);
expect(readTerminalPreferences()).toEqual({
...DEFAULT_TERMINAL_PREFERENCES,
fontSize: 16,
cursorBlink: false,
});
});
it("migrates the legacy font-size key on first read", () => {
localStorage.setItem(LEGACY_TERMINAL_FONT_SIZE_KEY, "20");
expect(readTerminalPreferences()).toEqual({
...DEFAULT_TERMINAL_PREFERENCES,
fontSize: 20,
});
expect(JSON.parse(localStorage.getItem(TERMINAL_PREFERENCES_KEY) ?? "null")).toEqual({
...DEFAULT_TERMINAL_PREFERENCES,
fontSize: 20,
});
});
it("round-trips normalized writes", () => {
const written = writeTerminalPreferences({
fontFamily: "system-mono",
fontSize: 22,
cursorStyle: "underline",
cursorBlink: false,
renderer: "canvas",
});
expect(written).toEqual({
fontFamily: "system-mono",
fontSize: 22,
cursorStyle: "underline",
cursorBlink: false,
renderer: "canvas",
});
expect(readTerminalPreferences()).toEqual(written);
expect(localStorage.getItem(LEGACY_TERMINAL_FONT_SIZE_KEY)).toBe("22");
});
it("keeps terminal font metrics wait best-effort when iOS rejects the full stack shorthand", async () => {
let readyAwaited = false;
const load = vi.fn((font: string) => {
if (font.includes(",")) {
return Promise.reject(new DOMException("Invalid font shorthand"));
}
return Promise.resolve([]);
});
const ready = Promise.resolve().then(() => {
readyAwaited = true;
});
await expect(
waitForTerminalFontMetrics(12, XTERM_FONT_FAMILY, {
load,
ready,
}),
).resolves.toBe(true);
expect(load).toHaveBeenCalledWith(expect.stringContaining("MesloLGS NF"));
expect(load).toHaveBeenCalledWith("12px \"MesloLGS NF\"");
expect(load).not.toHaveBeenCalledWith("12px \"Fusion Terminal Nerd Font Symbols\"");
expect(readyAwaited).toBe(true);
});
});