[Init] Initial commit - NetMesh terminal manager
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
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
This commit is contained in:
185
domain/terminalInlineImages.test.ts
Normal file
185
domain/terminalInlineImages.test.ts
Normal file
@@ -0,0 +1,185 @@
|
||||
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);
|
||||
});
|
||||
Reference in New Issue
Block a user