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

137 lines
4.4 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import type { WorkspaceNode } from "./models.ts";
import {
appendPaneToWorkspaceRoot,
cloneWorkspaceTree,
insertPaneIntoWorkspace,
reorderWorkspaceFocusSessionOrder,
resolveWorkspaceFocusSessionOrder,
} from "./workspace.ts";
const root: WorkspaceNode = {
id: "split-1",
type: "split",
direction: "vertical",
children: [
{ id: "pane-1", type: "pane", sessionId: "s1" },
{ id: "pane-2", type: "pane", sessionId: "s2" },
{ id: "pane-3", type: "pane", sessionId: "s3" },
],
};
test("resolveWorkspaceFocusSessionOrder follows tree order when no saved order exists", () => {
assert.deepEqual(resolveWorkspaceFocusSessionOrder(root), ["s1", "s2", "s3"]);
});
test("resolveWorkspaceFocusSessionOrder drops stale ids and appends new panes", () => {
assert.deepEqual(
resolveWorkspaceFocusSessionOrder(root, ["stale", "s3", "s1"]),
["s3", "s1", "s2"],
);
});
test("reorderWorkspaceFocusSessionOrder moves a session before a target", () => {
assert.deepEqual(
reorderWorkspaceFocusSessionOrder(root, undefined, "s3", "s1", "before"),
["s3", "s1", "s2"],
);
});
test("reorderWorkspaceFocusSessionOrder moves a session after a target", () => {
assert.deepEqual(
reorderWorkspaceFocusSessionOrder(root, ["s1", "s2", "s3"], "s1", "s3", "after"),
["s2", "s3", "s1"],
);
});
test("appendPaneToWorkspaceRoot ignores an existing session pane", () => {
assert.equal(appendPaneToWorkspaceRoot(root, "s2"), root);
});
test("insertPaneIntoWorkspace ignores an existing session pane", () => {
assert.equal(
insertPaneIntoWorkspace(root, "s2", {
direction: "vertical",
position: "right",
targetSessionId: "s1",
}),
root,
);
});
const nestedRoot: WorkspaceNode = {
id: "split-root",
type: "split",
direction: "vertical",
sizes: [0.8, 0.2],
children: [
{ id: "pane-a", type: "pane", sessionId: "s1" },
{
id: "split-inner",
type: "split",
direction: "horizontal",
sizes: [0.5, 0.5],
children: [
{ id: "pane-b", type: "pane", sessionId: "s2" },
{ id: "pane-c", type: "pane", sessionId: "s3" },
],
},
],
};
test("cloneWorkspaceTree remaps every sessionId and preserves direction/sizes", () => {
const map = new Map([["s1", "n1"], ["s2", "n2"], ["s3", "n3"]]);
const clone = cloneWorkspaceTree(nestedRoot, map);
assert.equal(clone.type, "split");
if (clone.type !== "split") return;
assert.equal(clone.direction, "vertical");
assert.deepEqual(clone.sizes, [0.8, 0.2]);
const inner = clone.children[1];
assert.equal(inner.type, "split");
if (inner.type !== "split") return;
assert.equal(inner.direction, "horizontal");
assert.deepEqual(inner.sizes, [0.5, 0.5]);
const collect = (n: WorkspaceNode): string[] =>
n.type === "pane" ? [n.sessionId] : n.children.flatMap(collect);
assert.deepEqual(collect(clone), ["n1", "n2", "n3"]);
});
test("cloneWorkspaceTree mints fresh node ids and does not mutate the source", () => {
const map = new Map([["s1", "n1"], ["s2", "n2"], ["s3", "n3"]]);
const clone = cloneWorkspaceTree(nestedRoot, map);
assert.notEqual(clone.id, nestedRoot.id);
assert.equal(nestedRoot.id, "split-root");
const collectSrc = (n: WorkspaceNode): string[] =>
n.type === "pane" ? [n.sessionId] : n.children.flatMap(collectSrc);
assert.deepEqual(collectSrc(nestedRoot), ["s1", "s2", "s3"]);
const collectIds = (n: WorkspaceNode): string[] =>
n.type === "pane" ? [n.id] : [n.id, ...n.children.flatMap(collectIds)];
const srcIds = new Set(collectIds(nestedRoot));
assert.ok(collectIds(clone).every(id => !srcIds.has(id)));
});
test("cloneWorkspaceTree uses pre-minted node ids when supplied", () => {
const clone = cloneWorkspaceTree(
nestedRoot,
new Map([["s1", "n1"], ["s2", "n2"], ["s3", "n3"]]),
new Map([["split-root", "new-root"], ["pane-a", "new-a"], ["split-inner", "new-inner"], ["pane-b", "new-b"], ["pane-c", "new-c"]]),
);
assert.equal(clone.id, "new-root");
if (clone.type !== "split") return;
assert.equal(clone.children[0].id, "new-a");
assert.equal(clone.children[1].id, "new-inner");
});
test("cloneWorkspaceTree keeps original sessionId when the map lacks it", () => {
const clone = cloneWorkspaceTree(
{ id: "p", type: "pane", sessionId: "s1" },
new Map(),
);
assert.equal(clone.type === "pane" && clone.sessionId, "s1");
});