Files
NetMesh/domain/terminalInlineImages.test.ts
zhaolei 3c72efcb7f
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
[Init] Initial commit - NetMesh terminal manager
2026-09-13 18:24:01 +08:00

186 lines
6.2 KiB
TypeScript

import assert from "node:assert/strict";
import test from "node:test";
import { normalizeTerminalSettings } from "./models/terminal.ts";
import {
normalizeInlineImageMaxMegapixels,
normalizeInlineImageSequenceLimitMb,
normalizeInlineImageStorageLimitMb,
resolveTerminalInlineImageAddonOptions,
resolveTerminalInlineImagesEnabled,
TERMINAL_INLINE_IMAGE_MAX_MEGAPIXELS_DEFAULT,
TERMINAL_INLINE_IMAGE_MAX_MEGAPIXELS_MAX,
TERMINAL_INLINE_IMAGE_MAX_MEGAPIXELS_MIN,
TERMINAL_INLINE_IMAGE_SEQUENCE_LIMIT_MB_DEFAULT,
TERMINAL_INLINE_IMAGE_SEQUENCE_LIMIT_MB_MAX,
TERMINAL_INLINE_IMAGE_SEQUENCE_LIMIT_MB_MIN,
TERMINAL_INLINE_IMAGE_STORAGE_LIMIT_MB_DEFAULT,
TERMINAL_INLINE_IMAGE_STORAGE_LIMIT_MB_MAX,
TERMINAL_INLINE_IMAGE_STORAGE_LIMIT_MB_MIN,
} from "./terminalInlineImages.ts";
const allProtocols = {
inlineImagesEnabled: true,
inlineImageKittyEnabled: true,
inlineImageSixelEnabled: true,
inlineImageIipEnabled: true,
};
test("inline image limits clamp untrusted persisted values", () => {
assert.equal(
normalizeInlineImageStorageLimitMb(1),
TERMINAL_INLINE_IMAGE_STORAGE_LIMIT_MB_MIN,
);
assert.equal(
normalizeInlineImageStorageLimitMb(100_000),
TERMINAL_INLINE_IMAGE_STORAGE_LIMIT_MB_MAX,
);
assert.equal(
normalizeInlineImageStorageLimitMb("128"),
TERMINAL_INLINE_IMAGE_STORAGE_LIMIT_MB_DEFAULT,
);
assert.equal(
normalizeInlineImageStorageLimitMb(Number.NaN),
TERMINAL_INLINE_IMAGE_STORAGE_LIMIT_MB_DEFAULT,
);
assert.equal(normalizeInlineImageStorageLimitMb(64.4), 64);
assert.equal(
normalizeInlineImageMaxMegapixels(0),
TERMINAL_INLINE_IMAGE_MAX_MEGAPIXELS_MIN,
);
assert.equal(
normalizeInlineImageMaxMegapixels(4096),
TERMINAL_INLINE_IMAGE_MAX_MEGAPIXELS_MAX,
);
assert.equal(
normalizeInlineImageMaxMegapixels(undefined),
TERMINAL_INLINE_IMAGE_MAX_MEGAPIXELS_DEFAULT,
);
assert.equal(
normalizeInlineImageSequenceLimitMb(-5),
TERMINAL_INLINE_IMAGE_SEQUENCE_LIMIT_MB_MIN,
);
assert.equal(
normalizeInlineImageSequenceLimitMb(999),
TERMINAL_INLINE_IMAGE_SEQUENCE_LIMIT_MB_MAX,
);
assert.equal(
normalizeInlineImageSequenceLimitMb(null),
TERMINAL_INLINE_IMAGE_SEQUENCE_LIMIT_MB_DEFAULT,
);
});
test("inline images stay off unless the master switch and one protocol are on", () => {
assert.equal(resolveTerminalInlineImagesEnabled(), false);
assert.equal(resolveTerminalInlineImagesEnabled({ ...allProtocols, inlineImagesEnabled: false }), false);
assert.equal(
resolveTerminalInlineImagesEnabled({
inlineImagesEnabled: true,
inlineImageKittyEnabled: false,
inlineImageSixelEnabled: false,
inlineImageIipEnabled: false,
}),
false,
);
assert.equal(
resolveTerminalInlineImagesEnabled({
inlineImagesEnabled: true,
inlineImageKittyEnabled: true,
inlineImageSixelEnabled: false,
inlineImageIipEnabled: false,
}),
true,
);
});
test("disabled inline images produce no addon options at all", () => {
assert.equal(resolveTerminalInlineImageAddonOptions(null), null);
assert.equal(
resolveTerminalInlineImageAddonOptions({ ...allProtocols, inlineImagesEnabled: false }),
null,
);
assert.equal(
resolveTerminalInlineImageAddonOptions({
inlineImagesEnabled: true,
inlineImageKittyEnabled: false,
inlineImageSixelEnabled: false,
inlineImageIipEnabled: false,
}),
null,
);
});
test("addon options convert user units into addon units and clamp them", () => {
const options = resolveTerminalInlineImageAddonOptions({
...allProtocols,
inlineImageStorageLimitMb: 64,
inlineImageMaxMegapixels: 4,
inlineImageSequenceLimitMb: 8,
});
assert.ok(options);
assert.equal(options.storageLimit, 64, "storage limit is passed through in MB");
assert.equal(options.pixelLimit, 4 * 1024 * 1024, "megapixels become a pixel count");
assert.equal(options.sixelSizeLimit, 8 * 1024 * 1024, "sequence limit becomes bytes");
assert.equal(options.iipSizeLimit, options.sixelSizeLimit);
assert.equal(options.kittySizeLimit, options.sixelSizeLimit);
assert.equal(options.enableSizeReports, true, "image producers need CSI 14/16/18 t");
assert.equal(options.showPlaceholder, true);
const clamped = resolveTerminalInlineImageAddonOptions({
...allProtocols,
inlineImageStorageLimitMb: 100_000,
inlineImageMaxMegapixels: 100_000,
inlineImageSequenceLimitMb: 100_000,
});
assert.ok(clamped);
assert.equal(clamped.storageLimit, TERMINAL_INLINE_IMAGE_STORAGE_LIMIT_MB_MAX);
assert.equal(
clamped.pixelLimit,
TERMINAL_INLINE_IMAGE_MAX_MEGAPIXELS_MAX * 1024 * 1024,
);
assert.equal(
clamped.kittySizeLimit,
TERMINAL_INLINE_IMAGE_SEQUENCE_LIMIT_MB_MAX * 1024 * 1024,
);
});
test("each protocol switch maps to its own addon support flag", () => {
const kittyOnly = resolveTerminalInlineImageAddonOptions({
inlineImagesEnabled: true,
inlineImageKittyEnabled: true,
inlineImageSixelEnabled: false,
inlineImageIipEnabled: false,
});
assert.ok(kittyOnly);
assert.equal(kittyOnly.kittySupport, true);
assert.equal(kittyOnly.sixelSupport, false);
assert.equal(kittyOnly.iipSupport, false);
});
test("terminal settings default to inline images off with clamped limits", () => {
const defaults = normalizeTerminalSettings();
assert.equal(defaults.inlineImagesEnabled, false);
assert.equal(defaults.inlineImageKittyEnabled, true);
assert.equal(defaults.inlineImageSixelEnabled, true);
assert.equal(defaults.inlineImageIipEnabled, true);
assert.equal(defaults.inlineImageStorageLimitMb, TERMINAL_INLINE_IMAGE_STORAGE_LIMIT_MB_DEFAULT);
assert.equal(defaults.inlineImageMaxMegapixels, TERMINAL_INLINE_IMAGE_MAX_MEGAPIXELS_DEFAULT);
assert.equal(defaults.inlineImageSequenceLimitMb, TERMINAL_INLINE_IMAGE_SEQUENCE_LIMIT_MB_DEFAULT);
const restored = normalizeTerminalSettings({
inlineImageStorageLimitMb: 4096,
inlineImageMaxMegapixels: 0,
inlineImageSequenceLimitMb: -1,
} as never);
assert.equal(restored.inlineImageStorageLimitMb, TERMINAL_INLINE_IMAGE_STORAGE_LIMIT_MB_MAX);
assert.equal(restored.inlineImageMaxMegapixels, TERMINAL_INLINE_IMAGE_MAX_MEGAPIXELS_MIN);
assert.equal(restored.inlineImageSequenceLimitMb, TERMINAL_INLINE_IMAGE_SEQUENCE_LIMIT_MB_MIN);
});