Files
NetMesh/domain/connectionLog.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

196 lines
5.2 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import type { ConnectionLog } from "./models.ts";
import { selectConnectionLogForTerminalDataCapture } from "./connectionLog.ts";
import {
MAX_PERSISTED_UNSAVED_TERMINAL_DATA_ENTRIES,
mergeConnectionLogsFromStorage,
mergeTerminalDataIntoLogs,
mergeTerminalDataMapsForStorage,
pruneTerminalDataMapForStorage,
} from "./connectionLogTerminalData.ts";
const baseLog: ConnectionLog = {
id: "log-base",
sessionId: "session-1",
hostId: "host-1",
hostLabel: "Example",
hostname: "example.com",
username: "user",
protocol: "ssh",
startTime: 1000,
localUsername: "local",
localHostname: "machine",
saved: false,
};
test("selectConnectionLogForTerminalDataCapture picks the active log for a normal session exit", () => {
const matchingLog = { ...baseLog, id: "active", startTime: 2000 };
const staleLog = {
...baseLog,
id: "stale",
sessionId: "session-2",
startTime: 3000,
};
assert.equal(
selectConnectionLogForTerminalDataCapture(
[staleLog, matchingLog],
{ sessionId: "session-1", hostname: "example.com" },
)?.id,
"active",
);
});
test("selectConnectionLogForTerminalDataCapture reuses the latest log for repeated captures after reconnect", () => {
const firstCapture = {
...baseLog,
id: "first-capture",
startTime: 2000,
endTime: 2500,
terminalData: "first disconnect",
};
const olderSameSession = {
...baseLog,
id: "older-same-session",
startTime: 1500,
endTime: 1800,
terminalData: "older data",
};
const otherSession = {
...baseLog,
id: "other-session",
sessionId: "session-2",
startTime: 3000,
};
assert.equal(
selectConnectionLogForTerminalDataCapture(
[otherSession, olderSameSession, firstCapture],
{ sessionId: "session-1", hostname: "example.com" },
)?.id,
"first-capture",
);
});
test("selectConnectionLogForTerminalDataCapture does not cross-match localhost logs without sessionId", () => {
const openLocalWithoutSession = {
...baseLog,
id: "open-local",
sessionId: undefined,
hostname: "localhost",
protocol: "local",
startTime: 3000,
};
const targetLocal = {
...baseLog,
id: "target-local",
sessionId: "session-local-a",
hostname: "localhost",
protocol: "local",
startTime: 2000,
};
assert.equal(
selectConnectionLogForTerminalDataCapture(
[openLocalWithoutSession, targetLocal],
{ sessionId: "session-local-b", hostname: "localhost" },
),
undefined,
);
});
test("mergeConnectionLogsFromStorage keeps in-memory terminal replay data", () => {
const memoryLog = {
...baseLog,
id: "memory",
terminalData: "captured output",
};
const storedLog = {
...baseLog,
id: "memory",
endTime: 2000,
};
const merged = mergeConnectionLogsFromStorage(
[memoryLog],
[storedLog],
{},
);
assert.equal(merged[0]?.terminalData, "captured output");
});
test("mergeTerminalDataIntoLogs hydrates unsaved logs from side storage", () => {
const storedLog = { ...baseLog, id: "hydrate" };
const hydrated = mergeTerminalDataIntoLogs([storedLog], {
hydrate: "side-store output",
});
assert.equal(hydrated[0]?.terminalData, "side-store output");
});
test("pruneTerminalDataMapForStorage caps unsaved replay buffers", () => {
const logs: ConnectionLog[] = Array.from({ length: 60 }, (_, index) => ({
...baseLog,
id: `log-${index}`,
startTime: index,
saved: false,
}));
const map = Object.fromEntries(
logs.map((log) => [log.id, `data-${log.id}`]),
);
const pruned = pruneTerminalDataMapForStorage(logs, map);
assert.equal(Object.keys(pruned).length, MAX_PERSISTED_UNSAVED_TERMINAL_DATA_ENTRIES);
assert.equal(pruned["log-59"], "data-log-59");
assert.equal(pruned["log-0"], undefined);
});
test("mergeTerminalDataMapsForStorage keeps replay data from other windows", () => {
const logs: ConnectionLog[] = [
{ ...baseLog, id: "local", startTime: 2000 },
{ ...baseLog, id: "remote", startTime: 1000 },
];
const merged = mergeTerminalDataMapsForStorage(
logs,
{ remote: "remote-window output", other: "other-window only" },
[{ local: "local-window output" }],
new Set(["local", "remote", "other"]),
);
assert.equal(merged.remote, "remote-window output");
assert.equal(merged.local, "local-window output");
assert.equal(merged.other, "other-window only");
});
test("mergeTerminalDataMapsForStorage prefers fresher local replay data for orphans", () => {
const logs: ConnectionLog[] = [{ ...baseLog, id: "local", startTime: 2000 }];
const merged = mergeTerminalDataMapsForStorage(
logs,
{ other: "stale snapshot" },
[{ other: "fresh local" }],
new Set(["local", "other"]),
);
assert.equal(merged.other, "fresh local");
});
test("mergeTerminalDataMapsForStorage drops deleted log replay buffers", () => {
const logs: ConnectionLog[] = [{ ...baseLog, id: "local", startTime: 2000 }];
const merged = mergeTerminalDataMapsForStorage(
logs,
{ local: "keep", deleted: "drop me" },
[],
new Set(["local"]),
);
assert.equal(merged.local, "keep");
assert.equal(merged.deleted, undefined);
});